Reference / x402 (experimental)

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 call

3. 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:

  1. 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.
  2. 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. Check GET /.well-known/x402 (enabled: true|false) to see the live state.
  3. Index keeps a free anon allowance. With the rail on, the first 1,000 keyless reads per IP per day on /v1/index still return 200 — the keyless-reads promise survives the flip. The 402 only starts once that daily budget is spent.
  4. Streams has no free quota. With the rail on, /v1/streams quotes 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