Ref: KB-2410-07
Your agent is halfway through a task and needs one piece of paid data: a premium market feed, a geocoding call, a search result. A human would open a pricing page, create an account, add a card and paste an API key. An agent cannot do most of that. x402 is an open standard that turns the purchase into part of the HTTP exchange itself: the server quotes a price in its response, the agent signs a payment, and the same request is retried with proof of payment attached.
This article explains what x402 is, walks through the negotiation flow message by message, separates negotiation (HTTP headers) from settlement (the on-chain transfer), and ends with a complete worked example using the exact field values from the official specification. Every technical claim links to its source.
What x402 is
The x402 specification describes itself as "an open payment standard that enables clients to pay for external resources" (x402 spec v2, section 1). The official docs describe it as "built around the HTTP 402 Payment Required status code" and allowing "clients to programmatically pay for resources without accounts, sessions, or credential management" (docs.x402.org). It is published under the Apache-2.0 license, and the docs state that "x402 as a standard has 0 fees built in" (same page).
The status code it builds on is old. RFC 9110, the current HTTP Semantics standard, still says only: "The 402 (Payment Required) status code is reserved for future use" (RFC 9110, section 15.5.3). x402 gives that code a concrete, machine-readable meaning.
A note on repositories: the reference code started at github.com/coinbase/x402. Its README now says the repo "moved ... under the x402 Foundation" and that coinbase/x402 "is now a development fork"; the canonical home is github.com/x402-foundation/x402.
The three parties
The spec defines three components (spec v2, section 3):
- Resource server: the API that wants to be paid.
- Client: "any application or agent that requests access to protected resources". This is your agent.
- Facilitator: "a service that handles payment verification and blockchain settlement".
The facilitator is optional. The docs call it "optional but recommended" and note that it "does not hold funds or act as a custodian"; it verifies and submits transactions based on payloads the client signed (docs: Facilitator). A server can also verify and settle locally.
Negotiation vs. settlement
This distinction is the most useful mental model for an agent developer.
- Negotiation happens in HTTP. The server says what it accepts, the client answers with a signed authorization. Nothing has moved on any chain yet. In protocol version 2 this uses three headers, each carrying Base64-encoded JSON (HTTP transport v2):
| Header | Direction | Carries |
|---|---|---|
PAYMENT-REQUIRED |
server to client, with status 402 |
PaymentRequired object |
PAYMENT-SIGNATURE |
client to server, on the retry |
PaymentPayload object |
PAYMENT-RESPONSE |
server to client, with the result |
SettlementResponse object |
-
Settlement happens on a ledger. The facilitator's
POST /verifyendpoint is defined as read-only: it "MUST NOT commit payment state or write onchain state".POST /settleis the step that "durably commits payment state", typically by broadcasting a transaction (spec v2, sections 7.1 and 7.2).
If you have read older tutorials: protocol version 1 used X-PAYMENT for the client's payload and X-PAYMENT-RESPONSE for the result, sent the requirements in the 402 response body, and named networks with plain strings such as base-sepolia. Version 2 renamed the headers and switched to CAIP-2 network identifiers such as eip155:84532 (V1 to V2 migration guide; HTTP transport v1). The spec's version history dates v2.0 to 2025-12-09.
The flow, step by step
In the default authorization flow, payment is "verified before the resource executes and settled afterward" (spec v2, section 2). The Coinbase Developer Platform docs list the same order: the server asks the facilitator to verify, performs the requested work, then asks the facilitator to settle, and finally returns the resource (CDP: How x402 works).
- The agent sends an ordinary request.
- The server answers
402 Payment Requiredwith aPAYMENT-REQUIREDheader listing one or more options inaccepts(scheme, network, amount, asset, payee). - The agent picks an option it supports and builds a
PaymentPayloadfor that scheme. - The agent retries the request with the payload in
PAYMENT-SIGNATURE. - The server calls the facilitator's
/verify(or verifies locally) and gets backisValid. - If valid, the server does the work.
- The server calls
/settle; the facilitator submits the transfer. - The server returns
200with the resource and aPAYMENT-RESPONSEheader containing the transaction hash.
Not every scheme follows this order. The spec also defines an upfront flow (settle, then run the resource) and an escrow flow (settle a deposit, run, settle the final charge), and says clients should prefer authorization when both are offered (spec v2, section 6.1).
Why the agent never needs gas: EIP-3009
For the exact scheme on EVM chains, the recommended transfer method is EIP-3009 transferWithAuthorization, used by tokens such as USDC (exact scheme on EVM). EIP-3009 lets a token holder sign an EIP-712 message authorizing a transfer, which someone else submits; its abstract lists "delegate the gas payment to someone else" as a goal. Each authorization carries validAfter, validBefore and a random 32-byte nonce rather than a sequential one.
So the agent's wallet signs a message; it does not send a transaction. The facilitator broadcasts it and pays the gas. The x402 EVM scheme spec states that "the Facilitator cannot modify the amount or destination". Replay protection comes from the nonce, which the token contract refuses to reuse, plus the validity window (spec v2, section 10.1).
A worked example, end to end
The values below are the example values from the official HTTP transport and EVM scheme specs, so you can check every field against the source. The network is Base Sepolia testnet (eip155:84532) and the asset 0x036CbD53842c5426634e7929541eC2318f3dCF7e is that network's USDC, listed with 6 decimals in the x402 network and token table.
1. The agent asks. POST https://api.example.com/premium-data with body {"query": "latest market data"} and no payment header.
2. The server quotes. It returns HTTP/1.1 402 Payment Required with a PAYMENT-REQUIRED header. Decoded:
{
"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:84532",
"amount": "10000",
"asset": "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
"payTo": "0x209693Bc6afc0C5328bA36FaF03C514EF312287C",
"maxTimeoutSeconds": 60,
"extra": { "name": "USDC", "version": "2" }
}]
}
amount is in atomic units: 10000 with 6 decimals is 0.01 USDC. extra.name and extra.version are the token's EIP-712 domain values, needed to build the signature.
3. The agent decides and signs. Before signing, a careful agent checks the quote against its own policy: is the network one it holds funds on, is the asset the token it expects, is 0.01 USDC within its per-call budget? The core spec lists "client-side budget management" as out of scope, so the policy belongs to the client implementation (more on SDK spend controls below). It then signs an EIP-3009 authorization:
"authorization": {
"from": "0x857b06519E91e3A54538791bDbb0E22373e36b66",
"to": "0x209693Bc6afc0C5328bA36FaF03C514EF312287C",
"value": "10000",
"validAfter": "1740672089",
"validBefore": "1740672154",
"nonce": "0xf3746613c2d920b5fdabc0856f2aeb2d4f88ee6037b8cc5d04a71a4462f13480"
}
The window is 65 seconds. to equals the quoted payTo, and value equals the quoted amount.
4. The agent retries. Same POST, now with PAYMENT-SIGNATURE: <base64>. Decoded, the PaymentPayload contains x402Version: 2, the resource, an accepted field that copies the chosen accepts entry, and a payload holding the 65-byte signature and the authorization above.
5. Verification (no money moves). The server POSTs { x402Version, paymentPayload, paymentRequirements } to the facilitator's /verify. For EIP-3009 the facilitator checks that the signature recovers to from, that the payer has enough balance, that amount and validity window meet the requirements, that token and network match, and simulates the transferWithAuthorization call (exact EVM scheme, Phase 2). It answers with a VerifyResponse such as {"isValid": true, "payer": "0x857b..."}.
6. The work. The API produces the market data.
7. Settlement (money moves). The server POSTs the same structure to /settle. The facilitator calls transferWithAuthorization on the USDC contract with the signed parameters, and 0.01 USDC moves from the agent's address to payTo.
8. Delivery. The server returns HTTP/1.1 200 OK with the data and a PAYMENT-RESPONSE header that decodes to:
{
"success": true,
"transaction": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
"network": "eip155:84532",
"payer": "0x857b06519E91e3A54538791bDbb0E22373e36b66"
}
(The hash is the spec's placeholder.) If settlement fails, the same header comes back on a 402 with "success": false and an errorReason such as insufficient_funds (HTTP transport v2).
In code
You rarely build these headers by hand. The buyer quickstart shows a fetch wrapper that performs steps 2 to 4 automatically:
import { wrapFetchWithPayment } from "@x402/fetch";
import { x402Client } from "@x402/core/client";
import { ExactEvmScheme } from "@x402/evm/exact/client";
import { privateKeyToAccount } from "viem/accounts";
const signer = privateKeyToAccount(process.env.EVM_PRIVATE_KEY as `0x${string}`);
const client = new x402Client();
client.register("eip155:*", new ExactEvmScheme(signer));
const fetchWithPayment = wrapFetchWithPayment(fetch, client);
const res = await fetchWithPayment("https://api.example.com/premium-data");
The same guide documents Python (pip install "x402[httpx]") and Go clients.
Practical advice for agent builders
These are recommendations from our own experience, not requirements of the spec:
-
Put a policy layer in front of the signer. Allow-list networks and assets, cap the price per call and per day, and flag quotes whose
payTochanges between calls to the same endpoint. The reference SDK helps here: per its buyer quickstart, the client by default "only pays recognized USD-pegged assets (e.g. USDC) and caps each payment at $1", configurable through spend controls, and anonBeforePaymentCreationhook can cancel a payment before it is signed (docs: Lifecycle Hooks). Daily totals and per-endpoint rules are still yours to write. - Use a dedicated low-balance wallet. The key that signs authorizations should hold only what the agent may spend.
-
Log the
PAYMENT-RESPONSE. The transaction hash is your receipt; check it on a block explorer when reconciling. -
Handle
settlement_pending. The spec defines it as non-terminal: the transaction was broadcast but not yet confirmed, and the response must include its hash so you can check the chain before retrying (spec v2, section 9). -
Start on testnet. The docs say the public
x402.orgfacilitator "is intended for development and testnet workflows" (docs: Facilitator).
Summary
x402 makes paying for an API call part of the HTTP exchange. The 402 response is a price quote, the retry carries a signed authorization, and the facilitator first verifies it without touching the chain, then settles it on-chain. For an agent, that means no accounts or API keys, only a funded wallet and a spending policy you control.
Written by Swift Bot Labs. Independent and educational; we have no affiliation with the x402 Foundation or Coinbase.
Sources
- x402 Protocol Specification v2: https://github.com/x402-foundation/x402/blob/main/specs/x402-specification-v2.md
- x402 HTTP transport v2: https://github.com/x402-foundation/x402/blob/main/specs/transports-v2/http.md
- x402 HTTP transport v1: https://github.com/x402-foundation/x402/blob/main/specs/transports-v1/http.md
- Scheme
exacton EVM: https://github.com/x402-foundation/x402/blob/main/specs/schemes/exact/scheme_exact_evm.md - Original repository (now a development fork): https://github.com/coinbase/x402
- x402 docs, Welcome: https://docs.x402.org/introduction
- x402 docs, Facilitator: https://docs.x402.org/core-concepts/facilitator
- x402 docs, Networks and token support: https://docs.x402.org/core-concepts/network-and-token-support
- x402 docs, Migration guide V1 to V2: https://docs.x402.org/guides/migration-v1-to-v2
- x402 docs, Quickstart for buyers: https://docs.x402.org/getting-started/quickstart-for-buyers
- x402 docs, Lifecycle hooks: https://docs.x402.org/advanced-concepts/lifecycle-hooks
- Coinbase Developer Platform, How x402 works: https://docs.cdp.coinbase.com/x402/how-it-works
- EIP-3009, Transfer With Authorization: https://eips.ethereum.org/EIPS/eip-3009
- RFC 9110, HTTP Semantics, section 15.5.3: https://www.rfc-editor.org/rfc/rfc9110.html#name-402-payment-required
- CAIP-2, Blockchain ID specification: https://standards.chainagnostic.org/CAIPs/caip-2
Top comments (0)