Skip to content

Three questions sit behind every failure on this page: did the request execute, is retrying safe, and what to do. Every error type below is marked with the first two:

Did my money move? What it means
No The request did not execute. Nothing was sent, debited, or changed
Maybe Execution is uncertain. Read the payout back before doing anything
Can I retry? What to do
As is Send it again unchanged, with the same idempotency key
After a fix Fix something first. The exact same request fails identically
Never Retrying cannot succeed

No error type on this page means “the payout was sent and then failed”. That is a payout whose status is failed, carrying a failureCode; see Payout status.

Every failure has the same shape. Branch on type, which is stable across versions; the HTTP status and the wording are not.

{
"type": "RATE_DRIFT_EXCEEDED",
"status": 400,
"detail": "Refusing to send: quoted 3384.65 but you expected ~9999 (6615 bps of drift, limit 200). Nothing was sent.",
"resolution": "Nothing was sent. Re-quote, show the payer the new amount, and send again.",
"requestId": "req-1c",
}

detail is always a string. resolution is optional, so fall back to detail. Validation failures add errors, the fields that failed. Every error body has requestId; on a success it is the x-request-id header, so log it. There is no retryable field; the Node client derives one from type.

A payout that was accepted and later failed is not an error response. It has status: failed and a failureCode (Track status & failures).

type Status Money moved? Retry? What to do
VALIDATION_ERROR 400 No After a fix Fix the fields named in errors
UNAUTHORIZED 401 No After a fix Key missing, malformed, unknown, revoked or copied incompletely
FORBIDDEN 403 No After a fix The key can’t access that organization or operation. Check AVVIO_ORG_ID
NOT_FOUND 404 No After a fix No such payout or recipient. Use ids we returned
ROUTE_NOT_FOUND 404 No Never No route matches. Payouts are sent to /payouts and read from /orders
RATE_LIMITED 429 No As is Wait for Retry-After, then resend
BAD_REQUEST 400 No After a fix A non-field 400 (expired quote, above the corridor maximum, non-positive amount). detail names it
PROVIDER_REJECTED 400 No After a fix The network refused before submission, usually below the corridor minimum
CONFLICT 409 Maybe After a fix Funding state changed under you (another transaction or request won). Re-read the payout
ACCOUNT_BLOCKED 403 No Never Your organization is suspended. Contact us
LIVE_KEY_ORG_NOT_APPROVED 403 No After a fix A live key wrote before business verification. GETs work; use a test key until approved
INSUFFICIENT_BALANCE 400 No After a fix Nothing was sent. Top up, then retry. A payroll run must branch on this
CRYPTO_PAYOUTS_DISABLED 400 No After a fix Use a key with scopes ["write", "crypto_payouts"]
WALLET_NOT_PROVISIONED 400 No After a fix No EVM wallet to pay a wallet recipient. Finish wallet setup in the dashboard
HISTORY_TOO_LARGE 413 No Never Your organization has more orders than GET /balance/history will replay. Page GET /balance_transactions instead
ORDERS_TEMPORARILY_UNAVAILABLE 503 No As is A payment-network read failed while building the page, and we won’t return a partial list as complete. Retry. (A cursor we didn’t issue is a 400 VALIDATION_ERROR, cursor: unrecognized)
INTERNAL 500 Maybe As is Nothing was recorded and the key was released. Retry with the same key; send the requestId if it persists
PAYOUT_LINKS_UNAVAILABLE 503 No As is Hosted payout links aren’t configured on this environment. Contact support
CORRIDOR_UNAVAILABLE 400 No After a fix Node client: the corridor isn’t on your routing. Pick one the corridors call lists
TIMEOUT 504 Maybe As is Node client. A send may exist. Retry with the same Idempotency-Key
NETWORK_ERROR 502 Maybe As is Node client (DNS, TLS, dropped connection). Retry with the same key, then read the payout back
type Status Money moved? Retry? What to do
KEY_EXPIRED 401 No After a fix Issue a new key; an expired key can’t be rotated
KEY_IP_NOT_ALLOWED 401 No After a fix The key is pinned and the request came from another address
type Status Money moved? Retry? What to do
IDEMPOTENCY_KEY_REQUIRED 400 No After a fix Add an Idempotency-Key, unique per operation
IDEMPOTENCY_KEY_INVALID 400 No After a fix Use 1–255 characters of A-Z a-z 0-9 _ . : -. A UUID works
IDEMPOTENCY_KEY_CONFLICT 409 No Never Same key, different body. Don’t retry; a different request needs a new key
IDEMPOTENCY_KEY_REQUEST_IN_PROGRESS 409 Maybe As is An identical request is still running. Back off and retry the same key
IDEMPOTENCY_UNAVAILABLE 503 No As is We couldn’t record the key and nothing executed. Retry the same key
PAYOUT_OUTCOME_UNKNOWN 500, 409 Maybe Never No proof a money operation didn’t execute; the payout may exist and the key is kept. Replays answer 409. Do not retry with a new key. Poll GET /orders?reference=, send support the requestId (Timeouts)
DUPLICATE_REQUEST_DETECTED 409 No After a fix An identical body under a different key within 15 minutes. Nothing executed. See below

Some HTTP clients mint a new key per attempt, so every retry would pay. DUPLICATE_REQUEST_DETECTED catches that for 15 minutes, and its body names originalIdempotencyKey, plus originalPayoutId when the first request finished with a payout.

  • If it was a retry, send it again with originalIdempotencyKey in the Idempotency-Key header (not the body, which rejects unknown properties). It replays and returns the original payout.
  • If you meant two payments, add X-Allow-Duplicate: true. This sends a second real payment.

