2xx HTTP status and an error
field. The HTTP status tells you the category of failure; the body tells you
the specific reason.
Error envelope
Theerror field is either a plain string (most endpoints) or a structured
{ code, message, details? } object (webhooks, partner onboarding URLs, newer
endpoints). Validation failures use a third hybrid: a string error with a
sibling top-level details array.
See Response format → Error responses
for the full shape contract and a Node normalizer you can drop into your
client.
String for most endpoints;
{ code, message, details? } for newer endpoints.
Always present on a non-2xx response.Structured form only. Stable, machine-readable identifier (e.g.
VALIDATION_ERROR, NOT_FOUND). Branch on this, not on the message text.Structured form only. Human-readable description. Safe to log; do not parse.
Structured form only. Optional context (e.g. Zod-flattened field errors).
May be absent.
Validation form only. Sibling of
error (not nested). Items are
{ field, message } describing one validation failure.HTTP status codes
| Status | Meaning |
|---|---|
400 | Bad request / validation error |
401 | Missing or invalid API key |
403 | Forbidden — insufficient scope, CSRF, or IP not allowed |
404 | Resource not found |
429 | Rate limit exceeded |
500 | Internal server error |
400 — Bad request / validation error
400 — Bad request / validation error
The request body or query failed validation (missing field, wrong type, out
of range). Inspect the
details array (string-form validation) or
error.details (structured form) for the offending fields, fix the
request, and resubmit. Retrying an unchanged request will fail again.401 — Missing or invalid API key
401 — Missing or invalid API key
No API key was sent, or the key is malformed, unknown, inactive, or expired.
Check the
x-api-key header. See Authentication.403 — Forbidden
403 — Forbidden
The key is valid but the request is not permitted: the key lacks the required
scope, the write request is missing or has an invalid
X-CSRF-Token, or the
source IP is not on the key’s whitelist.404 — Resource not found
404 — Resource not found
The referenced resource does not exist, or it exists but does not belong to
your customer. Verify the ID.
429 — Rate limit exceeded
429 — Rate limit exceeded
You have exceeded the request limit. Back off and retry after the delay in
the
Retry-After header. See Rate limiting.500 — Internal server error
500 — Internal server error
An unexpected error on our side. These are usually transient — retry with
exponential backoff. If it persists, contact support with the timestamp.
Handling errors gracefully
Normalize, then read code / message
Coerce the string and structured forms into one shape (see the Node sample
below). Branch on HTTP status for the broad category, then on the
normalized
code (when present) for the specific reason. Never depend on
the wording of the message text.Fix-and-retry vs. back-off-and-retry
400/403/404 are client errors — retrying an unchanged request will not
help. Only retry 429 (after Retry-After) and 500 (with exponential
backoff).Node
Verifying external actions: reject-list over allow-list
Some responses reflect the state of an action handed off to the underlying banking infrastructure (for example a payment or transactionstatus). When you
verify whether such an action succeeded, prefer a reject-list of known
failure states over an allow-list of known success states.
External systems may omit a status field, return a new value, or rename a field
without notice. An allow-list treats every unrecognized value as a failure — so
a benign new status silently breaks your integration. A reject-list treats only
known-bad values as failures, so missing or unknown values are assumed
successful.
Response format
The full success and error envelope contract.

