Errors

All errors follow a consistent structure. Use HTTP status codes for broad categorization and the error body for specific handling.

Error Response Format

{
  "error": {
    "type": "invalid_request_error",
    "message": "Parameter 'externalUserId' is required"
  },
  "requestId": "req-example"
}
FieldDescription
typeMachine-readable error category for programmatic handling
messageHuman-readable description for developers (do not show to end users)
requestIdOptional top-level request identifier for troubleshooting, when available

HTTP Status Codes

CodeMeaningAction
200Success (all operations)Process the response
400Bad RequestFix your request parameters
401UnauthorizedCheck your Bearer access token
402Payment RequiredResolve the account balance or test quota issue
403ForbiddenCheck service access; use error.type to identify product balance or quota failures
404Not FoundResource doesn't exist or has been deleted
409ConflictResolve the conflict (duplicate, locked, etc.)
429Too Many RequestsSlow down; honor Retry-After when provided
500Internal Server ErrorFollow endpoint-specific recovery rules; retry with backoff only when safe
502Bad GatewayGateway could not complete the upstream request; follow endpoint-specific recovery rules
503Service UnavailableTemporary failure; confirm whether the operation can be safely retried
504Gateway TimeoutGateway timed out waiting for the upstream; reconcile write outcomes before retrying

Error Types

The table below lists common error types. It is not exhaustive: use the individual
endpoint reference for operation-specific errors and recovery rules. Gateway authentication,
request-size, routing, and infrastructure failures can occur before the operation is processed.

TypeHTTPDescription
invalid_request_error400Parameter validation or malformed request
invalid_json400Request body is not valid JSON
authentication_error401Bearer access token invalid, expired, or missing
insufficient_balance402Calling account failed the shared balance check
test_quota_exceeded402Calling account failed the shared test quota check
permission_error403Account is not authorized for this service
insufficient_balance_error403Product-specific balance check failed; used by Reusable KYC preview and reuse
over_query_limit_error403Product-specific quota check failed; used by Reusable KYC preview and reuse
profile_not_found404Profile does not exist
case_not_found404AML case does not exist or does not belong to your account
alert_not_found404AML alert does not exist or does not belong to your account
match_not_found404AML match does not exist or does not belong to your account
profile_already_exists409Duplicate externalUserId
profile_deleted409Profile has been deleted
profile_unavailable409Profile state does not support this operation
profile_locked409Profile locked by another process
rate_limit_error429Rate limit exceeded; other rate-limit types may also be returned
internal_error500Unexpected service failure; used by Reusable KYC
api_error500 / 502 / 503 / 504Server or gateway failure. Distinguish by HTTP status and follow the endpoint's recovery rules.
service_unavailable503Used by some Application paths for lock / infrastructure fail-closed (service temporarily unavailable, please retry later)

Account and product access checks (402 / 403)

Individual, AML, and Client Access Links check the calling account's service access,
balance, and test quota before processing the operation. Balance and test quota failures
at this shared check return 402 insufficient_balance or 402 test_quota_exceeded.
These checks also apply to read-only queries, share-token creation, and Reusable KYC preview;
a 402 response does not mean that the requested operation incurred a charge.

Reusable KYC preview and reuse additionally check the recipient's Reusable KYC product access.
That check returns 403 reusable_kyc_disabled when the product is not enabled, or
403 insufficient_balance_error / 403 over_query_limit_error for product balance or quota failures.
These 403 types remain part of the current API. Handle the returned HTTP status and error.type
as documented; do not substitute a 402 type for a product-specific 403 type.

Handling Strategies

Client Errors (4xx)

For validation, authentication, and access failures, resolve the condition before retrying.
Rate limits (429) and some conflicts (409) need the handling documented for that condition.

if response.status_code == 400:
    error = response.json()["error"]
    log.warning(f"Bad request: {error['message']}")
    # Fix the request parameters
elif response.status_code == 409:
    error = response.json()["error"]
    if error["type"] == "profile_already_exists":
        # Handle duplicate: fetch existing profile instead
        pass

Server Errors (5xx)

These indicate a server-side issue, but do not establish whether a write took effect.
Follow the endpoint's recovery rules before retrying. In particular, a Reusable KYC reuse
request may have changed the recipient Profile even if its response was lost or failed;
see Reusable KYC: failures and retries.
Do not apply a blanket retry policy to write requests.

The following backoff example is for an operation already known to be safe to retry,
such as a read-only query:

import time

max_retries = 3
for attempt in range(max_retries):
    response = make_request()
    if response.status_code < 500:
        break
    time.sleep(2 ** attempt)

Rate Limiting (429)

Handle rate limits by HTTP status 429. A response can use rate_limit_error or another
rate-limit type; do not require one specific error.type to recognize this condition.
The diagnostic message is not a retry timer.

Honor Retry-After when it is provided; its value can be a delay in seconds or an HTTP date.
The header is optional. If it is absent or unusable, use bounded exponential backoff with
jitter and reduce request concurrency. There is no universal 60-second retry delay.

Before retrying a write, follow the endpoint's recovery rules. Waiting after a 429 does
not make repeated writes idempotent or resolve an earlier unknown outcome.

Request ID

Every response includes an X-Request-Id header. Include this when contacting support for faster debugging:

X-Request-Id: req_abc123def456