x402 guide · November 2026

Why does my x402 endpoint fail? A debugging checklist.

Frits Zwager, Fizzl · 1 November 2026 · we make x402 Doctor, one of the tools named here

An x402 payment is five steps between the agent, your server and a facilitator. When "the payment fails", one of those steps broke, and each one fails in its own way. Find the step first, then the fix. In the order a paying agent goes through them:

StepWhat the agent sees when it breaksCheck it with
1. The URL answers 402404, 401, a login page, or 200 for freecurl -i with the listed method
2. The 402 is one a client acceptsThe client throws before it signs, or the agent skips the endpointA free 402 check (x402 Doctor, x402lint, Coinbase's validate)
3. The payment reaches your serverA new 402 right after paying, with nothing settledYour server log: is PAYMENT-SIGNATURE there?
4. The facilitator verifies and settles itA 402 with an error reason such as insufficient_fundsThe errorReason; the facilitator's GET /supported
5. Your route answers after settlingPaid, then a 400, 404 or 500The PAYMENT-RESPONSE header and the transaction on-chain

1. Does the URL answer 402?

Call it the way the listing says, with no payment:

curl -i https://api.example.com/v1/price?symbol=BTC

You want HTTP/2 402 and a PAYMENT-REQUIRED header. If you get something else:

One more on this step: some older x402 SDK versions answered a HEAD request on a paid GET route with the paid answer, for free (x402-foundation/x402#3796). Update @x402/core and your framework adapter, or refuse HEAD on paid routes.

2. Is the 402 one a client accepts?

The PAYMENT-REQUIRED header is base64-encoded JSON. Decode it (echo '<value>' | base64 -d) and check what a standard client checks:

A free check does all of this in one go: x402 Doctor's web check reads the 402 the way a paying agent does and gives the fix as code for your stack. Coinbase's free validate API (POST https://api.cdp.coinbase.com/platform/v2/x402/validate) checks what the CDP Bazaar needs, and x402lint runs in CI. How these and four other checkers compare.

3. Does the payment reach your server?

If the agent paid and got a fresh 402 with no error reason, your server most likely never saw the payment:

4. Does the facilitator verify and settle it?

Your server hands the payment to a facilitator, which checks it (/verify) and puts it on-chain (/settle). When that fails, the 402 or the PAYMENT-RESPONSE header carries an error reason from the spec. The ones that point straight at the cause:

Error reasonUsually means
insufficient_fundsThe payer doesn't hold enough of the asset on that network. The buyer's problem, unless your price is in the wrong unit (atomic units: 10000 is $0.01 for 6-decimal USDC).
invalid_network, unsupported_schemeYour facilitator doesn't handle that network or scheme. Ask it: GET /supported lists what it settles.
invalid_exact_evm_payload_recipient_mismatchThe payment pays another address than your 402's payTo, often because payTo changed between the 402 and the payment (two instances, two configs).
…_authorization_valid_before, …_valid_afterThe authorization expired or isn't valid yet: maxTimeoutSeconds too short, or a clock off.
invalid_exact_evm_payload_signatureThe signature doesn't match the token's EIP-712 domain: wrong token name or version in extra, or another chain id.
invalid_payment_requirementsThe requirements echoed in the payment differ from what your server expects now: the price, asset or route config changed in between.
unexpected_settle_errorThe facilitator's own problem (RPC, gas, a timeout). Check its status; a buyer can retry safely with the same payment id when your route supports the payment-identifier extension.

Network-specific ones we see often: on Solana, PayAI rejects payments from Phantom, which adds Lighthouse instructions before the transfer (invalid_exact_svm_smart_wallet_program_not_allowed); agents, Solflare and Backpack work.

5. Does your route answer after settling?

The worst failure for a buyer: the payment settled and the answer was an error. In x402 Doctor's spot-buy of 18 October, 3 of 27 purchases ended that way (404, 404, and a 400 for a missing parameter). Two fixes:

When a buyer says they paid and got nothing, ask for the PAYMENT-RESPONSE header and paste it into x402 Doctor's free payment-proof check: it shows which transaction it points to, whether that transaction succeeded on-chain, and which USDC moved from whom to whom.

Tools, by step

ToolStepsCost
x402 Doctor web check (ours); CLI npx github:Fizzl13/x402-doctor <url>; GitHub Action Fizzl13/x402-doctor-action@v11, 2, and readiness for steps 3 to 5 (HEAD, payTo on-chain, Bazaar example)Free
x402 Doctor payment-proof check (ours)5Free
Coinbase CDP validate1, 2 (for the CDP Bazaar)Free, no key
x402lint2Free, MIT
Your facilitator's GET /supported and logs4Free

Questions

Is there a tool to debug why my x402 payment endpoint fails?

Yes. x402 Doctor's free web check at https://x402-doctor.fizzl.eu reads your 402 the way a paying agent does and gives each problem with the fix as code for your stack; it also runs as a CLI and a GitHub Action. Coinbase's free CDP validate API checks what the CDP Bazaar needs, and x402lint lints the 402 in CI. For a payment that settled but returned nothing, x402 Doctor's free payment-proof check reads the PAYMENT-RESPONSE header and shows the transaction on-chain.

Why does an agent get a 402 again after paying?

Either the server never saw the payment (an x402 v1 client sends X-PAYMENT instead of PAYMENT-SIGNATURE, a browser is blocked by CORS, or a proxy strips the header), or the facilitator rejected it, and then the 402 carries an error reason such as insufficient_funds, invalid_network or an expired authorization.

Why does my x402 endpoint answer 200 or 401 instead of 402?

The payment middleware runs after the route handler or after an API-key check, or its route key doesn't match the request's method and path. Register the payment middleware first: in x402 the payment is the authorization.