Why a header rather than a body?#
Because the request has to stay the same request.
The whole premise of x402 is that paying does not change what you asked for. A client sends GET /v1/search?q=..., gets a 402, and sends the identical request again with payment attached. If the payment went in the body, the retry of a GET would need a body, a POST would have its payload rewritten, and every existing API shape would need special handling.
A header sidesteps all of it. The method, path, query and body are untouched. One header appears.
What is inside X-PAYMENT?#
Base64-encoded JSON. Decoded, it is a small envelope:
{
"x402Version": 1,
"scheme": "exact",
"network": "base",
"payload": {
"signature": "0x...",
"authorization": {
"from": "0xBuyer...",
"to": "0xSeller...",
"value": "10000",
"validAfter": "1760000000",
"validBefore": "1760000600",
"nonce": "0x..."
}
}
}The envelope names the scheme and network so the server knows how to interpret the payload without guessing. The payload is scheme-specific. For exact on an EVM chain it is an EIP-3009 authorisation and its signature.
Note
Base64 is there so the value survives HTTP header rules. The JSON contains characters that are awkward in a header value, and some proxies are unkind to them. It is encoding, not obfuscation: anything on the path can read it.
Older implementations also accept PAYMENT-SIGNATURE as a header name. New work should send X-PAYMENT.
What comes back?#
On success, the resource, with status 200 and an X-PAYMENT-RESPONSE header. That is the receipt, also base64 JSON:
| Field | Meaning |
|---|---|
success | Whether settlement succeeded |
transaction | The settlement transaction hash |
network | Which chain it settled on |
payer | The address that paid |
The transaction hash is the part that matters beyond the request. It is what turns "the server says I paid" into something independently checkable: the buyer can look the hash up on a block explorer or in a settlement index and confirm the transfer, the amount and the recipient without trusting the seller's word.
What does a failure look like?#
This is where implementations diverge most, and where a client integration actually breaks.
- 402 again, with a fresh
accepts. The payment was invalid, expired or for the wrong terms. The body should say which. Re-signing against the new terms is the right response. - 402 with the same terms. Usually a verification failure rather than a terms mismatch. Retrying the same signature will fail the same way.
- 5xx. The seller or its facilitator failed. The payment may or may not have settled, and a client that assumes it did not can pay twice. Check the chain before retrying.
That last case is the one to design for. A seller should settle before responding or make the outcome recoverable, and a buyer should treat an unknown settlement state as unknown rather than as a failure. Errors in x402 sets out the status codes and bodies Roundhouse's own implementation uses.
Does the header work on MCP or other transports?#
No, and this catches people out.
x402 is an HTTP protocol. The payment rides on an HTTP header, which means the caller has to control HTTP headers. Over Model Context Protocol a tool call is a JSON-RPC message inside a session the client manages, and the tool itself cannot attach a payment header to anything. A paid MCP tool therefore has to be paid for some other way, usually by a prepaid balance on the account behind the connection.
A refusal that tells an MCP caller to "resend with an X-PAYMENT header" is telling it to do something it cannot do. If you are building both surfaces, the HTTP refusal and the MCP refusal need different wording. Charging for an MCP server covers what to do instead.
Frequently asked questions#
How large is the header?#
A few hundred bytes for a typical EVM exact payment after base64. Well inside normal header limits, but worth knowing if you run a proxy with a tight header cap.
Can I send a payment on the first request without being asked?#
Some servers accept it, and it saves a round trip when the client already knows the price. It is not guaranteed, because the client is then guessing at terms it has not been offered. Probing with an unpaid request first is the safe default.
Is the signature reusable?#
On-chain, no: the nonce is consumed on settlement. Before settlement, a server that releases its resource on verification alone can be made to release it repeatedly under one authorisation. Server-side nonce tracking before serving is the fix, not an optional hardening.
Should I log the X-PAYMENT header?#
Log the decoded metadata if you need it, not the raw header. It contains a signature that is valid until it expires or settles, and a log that holds live authorisations is a log that can spend money.
Why did my payment verify but not settle?#
Most often the nonce was consumed between verification and settlement, by a competing submission of the same authorisation. Short validity windows and settling promptly after verifying both reduce the window this happens in.
Where to check this yourself#
Make the exchange and read both headers. The first x402 payment guide walks through a real request and response pair, and GET /v0/test/x402 is a live endpoint that charges a cent and returns a real X-PAYMENT-RESPONSE. The hash in it resolves in /transactions once the settlement is indexed.
