Error codes
On failure the envelope carries data: null and a code from the
list below. Branch on the code; the HTTP status is only a hint.
Every endpoint in the API Explorer lists the codes that endpoint can return, under its responses. This page lists them all in one place.
Errors every endpoint can return
| Code | HTTP | When |
|---|---|---|
INVALID_REQUEST_DATA | 400 | Request validation failed — a field is missing, malformed, or unknown. |
INTERNAL_SERVER_ERROR | 500 | Unexpected server error. An internal alert is raised; retry is safe for reads. |
ACCESS_TOKEN_INVALID (401) can be returned by every authenticated endpoint — the token is
missing, invalid, or expired. The open endpoints listed under
Authentication never return it.
Your account
These relate to your account setup rather than to the request. A retry returns the same result, so resolve the account setting first, or contact us.
| Code | HTTP | When |
|---|---|---|
INVALID_SIGNATURE | 401 | The client assertion's signature or claims are invalid, or the assertion is stale. |
PARTNER_NOT_FOUND | 404 | The partner for this token no longer exists. |
PARTNER_ACCOUNT_LOCKED | 403 | The partner account is locked. |
PARTNER_IP_NOT_ALLOWED | 403 | The caller IP is not in your allowlist. |
PARTNER_INSUFFICIENT_BALANCE | 402 | Your crypto fund cannot cover the order. Top the fund up. |
USER_EMAIL_INVALID | 400 | userEmail is missing or malformed. |
The user and their KYC
A user must be verified before they can transact. See KYC.
| Code | HTTP | When |
|---|---|---|
USER_REGISTRATION_REQUIRED | 400 | The user is not registered. |
USER_KYC_VERIFICATION_REQUIRED | 400 | The user does not exist, has no KYC profile, or KYC is not verified. |
USER_KYC_UNDER_PROCESSING | 400 | A KYC submission is already being processed. |
KYC_PROFILE_UNDER_REVIEW | 400 | The KYC profile is pending review — the user cannot transact yet. |
KYC_PROFILE_NOT_ELIGIBLE | 400 | The KYC profile was rejected. |
KYC_EXTRA_INFO_REQUIRED_FOR_LATAM_LOCAL_USER | 422 | The KYC profile lacks fields this payment requires. The message lists them after Missing:. See Markets that need extra profile fields. |
KYC_DOCUMENT_ALREADY_REGISTERED | 400 | KYC is already verified, or the national ID belongs to another profile. |
KYC_DOCUMENT_FORMAT_INVALID | 400 | One or more document images are not valid base64 data URLs. |
HIGHER_KYC_LEVEL_REQUIRED | 400 | The service needs a higher KYC level than the user holds. |
NATIONALITY_NOT_SUPPORTED | 400 | The user's nationality is missing, or not supported for this service. |
HIGH_RISK_USER | 400 | The user is flagged as high risk. |
REQUESTED_INFO_NOT_FOUND | 404 | No KYC profile exists for this user yet. |
The recipient and the payout
| Code | HTTP | When |
|---|---|---|
BANK_NOT_SUPPORTED | 400 | The bank code is not active. Fetch the current bank list. |
INVALID_BANK_ACCOUNT | 400 | The bank account could not be verified. |
HIGH_RISK_BANK_ACCOUNT | 400 | The recipient account or name is flagged as high risk. |
INVALID_TRANSFER_CONTENT | 400 | The transfer description is invalid. |
FIAT_CURRENCY_NOT_SUPPORTED | 400 | The fiat currency is not supported. |
PAYMENT_CHANNEL_NOT_SUPPORTED | 400 | No payment channel is available for this fiat currency. |
QR_CODE_NOT_SUPPORTED | 400 | No supported format could decode the QR code. |
INVALID_PAYMENT_INFO | 400 | A PHP QR payout is missing the additionalData from the QR decoding step. Pass it through verbatim. |
INVALID_WALLET_ADDRESS | 400 | The wallet address is invalid for the given network. |
TOKEN_NOT_SUPPORTED_ON_NETWORK | 400 | The crypto currency is not supported on the given network. |
Amounts and limits
| Code | HTTP | When |
|---|---|---|
BUY_AMOUNT_BELOW_MIN | 400 | The crypto amount is below the minimum. |
BUY_AMOUNT_ABOVE_MAX | 400 | The crypto amount is above the maximum. |
SELL_AMOUNT_BELOW_MIN | 400 | The fiat or crypto amount is below the minimum. |
SELL_AMOUNT_ABOVE_MAX | 400 | The fiat or crypto amount is above the maximum. |
AMOUNT_OUT_OF_RANGE | 400 | The fiat amount is below the minimum allowed for this payout. |
TRANSACTION_AMOUNT_LIMIT_EXCEEDED | 400 | The per-transaction amount limit was exceeded. |
DAILY_AMOUNT_LIMIT_EXCEEDED | 400 | The daily amount or transaction-count limit was exceeded. |
WEEKLY_AMOUNT_LIMIT_EXCEEDED | 400 | The weekly amount limit was exceeded. |
MONTHLY_AMOUNT_LIMIT_EXCEEDED | 400 | The monthly amount limit was exceeded. |
Scan-to-Pay and Cashout quotes return the bounds as minAmount and maxAmount; for on-ramp and
off-ramp, each crypto currency carries them. Checking against those before you create the order
keeps these errors rare.
Orders
| Code | HTTP | When |
|---|---|---|
DUPLICATE_TRANSACTION_ID | 409 | The orderId already exists for your partner account. |
TRANSACTION_NOT_FOUND | 404 | No order matches that orderId for your partner account. |
TRANSACTION_CREATE_FAILED | 500 | The payout could not be completed after the order was created. The order is already refunded. |
WEBHOOK_SECRET_NOT_FOUND | 400 | The webhookSecretKey matches no registered webhook endpoint. |
DUPLICATE_TRANSACTION_ID usually means your retry worked the first time. Fetch the order rather
than treating it as a failure — see Scan-to-Pay & Cashout.
Locked quotes
These come back when you review or create an order with a quoteId. For any of them, request a new
locked quote.
| Code | HTTP | When |
|---|---|---|
QUOTE_NOT_FOUND | 404 | No locked quote matches the quoteId. |
QUOTE_EXPIRED | 410 | The locked quote has expired. |
QUOTE_ALREADY_USED | 409 | The locked quote was already used for an order. |
QUOTE_MISMATCH | 422 | The order does not match the locked quote, for example in currency, network, or amount. |
Temporary
These are the only codes worth retrying with backoff.
| Code | HTTP | When |
|---|---|---|
SERVICE_NOT_AVAILABLE | 503 | The service is not available for your account or the requested currency. |
SERVICE_UNDER_MAINTENANCE | 503 | Pricing is temporarily unavailable for this currency. |
SERVICE_TEMPORARILY_UNAVAILABLE | 503 | QR decoding is temporarily unavailable. |