/settle request will wait for an on-chain outcome before answering. This page documents both behaviors so you can build clients that handle them correctly.
Per-IP rate limits
The facilitator’s edge (nginx ingress) enforces limits per client IP address, with a separate budget for each endpoint group so that cheap read-only calls never compete with settlement for the same allowance:
Each rate has a burst allowance of 5× (short spikes above the sustained rate are absorbed; the edge rejects with HTTP 429 only once the burst allowance is exhausted). Limits may be tuned over time as capacity grows; any reduction will be announced in advance.
Because verify and settle draw from separate buckets, the common verify-then-settle pattern costs one request from each — a merchant settling 40 payments per second from a single IP stays inside both budgets. These are per-source-IP limits, not account-wide: if your infrastructure sends from multiple IPs, each IP gets its own set of buckets.
If you expect sustained single-IP volume near the
/settle budget, get in touch — the settlement lanes behind the edge have significantly more capacity than a single IP’s allowance, and we can set up a dedicated allowance for your address range.Telling responses apart: 402 vs 429 vs 5xx
The status code alone tells you how to react:
Retrying is safe in both non-402 cases even for
/settle: verification is read-only, and settlement is idempotent — re-submitting an identical payload returns the recorded outcome of the original attempt and can never cause a second on-chain payment.
Unsuccessful settlements that the facilitator did process return HTTP 200 with success: false and a machine-readable errorReason (for example transaction_failed, duplicate_settlement, or settlement_pending) — a JSON x402 body always means the facilitator handled the request.
The settlement_pending response
POST /settle waits for the on-chain outcome, but only up to a bounded response budget (currently 100 seconds). If the settlement is still in flight when the budget expires — for example during network congestion — the facilitator answers instead of letting the connection time out.
This applies to every supported network — Solana and all EVM chains alike. The response shape and the reconciliation procedure are identical everywhere; the only per-chain difference is whether the transaction field can be populated, covered below.
- It arrives with HTTP 200, like every other unsuccessful settlement, so standard x402 clients surface it in the normal
!successpath rather than as a thrown transport error. - It is not a verdict. The settlement job keeps running after the response is sent — the payment may still land on-chain. Do not treat
settlement_pendingas a failure, and do not treat it as a success.
How to reconcile: re-submit the identical payload
To learn the real outcome, re-POST the exact same payload (the same payment payload and payment requirements) to/settle:
- While the original attempt is still in flight, you receive
409 duplicate_settlement— keep polling with backoff. - Once the attempt resolves, the facilitator serves the recorded outcome: the cached success response (including the transaction hash) if the payment landed, or the recorded failure if it did not.
Solana vs EVM: whether transaction is populated
The transaction field of a settlement_pending response differs by chain family:
- Solana —
transactionis always empty. Send and confirmation happen inside a single settlement job, so no signature is available to the API before the outcome is known. Re-submitting the payload is the only reconciliation path on Solana — there is no hash to look up on-chain. - EVM (Base, Polygon, Arbitrum, Avalanche, Sei) — if the transaction was already broadcast when the budget expired,
transactioncarries the broadcast hash. You can watch that hash on-chain directly, in addition to (or instead of) polling/settle.
On EVM, a populated
transaction means the transaction was broadcast, not that it landed. Wait for confirmation on-chain, or poll /settle for the recorded outcome.Client-side timeouts
Some x402 client libraries default to shorter timeouts than the facilitator’s response budget (for example, 30 seconds in@x402/core’s HTTPFacilitatorClient). A client-side timeout behaves like an edge timeout: you get no response body, but the settlement is still in flight. The reconciliation procedure is the same — re-submit the identical payload to retrieve the recorded outcome.
Need help?
Join our Community
Have questions or want to connect with other developers? Join our Discord server.

