One status code, one header. Below is the full handshake, the shape of a 402, and where to
point a machine. The complete, machine-readable contract is the
OpenAPI spec.
§01 · the handshake
Seven steps, two round-trips.
01Agent sends a request with no payment.
02Service returns 402 with payment requirements — Base and Solana in the same challenge.
03Agent signs the payment with its wallet (USDC — EIP-3009 on Base, a signed transaction on Solana).
04Agent retries with the X-PAYMENT header.
05Service verifies the payment with the facilitator.
06Service processes the request and responds.
07Settlement happens asynchronously — the response never waits on it.
§02 · anatomy of a 402
Everything needed to pay.
A 402 carries one or more accepts entries. Each says how much, in which asset, on which network, to whom, and via which facilitator — enough for an agent to pay without ever talking to a human. Every stall here quotes two: pick the rail you already hold USDC on, and pay that entry exactly.
402 body
HTTP/1.1 402 Payment Required
{
"x402Version": 2,
"error": "Payment required. Sign the USDC authorization in accepts[0] and retry with the X-PAYMENT header.",
"accepts": [{
"scheme": "exact",
"network": "eip155:8453", // Base mainnet
"amount": "5000", // atomic USDC, 6 decimals -> $0.005
"asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"payTo": "0xFe25…A9C4",
"maxTimeoutSeconds": 300,
"extra": { "name": "USD Coin", "version": "2" } // EIP-712 domain - sign EXACTLY this
}, {
"scheme": "exact", // same scheme; the network is what differs
"network": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp", // Solana mainnet (CAIP-2)
"amount": "5000", // same price on either rail
"asset": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", // USDC-SPL mint
"payTo": "ARxR…97hD",
"maxTimeoutSeconds": 60,
"extra": { "feePayer": "Hbe1…LBLP" } // pays the network fee, not the price
}],
"resource": { // sibling of accepts, not inside it
"url": "https://true402.dev/api/v1/token-safety",
"description": "token-safety",
"mimeType": "application/json",
"serviceName": "true402"
}
}
§03 · the rails
USDC, on two chains.
Base:eip155:8453 — USDC via EIP-3009 transferWithAuthorization. The payer signs, the facilitator submits, so the payer needs no native gas and receiving is keyless.
Solana:solana — USDC-SPL, the same exact scheme; the network is what tells the two apart. The payload is a signed Solana transaction, and extra.feePayer names the account that pays the network fee.
Both, every time: a 402 quotes both rails at the same price; read accepts and pay the entry for the chain you already hold USDC on. Our own client packages currently sign the Base entry.
Different clocks: a Base authorization is good for the maxTimeoutSeconds in the quote. A Solana payment is bound to its blockhash instead, which expires roughly 60–90 seconds after signing — not after the quote — so sign it late and send it straight away.
Settlement: asynchronous — verified before the response, submitted after.
Not on this deployment: no testnet, and the Lightning (BTC) rail that exists in the codebase is switched off — /health/detailed reports it disabled.