Python SDK
The Python SDK does two things. guard and hold put a limit around
your code in a with block. And every API operation is a typed method,
so your editor knows each keyword and answer. It needs Python 3.10 or
later.
Install
Section titled “Install”pip install limitrySet LIMITRY_API_KEY to a key from API keys in the app. Use a test
key (lim_test_…) while you build.
Guard costly work
Section titled “Guard costly work”guard checks the limit, then runs the block only if it’s allowed.
Here it counts one AI call against a limit such as 100 a day:
from limitry import LimitExceeded, Limitry
limitry = Limitry() # reads LIMITRY_API_KEY
try: with limitry.guard(subject={"kind": "user", "id": "usr_123"}, action="ai-call"): reply = call_model(prompt)except LimitExceeded as error: print(f"Try again in {error.retry_after_seconds} seconds")When you only know the cost afterwards, such as an AI reply your product
pays for by the token, hold reserves an estimate (5 cents here), runs the block and
charges what it actually used. If the
block raises, the hold is released:
from limitry import Limitry
limitry = Limitry()
with limitry.hold( subject={"kind": "user", "id": "usr_123"}, action="ai-call", estimate=5) as held: response = call_model(prompt) held.cost(price_cents(response.usage)) # your prices, in centsIf Limitry can’t be reached, each limit’s fail mode decides: open
lets the work run, closed refuses it. Both take timeout (seconds to
wait for a decision, 1.5 by default) and fail_mode to force one.
Methods
Section titled “Methods”Each API operation is a method, named like its command in the
CLI: limitry limits create is
limitry.limits.create().
from limitry import Limitry
limitry = Limitry()
limitry.limits.create( name="AI replies per day", subject_kind="user", action="ai-call", amount=100, window="day",)limits = limitry.limits.list()- Ids in the path are arguments, and everything else is a keyword, in
Python’s style:
subjectKindissubject_kind=. Answers keep the API’s own names. - A method returns the response’s data. A failure raises an
ApiErrorwith the error’scode,message,statusandrequest_id. - Every write sends an idempotency key, and a
failed attempt (a network error, a timeout, a
5xx, a429) is retried with the same key, so it happens once. To make your own retry safe too, pass your key:request_options={"idempotency_key": key}. - A request waits up to 60 seconds for an answer (
timeout=).
Every method, linked to its fields and a full example under Endpoints:
Checks
| Method | What it does |
|---|---|
limitry.checks.create() | Check whether a subject may act |
Reservations
| Method | What it does |
|---|---|
limitry.reservations.commit() | Commit a reservation |
limitry.reservations.extend() | Extend a reservation |
limitry.reservations.release() | Release a reservation |
Limits
| Method | What it does |
|---|---|
limitry.limits.archive() | Archive a limit |
limitry.limits.create() | Create a limit |
limitry.limits.get() | Get a limit |
limitry.limits.grants.create() | Add credits to a balance |
limitry.limits.grants.list() | List a balance's grants |
limitry.limits.list() | List limits |
limitry.limits.restore() | Restore an archived limit |
limitry.limits.sync() | Sync limits from a list |
limitry.limits.update() | Change a limit |
Subjects
| Method | What it does |
|---|---|
limitry.subjects.get() | Get a subject |
limitry.subjects.reset() | Reset a subject's limits |
limitry.subjects.update() | Set a subject's anchor |
Usage
| Method | What it does |
|---|---|
limitry.usage.query() | Get a limit's usage over time |
limitry.usage.standing() | Get where a subject stands |
limitry.usage.subjects() | List who is using a limit now |
Workspace
| Method | What it does |
|---|---|
limitry.workspace.get() | Get the current workspace |
limitry.workspace.invitations.list() | List pending invitations |
limitry.workspace.members.list() | List workspace members |
limitry.workspace.teams.list() | List teams |
limitry.workspace.usage() | Get your plan's usage this period |
Webhooks
| Method | What it does |
|---|---|
limitry.workspace.event_types.list() | List event types |
limitry.workspace.webhook_deliveries.list() | List an endpoint's deliveries |
limitry.workspace.webhook_deliveries.redeliver() | Redeliver an event |
limitry.workspace.webhook_endpoints.create() | Add a webhook endpoint |
limitry.workspace.webhook_endpoints.delete() | Remove a webhook endpoint |
limitry.workspace.webhook_endpoints.enable() | Re-enable a webhook endpoint |
limitry.workspace.webhook_endpoints.get() | Get a webhook endpoint |
limitry.workspace.webhook_endpoints.list() | List webhook endpoints |
limitry.workspace.webhook_endpoints.test() | Send a test event |
Approvals
| Method | What it does |
|---|---|
limitry.workspace.approval_actions.list() | List the actions you can ask approval for |
limitry.workspace.approval_requests.create() | Ask a person to approve an action |
limitry.workspace.approval_requests.get() | Check an approval request |
limitry.workspace.approval_requests.redeem() | Redeem an approved request |
Audit events
| Method | What it does |
|---|---|
limitry.workspace.audit_events.list() | List workspace audit events |
Personal access tokens
| Method | What it does |
|---|---|
limitry.user.me() | Get the current user |
limitry.user.revoke_token() | Revoke the token making this request |
AsyncLimitry has the same methods to await, and guard and hold
as async with:
from limitry import AsyncLimitry
async def answer(prompt: str) -> str: async with AsyncLimitry() as limitry: async with limitry.hold( subject={"kind": "user", "id": "usr_123"}, action="ai-call", estimate=5 ) as held: response = await call_model(prompt) held.cost(price_cents(response.usage)) return response.textYour key
Section titled “Your key”Limitry()reads your key from theLIMITRY_API_KEYenvironment variable. Without it, it raises an error naming the variable. To pass the key yourself:Limitry(token=key).- A test key (
lim_test_…) acts in test, and a live key (lim_live_…) in live. See Test and live. - A personal access token names the workspace, and acts in test
unless you name live:
Limitry(token=token, workspace="acme", environment="live").