Anatomy of an x402 Payment Challenge

What 402 Payment Required actually means and what a x402 payment response looks like under the hood.
x402 turns HTTP’s long-unused 402 Payment Required into a way for machines to pay for APIs directly. A client hits an endpoint, gets a price, signs a payment, and retries the request, all inside normal HTTP.
But there’s a common misunderstanding: returning a 402 is not enough.
A 402 status code is just a signal. What makes it work is the structure of the response body. If that part is wrong or incomplete, no x402 client can actually pay you.
The basic flow
A working x402 exchange looks like this:
- Client requests a resource
- Server responds with
402 Payment Required+ payment details - Client signs a payment authorization locally
- Client retries the request with the payment proof (
X-PAYMENT) - Payment is verified and settled, and the server returns
200 OK
The key idea: the client never sends a blockchain transaction. It only signs a message. Settlement is handled separately.
👉 Read also: What is x402?
What a real 402 response looks like
The important part is the JSON body. A compliant x402 response includes an accepts array that describes how to pay:
{
"x402Version": 2,
"accepts": [
{
"scheme": "exact",
"network": "eip155:8453",
"asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"payTo": "0xAd04…a4a3",
"maxAmountRequired": "2000",
"resource": "https://api.example.com/v1/data",
"description": "Premium data access",
"mimeType": "application/json",
"maxTimeoutSeconds": 300
}
]
}
What each field is doing
- accepts → the core of the protocol. If it’s missing, nothing works.
- scheme → how payment is handled (usually
exact) - network → CAIP-2 chain ID (not a human label)
- asset → token contract (e.g. USDC)
- payTo → recipient wallet
- maxAmountRequired → amount in atomic units (not decimals)
- resource → what this payment unlocks
- maxTimeoutSeconds → how long this quote is valid
Everything here is meant to be machine-readable. No guessing, no parsing strings.
Paying it
The client reads one option from accepts[] and builds an EIP-3009 transferWithAuthorization payload:
{
"from": "0xAgentWallet…",
"to": "0xAd04…a4a3",
"value": "2000",
"validAfter": "0",
"validBefore": "1714723200",
"nonce": "0x…32-byte-random…"
}
It signs this locally with EIP-712 typed data, encodes the signed payload in base64, and replays the original request with it in the X-PAYMENT header. The server (or usually, a facilitator like Coinbase CDP) verifies the signature and amount, calls transferWithAuthorization on the token contract to settle on-chain, and returns 200 OK with the resource plus an X-PAYMENT-RESPONSE header carrying the settlement details.
The security falls out of the design: the signature commits to the exact amount, asset, and recipient, so a tampered quote invalidates it. The 32-byte nonce is recorded on-chain to avoid replay attacks.
The common mistake
A lot of implementations stop at the status code and return something like this:
{
"error": "402 Payment Required",
"price": "0.002 USDC",
"network": "Base",
"recipient": "0xAd04…a4a3"
}
It looks fine, but it’s not usable by x402 clients.
What’s missing:
- No
accepts[]→ clients don’t know how to process it - No structured
schemeorasset→ nothing to sign against - No CAIP-2 network ID → ambiguous chain definition
- No proper payment format → cannot generate a valid authorization
In practice, this means no SDK, no agent, and no facilitator can use it.
It’s just a human-readable price tag.
Quick sanity check
If you’re building this, your endpoint should satisfy:
-
x402Version+accepts[]present - Each option includes
scheme,network,asset,payTo,maxAmountRequired - Network uses CAIP-2 format
- Payment can be replayed via
X-PAYMENT - Settlement actually happens on-chain
If any of these is missing, the endpoint isn't really usable even if it returns 402. Also, make sure you're actually using a facilitator unless you know what you're doing.
*At x402radar, we index the x402 ecosystem by actively paying endpoints to verify their behavior in real conditions. A 402 response alone is not enough; we only list services that are truly payable and work end-to-end.
The payment challenge must be correctly structured, and transactions must actually settle on-chain. When an endpoint shows up as unpayable, it’s almost always due to an invalid or incomplete challenge body.