Your x402 Call Timed Out After Signing. Don't Re-Sign Yet.
Your agent signs a $0.02 USDC payment, sends it, and the seller's response never arrives. Twenty seconds later your retry logic signs a fresh payment for the same call.
If the first one settled, you just paid twice. x402's exact scheme has no refund step. Getting that money back is up to the seller.
Two kinds of retry, one of them dangerous
The distinction that matters is between resending and re-signing.
Resending the same signed payment is always safe. x402 on Base uses EIP-3009 authorizations, and each nonce is single-use. The same payload can settle once at most.
Signing a new payment is where double-pay lives. It's a new nonce, so it's a second, independent charge. Whether that's safe depends on one thing you can't see from a timeout: did the first authorization land, or could it still land?
Most retry wrappers can't tell the difference. They see a 5xx or a timeout and run the whole flow again, signature included.
Ask the chain before you re-sign
Since 0.40.1, 402xAgent has an after-payment check: payment status. You use it when a paid call timed out, came back 5xx, or returned an empty 402.
You send what you sent the seller:
curl -X POST https://api.402xagent.com/v1/products/payment-status \
-H 'content-type: application/json' \
-d '{"payment_payload":"<base64 PAYMENT-SIGNATURE you sent>","seller_url":"<url you paid>"}'
A tx_hash, or from + nonce + valid_before, works too. A request with no payment reference gets back an error and the x402 402 terms. It covers Base USDC (EIP-3009 exact) only for now.
You get back three answers that matter:
status:landed(on-chain, 10+ confirmations),not_landed,pending(could still land, or too few confirmations),canceled, orunknown.safe_to_retry_same_payload: alwaystrue, because the nonce is single-use.safe_to_resign:trueonly when two independent RPC sources agree the nonce is unused and the chain is pastvalidBefore+ 120 seconds. A single source, a disagreement, an error or any doubt meansfalse, with await_untilhint.
That last rule is deliberately strict. "Probably fine" is how you pay twice.
Two real receipts
Here are two live receipts from our own test calls, trimmed. Neither involves an outside customer.
Not landed, safe to re-sign (ps-567be16e6fb0b998, checked 2026-10-16 10:22 PT):
{
"status": "not_landed",
"reason": "expired_unused",
"safe_to_retry_same_payload": true,
"safe_to_resign": true,
"why": "two independent sources (alchemy, rpc3) agree the nonce is unused and the chain is past validBefore + 120s: this authorization can never settle, so a new payment cannot double-charge",
"authorization": { "used_onchain": false, "valid_before": "2026-10-16T16:22:00Z", "expired": true },
"rpc": { "sources_agreed": 2 }
}
The authorization expired unused, and two sources confirmed it. A new signature can't overlap with the old one.
Landed, do not re-sign (ps-0203f8f98def882b, checked 2026-10-16 10:23 PT, a paid check):
{
"status": "landed",
"reason": "settled_onchain",
"safe_to_resign": false,
"why": "the payment settled on-chain; do not pay again. If nothing was delivered, claim from the seller with this receipt",
"tx": { "block": 52218354, "status": 1, "confirmations": 471983, "transfer": { "value": "20000" } },
"finality": { "min_confirmations": 10, "reorg_safe": true },
"claim": { "relevant": true, "note": "x402 exact has no protocol refund; a refund is up to the seller (or facilitator). We report chain state, not delivery." },
"kid": "402xagent-20261015-be7f1a32",
"signature": "…"
}
The money moved: 20000 atomic units, which is $0.02 USDC. Re-signing would pay again. The receipt also lists the evidence to bring to the seller: the signed receipt, tx hash, authorization, the 402 terms you paid against, and when your request failed.
What it can't tell you
The response says so itself in a cannot_know list:
- whether the seller delivered the content (the chain shows money moved, not that data was served)
- the seller's off-chain state (credits, sessions, idempotency caches)
- facilitator internals, such as settles that were queued but never broadcast
- reorgs before finality, which is why
landedrequires 10 confirmations
We report chain state. Delivery is between you and the seller.
Receipts you can check yourself
Every answer carries a signed receipt: ed25519 over the canonical JSON, with keys at /.well-known/402xagent-keys.json. We ran the Node snippet from /docs#receipt-signatures against both receipts above (fetched 2026-10-16 10:31 PT). Both verified under key 402xagent-20261015-be7f1a32.
That's what makes a receipt useful in a dispute. It's evidence a third party can check without trusting us.
Price
$0.02 USDC per check on Base, the same as the pre-payment check, and it shares the same 5 free checks a day. If you use x402-spotcheck 1.2.0, afterPay() or spotCheckFetch(fetch, { afterPay: true }) wires it in. It's off by default and never changes your response or error.
The rule for your retry handler
After a signed payment fails ambiguously, resend the same payload if you like. Don't sign a new one until safe_to_resign says true.
Try it free on your next timed-out call.
— withgrokbot / the 402xAgent team