x402 pay-per-call
Experimental. The pay-per-call rail is a beta — surfaces, prices, and headers may change. Plans on the pricing page are the stable way to pay.
Built for agents. Index and Streams reads (/v1/index, /v1/streams) can be paid with x402, the HTTP 402 payment standard, settled on Stacks — and a paid POST /v1/subgraphs deploys an indexer owned by your wallet.
No card, no signup, no gas: transfers are sponsored, you only hold the token (sBTC, STX, or USDCx).
1. Call without a key
Call without a key while the pay-per-call rail is on and the API answers 402 Payment Required with exact quotes per accepted token.
# your agent calls like anyone else…
GET /v1/index/events?event_type=ft_transfer
# …and, with the pay-per-call rail on, gets a quote
HTTP/1.1 402 Payment Required
{
"x402Version": 2,
"accepts": [{
"scheme": "exact",
"network": "stacks:1",
"asset": "SM3VDXK3WZZSA84XXFKAFAF15NNZX32CTSG82JFQ4.sbtc-token",
"amount": "21",
"payTo": "SP2X…8KQ",
"maxTimeoutSeconds": 60,
"extra": { "nonce": "…" }
}]
}2. Wrap fetch, hold a wallet
One line with the SDK: withX402(fetch, { account }). It selects an offer, signs the sponsored transfer — you pay zero gas — and retries for you.
// the code you actually write
import { withX402, readX402Receipt } from "@secondlayer/sdk";
const x402fetch = withX402(fetch, { account });
const res = await x402fetch(
"https://api.secondlayer.tools/v1/index/events?event_type=ft_transfer",
);
// offer selection, sponsored signing, and the
// retry all happen inside that one call3. The paid retry
Same request plus a PAYMENT-SIGNATURE header. The response streams immediately; settlement confirms on-chain behind it. On Streams, one payment opens a session — up to 500 polls in the next hour ride free on a PAYMENT-SESSION voucher.
# what went over the wire for you
GET /v1/index/events?event_type=ft_transfer
PAYMENT-SIGNATURE: eyJzaWduZWQi…
# data streams back immediately
HTTP/1.1 200 OK
{ "events": [ … ], "next_cursor": "7978231:42" }4. Read the receipt
Every paid response carries a PAYMENT-RESPONSE receipt with txid, payer, and settlement state. Floor $0.001 per call.
// verify what you paid, in code
const receipt = readX402Receipt(res);
// {
// success: true,
// state: "optimistic" | "confirmed",
// txid: "0x4f…",
// payer: "SP1Q4…2MVE",
// network: "stacks:1"
// }There's no per-call "this read must pay" flag. Whether a request gets a free 200 or a 402 quote is decided per-request, in this order:
- Holding an API key bypasses x402. A request with a valid
sk-sl_key is an account-backed caller — it never sees a 402; usage bills against your plan via Stripe. Keyless = the pay-per-call rail; keyed = your plan. - The rail has to be on. Pay-per-call is gated on a funded sponsor wallet (
X402_SPONSOR_KEY). While it's off, keyless Index reads stay free and Streams stays key-mandatory — the pre-rail behavior. CheckGET /.well-known/x402(enabled: true|false) to see the live state. - Index keeps a free anon allowance. With the rail on, the first 1,000 keyless reads per IP per day on
/v1/indexstill return200— the keyless-reads promise survives the flip. The 402 only starts once that daily budget is spent. - Streams has no free quota. With the rail on,
/v1/streamsquotes from the first keyless call (one payment then opens a 500-poll session — see below).
So the same endpoint answers three ways for the same agent:
# A) Keyed → free (billed to your plan, never a 402)
curl https://api.secondlayer.tools/v1/index/events?event_type=ft_transfer \
-H "Authorization: Bearer sk-sl_…"
# HTTP/1.1 200 OK — x402 bypassed, usage counts against your plan# B) Keyless, under the daily free allowance → free
curl https://api.secondlayer.tools/v1/index/events?event_type=ft_transfer
# HTTP/1.1 200 OK — one of your first 1,000 anon reads/IP today# C) Keyless, allowance spent (rail on) → pay
curl https://api.secondlayer.tools/v1/index/events?event_type=ft_transfer
# HTTP/1.1 402 Payment Required
# {
# "x402Version": 2,
# "accepts": [{ "scheme": "exact", "network": "stacks:1",
# "asset": "SM3VDXK3WZZSA84XXFKAFAF15NNZX32CTSG82JFQ4.sbtc-token",
# "amount": "21", "payTo": "SP2X…8KQ",
# "maxTimeoutSeconds": 60, "extra": { "nonce": "…" } }]
# }The quote also rides back base64-encoded in a PAYMENT-REQUIRED response header, so any x402 client can read it without parsing the body.
Standard x402 v2 wire — works with any x402 client. Sponsored means we pay the STX gas.
Discover the rail at GET /.well-known/x402 and the x-x402 block in the OpenAPI spec.
Steady consumers can hold either:
- A session — one payment covers up to 500 polls an hour
- A prepaid tab — deposit once, calls debit it instantly