Reservations
Some work only knows its cost afterwards, like an AI reply your product
pays for by the token. A reservation sets aside what the work will
probably cost while it runs, then you commit the actual amount. The
examples on this page reserve 5 cents for a user’s ai-call against a
budget of 200 cents a month, and commit what the call cost.
In one step
Section titled “In one step”The SDKs’ reserve reserves cost, runs your code, then commits what
it reports, or releases the reservation if your code fails:
import { createClient } from "@limitry/sdk";
const limitry = createClient();
const answer = await limitry.reserve( { subject: { kind: "user", id: "usr_123" }, action: "ai-call", cost: 5 }, async (reservation) => { const response = await callModel(prompt); reservation.cost(priceCents(response.usage)); // your prices, in cents return response; },);from limitry import Limitry
limitry = Limitry()
with limitry.reserve( subject={"kind": "user", "id": "usr_123"}, action="ai-call", cost=5) as reservation: response = call_model(prompt) reservation.cost(price_cents(response.usage)) # your prices, in centsThe steps below are what reserve does, for when you reserve, commit
and release yourself.
1. Reserve
Section titled “1. Reserve”Make a check with mode: "reserve" and what the work will probably
cost as the cost:
import { createClient } from "@limitry/sdk";
const limitry = createClient();
const answer = await limitry.checks.create({ subject: { kind: "user", id: "usr_123" }, action: "ai-call", cost: 5, mode: "reserve",});from limitry import Limitry
limitry = Limitry()
answer = limitry.checks.create( subject={"kind": "user", "id": "usr_123"}, action="ai-call", cost=5, mode="reserve",)limitry checks create --subject '{"kind":"user","id":"usr_123"}' \ --action ai-call --cost 5 --mode reservecurl -X POST https://api.limitry.com/v1/checks \ -H "Authorization: Bearer $LIMITRY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "subject": { "kind": "user", "id": "usr_123" }, "action": "ai-call", "cost": 5, "mode": "reserve" }'It decides like any other check. If it’s allowed, Limitry reserves the cost: other checks for that subject see it as used. The answer includes the reservation:
{ "allowed": true, "limits": [{ "limitId": "lmt_…", "remaining": 195, "…": "…" }], "reservation": { "id": "rsv_…", "expiresAt": "2026-10-04T12:05:00Z" }}If the check is refused, Limitry reserves nothing and there’s no
reservation.
2. Commit or release
Section titled “2. Commit or release”When the work is done, commit what it actually used, here 3 cents:
await limitry.reservations.commit("rsv_…", { cost: 3 });limitry.reservations.commit("rsv_…", cost=3)limitry reservations commit rsv_… --cost 3curl -X POST https://api.limitry.com/v1/reservations/rsv_…/commit \ -H "Authorization: Bearer $LIMITRY_API_KEY" \ -H "Content-Type: application/json" -d '{ "cost": 3 }'If it used less than it reserved, Limitry gives the rest back at once: the user’s budget shows 197 cents left, not 195. If it used more, Limitry records the actual cost in full, even past the limit, because the work did happen. The next check then sees the true total.
If the work didn’t happen, release the reservation instead:
reservations.release(id) (limitry reservations release <reservation-id>)
gives all of it back.
A commit or release is safe to retry: the same one gets the same
answer. Committing again with a different cost, releasing a committed
reservation, or committing a released one is refused with 400.
Expiry
Section titled “Expiry”A reservation lasts ttlSeconds, which you set on the check: 300 by
default, 3,600 at most. One that nobody commits or releases gives
itself back when it expires, so a crashed worker never keeps a subject
blocked. If the work did finish after all, a late commit within 24
hours still charges the full cost it reports.
For longer work, extend it as a heartbeat:
reservations.extend(id, { ttlSeconds: 600 }) makes it expire that
long from now (reservation.extend() inside reserve, in both SDKs).
A reservation can also take a slot of a
concurrent limit.
Good to know
Section titled “Good to know”- A subject can have at most 1,000 open reservations. Past that, the
check is refused with
reason.code: "too_many_reservations". - A reservation counts as one check on your plan. Committing and releasing are free.
- Reservations need the same
checks:writescope as checks.