Agnic
X402

Core Concepts

The X402 protocol — HTTP 402 flow, PaymentRequirements, the X-PAYMENT header, schemes, and facilitators.

X402 Core Concepts

X402 is an open standard for paying for HTTP resources with on-chain settlement. It uses the long-unused HTTP 402 Payment Required status code as the signal for "this resource costs money — here's how to pay."

This page covers the protocol itself: the wire format, the objects, the schemes. If you just want to call a paid endpoint, skip to X402 Fetch.

The HTTP 402 Flow

┌─────────┐                                ┌─────────┐
│ Client  │  1. GET /resource              │ Server  │
│         │ ──────────────────────────────>│         │
│         │                                │         │
│         │  2. 402 + PaymentRequirements  │         │
│         │ <──────────────────────────────│         │
│         │                                │         │
│         │  3. Sign authorization         │         │
│         │     (EIP-712 / partial tx)     │         │
│         │                                │         │
│         │  4. GET /resource              │         │
│         │     X-PAYMENT: <base64>        │         │
│         │ ──────────────────────────────>│         │
│         │                                │  5. Verify
│         │                                │     (+ settle
│         │                                │      via facilitator)
│         │  6. 200 OK + resource          │         │
│         │     X-PAYMENT-RESPONSE: <b64>  │         │
│         │ <──────────────────────────────│         │
└─────────┘                                └─────────┘

Two request/response cycles, one signature. No accounts created, no keys exchanged.

The PaymentRequirements Object

When an X402 server returns 402, the body is a JSON document describing what it accepts:

{
  "x402Version": 1,
  "error": "Payment required",
  "accepts": [
    {
      "scheme": "exact",
      "network": "base",
      "maxAmountRequired": "250000",
      "resource": "https://api.example.com/v1/generate",
      "description": "AI image generation",
      "mimeType": "application/json",
      "payTo": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb7",
      "maxTimeoutSeconds": 300,
      "asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
      "extra": {
        "name": "USD Coin",
        "version": "2"
      }
    }
  ]
}

Top-level fields

FieldTypeDescription
x402VersionnumberProtocol version
errorstringHuman-readable reason for the 402
acceptsarrayOne or more PaymentRequirement entries — client picks one

accepts[] entry

FieldTypeDescription
schemestringAuthorization scheme: "exact" or "upto"
networkstringChain identifier, e.g. "base", "base-sepolia", "solana"
maxAmountRequiredstringMax cost in atomic units (USDC has 6 decimals — 250000 = $0.25)
resourcestringCanonical URL of the gated resource
payTostringRecipient wallet address
assetstringToken contract address (USDC on the given network)
maxTimeoutSecondsnumberHow long the signed authorization remains valid
extraobjectScheme-specific metadata (e.g. EIP-712 domain name/version)
descriptionstringOptional human-readable description
mimeTypestringOptional content type of the resource

Multiple entries in accepts let the server offer a choice — "pay $0.25 on Base, or $0.26 on Solana." The client picks one and signs for it.

The X-PAYMENT Header

The client's signed authorization is a base64-encoded JSON object sent in the X-PAYMENT header:

X-PAYMENT: eyJ4NDAyVmVyc2lvbiI6MSwic2NoZW1lIjoiZXhhY3QiLCJuZXR3b3JrIjoiYmFzZSIsInBheWxvYWQiOnsuLi59fQ==

Decoded:

{
  "x402Version": 1,
  "scheme": "exact",
  "network": "base",
  "payload": {
    "signature": "0x...",
    "authorization": {
      "from": "0xPayer...",
      "to": "0xRecipient...",
      "value": "250000",
      "validAfter": "1734567890",
      "validBefore": "1734568190",
      "nonce": "0x<32 random bytes>"
    }
  }
}
FieldDescription
x402VersionMust match the server's version
schemeThe scheme selected from accepts[].scheme
networkThe network selected from accepts[].network
payloadScheme-specific proof — see below

On success, the server replies with X-PAYMENT-RESPONSE (also base64 JSON) containing the settlement transaction hash and payer address.

Authorization Schemes

exact — EVM (EIP-3009)

Uses EIP-3009 transferWithAuthorization, a gasless token-transfer primitive built into USDC. The client signs an EIP-712 typed-data structure; the server (or its facilitator) submits the signature on-chain and the token contract executes the transfer.

Authorization fields:

FieldDescription
fromPayer address
toRecipient address (matches payTo)
valueAmount in atomic units (matches maxAmountRequired)
validAfterUnix timestamp — earliest valid time
validBeforeUnix timestamp — expiry
nonce32 random bytes — prevents replay at the contract level

The nonce is enforced by the token contract itself: replay is impossible even without server-side tracking.

upto — EVM (EIP-2612)

Uses EIP-2612 permit to pre-authorize a spending cap. The server charges the actual cost (≤ cap) at settlement. Useful when cost isn't known up-front — streaming responses, variable-token LLM calls.

Agnic auto-selects exact or upto based on the server's accepts array.

exact — Solana

On Solana, the payload is a partially-signed transaction (base64-encoded) with instructions in this exact order:

  1. SetComputeUnitLimit (≤ 40,000)
  2. SetComputeUnitPrice (≤ 5 microlamports/unit)
  3. TransferChecked (the actual USDC transfer)
  4. Optional Lighthouse assertions

The server/facilitator co-signs and submits.

Facilitators

X402 servers don't want to hold private keys or run chain infrastructure. That's what a facilitator is for — a third-party service that verifies and settles payments on the server's behalf. A facilitator exposes three endpoints:

EndpointPurpose
POST /verifyCheck that an X-PAYMENT is valid, without moving any money
POST /settleActually submit the transfer on-chain
GET /supportedList the { scheme, network } pairs the facilitator handles

A server's typical flow: verify first (fast, off-chain), serve the resource, then settle asynchronously.

Public facilitators exist for Base, Base Sepolia, Solana, Avalanche and others. Agnic runs its own verified settlement path for the networks it supports.

Networks

X402 is chain-agnostic. Current production deployments use:

NetworkChain ID / CAIP-2USDC contract
Baseeip155:84530x8335...02913
Base Sepoliaeip155:845320x036C...CF7e
Solana Mainnetsolana:mainnetEPjF...Dt1v
Solana Devnetsolana:devnetGh9Z...fmjy
Avalancheeip155:43114(native USDC)

accepts[].network uses short names ("base", "solana") in the wire format; CAIP-2 is used by facilitators' /supported.

Replay & Expiry Protection

Every authorization carries three safety properties:

  1. Nonce — 32 random bytes, enforced by the token contract on EVM. One-shot.
  2. Time windowvalidAfter / validBefore bound when the authorization is usable.
  3. Amount capvalue (exact) or permit allowance (upto) bounds how much can move.

A signature leaked after the time window is useless; a replay of a consumed nonce reverts at the contract.

Error Codes

Standard error strings returned by facilitators and servers:

  • insufficient_funds
  • invalid_scheme
  • unsupported_scheme
  • invalid_network
  • invalid_x402_version
  • invalid_exact_evm_payload_signature
  • invalid_exact_svm_payload_transaction_instructions_length
  • invalid_transaction_state

How Agnic Implements This

You never touch the wire format unless you want to. Agnic's client library (and /api/x402/fetch) does all of the above — parse 402, pick a scheme, sign EIP-712 or build a Solana tx, attach X-PAYMENT, retry, surface the result.

If you need the raw header for a custom middleware, /api/sign-payment returns it directly.

Further Reading