Add pay-per-call pricing to an API
Charge AI agents and API clients a fixed price per request with HTTP 402, using Tollstile.
Use this when you want each call to a route to cost a fixed amount, for example $0.05 per request.
1. Create one Tollstile instance
import { createTollstile, memoryLedger, testRail } from "tollstile";
export const toll = createTollstile({
rails: [testRail()], // replace with live rails in production
ledger: memoryLedger(), // replace with a database ledger in production
});Create it once per process and import it wherever routes are defined.
2. Wrap the route
import { Hono } from "hono";
import { tollstile } from "@tollstile/hono";
import { toll } from "./toll";
const app = new Hono();
app.get("/weather", tollstile(toll.price("$0.05")), (c) => c.json({ forecast: "clear" }));toll.price() validates the route against every rail where it is defined, so a misconfiguration fails at startup.
3. What callers see
- Without payment:
402 Payment Requiredwithprice, a signedquote, and an offer per rail inaccepts. - With a valid payment: your handler runs, the charge settles after it succeeds, and the response carries a receipt header.
- If your handler throws or answers
400or above: the reservation is released and nothing is charged.
4. Price several routes
app.get("/weather", tollstile(toll.price("$0.01")), weather);
app.post("/v1/generate", tollstile(toll.price("$0.05")), generate);
app.post("/v1/render", tollstile(toll.price(upTo("$0.50"))), render); // see Charge for usageChecklist for production
- Pass
secretfrom your secret store when using live rails. - Use a database ledger so charges survive restarts.
- Run
toll.reconcile()on a schedule. - Name routes with path parameters explicitly:
toll.price("$0.05", { resource: "GET /users/:id" }).
Retries
Send Idempotency-Key on the first paid request and keep it on retries of the same request (on MCP: _meta["tollstile/idempotency-key"]). A completed charge returns 409 already_paid; an in-flight charge returns 409 request_in_progress; an unknown outcome returns 503 payment_outcome_unknown. Do not start a new payment while the outcome is unknown. Released/refunded attempts may run again. See Idempotency for request matching and rail-specific key scopes.
Using Tollstile with coding agents
Give Claude Code, Codex, Cursor, and other coding agents what they need to add payments with Tollstile.
Monetize an API with x402
Charge per request in USDC with x402 on a Hono API. Build on the test rail, switch to x402 exact on Base Sepolia, and use upto for variable prices.