Skip to content

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.

Terminal window
pip install limitry

Set LIMITRY_API_KEY to a key from API keys in the app. Use a test key (lim_test_…) while you build.

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 cents

If 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.

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: subjectKind is subject_kind=. Answers keep the API’s own names.
  • A method returns the response’s data. A failure raises an ApiError with the error’s code, message, status and request_id.
  • Every write sends an idempotency key, and a failed attempt (a network error, a timeout, a 5xx, a 429) 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

MethodWhat it does
limitry.checks.create()Check whether a subject may act

Reservations

MethodWhat it does
limitry.reservations.commit()Commit a reservation
limitry.reservations.extend()Extend a reservation
limitry.reservations.release()Release a reservation

Limits

MethodWhat 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

MethodWhat 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

MethodWhat 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

MethodWhat 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

MethodWhat 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

MethodWhat 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

MethodWhat it does
limitry.workspace.audit_events.list()List workspace audit events

Personal access tokens

MethodWhat 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.text
  • Limitry() reads your key from the LIMITRY_API_KEY environment 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").