Skip to main content

Digital-asset errors

Every error uses the one envelope: {"success": false, "error": "<code>", "message": "…", "details": {…}}. Branch on error and details; show message to a person. Codes that any route can return — authentication, scopes, rate limits, lockdown — are in the error reference.


Was anything recorded?​

On POST /v1/banking/payouts from a digital-asset account:

  • Without details.idempotency_key_spent: true, nothing was recorded or sent, the step-up was not spent and the Idempotency-Key is unused. Correct the request and send it again under the same key.
  • With details.idempotency_key_spent: true — every error after the send was recorded carries it, a 5xx included — the key is spent. Its payout, details.payout_id, is failed — nothing reached the provider, or the provider refused its transfer outright (422 destination_not_payable, provider_refused) — or, for 503 payout_outcome_unknown, being confirmed. Read it with GET /v1/banking/payouts/{payout_id}, and use a new key for a new send.

On earlier_payout_unconfirmed, details.payout_id is the earlier payout; a send recorded and then refused so names its own in details.recorded_payout_id.


Onboarding and accounts​

StatuserrorWhen
503digital_assets_unavailableNo digital-asset rail on this deployment (production today), or its provider offers no sandbox approval or deposits
409digital_assets_onboarding_requiredOpening an account, a wallet or sending before your verification with the provider is active — details: {state, next_steps}
409digital_assets_onboarding_incompleteThe provider holds too little about you to open the account or wallet (no address, terms not accepted). Complete its verification and try again
409conflictOpening an account: "you already hold a USDC account". Sandbox approval: the provider already holds a wallet for a customer from an unfinished hosted verification — finish that verification
422currency_unavailableOpening an account in an asset not offered here
403account_not_verifiedYour business is not verified (KYB). The sandbox lets a pending account through
403currency_limit_reachedYour plan's currency limit is used up. All digital assets together count as one
422account_not_closableClosing the USDC account
429rate_limitedSandbox approval: more than 30 calls an hour for your account
400bad_requestSandbox approval repeated more than 24 hours after an approval that has not completed
503service_unavailableThe provider cannot be reached. Retry with backoff

Wallets​

StatuserrorWhen
400bad_requestNo Idempotency-Key
422network_unsupportedNo asset is offered on that chain here
409digital_assets_onboarding_required, digital_assets_onboarding_incompleteAs for opening an account
403account_not_verifiedAs above
503digital_assets_unavailableNo digital-asset rail

Test funds and other sandbox tools​

RouteStatuserrorWhen
simulate-deposit400bad_requestNo Idempotency-Key; an amount not positive, over 100,000 or past six decimal places
simulate-deposit404not_foundNot one of your accounts
simulate-deposit409conflictThe account is not open
simulate-deposit409wallet_not_openNo wallet of yours on the network named, or on any chain carrying the asset
simulate-deposit422account_not_digitalA bank account — use the faucet
simulate-deposit422asset_not_on_networkThe asset is not offered on that chain
simulate-arrival404not_foundNot one of your payouts
simulate-arrival422not_eligibledetails.reason: not_a_send_back, not_accepted, returning, too_old, not_to_a_sandbox_account, no_mock_rail, no_digital_rail
simulate-arrival503service_unavailableThe arrival is being booked by another request at that moment; ask again shortly
simulate-completion404not_foundNot one of your payouts
simulate-completion409not_simulatabledetails.reason: debit_not_seen (ask again in a few seconds), not_accepted, needs_reconciliation, provider_state (details.partner_status), wallet_not_open, asset_not_on_network, arrival_not_seen — see Settling a send now
simulate-completion422not_eligibledetails.reason: not_a_digital_asset_send, completes_at_provider (on chain, across chains, by @handle), no_casp_layer, no_digital_rail, provider_not_sandbox
simulate-completion503service_unavailableBeing completed by another request at that moment, the provider could not be read, or its sandbox did not take a swap's bought asset; ask again shortly
faucet422asset_unsupportedA digital asset (USDC, EURC, …): the faucet credits bank accounts only — use simulate-deposit
any429rate_limitedMore than 30 requests an hour from your account to that route; the message says how many minutes are left
any503digital_assets_unavailableNo digital-asset rail, or no sandbox deposits at its provider

