Overview
The Protegrity Data Protection API v4 (SecOps v4) lets callers protect, unprotect, and reprotect (unprotect with one data element, then protect with another) sensitive data values according to a configured data security policy.
This is the new, canonical JSON API and is the recommended interface for all new integrations. It replaces the older v1 and Legacy REST formats, which are now deprecated.
- Base path:
/pty/api/secops/v4 - Content type:
application/jsonfor both request and response - Method: all operations are HTTP
POST
Note
SecOps v4 is served only at/pty/api/secops/v4/*. Requests on this path are never handled by the v1 or Legacy formats, even if the body looks like a legacy request.Endpoints
| Method | Path | Purpose |
|---|---|---|
| POST | /pty/api/secops/v4/protect | Protect data values using a data element. |
| POST | /pty/api/secops/v4/unprotect | Unprotect previously protected values. |
| POST | /pty/api/secops/v4/reprotect | Unprotect with one data element and protect with another. |
Authentication
Authentication uses a JWT bearer token supplied in the Authorization header (the scheme keyword is matched case-insensitively):
Authorization: Bearer <token>
Enforcement is configured at deployment time and controlled by two configuration properties: authorization (set to jwt to enable JWT mode) and jwt_verify (set to 1 to verify the token signature).
When authorization is set to jwt:
- A missing, empty, or malformed
Authorizationheader returns HTTP403, regardless of thejwt_verifysetting. - Signature and expiry verification runs only when
jwt_verifyis1. A failed verification (bad signature, expired token, and so on) returns HTTP403. Whenjwt_verifyis not1, the token is decoded for its claims but the signature is not checked. - The user identity is taken from a JWT claim (configurable with
jwt_user_claim, defaultcognito:username). See theuserfield note under Request for how the bodyuserfield interacts with this.
Note
A missing requireduser is an HTTP 400 validation error, not a 403. HTTP 403 is reserved for Authorization header and token problems.Request
protect / unprotect
{
"user": "alice",
"payload": [
{
"dataElement": "DE_SSN",
"data": ["675-00-7848", "105-74-8112"],
"encoding": "utf8",
"externalIv": "s40de6wf6",
"externaltweak": "e8wf6s30d",
"id": "1"
}
]
}
reprotect
The reprotect operation adds the new* fields that describe the target data element.
{
"user": "alice",
"payload": [
{
"dataElement": "DE_SSN",
"newDataElement": "DE_SSN_2",
"data": ["340-75-9971"],
"externalIv": "s40de6wf6",
"newExternalIv": "02983hd7sz",
"externaltweak": "e8wf6s30d",
"newExternaltweak": "h4egm1hjd"
}
]
}
Field reference
| Field | Location | Type | Required | Notes |
|---|---|---|---|---|
user | top-level | string | Optional (conditional at runtime — see note below) | Identity performing the operation. |
payload | top-level | array (min 1 item) | Required | One or more work items; each is processed independently. |
dataElement | payload item | string | Required | Policy data element. In reprotect this is the source data element. |
newDataElement | payload item | string | Required for reprotect | Target data element that the values are protected with during reprotect. |
data | payload item | array of string/number (min 1) | Required | Values to process. null entries are allowed. |
encoding | payload item | enum | Optional, default utf8 | One of: utf8, hex, base64, base64_mime, base64_pem, base64_url. |
externalIv | payload item | string | Optional | External initialization vector. In reprotect, the IV for the source data element. |
newExternalIv | payload item | string | Optional (reprotect) | IV for the target data element. |
externaltweak | payload item | string | Optional | External tweak used with FPE. Source-data-element tweak in reprotect. Note the lowercase t. |
newExternaltweak | payload item | string | Optional (reprotect) | Tweak for the target data element. Note the lowercase t. |
id | payload item | string or number | Optional | Client correlation tag, echoed back in the matching result with its JSON type preserved (a number stays a number, a string stays a string). A string id longer than 128 characters is rejected with an HTTP 400 validation error (maxLength: 128), enforced consistently across protect, unprotect, and reprotect. The number form is unconstrained. |
Note
v4 uses camelCase field names (dataElement, externalIv), unlike the snake_case used by the v1 and Legacy formats (data_element, external_iv). The tweak fields externaltweak and newExternaltweak are intentionally all lowercase (not externalTweak).Is the user field required?
The user field is not unconditionally required. Whether it is needed depends on the deployment’s authorization mode:
- No authorization (
authorizationunset or notjwt): the bodyuserfield is required. The request fails with HTTP400if it is missing. - JWT authorization (
authorization=jwt): the user is taken from a JWT claim (jwt_user_claim, defaultcognito:username). The bodyuserfield is honoured only when proxy-user is enabled (allow_assume_user=1); otherwise it is ignored. If no user can be resolved from the token, the request fails with HTTP400. - Service user (
service_userconfigured): the bodyuserfield is ignored entirely and the configured service user is used.
Empty data array
Eachdata array must contain at least one value. A missing data array, or an empty data array, is rejected with an HTTP 400 validation error.Response
Success (HTTP 200)
Both full success and partial success return HTTP 200. The response envelope is { errorCount, results }, where the order of results matches the order of the input payload.
{
"errorCount": 0,
"results": [
{ "encoding": "utf8", "data": ["340-75-9971", "064-18-7624"], "returnCode": 8 }
]
}
Each result is one of two shapes:
- Success result (
resultSuccess):returnCode(the engine’s success code —6for protect,8for unprotect,50for reprotect, or11when an inactive key was used),encoding,data[], and optionalid. - Failure result (
resultFailure):returnCode(a non-success engine code),message, and optionalid.
A partial-success response (one item failed, one succeeded) still returns HTTP 200:
{
"errorCount": 1,
"results": [
{ "id": "1", "message": "Input too short", "returnCode": 22 },
{ "id": "2", "encoding": "base64", "data": ["..."], "returnCode": 8 }
]
}
Output encoding
When the caller does not set an inputencoding (it defaults to utf8), binary data elements are returned as hex and all other data elements are returned as utf8. When the caller supplies an explicit encoding, that same encoding is echoed back in the result.Error responses
| HTTP | When | Body shape |
|---|---|---|
200 | Full or partial success. Per-item failures appear in results and are counted by errorCount. | { errorCount, results[] } |
400 | A request-level validation error — for example, a missing or empty payload; a missing dataElement (or newDataElement for reprotect) or data; a missing or unresolvable user; an empty data array; an id string longer than 128 characters; or an invalid data item. The request was not processed. | { "message": "..." } |
403 | An Authorization header or token problem: missing, empty, malformed, or (when jwt_verify=1) a failed signature or expiry verification. | { "message": "..." } |
500 | A server-side fault — a configuration error (for example, signature verification is enabled but no signing secret is configured), the policy being missing or unavailable, or any other unexpected error. | { "message": "..." } |
400 versus 500
The status code is chosen by the kind of failure: an authentication or authorization problem returns403; a server configuration problem, a missing or unavailable policy, or any other unexpected error returns 500; and a request validation problem returns 400. All three error statuses share the same body shape — a single { "message": "..." } object.Return codes
returnCode is the protection engine’s return code. A success result carries a success code; a failure result carries a failure code together with a descriptive message.
Success codes (on a success result):
returnCode | Meaning |
|---|---|
6 | Protect succeeded. |
8 | Unprotect succeeded. |
11 | Unprotect succeeded using an inactive key. |
50 | Reprotect succeeded. |
10 | Access OK; no data transformed. |
27 | Application authorized. |
Failure codes (on a failure result):
returnCode | Meaning |
|---|---|
1 | User not found in the policy. |
2 | Data element not found in the policy. |
3 | User lacks permission for the requested operation. |
4 | Tweak is null. |
5 | Integrity check failed. |
7 | Protect operation failed. |
9 | Unprotect operation failed. |
12 | Input is null or not within allowed limits. |
13 | Internal error (also used when an unexpected internal fault has no other engine code). |
14 | Failed to load the data encryption key. |
15 | Tweak input is too long. |
19 | Unsupported tweak for the data element. |
20 | Out of memory. |
21 | Input or output buffer too small. |
22 | Data is too short to protect or unprotect. |
23 | Data is too long to protect or unprotect. |
26 | Unsupported algorithm or action for the data element. |
28 | Application not authorized. |
31 | Policy not available. |
44 | Input data content is not valid. |
49 | Unsupported input encoding for the data element. |
Examples
protect
Simple protect call with the minimum required input:
{
"user": "alice",
"payload": [
{ "data": ["George Washington"], "dataElement": "DE_NAME" }
]
}
Response:
{
"errorCount": 0,
"results": [
{ "encoding": "utf8", "data": ["EdVz2X i5a2FXNW5jR"], "returnCode": 6 }
]
}
Protect using FPE with an external tweak:
{
"user": "alice",
"payload": [
{
"data": ["675-00-7848", "105-74-8112"],
"dataElement": "DE_FPE",
"externaltweak": "e8wf6s30d"
}
]
}
unprotect
Simple unprotect call with the minimum required input:
{
"user": "alice",
"payload": [
{ "data": ["EdVz2X i5a2FXNW5jR"], "dataElement": "DE_NAME" }
]
}
Response:
{
"errorCount": 0,
"results": [
{ "encoding": "utf8", "data": ["George Washington"], "returnCode": 8 }
]
}
reprotect
Simple reprotect call (from one data element to another):
{
"user": "alice",
"payload": [
{
"data": ["EdVz2X i5a2FXNW5jR"],
"dataElement": "DE_NAME",
"newDataElement": "DE_NAME_2"
}
]
}
Response:
{
"errorCount": 0,
"results": [
{ "encoding": "utf8", "data": ["m9yGNp v2ZiB2YWx1"], "returnCode": 50 }
]
}
Error examples
A 400 response for a request-level validation error (for example, a missing payload):
{ "message": "'payload' parameter is missing" }
A 403 response when the authorization token is missing or expired:
{ "message": "Authorization header was not found" }
A 500 response for a configuration error:
{ "message": "JWT secret is missing" }
Headers
| Header | Direction | Notes |
|---|---|---|
Authorization | request | Bearer <jwt> (when JWT authorization is enabled). |
X-Correlation-ID | request → response (conditional) | Optional request-tracking ID. When the request supplies it, it is echoed back on every response — on full-success, partial-success, and all-failure 200 responses, and on 400, 403, and 500 responses. When the request omits it, no header is returned. |
Migrating from v1 / Legacy
| Aspect | v1 / Legacy | SecOps v4 |
|---|---|---|
| Path | Any path except secops | Only /pty/api/secops/v4/* |
| Operation selection | Last segment of the URL path (…/protect, and so on) | Last segment of the URL path (/protect, /unprotect, /reprotect) — same mechanism |
| Format selection | Body must contain the arguments array | Request path must start with /pty/api/secops/v4 |
| Request wrapper | arguments | payload |
| Data element field | data_element / old_data_element | dataElement / newDataElement |
| External IV field | external_iv / old_external_iv | externalIv / newExternalIv |
| FPE tweak | Not present | externaltweak / newExternaltweak |
| Success envelope | { success, results } | { errorCount, results } |
| 400 error body | Success-shaped envelope | { message } object |
Note
The v1 and Legacy formats remain functional but are deprecated and will be removed in a future release. Migrate to the Protegrity Data Protection API v4 at base path/pty/api/secops/v4.Feedback
Was this page helpful?