Downgrade the model when budget is tight
Reroute to a cheaper model instead of blocking — no change to your request code.
Instead of blocking a user when their budget runs out, keep them working on a cheaper model. A Reroute rule swaps the model before the call is dispatched, so your app never sees the difference.
The rule
On the Firewall page, Cost & access tab, click New rule from template and pick a Save money card:
Switch to a cheaper model after $X — the budget-gated version. Set the amount you want to switch after, the reset period, and the cheaper model. Until the pool crosses that limit, calls run normally.
Send free users to a cheaper model — the unconditional version. No limit at all: every call on the plan you name is swapped, from the first one. There are per-team and per-session variants too (Switch each team or feature to a cheaper model after $X, Switch a session to a cheaper model after $X).
Same-provider swaps only — pick a smaller or cheaper model from the same provider. A cross-provider target is rejected. The target also has to be a model TokenPolice already has pricing for, or the rule won't save.
Check the swap really happens in your app
Reroute does not switch the model on some frameworks — including LangChain, LangGraph, LlamaIndex, Pydantic AI, and the Vercel AI SDK. Those calls still run on the original model. Confirm a swap actually happens in your app before you enforce this in production.
The snippet
There's nothing to change in your request code — the SDK rewrites the model and your
create() call returns from the cheaper model as normal. The only requirement is that your app
runs in enforce, since reroute (like block) only acts when both dials say enforce:
import token_police as tp
tp.init(
api_key=os.environ["TOKENPOLICE_API_KEY"],
base_url="https://collect.tokenpolice.ai",
firewall="enforce", # in dry_run the reroute is only recorded, not applied
)import { init } from "token-police";
init({
apiKey: process.env.TOKENPOLICE_API_KEY!,
baseUrl: "https://collect.tokenpolice.ai",
firewall: "enforce",
});A reroute never silently unpins a model you asked for: if the target resolves to the same model you already requested, nothing is swapped.
In Dry-run the rule records a "Would reroute…" projection instead of acting, so you can see how often it would fire before you turn it on — check it in the dashboard. See Actions.

