Research guide · x402 buyer safety · 12 September 2026
x402 retries without duplicate payment
Autonomous buyers fail in ordinary ways: a request times out, a process restarts, a load balancer drops the response, or settlement succeeds while the application result never reaches the agent. The dangerous response is to create a fresh payment and try again. x402's payment-identifier extension gives buyers and sellers an explicit idempotency key for one logical purchase.
Published 12 September 2026 · sources checked 12 September 2026
1 purchase
One logical purchase gets one persistent payment ID
same retry ID
Transport retries reuse the identifier instead of minting a new purchase
optional extension
If the seller does not advertise support, do not assume duplicate-safe retry semantics
Why this matters
A timeout is not evidence that payment failed
x402 separates payment evidence from application delivery. A buyer can lose the HTTP response after a payment has been committed, so “I did not receive the result” cannot safely become “pay again”. The correct first move is to reconcile the payment state and then decide whether the same logical purchase should be retried.
The official x402 extension documentation describes payment-identifier specifically for network failures, client crashes, load-balanced retries and development replay. A seller advertises support in the payment requirements; the buyer attaches a unique identifier; and the seller caches the result keyed by that identifier for a configured retention period.
This is complementary to scheme-level replay protection. Cryptographic replay controls stop an authorization from being replayed incorrectly; idempotency answers an application question: “is this retry the same purchase or a new purchase?”
Buyer runbook
Treat the identifier as the purchase identity, not the HTTP attempt
| State | Buyer action | Rule |
|---|---|---|
| Initial 402 | Read the live payment requirements and check whether payment-identifier is advertised. | Do not spend yet. |
| Create logical purchase | Generate one payment ID and persist it with the exact method, URL, body or parameters, quoted terms and local purchase intent. | This ID survives transport retries and process restarts. |
| Paid attempt | Send the payment payload carrying the advertised extension and retain the resulting settlement/application evidence. | Do not rotate the ID just because the HTTP attempt changes. |
| Timeout / lost response | Check settlement evidence first. If a retry is justified, send the same logical request with the same payment ID. | A new ID can turn one intended purchase into two. |
| Different purchase | Create a new payment ID only when the buyer has intentionally created a new logical purchase. | Never use one ID as a global session key. |
Seller contract
Idempotency needs a request binding, not just a cache key
The official guidance recommends generating IDs at the logical-request level, persisting them for long-running operations and never reusing them across different logical requests. Sellers choose their cache retention window and should use durable shared storage rather than an in-memory map when requests can land on different instances.
For a stronger implementation, bind the identifier to a normalized request fingerprint — method or tool name, canonical resource, request body or parameters, selected scheme, network, asset, amount and recipient. If the same ID arrives with materially different purchase semantics, reject it rather than returning an unrelated cached response.
The extension is optional. Buyers should only attach it when the seller declares it, and sellers should state whether it is optional or required. An agent must not invent support from a directory description or assume every x402 middleware has equivalent retry behavior.
Failure diagnosis
If the paid retry still returns 402, separate “unpaid” from “rejected”
The x402 documentation says a client that keeps receiving 402 Payment Required after attaching PAYMENT-SIGNATURE should check signature/network fields, exact amount matching and available funds or policy rejection. Do not create a second payment merely because the HTTP status stayed 402.
There is also an open x402 Foundation issue from 13 August 2026 reporting a middleware path where rejected/invalid Stellar retries expose the payment-error header to CORS but do not actually emit the rejection reason. That is implementation evidence, not a protocol-wide rule, but it is a useful warning: an identical-looking 402 can hide materially different causes. Preserve client-side payment state and facilitator evidence instead of treating every 402 as a fresh invoice.
When the extension is absent
Fail closed on uncertain paid retries
- Check for
PAYMENT-RESPONSE, transaction evidence or the provider's documented settlement lookup before spending again. - Persist the original payment requirements, signed payload metadata and exact request fingerprint long enough to reconcile a crash or timeout.
- Cap per-call and session spend so one retry bug cannot drain an autonomous wallet.
- Prefer providers with explicit idempotency and settlement semantics when the same purchase can be retried automatically.
For the broader evidence model, read how to verify an x402 API before paying. For seller discovery problems, use the Bazaar indexing troubleshooting guide. Qualified buyers can inspect zFinia's own machine-service catalogue at /api.
Primary sources