Sato Hub
← Back to wiki

Paying Once When the Network Says Maybe: Idempotent x402 Retries

Last updated 2026-09-08

x402 puts a payment inside an HTTP request. The hard part is not the first call; it is the retry after a timeout, when the agent cannot tell whether the seller received the payment. Idempotency keys, bounded retries, and treating 'unknown' as unknown keep an agent from paying twice or giving up on a payment that landed.

Key takeaways

  • A 402 response is a quote: it names the network, asset, amount and the seller's address. Nothing has been paid yet.
  • The dangerous moment is a timeout after the paid request was sent. The payment may or may not have settled; treat it as unknown, never as failed.
  • Reuse the same payment payload on retry. A fresh signature is a fresh payment.
  • Bound the retries, log the payment identifier, and reconcile against the chain or the facilitator before paying again.

One operator removed x402 from their MCP server after six weeks. The reason was not the protocol; it was retries, refunds, and customers who could not tell if they had paid. This page is the client-side discipline that avoids that: how to retry an x402 request so that the seller is paid exactly once, and how to know when you genuinely do not know. Sato Hub measures how many catalogued x402 resources actually answer a 402 each week; this is what to do once one does.

Why It Matters

Agents run unattended and retry by default. A retry policy written for ordinary HTTP — fail, wait, resend — silently becomes a double-spend policy the moment the request carries money. At sub-cent prices nobody notices; at real prices the seller sees refunds and the buyer sees a bill they cannot reconcile. The protocol gives you the pieces to do this right; the client has to use them.

How It Works

  • 1. Request. The agent calls the resource. The server answers 402 with a body listing what it accepts: scheme, network (for example `eip155:8453` for Base), asset, amount, the seller's `payTo` address, and a validity window. This is a quote; store it.
  • 2. Pay. The agent constructs the payment payload — for the `exact` scheme on an EVM chain, a signed EIP-3009 `transferWithAuthorization` for the quoted amount, with a nonce and a validity window — and resends the request with the payload in the `X-PAYMENT` header.
  • 3. Settle. The server (or its facilitator) verifies the payload and settles it on-chain, then returns the resource with a settlement receipt header. Settlement can take a block or two; the HTTP response may not wait for it.
  • 4. The ambiguous case. The agent's request times out or the connection drops after step 2. The signed authorization exists; the facilitator may have broadcast it. Sending a NEW authorization now means paying twice if the first one landed.
  • 5. Retry correctly. Resend the identical payload (same nonce, same signature). The facilitator's replay protection — the EIP-3009 nonce — makes a duplicate settlement impossible: it either settles once or rejects the second attempt as already used. Then reconcile: check the authorization's nonce state on-chain or the facilitator's status endpoint before deciding it failed.

Key Components

  • The 402 body (`PaymentRequirements`): scheme, network, asset, amount, payTo, validity — the quote
  • A signed payment authorization with a unique nonce (EIP-3009 on EVM), which is the idempotency key
  • A facilitator that verifies and settles, and whose replay protection is the thing you rely on
  • A local payment ledger keyed by nonce: quote, payload, attempts, last known state
  • A reconciliation step that reads the chain or the facilitator before a payment is declared failed
  • A retry budget with backoff, and a hard stop that escalates to a human or the operator

The idempotency key is the nonce, not the request

HTTP idempotency keys live in a header and are honoured by the server's memory. In x402 the durable idempotency key is the signed authorization's nonce, which the token contract itself refuses to accept twice. That is stronger than a server promise — and it only helps if the client reuses the payload. Generate the nonce once per intended payment, persist it before the first send, and never mint a second one for the same purchase until the first is confirmed dead (expired validity window, and no settlement on-chain).

States an agent must keep apart

quoted (402 received, nothing sent), sent (payload sent, no response), settled (receipt header or on-chain settlement seen), rejected (server or facilitator refused before settlement), expired (validity window passed with no settlement). Only rejected and expired justify a new authorization. sent with a timeout is not rejected; it is sent. Most double payments come from collapsing those two.

Refunds are not part of the protocol

x402 settles a transfer. If a seller returns an error after settlement, the money has still moved. Refunds are a seller policy, not a protocol step, so a client cannot assume one. The practical consequence: reconcile before retrying, and prefer sellers whose 402 responses and status endpoints are reliable — the weekly *answers 402* measurement on Sato Hub's x402 venue page is one input to that choice.

Which listed tools implement the client side

The x402 reference SDKs (x402-fetch for Node, the Python package) build the authorization and resend for you; whether they persist the payload across a process restart is your responsibility. Coinbase AgentKit wraps the same flow for agents. Wallet-side, Coinbase Agentic Wallets and MetaMask's x402-enabled MCP handle signing under a policy. Each listing below carries its Sato Score and whether we reproduced its install.

Examples

  • A data agent buys a $0.01 API call, the connection drops after sending the payment; it resends the identical payload, the facilitator reports the nonce already settled, and the agent fetches the resource without paying again.
  • A research agent's quote expires while it deliberates; it requests a fresh 402 rather than signing against a stale amount.
  • An operator's runtime persists every authorization to disk before sending, so a crash mid-payment resumes with the same nonce after restart.
  • A buyer sets a per-seller retry budget of three attempts and a daily spend cap in its session-key permission, so a misbehaving seller cannot drain it through repeated 402s.

Risks & Limitations

  • Generating a new authorization on every retry is the default behaviour of a naive HTTP client and pays twice on any timeout after settlement.
  • Facilitator status endpoints differ by implementation; an agent that assumes one shape will misread 'unknown' as 'failed'.
  • A stale 402 quote can carry an amount the seller no longer honours; paying against it wastes the transfer.
  • Sub-cent prices hide the problem in testing; the same code at real prices produces real double charges.

Frequently Asked Questions

If I resend the same payload and it was already settled, do I get the resource?

That depends on the seller. Well-behaved servers recognise the settled nonce and return the resource; others return an error. Either way you have not paid twice, which is the property this page is about.

How long should I wait before treating a sent payment as expired?

Until the authorization's own validity window (validBefore) has passed AND an on-chain or facilitator check shows no settlement. Time alone is not enough.

Does x402 v2 change any of this?

v2 adds CAIP network identifiers, pluggable facilitators and a discovery extension. The settlement primitive and the nonce-based replay protection are the same, so the retry discipline is unchanged.

Is any of this measured on Sato Hub?

Two related figures, weekly: how many catalogued x402 resources actually answer HTTP 402 with a parseable quote, and how many settlements reach sellers that look like real demand rather than one automated buyer. Both are on the x402 venue page with their method and sample.

Sources

Related Resources

Related Wiki Pages

Cite this page

Sato Hub. "Paying Once When the Network Says Maybe: Idempotent x402 Retries." Sato Hub, updated 2026-09-08, accessed 2026-09-08. https://satohub.ai/wiki/idempotent-x402-payments

This page is refreshed daily. Citations include the date so a reader can tell which snapshot a claim came from.

Spotted an error or something outdated?Submit a correction →

Join the Sato Hub Briefing

One email a week — the agents, tools, and infrastructure that actually shipped, and why they matter.