Requirements
Conditions every admitted request must meet, checked after the payer is known and before anything is reserved.
Pre-release · planned API
toll.price("$0.40", {
require: [
limit({ perPayer: "100/hour", spendPerDay: "$20" }),
when(amountOver("$5"), strongerCheck),
],
});A requirement receives:
| Field | Use |
|---|---|
context | The normalized request context |
price | The price being charged |
payer | The rail payer or the policy account |
quote | The quote the proof carried, with a fresh nonce |
ledger | Read access for limits |
claims | A single-use store for nonces and replay windows |
now | The injected clock |
signal | Aborted when the provider timeout elapses |
and returns { ok: true } or { ok: false, status: 402 | 403 | 429 | 503, reason }.
When evidence cannot be checked right now, for example an agent's key directory is unreachable, answer 503 or throw TollstileError with PROVIDER_UNAVAILABLE or PROVIDER_TIMEOUT. Tollstile answers 503 requirement_unavailable, so a temporary outage never looks like a permanent 403.
Context
type Context = {
transport: "http" | "mcp";
request: Request | null;
mcp: { tool: string; arguments: unknown; meta: object; clientCapabilities: object } | null;
principal: { id: string } | null;
resource: string;
requestId: string;
extras: unknown; // the framework object, as an escape hatch
};Built-in and planned
| Requirement | Status |
|---|---|
limit(), payers(), when() | Implemented |
verifiedAgent() — HTTP message signatures, Web Bot Auth | In development |
userMandate() — AP2 mandates bound to the quote nonce | In development |
Tollstile verifies identity and authorization evidence. It never issues identities.