Skip to main content

Prerequisites

You have attempted a payment via Quickstart (using CLI) or SDK quickstart.

Quick diagnosis

NO_SETTLER_FOR_CORRIDOR

No settlement operator currently covers the source and destination pair you asked for, so the payment was never offered to anyone.
Retrying the same pair will not help. That is what NOT_RETRYABLE_FIX_REQUEST means: the request has to change, not be repeated. Either pick a different corridor, or check the pair against Supported networks in case an asset ID is pointing at a chain you did not intend. This describes right now. Providers connect and disconnect, so a pair with no provider today may have one later. It is not a statement that the corridor will never be supported. Told apart from NO_QUOTES_RECEIVED by whether anyone was asked. Here nobody was: no settlement operator serves the route. There, settlement operators were offered the payment and none quoted — read decline_summary before you change a clock.

NO_QUOTES_RECEIVED

Submit succeeded — your integration worked — but no settlement operator quoted during the quote window. Delivery never started.
Delivery never started. Nobody was selected, so this is about the quote window or the corridor, and rarely about your delivery deadline. A retry needs a new request_id. The failed payment’s request_id is used up; sending it again returns the same failure. Read decline_summary to see why. GET /v1/payments/{payment_id}/status carries requested_count (how many settlement operators were asked) and decline_summary (how many declined, and why). A failed POST /v1/payments response carries them too. What each reason means, and what to change on the next payment: Why nobody quoted. This is not a spending approval or signing error.

QUOTES_EXPIRED

Quotes arrived, but none could be selected when the quote window closed, usually because they had already expired. Each settlement operator chooses how long its quote stays valid. Use a shorter quote window and a new request_id. See Deadlines.

QUOTE_WINDOW_TOO_LONG

A reason in decline_summary, not an error.code: the payment fails with NO_QUOTES_RECEIVED. The settlement operators declined because your quote window ends after their quotes would expire. Send a new payment with a new request_id and a shorter quote window. See Decline reasons.

MAX_SOURCE_AMOUNT_TOO_LOW

A reason in decline_summary, not an error.code: the payment fails with NO_QUOTES_RECEIVED. The settlement operator’s price is above your max_source_amount. Do not resend the same payment. Send a new payment with a new request_id and a max_source_amount of at least the recipient amount plus the operator’s charge; Get a price quote shows the charge. See Decline reasons.

INTERNAL

A reason in decline_summary, not an error.code: the payment fails with NO_QUOTES_RECEIVED. The settlement operator hit an unexpected error while pricing your payment. Some operators also send it when your max_source_amount is below their price, so check that it covers the recipient amount plus the operator’s charge. Then send a new payment with a new request_id. See Decline reasons.

Stuck in processing

Poll every 2–5 seconds:
Optional timeline for debugging:
How long pending lasts depends on the corridor: seconds on most chains, up to a few minutes on Ethereum, and longer for a large payment while the settlement operator waits for the source chain to finalize your deposit (see Finality). Before escalating, check /timeline to see which step is slow. Do not resubmit the same payment with a new request_id unless you intend a new payment.

Settlement slower than the gateway wait

A payment that takes longer than the gateway waits is reported as still settling. That is pending, not a failure. Do not open a second payment with a new identifier while the first is still settling. What to do next, for the API and for x402 and MPP: When a payment is still settling. For out-of-band reconciliation, /status and /timeline by payment_id are the authoritative record.

Payment authorization and balance errors

Settlement fails if:
  • Payment authorization was never set for the source USDC/token
  • The source account has an insufficient token balance
The payment can then fail with MISSING_TOKEN_APPROVAL or INSUFFICIENT_FUNDS (HTTP 422). No funds were moved. Fix:
  1. Approve USDC spend on the source rail
  2. Confirm balances on that chain in your wallet explorer
  3. Resubmit with a new request_id if the previous payment failed
For token approval details, see Token approvals.

Wrong asset ID or chain

The gateway validates that source and destination rails are chains it serves (the ones /v1/defaults lists). It does not validate that a corridor has settlement coverage.

Wrong token variant

Similarly named tokens are not interchangeable. “USDC” on one chain, a bridged “USDC.e,” and a chain-specific tokenized currency like Tempo’s pathUSD are different contracts with different addresses — and often that’s the difference between a payment that settles and one that silently doesn’t. Common mistakes:
  • Using native USDC where the corridor expects a bridged variant (USDC.e), or vice versa.
  • Assuming a chain has native USDC when it doesn’t — Tempo, for example, carries a bridged USDC.e but no native USDC, and pathUSD is its canonical 6-decimal tokenized currency.
  • Copying a token address from the wrong chain (the same symbol, different network).
Fix:
  1. Identify the exact asset for your corridor by chain and contract address — not by symbol alone. Copy from Supported assets, keyed by network.
  2. Confirm you’re watching that same contract in your wallet/explorer on the destination chain — a balance that “didn’t change” is often the right funds landing on a token you weren’t looking at.
  3. If your integration hardcodes addresses, prefer resolving them from the gateway (the examples read corridor addresses from /v1/defaults) so they can’t drift.

Recipient received nothing

If a payment reports success but the receiving wallet shows no change:
  1. Confirm DEST_ADDRESS (or your destination address) is exactly the address you’re checking, on the destination chain.
  2. Confirm you’re watching the correct destination token — see Wrong token variant.
  3. Confirm via the gateway first: poll /status and /timeline by payment_id to get the settlement transaction hash, then verify that hash on the destination-chain explorer. A fresh retry with a new request_id is a second payment — retry only with the same request_id.

Gateway unreachable

A 200 means the gateway is reachable. Any other HTTP answer means the gateway is up but can’t serve defaults right now (what each one means): retry, then contact Atum support rather than changing your code. Only a connection error or a timeout points at your network or VPN.

Still stuck?

Ask in the Atum Discord — support is community-based, not on-demand. Include:
  • payment_id
  • request_id (if set)
  • Output of /status and /timeline
  • Source and destination CAIP-19 strings
  • Whether you are on testnet or mainnet

Next steps

  • Refunds: what the refund statuses mean and how to get your funds back yourself
  • Deadlines — which clock each “expired” error refers to, and how to choose values that avoid them
  • After submission — how to read status and decline_summary on a live payment
  • Reconciliation — the fields to record for every payment, and how to separate Atum fees from gas and swap costs
  • Supported networks
  • Ask in Discord