The x402 Payment Protocol
How HTTP 402 Payment Required became a real payment rail: the request/quote/sign/settle handshake, the EIP-3009 stablecoin authorization underneath it, the facilitator model, and what it means for payment engineers coming from card rails.
Headers & schemas
All protocol data travels as base64-encoded JSON in three HTTP headers (v2). Protocol v1 — still widely deployed — used X-PAYMENT headers and put the payment requirements in the 402 response body:
| Purpose | v2 (current) | v1 (legacy) |
|---|---|---|
| Requirements (server → client) | PAYMENT-REQUIRED header | 402 JSON body |
| Signed payment (client → server) | PAYMENT-SIGNATURE | X-PAYMENT |
| Settlement receipt (server → client) | PAYMENT-RESPONSE | X-PAYMENT-RESPONSE |
| Network identifiers | CAIP-2 — eip155:8453 | strings — base |
| Amount field | amount | maxAmountRequired |
A 402 response, decoded
HTTP/1.1 402 Payment Required
PAYMENT-REQUIRED: eyJ4NDAyVmVyc2lvbiI6Miw… (base64 of ↓)
{
"x402Version": 2,
"error": "PAYMENT-SIGNATURE header is required",
"resource": {
"url": "https://api.example.com/premium-data",
"description": "Access to premium market data",
"mimeType": "application/json"
},
"accepts": [{
"scheme": "exact",
"network": "eip155:8453",
"amount": "10000",
"asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"payTo": "0x209693Bc6afc0C5328bA36FaF03C514EF312287C",
"maxTimeoutSeconds": 60,
"extra": { "name": "USDC", "version": "2" }
}]
}Amounts are atomic token units: "10000" at USDC's 6 decimals is $0.01. The extra object carries the EIP-712 domain (token name and version) the wallet needs to build the signature.
The signed authorization
PAYMENT-SIGNATURE: eyJ4NDAyVmVyc2lvbiI6Miw… (base64 of ↓)
{
"x402Version": 2,
"accepted": { …chosen entry from accepts… },
"payload": {
"signature": "0x2d6a7588d6acca50…af148b571c",
"authorization": {
"from": "0x857b06519E91e3A54538791bDbb0E22373e36b66",
"to": "0x209693Bc6afc0C5328bA36FaF03C514EF312287C",
"value": "10000",
"validAfter": "1740672089",
"validBefore": "1740672154",
"nonce": "0xf3746613c2d920b5…62f13480"
}
}
}The authorization block is the exact EIP-3009 message the token contract will validate on-chain. The server or facilitator cannot alter the value or recipient without invalidating the signature — and the nonce is burned at the contract level on settlement, so the same authorization can never be settled twice.
Facilitator API
| Endpoint | Purpose |
|---|---|
| POST /verify | Validate a PaymentPayload against PaymentRequirements without touching the chain — signature recovery, balance check, exact-amount match, time window, simulation. Returns { isValid, invalidReason?, payer }. |
| POST /settle | Broadcast the transfer. Returns { success, transaction, network, payer }. |
| GET /supported | Lists supported scheme/network pairs and the facilitator's signer addresses. |
| GET /discovery/resources | The Bazaar: browse x402-enabled resources with pricing upfront. |