Sends​

POST /v1/banking/payouts and its quote, from a digital-asset account. "Recorded" means the answer carries details.idempotency_key_spent: true.

StatuserrorWhen
400bad_requestMore than one destination; currency not the account's asset; more than two decimal places; no source_network; a chain no send leaves from; a top-level destination_network other than destination.network, or any on a send to an IBAN, a bank account or by handle; a destination.network on a send by handle; a memo on a chain other than Stellar; an address not on the chain; a malformed IBAN, BIC, business identifier or country; a reference the rail does not take, or any reference on chain, by handle or for a swap; a holder's name outside 3–35 characters; a swap into the asset it sells; rail, fx_quote_id or beneficiary_id beside a send; your own handle. Recorded: the rail's own checks refused it, nothing sent
400bad_request (bank accounts)A routing number, account number, sort code, CLABE or Pix key that fails its rule; a rail the account is not paid over; a US holder without a whole address and state; a us_bank without bank_name (or blank, over 256 characters, a control character), named as destination.bank_name; a trusted us_bank entry approved without one (details.fields, details.trusted_beneficiary_id)
400insufficient_balanceRecorded. The wallet on that chain, less what your other payouts from it hold, does not cover the send and its headroom (1 %; 5 % on Ethereum). Each holds its amount and headroom until its debit is read, from a minute after that only the headroom, and what is left of it for about a minute after it finishes — see Holds. The message names what is free and what the send needs, the amount and the headroom apart: available 9.10 USDC, needed 10.10 USDC: 10.00 USDC for the payout plus 0.10 USDC headroom, held while it is in flight. Nothing sent
400trusted_beneficiary_requiredAn API key sent destination details, or no trusted_beneficiary_id — see Sending with an API key
401two_factor_requiredA session without X-Step-Up-Token
403step_up_binding_mismatch, step_up_not_linked, step_up_invalid, step_up_expired, step_up_already_usedThe step-up
403session_requiredA session or key acting for another account (Cxc-Account)
403permission_deniedA seat without payouts.create
403insufficient_scopeA restricted key without payments:write
404not_foundAn account, trusted beneficiary or handle that is not yours or does not exist
409account_not_activeThe account is not open
409wallet_not_openNo wallet of yours on source_network (details.network): open one with POST /v1/banking/digital-assets/wallets
409digital_assets_onboarding_requiredYour verification with the provider is not active; or (details.rail) the send is paid over a rail the provider has not enabled for you — a bank account outside SEPA over USD (ACH, wire, FedNow), GBP (Faster Payments), MXN (SPEI) or BRL (Pix), or an IBAN while your EUR (SEPA) rail is not enabled. Nothing recorded, the step-up not spent
409earlier_payout_unconfirmedAn earlier payout of yours on the digital-asset rail — any send, or a send-back — is still being confirmed (details.payout_id), or parked for support (details.resolve_by). Nothing recorded: send this one again, under the same key, once that payout reads submitted or failed, usually within minutes
409idempotency_key_reuseThe key was used for another body
409conflictThe provider already holds a registration of this IBAN or bank account that we have not recorded. Nothing sent; support resolves it
422corridor_unsupporteddetails.corridor: sends are off here, it is production, or not a route the provider offers — or a bank kind closed to your business's region (type bank)
422asset_not_on_networkThe chain does not carry the asset here (a swap: either asset); details.asset, details.network
422amount_below_minimumUnder the provider's minimum (details.minimum, details.currency) — see Minimums
422travel_rule_incompleteThe beneficiary or holder lacks what the travel rule needs; details.fields lists every field
422wallet_attestation_requiredPast 1,000 of the asset to your own self-custodied wallets in 30 days; details.asset, threshold, window_days, sent, remaining
422destination_is_own_walletThe address is one of your own wallets
422recipient_cannot_receiveBy handle: they hold no open account in the asset, are not verified, or the asset may not reach their region; details.asset
422digital_send_limit_exceededOver a per-asset cap; details.asset, window, cap, used, remaining
422beneficiary_not_trustedThe trusted beneficiary is revoked, cooling_down (an API key), or a handle entry whose handle names someone else (recipient_changed); details.reason
422destination_not_payable (details.reason provider_refused)Recorded. The provider refused the transfer when it was created, for good, in answer to the only request sent — a Stellar account with no trust line for the asset, a field it will not take, a rail your provider customer is not endorsed for. Only a refusal of what you sent is in the provider's words: the message carries its sentence, and details.provider_field names the field when it named one. Any other refusal is in our words and says to contact support; it carries details.provider_field only for a rail (destination.payment_rail), and you still contact support rather than change that field. Nothing was created and nothing is held: the payout is failed, and the next send is not held behind it. Change the field and send again under a new key — or, for a refusal in our words, contact support first. See A refusal when the transfer is created
422destination_not_payableNothing sent; details.reason: not_trusted — the entry was revoked before the send's hold was written (recorded failed); rail_not_supported — the provider reports the bank account cannot be paid over the rail asked; provider_record_mismatch — to an IBAN or bank account: the provider's record of the payee no longer matches it, contact support; not_prepared — to an IBAN or bank account: its registration with the provider was not found when the transfer was about to be made, send it again; own_wallet — the address is one of your own wallets, as the rail found when it sent (otherwise refused earlier as destination_is_own_wallet); recipient_cannot_receive — by handle: the recipient's wallet could not be reached when the rail sent
500internal_error, database_errorOurs. Nothing recorded — or, recorded: nothing sent, closed failed within minutes
503service_unavailableThe provider is down. Nothing recorded: retry with backoff under the same key. Or recorded failed, nothing sent (details.idempotency_key_spent: true) — among them the provider refusing our own credentials when the transfer was created: ours to fix, and the next send is not held behind it. Then retry later under a new key: the same key answers with the failed payout
503payout_outcome_unknownRecorded. The provider did not confirm the send: no answer, an outage, a rate limit, a conflict, or a refusal that came after a retried attempt (the attempt before it may have created the transfer). Only a refusal of the single request sent is 422 destination_not_payable (provider_refused) above. Send it again only under the same Idempotency-Key, which answers with the payout once it is known: submitted, or failed once the provider has twice found nothing under it (seven minutes or more). Until then your other sends on the digital-asset rail are refused 409 earlier_payout_unconfirmed

