Soren

Does your x402 client handle the failures?

The happy path is easy. Everyone gets it right. What nobody can test is the rest — and the rest is where money goes missing.

Every case below is a failure we hit in our own production code. The pending-settlement case exists because we treated a broadcast-but-unconfirmed transfer as a flat refusal for a week. The malformed-header case exists because one of our endpoints shipped a 402 with no PAYMENT-REQUIRED header at all and was unpayable by every v2 client. These are not hypotheticals.

The suite is free

Nine cases, no payment, no signup: GET https://soren.com/v1/conformance/{case}

They are free because they cannot honestly charge — a simulated failure settles nothing, and billing you for a fake error is the quickest way to make a test service worthless. Start at /v1/conformance for the machine-readable index.

CaseWhat it injectsYour client should
underpaidAuthorization below the quoteRe-read accepts[] and sign the full amount
overpaidAuthorization above the quoteSign exactly the quote — nothing refunds the excess
expiredA one-second validity window, in body and headerAbandon it and request a fresh quote
replayed-nonceA nonce already usedFresh nonce per attempt; never re-sign an identical authorization
wrong-networkRequirements on a different chainRefuse to sign — this is what stops a mainnet key signing a testnet quote
wrong-assetAn unexpected token contractRefuse to sign; check accepts[].asset against a known address
malformed-headerUndecodable header, valid bodyFall back to the body — v1 servers send only a body
settle-timeoutBroadcast but unconfirmed, with a tx hashTreat as unresolved, not refused. Record the hash; do not re-sign
double-402402 forever, even when paidGive up after a bounded number of attempts

The two that matter most

settle-timeout is the one almost nobody handles. A settlement that was broadcast but has not confirmed is not a refusal — the transfer may still land. A client that treats it as failure and re-signs can pay twice; one that treats it as success can be served nothing. The correct behaviour is to record the transaction hash and resolve it out of band.

double-402 is the one that produces runaway spend. A server that answers 402 no matter what you pay will drain a wallet that retries without a bound. If your client does not stop, it has an unbounded spend bug, and this is the cheapest place to find that out.

Paid companions

These settle real payments and do real work, which is why they are priced.

EndpointWhat it doesPrice
/v1/echo-paymentDecodes your signed EIP-3009 authorization and hands it back field by field — payer, value, recipient, validity window, nonce. For when a signer keeps being rejected and “invalid” is all you get.$0.02
/v1/paid-pingA heartbeat that costs money, so it proves verification and settlement are alive — not merely that the server answers.$0.01
/v1/roundtripThe same, plus how long settlement actually took, server-side. For setting your timeouts from evidence.$0.01
/v1/testpaymentA full successful payment, echoed back so you can assert against it.$0.10

Measured on Base: verification and settlement together typically complete in one to three seconds. A client timeout under five seconds will produce false failures on a perfectly healthy network.

When your client works, there is data worth buying with it: cross-store game pricing with real observed history, and signed oracles over public-domain sources.