npm packages are not installable yet: [email protected] can be published after 2026-09-16 10:30 UTC. Details
Tollstile

Charge for usage

Authorize a maximum per call and settle only what the handler actually used — for LLM, image, and video generation.

Public Beta · early access
import { upTo } from "tollstile";

app.post("/v1/render", tollstile(toll.price(upTo("$0.50"))), async (c) => {
  const video = await render(await c.req.json());
  await storage.put(video);
  await c.get("payment").fulfill({ amount: costOf(video) }); // e.g. "$0.12"
  return c.json(video);
});
  • The payer authorizes up to $0.50. The charge settles the fulfilled amount after the handler.
  • fulfill() marks the moment the service exists. If the handler fails after fulfilling, the charge still settles.
  • A fulfilled amount of $0 releases the reservation.
  • If a variable route never calls fulfill(), nothing is charged and an error event with FULFILLMENT_MISSING is emitted.
  • Variable prices need the authorization flow and a rail with variableAmount: x402 with upto configured, L402, or KYAPay. The execution plan excludes incompatible rails, including MPP charge rails. Compatible rails still serve the route; only a route with no compatible rail is refused. Inspect gate.plan or toll.explain(gate).

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.

On this page