For nearly three decades, 402 Payment Required was the web's most famous unused status code — written into the HTTP specification, implemented by almost no one, and returned to developers mostly as a billing error. In 2025 and 2026 that changed. HTTP 402 is now the status code AI agents and APIs use to settle payment per request. This guide covers what 402 means, why it stayed dormant so long, how the modern payment flow works, and how to return one from your own API.
What is HTTP 402 Payment Required?
HTTP 402 Payment Required is a client-error (4xx) status code a server returns when access to a resource is gated behind a payment. The current HTTP specification — RFC 9110, §15.5.3 — defines it in a single line: the code is "reserved for future use." Because no standard convention was ever pinned down, services historically used 402 however they liked.
That vagueness is the whole story. The code has existed since the late 1990s (it appears in RFC 2068, published in 1997) as a placeholder for "digital cash or micropayment systems" that never standardized. The slot was reserved; the payment layer that would fill it never shipped — until the clients calling your API stopped being people and started being programs with budgets. For the plain-English version of that shift, see what is x402; for the glossary entry, see HTTP 402.
402 vs 401 vs 403: what's the difference?
These three 4xx codes are constantly confused. They answer three different questions.
| Status | Name | What it means | How a client fixes it |
|---|---|---|---|
| 401 | Unauthorized | The server doesn't know who you are | Provide or refresh credentials |
| 403 | Forbidden | The server knows who you are, but you're not allowed | Nothing — you lack permission; credentials won't help |
| 402 | Payment Required | Access is gated behind a payment | Pay the quoted amount, then retry the request |
The one-line mnemonic: 401 is about identity, 403 is about permission, 402 is about money. A 402 is the only one of the three a client can resolve by doing something new — paying — rather than by having different credentials.
Why 402 sat unused for ~30 years
The code was reserved for a micropayment web that never arrived. Through the 2000s and 2010s the web monetized two ways instead: advertising and monthly subscriptions. Both made sense for human readers. A single monthly checkout scales better than a payment prompt on every page, and there was no wallet a browser could draw from automatically to answer a per-request charge.
So 402 had no client that could act on it. With no standard behaviour, the few services that returned it repurposed the code as a generic "there's a billing problem" signal — which is exactly how you still encounter it today.
How real services use HTTP 402 today
Before the 2025–2026 revival, 402 mostly showed up as an error. Here's what it signals across common platforms:
| Service | What a 402 means there | Payment model |
|---|---|---|
| Stripe | A charge failed (card declined, insufficient funds) | Card billing |
| Shopify | Store frozen for unpaid invoices | SaaS billing |
| Google APIs | Quota exceeded / billing not enabled on the project | API quota |
| x402 (Coinbase, 2025) | "This request costs USDC — pay and retry" | Per-request stablecoin |
| Stripe MPP (Stripe + Tempo, 2026) | "Pay and retry" — a signed 402 challenge settled via Stripe | Per-request (stablecoin or card) |
The first three treat 402 as a dead end you resolve in a billing dashboard. The last two treat it as a live instruction the caller can act on programmatically. That difference is the entire 2026 story.
What changed: clients that can pay
The missing piece was never the status code — it was a client that could read "this costs money," pay, and continue without a human. Autonomous software supplied it. AI agents, crawlers, and MCP tools all make requests on someone's behalf and run against a task budget, which is exactly the shape a per-request charge needs. (We wrote about the underlying payments gap the agentic web left open.)
Two implementations turned the reserved code into working infrastructure:
- x402 — an open, HTTP-native protocol introduced by Coinbase in 2025 that gives 402 a concrete meaning: an unpaid request to a metered route is answered with a machine-readable challenge quoting the exact price in USDC, the caller pays and retries, and the server verifies before serving. It's now stewarded by the x402 Foundation under the Linux Foundation, with founding members including Coinbase, Cloudflare, Google, Visa, and Stripe.
- Stripe MPP — the Machine Payments Protocol, co-authored by Stripe and Tempo and launched in March 2026. It's built on the same per-request 402 challenge as x402; the difference is the rails and the extras — MPP routes settlement through Stripe (stablecoin on Tempo, or fiat via cards) and layers on subscription and streaming primitives that x402 leaves out. We compare the two in x402 vs Stripe's MPP.
Both are real uses of a real 402. They differ in how the money moves, not in the signal.
How an HTTP 402 payment flow works
A modern 402 is precise. It doesn't say "this might cost money, check the docs" — it states the price and everything needed to pay, in the first response. A typical x402-style challenge looks like this:
HTTP/1.1 402 Payment Required
Content-Type: application/json
{
"price": "0.005",
"currency": "USDC",
"chain": "base",
"nonce": "01J8Z9K2...",
"expires_at": "2026-06-29T12:00:00Z"
}
From there the caller runs a four-step loop:
- Request the resource normally.
- Read the 402 challenge — check the price against the remaining task budget and confirm the challenge hasn't expired.
- Pay the quoted amount and capture the settlement reference.
- Retry the original request with proof of payment (and the nonce carried back unchanged). The server verifies and returns
200with the body, or a precise failure.
That's the whole client path. For the buyer's side in depth, see how AI agents pay for APIs; for the byte-level wire format, see the x402 technical deep dive.
How to return a 402 from your own API
At the protocol level, returning a 402 is ordinary HTTP — here's the bare mechanism in Node's standard library:
import { createServer } from "node:http";
createServer((req, res) => {
res.writeHead(402, { "Content-Type": "application/json" });
res.end(JSON.stringify({
price: "0.005",
currency: "USDC",
chain: "base",
}));
}).listen(3000);
Returning the code is trivial. The work is everything around it: quoting a signed, tamper-proof price; issuing and tracking a nonce so a payment can't be replayed; verifying settlement; and failing closed so an outage never gives paid content away for free. Hand-rolling that per language is how bugs get in.
That's the layer Paywall handles. You register a route and a price, add one middleware from the SDK for your stack — Express, Next.js, FastAPI, Django, Laravel, Go, Spring Boot, ASP.NET Core, or Rails — and the route returns a signed 402 challenge to unpaid callers, verifies payment, and pays you in USDC to your wallet automatically. Every account includes a test mode that runs the full challenge → pay → verify → allow loop with synthetic settlement, so you can wire it up in CI before a real cent moves; going live is an environment-variable change. The exact request format is frozen as the X402v1 wire contract, so all nine SDKs sign byte-identically. Walk through it in the developer integration guide.
Running a website rather than an API? You don't need to touch 402 yourself at all — Paywall can quote AI crawlers a price at the Cloudflare edge before the request reaches your origin, while humans pass through untouched. See for site owners and don't block AI crawlers — charge them.
When a 402 is an error, not a payment prompt
If you received a 402 and you're not integrating x402, it's almost certainly a billing signal, not a payment challenge. Check the source:
- From Stripe — a charge was declined. Inspect the error body for the decline reason; it's not something the client retries by "paying the response."
- From Shopify — the store is frozen for unpaid invoices. Resolve the account balance.
- From a Google/cloud API — billing isn't enabled or a quota is exhausted. Enable billing or raise the quota.
A genuine x402 or MPP 402 is the opposite of a dead end: it carries a machine-readable price and a way to pay it in the same response. If the 402 you got has no price or payment instructions in the body, treat it as an application-level billing error.
FAQ
Is HTTP 402 a standard status code? It's part of the HTTP specification but was left "reserved for future use" (RFC 9110, §15.5.3), with no standardized convention. Protocols like x402 and Stripe's MPP now give it concrete, interoperable behaviour.
What's the difference between 402, 401, and 403? 401 means you're not authenticated, 403 means you're authenticated but not permitted, and 402 means access is gated behind a payment you can make and then retry.
Can I use HTTP 402 in my own API? Yes. Any server can return a 402. The hard part is the price signing, nonce/replay protection, settlement verification, and fail-closed behaviour around it — which is what an x402 SDK provides.
What does a 402 from Stripe mean? Stripe returns 402 when a charge fails — for example a declined card or insufficient funds. That's a billing error, distinct from an x402 payment challenge.
Is HTTP 402 only for crypto? No. The status code is payment-agnostic. x402 settles in USDC, while Stripe's MPP supports multiple rails; the code itself just signals "payment required."
Do browsers show a 402? No. No browser has native UI for 402; a user would see a generic 4xx error. 402 is meant for programmatic clients — SDKs and agents — that can read the challenge and act on it.
How do AI agents pay a 402? The agent's runtime parses the challenge, pays the quoted amount from a wallet it manages, and retries the request with proof of payment. See how AI agents pay for APIs.
Next steps
- New to the concept: what is x402? and the glossary
- Selling an API to agents: for developers and the nine SDKs
- Charging AI crawlers on a website: for site owners
- Comparing your options: x402 vs Stripe's MPP and x402 vs API keys
- Ready to try it end to end: create an account and run it in test mode