Payable to bearer, on demand.
Scip settles a stablecoin payment inside the request that asks for it. The price arrives in a response header and the money moves before the body does — no account, no invoice, no checkout.
HTTP/1.1 402 Payment Required
pay-to: 0x7A3f…9C21
chain: robinhood-mainnet- GET /v1/quote0.0020 USDC
- POST /v1/backtest0.2500 USDC
- GET /v1/filings0.0500 USDC
- POST /v1/transcribe0.0400 USDC
- GET /v1/orderbook0.0015 USDC
- POST /v1/embed0.0008 USDC
Example routes. One stub is green: the request being paid for right now.
Four messages, one round trip
x402 turns payment into a handshake. Nothing is stored between the two requests, so a caller that has never seen your API before can pay it on first contact.
- 1client
Ask, without paying
A caller requests the resource the ordinary way. It does not need to know the price yet, or hold an account.
GET /v1/quote?symbol=HOOD HTTP/1.1 host: api.example.com - 2server
Quote the price
The server answers 402 and names its terms: the amount, the asset, the address to pay, and the chain to pay it on.
HTTP/1.1 402 Payment Required content-type: application/json { "x402Version": 1, "accepts": [{ "scheme": "exact", "network": "robinhood", "maxAmountRequired": "2000", "payTo": "0x7A3f…9C21" }] }
- 3client
Sign and retry
The caller signs a transfer authorization for exactly that amount and repeats the request with the signature attached. It never sends a private key, and never more than the quote.
GET /v1/quote?symbol=HOOD HTTP/1.1 x-payment: eyJzY2hlbWUiOiJleGFjdCIsInBheWxvYWQ… - 4server, then facilitator
Verify, answer, settle
Scip checks the signature, lets the route run, then submits the transfer on Robinhood Chain and returns the receipt beside the response body.
HTTP/1.1 200 OK x-payment-response: eyJzdWNjZXNzIjp0cnVlLCJ0eEhhc2gi… content-type: application/json
Why this rail
A per-request payment only works if confirming it costs less than the thing being sold, and takes less time than serving it.
- 100 ms
- Robinhood Chain block time. A payment can confirm inside the same round trip that asked for the resource.
- 402
- The status code HTTP reserved for payment in 1997 and left undefined. x402 is the definition that arrived.
- 1 header
- What a server adds to start charging. No checkout page, no billing portal, no invoices to reconcile later.
Price a route
Two changes: one on the server that quotes, one on the client that pays. Everything between them is the ordinary request you already have.
On the server
import { paywall } from "@scip/x402";
export const middleware = paywall({
network: "robinhood",
payTo: process.env.SCIP_PAYEE,
routes: {
"/v1/quote": "0.0020",
"/v1/backtest": "0.2500",
},
});
export const config = { matcher: "/v1/:path*" };On the client
import { withPayment } from "@scip/x402/client";
const pay = withPayment(fetch, {
signer,
maxPerCall: "0.05",
});
// Reads the 402, signs, retries once.
const res = await pay(
"https://api.example.com/v1/quote?symbol=HOOD"
);