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.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.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 newrequest_id. See Deadlines.
QUOTE_WINDOW_TOO_LONG
A reason indecline_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 indecline_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 indecline_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: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
MISSING_TOKEN_APPROVAL or INSUFFICIENT_FUNDS (HTTP 422). No funds were moved.
Fix:
- Approve USDC spend on the source rail
- Confirm balances on that chain in your wallet explorer
- Resubmit with a new
request_idif the previous payment failed
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.
- Copy asset IDs from Supported assets
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’spathUSD 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.ebut no native USDC, andpathUSDis its canonical 6-decimal tokenized currency. - Copying a token address from the wrong chain (the same symbol, different network).
- Identify the exact asset for your corridor by chain and contract address — not by symbol alone. Copy from Supported assets, keyed by network.
- 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.
- 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:- Confirm
DEST_ADDRESS(or your destination address) is exactly the address you’re checking, on the destination chain. - Confirm you’re watching the correct destination token — see Wrong token variant.
- Confirm via the gateway first: poll
/statusand/timelinebypayment_idto get the settlement transaction hash, then verify that hash on the destination-chain explorer. A fresh retry with a newrequest_idis a second payment — retry only with the samerequest_id.
Gateway unreachable
Still stuck?
Ask in the Atum Discord — support is community-based, not on-demand. Include:payment_idrequest_id(if set)- Output of
/statusand/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_summaryon 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