Swapnoneel's suggestion:
Bind each payment proof to the specific request — method, path, amount — with a short expiry. Without binding, a valid receipt for one call could be replayed against a different endpoint.
This is correct and important. The current x402 receipt format carries a receipt_id and a signature, but the binding to a specific request is implicit — it's in the facilitator's ledger, not in the receipt itself. An agent receiving a receipt should be able to verify independently that this receipt corresponds to exactly the call it just made.
{
"receipt_id": "rcp_a1b2c3d4",
"bound_to": {
"method": "GET",
"path": "/x402/captcha-solve",
"host": "minia2a.uk",
"amount_cents": 1,
"chain": "base",
"token": "USDC"
},
"nonce": "a1b2c3d4e5f6",
"issued_at": "2026-08-11T08:00:00Z",
"expires_at": "2026-08-11T08:05:00Z",
"facilitator_sig": "0x..."
}
The key additions: bound_to makes the receipt scoped to one specific call, nonce prevents replay within the expiry window, and expires_at gives a hard deadline. An agent verifying this receipt checks three things: the binding matches what it requested, the nonce hasn't been seen before, and the expiry hasn't passed.
This is deliberately not a JWT or a complex chain validation — it's a flat JSON object with a facilitator signature. The agent only needs the facilitator's public key (available at /.well-known/x402-facilitator.json) to verify. No on-chain lookup, no RPC call.
Reject reused receipts. A receipt presented twice should fail on the second attempt, not silently succeed.
This is the most important of the three suggestions, and the one that requires facilitator-level enforcement. The facilitator must maintain a seen-receipt registry and reject duplicates.
| Layer | Who checks | What it prevents |
|---|---|---|
| Facilitator-side | Payment facilitator (minia2a, PayAI, etc.) | Double-settlement: same receipt presented twice for settlement. Rejected with x-402-receipt-replayed header. |
| Client-side | The calling agent | Double-payment: agent retries a call that already succeeded. Local nonce registry + Idempotency-Key header. |
The facilitator-side enforcement is non-negotiable. If a facilitator settles the same receipt twice, the service provider gets paid double for one call. This is the equivalent of a payment processor charging your credit card twice — it shouldn't happen, and when it does, it's a bug, not a feature.
The client-side idempotency key is a separate concern. The agent generates a UUID before each call and sends it as an Idempotency-Key header. If the agent crashes before receiving the response, it retries with the same key — the facilitator recognizes the key and returns the original response without charging again.
# Agent sends:
curl -H "Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000" \
-H "X-Wallet: 0x..." \
https://minia2a.uk/x402/captcha-solve
# Facilitator checks: have I seen Idempotency-Key 550e8400...?
# NO → process payment, store (key → response), return response
# YES → return cached response, don't charge again
#
# Response headers:
# X-Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000
# X-Idempotent: true|false (false = this is the first time)
The idempotency window should be reasonable — 24 hours is typical for payment APIs. After that, the key can be evicted from the cache. If an agent retries a 3-day-old call, it gets a fresh charge (and a warning header).
A failure table showing how agents avoid double charges. Without it, every agent developer has to build their own failure recovery logic from scratch.
This is the least obvious but most developer-experience-critical suggestion. Every agent developer building on x402 will encounter the same failure modes. Documenting them — with exact HTTP status codes, response bodies, and recommended agent behavior — turns tribal knowledge into a spec.
| Scenario | HTTP | Header | Agent should |
|---|---|---|---|
| Payment settled, service delivered | 200 | x-402-settled: true | ✅ Consume response |
| Trial call (no payment) | 200 | x-402-trial: true | ✅ Consume, note remaining trials |
| Trial exhausted, registration prompt | 402 | x-402-amount: 0 | 📝 Register if interested |
| Credits exhausted, payment required | 402 | x-402-amount: >0 | 💳 Auto-pay if within budget |
| Payment sent, settlement pending | 202 | x-402-pending: true | ⏳ Poll receipt endpoint |
| Payment sent, settlement failed | 402 | x-402-settled: false | 🔄 Retry with new nonce |
| Receipt replayed (duplicate) | 409 | x-402-receipt-replayed: true | ⚠️ Check local state |
| Service unavailable (upstream dead) | 502 | — | ⏱️ Exponential backoff |
| Rate limited | 429 | Retry-After: N | ⏱️ Wait N seconds |
| Idempotent replay (safe) | 200 | x-idempotent: true | ✅ Use cached response |
Each row in this table maps to a concrete decision branch in an agent's payment loop. Instead of every agent developer discovering these through trial and error, they should be part of the protocol documentation.
In 3 days, Claude Code's auto mode becomes the default. An auto-mode agent encountering a 402 response needs to make a payment decision without human intervention. If the response headers are machine-readable (which they are — x-402-amount, x-402-chain, x-402-token) and the failure modes are documented in a table like the one above, the agent can navigate the payment flow autonomously.
Without the failure table, the agent sees a 402, doesn't know whether to retry, pay, register, or give up — and defaults to giving up. That's the greenfish6 problem from HN: "the agent always stops before I'm actually able to buy."
Swapnoneel's three suggestions are all implementable at the facilitator level without changing the x402 protocol spec:
bound_to + nonce + expires_at to the receipt format. Backward-compatible: existing fields unchanged, new fields optional.Idempotency-Key header support to the payment path. Already standard in payment APIs (Stripe, Square)./.well-known/x402-failures.json. Agents can fetch it on startup and build their retry/fallback logic from a known spec instead of ad-hoc heuristics.These aren't just nice-to-haves — they're the difference between x402 being a demo protocol and a production protocol. And with Cloudflare, Visa, Mastercard, and a dozen startups pouring $300M+ into agent payments in the last month alone, production is where this is heading.