Skip to content

Status Codes

Every failure has the same flat shape, on every endpoint: a message, a code, details where there are any, and meta.

{
"error": "Invalid query parameters",
"code": "INVALID_QUERY",
"details": {
"issues": [
"limit: Expected number, received nan",
"Unrecognized key(s) in object: 'offset'"
]
},
"meta": {
"apiVersion": 2,
"timestamp": "2026-10-09T12:00:00.000Z"
}
}
Field Meaning
error A sentence for people. It can change; do not match on it.
code A stable, machine-readable code. Match on this.
details Present only for some codes: what was wrong, or what the request can do instead.
meta apiVersion (2) and timestamp, as on a success.

There is no retryable field. When waiting and retrying may succeed, the answer carries a Retry-After header with the seconds to wait.

Status Meaning
200 Success. A transfer create whose Idempotency-Key was already used also answers 200, with the transfer it created.
201 Created: a customer, a wallet, a case, a note, a webhook subscription, a rule or a threshold; a provider or integration saved for the first time; a transfer completed at once below the Travel Rule threshold.
202 Accepted, with work still to do: a queued transfer, or an action on a transfer's information requests.
204 An OPTIONS request.
400 The request cannot be used as it is: an unreadable query, body or cursor, a missing or invalid field, an unknown action, or a transfer state the action does not apply to.
401 The API key is missing, malformed, unknown or revoked.
403 The key lacks the scope, or its owner's role the permission; the change needs a live key; the company is suspended or its plan lacks the feature; or the request carried the dashboard's session cookie.
404 The path does not exist, the host names no company, or the record is not in the key's environment.
405 The path does not take the method. Allow lists the methods it takes.
409 The request conflicts with the record's current state: a duplicate, a concurrent change, a closed case, a blocked erasure, a connection with no saved credentials.
413 The body is over 64 KiB.
422 A well-formed body that a case, rule, threshold, webhook, provider or integration does not accept, or a link to a record that does not exist.
429 A rate limit or the company's usage limit. Retry-After says when to try again.
500 An unexpected error. The answer says nothing more.
503 Temporarily unavailable: a lookup timed out, encrypted data cannot be read just now, the company is not ready, or a provider failed. Retry-After is sent when a retry may succeed.

VALIDATION_ERROR is 400 on customers, wallets and transfers, and 422 on cases, rules, thresholds, webhooks, providers and integrations.