Send-back to your EUR account​

StatuserrorWhen
400bad_requestbeneficiary_id as well, an fx_quote_id, a rail other than sepa, more than two decimal places, or a destination account that does not hold currency
400bad_request (recorded)"The payout was not sent: …" — the provider could not be read before the transfer was created. Nothing sent; use a new key
400insufficient_balanceRecorded. The USDC account's balance, less what your other USDC payouts from the same wallet hold — send-backs, sends and swaps — does not cover this one's max_source_amount. A send-back holds its whole max_source_amount until its debit is read, from a minute after that only the part above the debit, and what is left of it for about a minute after it finishes. The message names what is free, what this send-back needs, and that need's two parts: its estimate and the headroom held on top
401 / 403two_factor_required, step_up_*A session's step-up
403session_requiredA session or key acting for another account
403insufficient_scopeA restricted key without payments:write
404not_founddestination_account_id or source_account_id is not one of your accounts
409conflictThe provider already holds a registration of the destination that we have not recorded; support resolves it
409earlier_payout_unconfirmedAnother send-back from the account is still being confirmed (details.payout_id)
422corridor_unsupportedNot offered here: details.corridor {"type": "own_account", "currency", "source_currency"}
422destination_not_payableNothing sent; details.reason: same_provider, not_active, no_iban, currency (the account does not hold EUR), holder_not_customer (not held in your company's legal name), sandbox_only; holder_name_length — the account's legal name is outside the provider's 3 to 35 characters, so it cannot be registered: contact support; holder_name_unsplittable — an individual's account whose name has no first and last name: contact support; account_changed — the account's IBAN changed since it was registered: contact support; provider_record_mismatch — the provider's record of the account no longer matches it: contact support; not_prepared — its registration was not found when the transfer was about to be made: send it again
422destination_not_payable (details.reason provider_refused)Recorded (details.payout_id). The provider refused the transfer when it was created, for good, in answer to the only request sent. Only a refusal of what you sent is in the provider's words: the message carries its sentence, and details.provider_field names the field when it named one. Any other refusal is in our words and says to contact support; it carries details.provider_field only for a rail (destination.payment_rail), and you still contact support rather than change that field. Nothing was created and nothing is held: the payout is failed, and the next send-back is not held behind it
422payee_name_mismatchThe provider's name check says the account is not held in your name; details.resolve_by is support
422plan_limit_exceededOver the plan's limit, measured on the EUR
503service_unavailableUnavailable right now; nothing recorded. Retry with backoff. Recorded (details.idempotency_key_spent, details.payout_id): the provider refused our own credentials, at the transfer's create or before it — the payout is failed, the next send-back is not held behind it; a new key, later
503payout_outcome_unknownRecorded; the provider did not confirm it. Only the same key

Convert EUR into USDC​

StatuserrorWhen
400bad_requestbeneficiary_id, fx_quote_id, a reference, a rail other than sepa; under 1.00 EUR or more than two decimal places
404not_foundNot one of your accounts
409destination_not_readydetails.reason payee_settling or registration_pending; send the same request (same key) again from details.ready_at
409earlier_payout_unconfirmedAn earlier convert from the account is still being confirmed (details.payout_id)
422corridor_unsupportedNot offered: details.corridor {"type": "own_account", …}
422destination_not_payabledetails.reason: not_active, no_iban, account_changed, payee_refused, payee_address_unknown (no complete registered address for your company: complete it, or contact support)
422payee_name_mismatchThe bank's name check does not confirm the USDC account under its provider's name; details.resolve_by is support
422plan_limit_exceededOver the plan's limit, measured on the EUR
401 / 403two_factor_required, step_up_*A session's step-up
503service_unavailableYour bank or the provider is unavailable. Retry with backoff
504gateway_timeoutThe provider did not answer in time. Retry
503payout_outcome_unknownRecorded; your bank did not confirm the payment. Only the same key
500database_errorRecorded, nothing sent; closed failed within minutes

Trusted beneficiaries​

StatuserrorWhen
400bad_requestA malformed field, a field of another kind, a missing network, address or iban, a us_bank without bank_name, a cxc_handle entry for your own handle; no Idempotency-Key
401two_factor_requiredNo step-up
403session_requiredAny API key, master keys included
403delegation_not_supportedA session acting for another account
403permission_denied, step_up_*A seat without payouts.create; the step-up
403account_not_verifiedYour business is not verified
404not_foundApproving a cxc_handle entry for a handle no CashXChain account has; revoking an id that is not yours
409trusted_beneficiary_existsThe destination already has an active entry (details.trusted_beneficiary_id)
409idempotency_key_reuseThe key was used for another body
422travel_rule_incomplete, destination_is_own_wallet, network_unsupportedAs for a send
422corridor_unsupportedGBP, MXN or BRL for a business in the EEA — nothing approved
503digital_assets_unavailableNo digital-asset rail

The route lock​

StatuserrorWhen
400bad_requestquote_id is empty
404not_foundNo quote of yours has this id
422route_quote_expiredAfter expires_at (details.quote_id, details.expired_at)
409route_quote_usedThe quote was spent on another payout
422route_quote_mismatchThe body is not the one quoted (details.fields)
409route_changedThe route would be another now (details.quoted_route, details.current_route); nothing sent

Quotes​

A quote runs the send's checks short of the travel rule's completeness, the caps and who is asking, and answers the same codes for them. On a convert's quote the provider may also refuse: 404 not_found (the account is not open at the provider), 409 conflict (your verification there is not active), 400 bad_request (below its minimum), 504 gateway_timeout, and 503 service_unavailable when it gives no estimate.