For 27 years, HTTP status code 402 sat in the spec doing nothing. "Payment Required" was reserved back in RFC 2616 in 1999 and never standardized, because nobody could agree on how the internet should actually move money inside an HTTP request. Every API that wanted to charge for access built its own workaround instead: API keys, OAuth, a billing dashboard, a Stripe checkout page, a human typing in a credit card number.
None of that works for an AI agent. It can't fill out a signup form, solve a CAPTCHA, or wait three days for a vendor to approve an API key application. It needs to discover a paid endpoint and pay for it in the same request, with no human in the loop. That gap is why 402 got resurrected in 2025 as x402, an open protocol built by Coinbase that lets a client attach a signed stablecoin payment directly to an HTTP request. By March 2026 it had processed more than 119 million transactions on Base and 35 million on Solana, according to protocol usage data reported by Coinbase, and on February 10, 2026, Stripe shipped native x402 support under a preview API called Machine Payments. That's the part worth paying attention to: this isn't a crypto-native curiosity anymore. It's showing up in mainstream payment infrastructure.
This guide covers how the x402 protocol actually works at the HTTP level, real server and client code you can run today, how it stacks up against Google's competing Agent Payments Protocol, and the security tradeoffs the marketing pages leave out.
Why HTTP 402 Instead of an API Key
Every existing "pay for API access" model assumes a human sets it up once and a machine uses it many times. An API key is provisioned by a person, stored in a secrets manager, and reused for months. That model breaks down for autonomous agents, because an agent can't know in advance which paid API it'll need three tool calls from now. You end up choosing between provisioning it a key for every service it might ever touch (a standing-access liability nobody wants to own) or provisioning nothing and hoping it never hits a paywall mid-task.
x402 flips the model: instead of an account and a standing credential, the resource itself advertises its price in the 402 response, and the client pays per request with a wallet it already controls. No signup, no dashboard, no key rotation policy. The tradeoff, covered honestly in the security section below, is that you've traded "credential leak" risk for "bearer payment token" risk instead of eliminating risk.
How the x402 Protocol Works
The flow is a single HTTP round trip plus a retry, with no out-of-band signup step:
- Client requests a resource. A normal
GETorPOSTto a paid endpoint, no auth headers. - Server responds
402 Payment Required. The response body is JSON describing what the server accepts: which blockchain network, which stablecoin, how much, and where to send it. - Client builds and signs a payment. The client's wallet signs an authorization for the exact amount, off-chain, using EIP-3009 transfer authorizations for EVM chains (no gas fee paid by the client for this step).
- Client retries the request with the signed payment attached.
- Server verifies the signature, either locally or by calling a facilitator's
/verifyendpoint, then does the work and settles the payment on-chain (directly or via the facilitator's/settleendpoint). - Server responds
200 OKwith the resource and a settlement receipt.
Here's the actual JSON from the x402 v2 specification for a 402 response body:
JSON{ "x402Version": 2, "error": "payment 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" } } ] }
Read that JSON like a price tag: network is a CAIP-2 chain identifier (eip155:84532 is Base Sepolia testnet), amount is USDC in its smallest unit (10000 = $0.01, since USDC has 6 decimals), asset is the USDC contract address on that chain, and payTo is where the funds land. maxTimeoutSeconds bounds how long the client has to complete the round trip before the quote expires.
The client's retried request carries a PaymentPayload with the same accepted terms plus a signed authorization (from, to, value, a validAfter/validBefore time window, and a random nonce that the token contract permanently records on-chain to prevent reuse):
JSON{ "x402Version": 2, "accepted": { "scheme": "exact", "network": "eip155:84532", "amount": "10000", "asset": "0x036CbD53842c5426634e7929541eC2318f3dCF7e", "payTo": "0x209693Bc6afc0C5328bA36FaF03C514EF312287C", "maxTimeoutSeconds": 60 }, "payload": { "signature": "0x2d6a7588d6acca505cbf0d9a4a227e0c52c6c34008c8e8986a1283259764173608a2ce6496642e377d6da8dbbf5836e9bd15092f9ecab05ded3d6293af148b571c", "authorization": { "from": "0x857b06519E91e3A54538791bDbb0E22373e36b66", "to": "0x209693Bc6afc0C5328bA36FaF03C514EF312287C", "value": "10000", "validAfter": "1740672089", "validBefore": "1740672154", "nonce": "0xf3746613c2d920b5fdabc0856f2aeb2d4f88ee6037b8cc5d04a71a4462f13480" } } }
If you're inspecting one of these payloads by hand, our Unix Timestamp Converter will decode validAfter/validBefore into readable dates in one paste, and the JSON Formatter is the fastest way to pretty-print a raw 402 response body before you start reading it.
A "Facilitator" Does the Blockchain Work
The server itself doesn't need wallet infrastructure or a node connection. A facilitator is a third-party service that verifies signatures and submits settlement transactions on the server's behalf, so a Node.js API can accept stablecoin payments without ever touching a blockchain SDK directly. Coinbase runs a free public facilitator for testnets, plus a production one at api.cdp.coinbase.com gated behind a CDP API key. Convenient, yes, but it's also the protocol's biggest centralization point - more on that in the security section below.
Server Code: Accepting Payments in Express
This is the pattern from Coinbase's own quickstart docs and mirrored in Stripe's Machine Payments docs almost verbatim, which is a good sign it's stable:
npm install @x402/express @x402/evm @x402/core
JavaScriptimport express from "express"; import { paymentMiddleware, x402ResourceServer } from "@x402/express"; import { ExactEvmScheme } from "@x402/evm/exact/server"; import { HTTPFacilitatorClient } from "@x402/core/server"; const app = express(); const payTo = process.env.PAYOUT_ADDRESS; // your wallet address // Coinbase's free public facilitator (use api.cdp.coinbase.com in production) const facilitatorClient = new HTTPFacilitatorClient({ url: "https://x402.org/facilitator", }); const server = new x402ResourceServer(facilitatorClient).register( "eip155:84532", // Base Sepolia testnet new ExactEvmScheme(), ); app.use( paymentMiddleware( { "GET /weather": { accepts: [ { scheme: "exact", price: "$0.001", network: "eip155:84532", payTo, }, ], description: "Get current weather data", mimeType: "application/json", }, }, server, ), ); // This handler only runs after payment is verified - no payment logic in here at all app.get("/weather", (req, res) => { res.json({ weather: "sunny", temperature: 70 }); }); app.listen(3000, () => console.log("Paid API running on port 3000"));
The middleware intercepts the request before it reaches your route handler. If there's no valid payment attached, it returns the 402 with pricing terms and your handler never runs. If payment verifies, the handler runs like any other Express route - it has no idea money changed hands.
Client Code: Paying Automatically
The client side wraps fetch (or axios) so payment happens transparently on a 402 response, no manual retry logic:
npm install @x402/fetch @x402/evm
JavaScriptimport { x402Client, wrapFetchWithPayment } from "@x402/fetch"; import { registerExactEvmScheme } from "@x402/evm/exact/client"; import { privateKeyToAccount } from "viem/accounts"; const signer = privateKeyToAccount(process.env.EVM_PRIVATE_KEY); const client = new x402Client(); registerExactEvmScheme(client, { signer }); const fetchWithPayment = wrapFetchWithPayment(fetch, client); // First call gets a 402, signs a payment, and retries automatically const response = await fetchWithPayment("http://localhost:3000/weather"); const data = await response.json(); console.log(data); // { weather: "sunny", temperature: 70 }
Python has the same shape, useful if your agent framework is LangChain or a custom Python loop:
pip install "x402[httpx]"
Pythonimport asyncio, os from eth_account import Account from x402 import x402Client from x402.http.clients import x402HttpxClient from x402.mechanisms.evm import EthAccountSigner from x402.mechanisms.evm.exact.register import register_exact_evm_client async def main(): client = x402Client() account = Account.from_key(os.getenv("EVM_PRIVATE_KEY")) register_exact_evm_client(client, EthAccountSigner(account)) async with x402HttpxClient(client) as http: response = await http.get("http://localhost:3000/weather") print(response.json()) asyncio.run(main())
Run the server, fund a Base Sepolia testnet wallet with a few cents of testnet USDC from the Coinbase faucet, and that client call completes in a few seconds with zero manual steps.
x402 for MCP Tools
If you're already building MCP servers, the @x402/mcp package wraps a tool so that calling it triggers the same 402-then-pay flow. An agent like Claude can pay per tool call, instead of your team provisioning a shared API key for every data source the agent might touch. The mechanics are the same as the fetch wrapper above, just adapted to MCP's request/response shape: the wrapper returns the payment requirements as structured tool output, signs a payment, retries, and hands back the real result.
x402 vs AP2 vs Other Agent Payment Protocols
x402 isn't the only agent payment spec announced in the last year. Google published its own Agent Payments Protocol (AP2) around the same time, and the two get compared constantly, but they're solving different problems:
| Protocol | Backer | What it actually does | Money moves via |
|---|---|---|---|
| x402 | Coinbase / open foundation | HTTP-native payment rail: request, get a 402, pay, retry | Stablecoins on-chain (Base, Solana, Polygon, more) |
| AP2 | Authorization framework: defines how a human grants an agent permission to spend, via signed "mandates" | Delegates to existing rails, including x402 | |
| ACP | Various (agentic commerce coalition) | Checkout-style commerce flow for agent-initiated purchases | Card networks and existing PSPs |
The distinction that actually matters when you're picking one: x402 answers "how does the money move," AP2 answers "who authorized the agent to spend it." They're not really competitors - AP2's own docs describe x402 as one of the payment methods an AP2 mandate can wrap. Building an agent that spends on a user's behalf with spending limits and human approval baked in? That's an AP2-shaped problem. Building an API that just needs to get paid per call by anything showing up with a signed authorization? That's exactly what x402 does.
The Security Tradeoffs Nobody Puts on the Landing Page
Every write-up of x402 leads with "no signup, no API key." Fewer mention what you're trading for that convenience. A 2026 academic paper, Five Attacks on x402 Agentic Payment Protocol, and independent security researchers have documented real weak points:
- A signed payment is a bearer credential. If an intercepted
PaymentPayloadgets resubmitted to a facilitator before the original settles, replay is only prevented if the underlying token contract's nonce tracking is airtight, and researchers have found implementation gaps where it wasn't. Treat a signed payment header the same way you'd treat an unencrypted API key in transit: never log it, always use TLS, never pass it through an intermediary you don't trust. - The verify/settle gap is real. Verification (checking the signature is valid) and settlement (the transaction actually confirming on-chain) are two separate steps. A server that does the work immediately after verification but before settlement confirms can, in theory, deliver a paid resource for a payment that later fails to settle. Wait for settlement confirmation before returning anything expensive.
- Facilitators are a trust and availability bottleneck. Coinbase's facilitator handles the bulk of production traffic today. If it has an outage, every server relying on it for
/verifyand/settlecalls effectively goes dark, even though the underlying blockchain is fine. If you're running anything beyond a demo, know your facilitator's uptime history before depending on it. - Give agent wallets a hard spending ceiling. Since the whole point of x402 is that an agent's wallet pays autonomously with no human in the loop, the wallet itself is your only remaining backstop. Fund it with exactly what a session should be able to spend, and never point
payTologic at a general-purpose treasury key. The same least-privilege instinct we cover in our non-human identity security guide applies directly here.
None of this makes the protocol unusable - plenty of production traffic is already flowing through it - but "the agent pays autonomously with no human checkpoint" is precisely the failure mode security teams have been warning about with AI agent credentials generally. Don't skip the spending limit just because the demo worked.
How to Accept x402 Payments in Your API: A 5-Step Quickstart
- Pick a network and facilitator. Start on Base Sepolia (testnet) with Coinbase's free facilitator at
https://x402.org/facilitatorbefore touching mainnet or real funds. - Install the server package for your framework:
npm install @x402/express @x402/evm @x402/core(Express), or the@x402/hono/@x402/next/@x402/fastifyequivalents. - Register a payment scheme and wallet address, then wrap the routes you want to charge for with
paymentMiddleware, setting apriceandnetworkper route. - Test the full round trip with the client SDK (
@x402/fetchor the Pythonx402[httpx]package) using a funded testnet wallet, confirming you get a 402 on the first call and a 200 with your data on the retry. - Add spending guardrails before production: a hard balance cap on the wallet you use for
payTo, settlement confirmation before returning paid data, and monitoring on your facilitator's uptime.
Working With x402 Payloads
A few DevToolLab tools come up constantly once you're actually debugging this stuff instead of just reading about it:
- JSON Formatter - pretty-print a raw 402 response body or a
PaymentPayloadbefore you try to read it - Unix Timestamp Converter - decode
validAfter/validBeforefields, which are raw Unix seconds, into human-readable timestamps - Base64 Encoder Decoder - some facilitator implementations base64-encode the payment header before it hits the wire; decode it to inspect the JSON underneath
- cURL Command Generator - build a manual test request against your
/verifyor/settlefacilitator endpoint without hand-writing the headers - Hex to Decimal Converter - convert a
nonceor raw tokenvaluebetween hex and decimal when you're cross-checking an on-chain transaction
Conclusion
x402 is one of the few "AI agent" protocols from the last two years that solves a problem nobody had a good answer for: letting software pay for something in the same request it asks for it, with no account and no standing credential. The code is genuinely simple - the Express and fetch examples above are close to copy-paste working. But "no human in the loop" cuts both ways: there's also nobody left to catch the mistake. Start on testnet, cap what your agent's wallet can actually spend, and treat every signed payment payload with the same care you'd give a credential, because that's exactly what it is.