Status Code When
401 MISSING_KEY No x-api-key header.
401 INVALID_FORMAT The key is not in the issued format: covalence_pk_ and 64 hexadecimal characters.
401 KEY_NOT_FOUND No key of this company matches. A key of another company is not found either.
401 KEY_REVOKED The key was revoked, or its owner lost access: their membership ended, their account was disabled, their role no longer allows the key's environment, or the company's access to API keys is unavailable.
403 INSUFFICIENT_SCOPE The key lacks the endpoint's scope. The message names it.
403 INSUFFICIENT_PERMISSION The key's owner's role lacks the permission the action needs, or the action needs a second scope (a suspicion report needs strs:read, a report download transfers:read).
403 CSRF_VALIDATION_FAILED A POST, PUT, PATCH or DELETE carried the dashboard's session cookie.
403 TENANT_SUSPENDED The company is suspended.
403 TENANT_FEATURE_DISABLED The company's plan does not include the feature or the provider.
404 NOT_FOUND The path does not exist, or the host names no company.
405 METHOD_NOT_ALLOWED The path does not take the method.
400 INVALID_JSON The body is not JSON.
413 BODY_TOO_LARGE The body is over 65,536 bytes.
400 VALIDATION_ERROR Text with a NUL character (U+0000) in the path, the query or the body.
400 INVALID_QUERY A query the list or search cannot read, or a parameter it does not take. details.issues names each problem.
400 INVALID_CURSOR A cursor that the list did not hand out, such as an item's ID.
409 CONFLICT Another request changed the same record at the same time. Retry.
429 RATE_LIMITED A rate limit. See Rate Limits.
429 TENANT_LIMIT_EXCEEDED The company's usage limit is reached. Retry-After says when it resets, when that is known.
500 INTERNAL_ERROR An unexpected error.
500 VALIDATION_ERROR The key could not be checked, through an internal failure.
503 SERVICE_UNAVAILABLE Encrypted data cannot be read just now (Retry-After: 30; nothing was read or written in plaintext), or the company's routing could not be read.
503 TENANT_UNAVAILABLE The company is not ready yet.
Status Code When
400 VALIDATION_ERROR The body is not a JSON object; externalId or name is not text of at most 255 characters; a Travel Rule identity is invalid (details.issues).
400 REASON_REQUIRED An erasure without a reason.
404 CUSTOMER_NOT_FOUND No such customer in the key's environment. Setting a Travel Rule identity also needs the customer to be active.
409 EXTERNAL_ID_IN_USE Another customer of the environment has this externalId. details.customerId names it, and details.deactivated says whether it is deactivated.
409 CUSTOMER_ERASED An erased customer cannot be reactivated.
409 LEGAL_HOLD The customer's records are under a legal hold or a retention obligation, and cannot be erased.
409 IN_FLIGHT The customer has transfers in flight. details.activeTransferIds lists them.
409 METADATA_NOT_OBJECT The customer's metadata is not a JSON object, so an identity cannot be stored in it.
409 CONFLICT The customer's metadata changed while the identity was being stored. Retry.
Status Code When
400 MISSING_FIELDS A registration without address, network or customerId; a verification without address.
400 INVALID_FIELDS customerId is not a string; label is not a string or null; a verification's address or network is not a string.
400 INVALID_ADDRESS The address is not in the network's format.
400 UNSUPPORTED_NETWORK The network is not supported. The message lists those that are.
400 CUSTOMER_DEACTIVATED The customer is deactivated.
400 VALIDATION_ERROR A label change whose body is not a JSON object.
404 CUSTOMER_NOT_FOUND No such customer in the key's environment.
404 WALLET_NOT_FOUND No such wallet in the key's environment.
409 WALLET_ADDRESS_TAKEN The address is registered to another customer of the environment.
Status Code When
400 VALIDATION_ERROR A create body that fails validation (details.validationErrors, details.schemaName: "create-transfer"), an asset disabled in the environment, an originator customer or address that does not match, an originator without a country, or no provider able to route the transfer. An accept with a txHash that is not a transaction hash. A reject body that fails validation (details.validationErrors).
400 MISSING_REQUIRED_FIELD A reject or retry without a reason. details.field is reason.
400 INVALID_REQUEST No action, or one the endpoint does not take: details.allowedActions lists accept, reject and retry. Also an action the transfer's workflow refuses; the message says why.
400 INVALID_TRANSFER_STATE A retry of a transfer that is not failed or held. details has currentState, action and allowedStates.
404 TRANSFER_NOT_FOUND No such transfer in the key's environment, whatever the action. details has resource and id.
409 CONFLICT Two creates collided, and the transfer could not be matched to an Idempotency-Key.
503 TIMEOUT The create's price or threshold lookup timed out. Retry-After: 5.
400 INVALID_INFORMATION_REQUEST An information request action that is not valid. details.issues names each problem.
Provider's Provider's code An information request the provider refused. Its 400, 404 and 409 keep their status; any other refusal is 503. The code is the provider's (HTTP_502, for one).
Status Code When
400 INVALID_QUERY A limit that is not a positive whole number, a query over 100 characters, or an asset filter or page it cannot read.
400 INVALID_CURSOR A VASP search cursor that is not one the search handed out.
429 RATE_LIMITED Too many VASP searches for the company and environment. Retry-After says when to search again.
Status Code When
404 CASE_NOT_FOUND No such case in the key's environment.
409 CASE_CLOSED The case is closed: it cannot be changed or resolved again. Notes can still be added.
422 VALIDATION_ERROR The body fails validation. details.issues names each problem.
422 TRANSFER_NOT_FOUND transferId names no transfer in the key's environment.
422 RULE_NOT_FOUND ruleId names no compliance rule in the key's environment.
422 INVALID_ASSIGNEE assigneeId is not an active member whose role can view cases.
Status Code When
403 INSUFFICIENT_PERMISSION The key lacks strs:read, or its owner's role lacks reports:view or strs:view. A download also needs transfers:read and transfers:view.
403 PII_ACCESS_REQUIRED A download by a key whose owner's role lacks pii:view: the file holds the report in full.
404 REPORT_NOT_FOUND No such report in the key's environment.
409 TRANSFER_NOT_FOUND The report's transfer is not in the key's environment.
422 REPORT_TOO_LONG_FOR_PDF The report's text is longer than its PDF draws. GET /api/v2/reports/:id has it in full.
503 PDF_RENDERER_BUSY Another report with Chinese, Japanese or Korean text is being drawn. Retry-After: 5.
Status Code When
404 WEBHOOK_NOT_FOUND No such subscription in the key's environment.
404 DELIVERY_NOT_FOUND No such delivery of this subscription.
409 DELIVERY_NOT_FAILED Only a failed delivery can be retried.
409 WEBHOOK_NOT_ACTIVE The subscription is not active.
422 VALIDATION_ERROR The body fails validation. details.issues names each problem.
422 INVALID_URL The URL is not a public http or https address.
Status Code When
404 PROVIDER_NOT_FOUND, INTEGRATION_NOT_FOUND No such provider or integration.
422 VALIDATION_ERROR The body fails validation. details.issues names each problem.
422 UNKNOWN_FIELDS Credential fields the provider or integration does not take. details.fields lists them.
422 MISSING_FIELDS Required credential fields with no value, neither sent nor saved before. details.fields lists them.
422 INVALID_FIELDS Sygna settings that are not valid. details.fields lists them.
409 NOT_CONFIGURED Enabling or testing before credentials are saved for the key's environment.
403 LIVE_KEY_REQUIRED Enabling or disabling needs a live key: the switch routes both environments.
Status Code When
404 RULE_NOT_FOUND No such rule in the key's environment.
422 VALIDATION_ERROR The body fails validation. For a rule, details.issues is a list of { "path", "message" }; for a threshold, a list of strings.
404 THRESHOLD_NOT_FOUND No such threshold.
409 THRESHOLD_EXISTS The company already has a threshold of this type for the jurisdiction.
422 IMMUTABLE_FIELD A change to a threshold's jurisdiction or type. Create a new threshold instead.
403 LIVE_KEY_REQUIRED A threshold change by a test key: thresholds apply to both environments.
Limit Applies to Answer
Address Requests from one network address, per minute, before their key is checked 429 RATE_LIMITED with Retry-After, X-RateLimit-Limit and X-RateLimit-Remaining: 0
Key Each API key, per minute, at the rate set for the key 429 RATE_LIMITED, details.rateLimit (remaining, resetTime), Retry-After, x-ratelimit-remaining and x-ratelimit-reset (an ISO 8601 time)
Company All of the company's authenticated API requests and provider callbacks together, per minute 429 RATE_LIMITED with Retry-After, x-ratelimit-limit and x-ratelimit-remaining: 0
VASP search All of the company's keys, per environment 429 RATE_LIMITED with Retry-After
Usage The company's plan 429 TENANT_LIMIT_EXCEEDED with Retry-After when the reset time is known

A per-key refusal:

{
"error": "API key rate limit exceeded",
"code": "RATE_LIMITED",
"details": {
"rateLimit": {
"remaining": 0,
"resetTime": "2026-10-09T12:00:42.000Z"
}
},
"meta": {
"apiVersion": 2,
"timestamp": "2026-10-09T12:00:00.000Z"
}
}
  • Wait for Retry-After before retrying a 429 or 503.
  • Retry a 409 CONFLICT as it is: another change won the race.
  • Send POST /api/v2/transfers with an Idempotency-Key: a retry with the same key answers 200 with the transfer the first request created, and never creates a second one.
  • Do not retry other 4xx answers unchanged: fix the request first.