true402
protocol reference

How 402 works.

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.

  1. 01 Agent sends a request with no payment.
  2. 02 Service returns 402 with payment requirements — Base and Solana in the same challenge.
  3. 03 Agent signs the payment with its wallet (USDC — EIP-3009 on Base, a signed transaction on Solana).
  4. 04 Agent retries with the X-PAYMENT header.
  5. 05 Service verifies the payment with the facilitator.
  6. 06 Service processes the request and responds.
  7. 07 Settlement 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.
§04 · for machines

Discover without docs.