HTTP has had a status code for this since 1997 and almost nobody has used it. Status 402, Payment Required, sat in the specification as a placeholder for a web that never arrived.
Pay — pay.sh — is an attempt to make it real: “The missing payment layer for HTTP — x402 & MPP payment challenges with user-authorized stablecoin signing.” It is MIT licensed, from the Solana Foundation, and the quickest way to understand it is to look at an actual challenge.
We ran the documented example
The README demonstrates the problem with two commands. Without Pay you get a 402; with it, the challenge is handled and you get the response. So we ran the first one against the project’s public debugger:
curl -i https://debugger.pay.sh/mpp/quote/AAPL
The response, abbreviated:
HTTP/2 402
content-type: application/problem+json
www-authenticate: Payment id="039oBcQ…", realm="payment-debugger…",
method="solana", intent="charge", request="eyJhbW91bnQiOiIxMDAwMCIs…",
description="Stock quote: AAPL", expires="2026-10-11T23:44:17.615Z"
{"type":"https://paymentauth.org/problems/payment-required",
"title":"Payment Required","status":402,
"detail":"Payment is required (Stock quote: AAPL)."}
This is a real protocol exchange, not a mock-up, and three things in it are worth noticing.
It reuses existing HTTP machinery. The challenge arrives in WWW-Authenticate, the same header that carries Basic and Bearer challenges, with method="solana" where a scheme name normally goes. The body is application/problem+json — RFC 7807 problem details, with a documented problem type URI. Nothing here is a bespoke envelope; a payment is modelled as an authentication challenge, which is exactly the right instinct.
The challenge expires. Issued at 23:39:17, expiring at 23:44:17 — a five-minute window. A payment challenge has to be short-lived or it becomes a replayable voucher, so this is correct and it means clients must handle expiry rather than queue challenges.
The amount is in the challenge, encoded. Decoding the base64 request parameter gives the terms:
{"amount":"10000",
"currency":"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"recipient":"7kwhK3ytM3gixNgJvjZ6sMGsrnRNio4p7hACCLae4tTP",
"methodDetails":{"decimals":6,"feePayer":true,"network":"localnet",
"recentBlockhash":"SURFNETxSAFEHASHxxxx…","tokenProgram":"Tokenkeg…"}}
Six decimals and an amount of 10000 means 0.01 of the named token — one cent. feePayer: true with a fee-payer key means the server sponsors the transaction fee rather than the caller. And network: "localnet" with a placeholder blockhash confirms this particular endpoint is a demonstration: you can inspect the entire protocol without spending anything real.
That is a well-built demo. You can read the shape of the whole system from one curl.
What the client actually does
Pay wraps a command rather than replacing it:
pay curl https://debugger.pay.sh/mpp/quote/AAPL
pay claude
pay codex
When the wrapped process receives a 402, Pay detects which protocol is in play — it supports both MPP (Machine Payments Protocol) and x402 — prepares the stablecoin transaction, asks the local wallet to authorise and sign it, and retries the request with the payment proof attached.
The pay claude and pay codex forms are the point of the exercise. An agent session can call a paid API and the payment happens in the wrapper, through a local wallet, without the agent holding credentials or the API needing an account relationship with you. There is also a built-in MCP server so assistants can request paid calls through the same approval flow, and pay acp support for goose, claude and codex.
The permissions model is the part that matters
Any tool that lets an autonomous process spend money needs to be judged on its limits, not its features. Pay’s are declarative:
origins: [https://api.example.com]
networks: [mainnet]
max_payment: "$1.00"
allow_any_asset: false
An origin allowlist, a network allowlist, a per-payment ceiling, and a refusal to accept arbitrary assets. Equivalent flags exist for one-off use: --allow-origin, --allow-network, --max-payment '$1.00'.
And the sentence that matters most, quoted from the README:
“Stateful MPP sessions and subscriptions fail closed while a permission policy is active.”
Fail closed. Not “warn and proceed.” Recurring commitments — the category where an agent could do real damage — are refused rather than approximated when a policy is in force. That is the correct default for money, and its presence is a reasonable proxy for how carefully the rest was thought about.
What the model does not include, and you should notice: there is no cumulative budget in that policy. max_payment caps a single payment; a thousand one-cent calls is a thousand approved payments. Set origin and network allowlists tightly and watch the wallet.
Current state, honestly
The repository is active — the most recent commit was 9 October 2026 — and substantial, at 716 tracked files, predominantly Rust with TypeScript and a web UI alongside. There is an embedded Payment Debugger that renders each 402 cycle as a sequence diagram locally, which is the kind of tool that only exists when someone has debugged this protocol in anger.
It is also version 0.1.1. Pre-1.0, on protocols that are themselves new. Both MPP and x402 are young specifications, and the interesting question is not whether Pay works but whether anyone will serve 402 challenges at scale. Today the answer is mostly demonstration endpoints.
Why it is worth watching anyway
The reason to care is architectural rather than speculative. Agent-driven API consumption breaks the assumptions of per-seat subscriptions and pre-provisioned API keys: you cannot sign up for an account on behalf of a process that decided ten seconds ago it needed one query from a service you have never used. Per-request settlement is a genuine answer to that, and HTTP already reserved a status code for it.
Whether stablecoin settlement is the answer is a separate argument. But the engineering here is sober — existing headers, RFC 7807 bodies, short-lived challenges, a fail-closed policy engine, a local wallet approval step — and that is unusual in this space.
If you are working at the program level on Solana rather than the payment level, Anchor is the framework underneath; if your problem is charging humans for software rather than machines for API calls, Polar is the conventional answer and does not involve a wallet.
The finding: you can watch this protocol work in one command, and the challenge is just WWW-Authenticate plus RFC 7807 with a five-minute expiry and a one-cent amount on localnet. The permission policy fails closed on subscriptions, which is the right instinct — and it caps individual payments rather than totals, so the allowlists are what you should actually tighten.
Primary link
Learn more at: https://github.com/solana-foundation/pay






