request_id on a retry and the gateway returns that payment or quote-request with its current status. Using the same request_id prevents making a second payment or opening a second quote-request batch.
This page is the API-reference summary. For the concepts behind it — the two guarantees, per-integration usage (SDK, CLI, x402, MPP), and deliver-once guidance on the acceptance side — see the Idempotency guide.
Unlike header-based schemes, the key is a field in the request body, not an HTTP header, and it is not required to be a UUID. See
request_id below.The key: request_id
You choose the value. A stable, unique-per-operation string works best (an order id, or a UUID if you already mint them).
Store it before you send the request — it’s the only thing that links a retry to its original.
Supported endpoints
Idempotency applies to state-changing (POST) endpoints. Each has its own key: reusing one across the two does not carry over.
GET reads (/status, /resolve, /timeline) have no side effects, so there is nothing to deduplicate.
Detecting a replay
Every write response carriesidempotent_replay (boolean, always present):
true— you were handed a resource that already existed; nothing new was created or charged.false— this request created it.
Reusing a key with different terms
Arequest_id locks in one set of economics — who pays, who receives, in which assets, and how much (source, destination, fulfillment_amount, max_source_amount). Reuse it with any of those changed and the gateway rejects the request rather than merging the change or silently returning the original.
Exempt (you may change these freely on a retry):
- Deadlines —
quote_deadlineandfulfillment_deadline. An expired deadline on a retry is not an error; the request resolves onto what already exists. - The signature — re-sign, or resend the original bytes. Only
request_idmust stay fixed.
Errors
Retrying by status
A safe retry depends on the payment’sstatus:
Note that
pending and failed call for opposite actions, so make sure to preserve the mental model:
pending— still settling, so reuse the samerequest_id(or just poll). Minting a new key here starts a second payment: a double charge.failed— terminal. Reusing itsrequest_idonly hands you back the same failed payment, so a genuine re-attempt needs a newrequest_id.
Example
sender_auth signature — there is no API key. Re-send the exact same request, with the same request_id, to recover the original result after a timeout or crash; the response’s idempotent_replay tells you whether it was created now or already existed.