Fifteen minutes covers a crashed job that requeues on a backoff. It is shorter than the seven-day key retention because content can’t tell a retry from a genuine repeat: two identical advances in a week are ordinary payroll. A unique reference per payment means the guard never fires falsely. Idempotency covers retention and exceptions.

type Status Money moved? Retry? What to do
DESTINATION_ACCOUNT_NOT_FOUND 404 No After a fix Refused before pricing, so a stale id can’t report completed with nobody paid. Pay only ids we returned
RATE_DRIFT_EXCEEDED 400 No After a fix The quote moved past expectDestination. Re-quote, show the new amount, send again
QUOTE_UNVERIFIABLE 400 No After a fix We couldn’t compare the quote to your expectation, so nothing was sent. detail says why
QUOTE_NOT_POSITIVE 400 No After a fix Nothing would arrive after fees. Increase the amount and re-quote
EXACT_OUTPUT_UNSUPPORTED 400 No After a fix The routing can’t lock the receiving amount. Check capabilities.exactOutput
INDICATIVE_PRICING_UNAVAILABLE 400 No Never The routing prices only against a recipient (capabilities.indicativePricing: false). Create the recipient, then price
PAYOUT_NOT_CANCELABLE 400 No Never Only a payout awaiting your own funds can be canceled
INSUFFICIENT_SCOPE 403 No After a fix Read-only key, or a missing consent (refunds). Use a write key; an owner or admin can add refunds
LIVE_MODE_UNSUPPORTED 400 No After a fix A live key on a sandbox-only route. Use an avvio_test_* key
PAYOUT_LIMIT_EXCEEDED 422 No After a fix Over a single, daily or per-end-user limit, named in the message. Split it, or ask us to raise it
PAYOUT_REFUSED 422 No Never Final refusal for this recipient. Contact us with the requestId
USE_POST_PAYOUTS 403 No After a fix An approval threshold or velocity cap applies, which only POST /payouts enforces. Send it there; it may answer 202
BENEFICIARY_EXTERNAL_ID_CONFLICT 409 No After a fix The externalId names a recipient with other account details. Use a new one, or read the existing recipient
BANK_ACCOUNT_ALREADY_LINKED 409 No After a fix The account is on another recipient. Pay existingRecipientId / existingMethodId
PAYOUT_ACCOUNT_PROVIDER_UNAVAILABLE 503 No As is The account couldn’t be registered and nothing was saved. Retry with the same Idempotency-Key
FUNDING_NOT_APPLICABLE 501 No Never The payout settles from your balance. Fund only when requiresFunding is true
FUNDING_TRANSACTION_INVALID 400 No After a fix The transaction doesn’t fund this payout (reverted, wrong token, address or wallet, short). Nothing recorded
FUNDING_NOT_YET_VERIFIABLE 409 No As is Not mined or readable yet. Nothing recorded. Confirm the same hash later
FUNDING_TRANSACTION_ALREADY_USED 409 No After a fix It funded another payout, named in detail. Send a separate transfer
PAYOUT_NOT_FUNDABLE 400 No Never The payout is canceled or finished. If you still owe the recipient, create a new payout
FUNDING_QUOTE_EXPIRED 409 No After a fix Dashboard wallet funding: the quote expired and the payout wasn’t sent. Funding already sent stays recorded. Refresh and review the new price
LINK_EXPIRED 400 No After a fix A checkout draft’s expiresAt has passed. PATCH a later one (or null) and publish. In a publish: true create it is publishError.type on a 201

Every refusal here left the money where it was. Only REFUND_OUTCOME_UNKNOWN may have moved it.

type Status Money moved? Retry? What to do
REFUND_NOT_ALLOWED 400 No Never Already refunded in full, charged back, failed or pending
REFUND_DISPUTED 400 No After a fix A dispute decides. Wait; a loss arrives as checkout_payment.reversed
REFUND_EXCEEDS_REMAINING 400 No After a fix More than amountBase - refundedBase. Lower it, or omit it to refund the rest
REFUND_IN_PROGRESS 409 No After a fix One refund at a time. Once refundedBase moves, send another if needed
REFUND_OUTCOME_UNKNOWN 502 Maybe Never It may have gone through. Don’t resend; the payment is re-read and the event follows if it did
type Status Money moved? Retry? What to do
BATCH_NOT_FOUND 404 No After a fix No batch with that id in your organization
PAYOUT_BATCH_NOT_CONFIRMABLE 409 No After a fix Not awaiting_confirmation. Read it back; it may still be validating
PAYOUT_BATCH_NOT_CANCELABLE 409 No Never Creation started, so the run is committed. Cancel single pending payouts with POST …/payouts/{payoutId}/cancel
PAYOUT_BATCH_AWAITING_APPROVAL 409 No After a fix The run needs approvers, or one rejected it. approvalId names the request
PAYOUT_BATCH_DUPLICATE_REFERENCE 409 No After a fix externalReferenceId already names run originalBatchId. Read it, or pick a new id
MASS_PAYOUTS_DISABLED 403 No Never Your organization opted out of batches. Contact support
PAYOUT_LINK_UNUSABLE 400 No After a fix Expired, spent, or failed at execution. Links are single-use; mint a new one

A failed line inside an accepted batch is an item with status invalid or create_failed and errors[], read with ?status=invalid. Submitting a spent payout link returns the original payout with status: "already_submitted". A 404 on a link route covers expired, spent, forged and unknown links alike, so probing learns nothing.

Was this page helpful?