POST /x402/access handles three cases based on the request body and headers:
- Discovery — no
planIdin the body, returns all available plans. - Challenge —
planIdpresent, nopayment-signatureheader, creates a PENDING record. - Settlement —
planIdpresent with apayment-signatureheader, settles on-chain and returns anAccessGrant.
Sequence Diagram
Three Cases
- Case 1: Discovery
- Case 2: Challenge
- Case 3: Settlement
Send an empty body (or omit The
planId) to discover all available plans. No PENDING record is created — this is a pure pricing query.Request
Response
accepts array contains one entry per plan configured in SellerConfig.plans. Each entry includes the USDC contract address, the amount in base units (6 decimals), and the seller’s wallet address.HTTP Headers Reference
| Header | Direction | Format | Purpose |
|---|---|---|---|
payment-required | Server to Client (402) | base64 JSON | PaymentRequirements containing plan pricing and wallet address |
www-authenticate | Server to Client (402) | Payment realm=..., accept="exact" | HTTP spec compliance; includes challenge=... when a PENDING record is created |
payment-signature | Client to Server | base64 JSON | X402PaymentPayload with the signed EIP-3009 authorization |
payment-response | Server to Client (200) | base64 JSON | X402SettleResponse with the on-chain txHash |
x-a2a-extensions | Client to Server | presence check | When present, the x402 middleware passes through to the A2A handler instead of processing the x402 flow |
EIP-3009 Authorization
Thepayment-signature header carries a signed EIP-3009 transferWithAuthorization. This means the client signs an off-chain authorization that permits a specific USDC transfer, but never sends a transaction directly and never pays gas.
The server (or a facilitator like Coinbase CDP) executes the transferWithAuthorization call on-chain, paying the gas fees. The USDC moves from the client’s wallet to the seller’s wallet in a single atomic transaction.
Decoded payment-signature Structure
payload.signature— the EIP-3009 signature authorizing the USDC transfer.payload.authorization— the transfer parameters: sender, recipient, amount (in USDC base units, 6 decimals), validity window, and a random nonce.accepted— echoes thePaymentRequirementsfrom the 402 response, so the server can verify the client accepted the correct terms.

