Authentication
The public API accepts a workspace API key in the standard Bearer header:
Authorization: Bearer YOUR_API_KEYcurl \ -H "Authorization: Bearer YOUR_API_KEY" \ https://api.limitry.com/v1/workspaceThe response names the workspace the key belongs to:
{ "id": "…", "name": "Example Workspace" }API keys belong to a workspace
Section titled “API keys belong to a workspace”A key acts as a workspace, not a person. It keeps working if the person who created it leaves the workspace. It never carries a user session, so nobody can use it to sign in.
Test and live keys
Section titled “Test and live keys”Every key also belongs to one environment, and its prefix says which:
lim_test_… for test, lim_live_… for live. A test key reads and
changes only test limits and counts, and a live key only live ones. The
API paths are the same for both. See Test and live.
A test key can read workspace-wide things, such as members, webhook endpoints and the audit log, but can’t change them. Use a live key or a personal access token for that.
Creating a key
Section titled “Creating a key”Workspace owners create keys in the app, under Settings → API Keys. The key belongs to the environment the app shows (test or live, picked with the toggle at the top right), and the page lists only that environment’s keys.
- Give it a name that says where it’s used, such as
production-backend. - Choose what it may do (see Access). A new key starts at Check limits, what most integrations need.
- Copy the secret. We show it once and you can’t view it again, so put it in your secret manager straight away.
The list of keys shows only what is safe to show: the name, the prefix and the next four characters, the access, and when it was created and last used. If a secret is lost, create a new key and revoke the old one.
Revoking and rotating
Section titled “Revoking and rotating”Owners can revoke a key at any time under Settings → API Keys. Most requests refuse it at once. Checks and reservations cache a key for speed, so they can keep accepting a revoked key for up to 60 seconds. You can’t restore a revoked key.
To rotate a key without downtime:
- Create a new key.
- Switch your integration to it.
- Revoke the old key.
Access
Section titled “Access”When you create a key or a token, you choose what it may do:
| Choice | What it gets |
|---|---|
| Check limits | Checks and reads limits. Where a new API key starts. |
| Read only | Can view everything, never change. Where a personal token starts. Later permissions aren’t added. |
| Full access | Everything, including what the API adds later. |
| Custom | Only the permissions you pick. |
Permissions
Section titled “Permissions”Custom lists each permission with what it may do: No access, View, or View and change. Behind each choice are scopes, the ids the API checks. The API reference shows the scope each endpoint needs.
Limits and checks
- Limits: View is
limits:read; View and change addslimits:write. - Checks: Use is
checks:write.
Workspace
- Workspace details: View is
workspace:read. - Members: View is
workspace.members:read. - Teams: View is
workspace.teams:read. - Audit log: View is
workspace.audit:read. - Approvals: View is
workspace.approvals:read; View and request addsworkspace.approvals:write.
Developers
- Webhooks: View is
workspace.webhooks:read; View and change addsworkspace.webhooks:write.
Check limits is checks:write and limits:read.
Give an integration only what it needs. Calling an endpoint the
credential wasn’t given returns 403 forbidden:
{ "error": { "code": "forbidden", "message": "This credential is not granted the workspace.audit:read scope", "requestId": "…" }}You can change an API key’s access at any time: on Settings → API Keys, click Edit access on its row. The key stays the same, so nothing needs updating where it’s used, and the change applies within a minute. You can’t change a personal access token’s access: create a new token and revoke the old one.
Personal access tokens
Section titled “Personal access tokens”A personal access token (pat_…) acts as you, not as a workspace.
Use one for your own scripts, CI jobs and the CLI. Create it in
the app under Account → API tokens, or let the CLI create
one. Its login opens your browser, and once you approve, the command
line creates the token for that computer and stores it for you.
A personal access token:
- works in the workspaces you choose when you create it, all of yours or specific ones, with the access you give it;
- is also limited by your role in each workspace. For example,
GET /v1/workspace/audit-eventsis for owners only, as the audit page is in the app. (A workspace API key is the workspace itself and has no role.) - expires when you choose: after 30 days, 90 days, a year, or never;
- identifies you at
/v1/user/me:
curl \ -H "Authorization: Bearer YOUR_PERSONAL_ACCESS_TOKEN" \ https://api.limitry.com/v1/user/me{ "id": "…", "name": "Casey Customer", "email": "casey@example.com", "workspaces": [ { "id": "…", "name": "Example", "slug": "example", "role": "owner" } ]}Everywhere else, a personal access token has to say which workspace it’s
acting in, with the X-Workspace header set to the workspace’s slug.
The call then runs with your membership in that workspace and the
token’s scopes:
curl \ -H "Authorization: Bearer YOUR_PERSONAL_ACCESS_TOKEN" \ -H "X-Workspace: example" \ https://api.limitry.com/v1/workspaceA personal access token works in test unless the request says
otherwise. To act in live, add X-Environment: live:
curl \ -H "Authorization: Bearer YOUR_PERSONAL_ACCESS_TOKEN" \ -H "X-Workspace: example" \ -H "X-Environment: live" \ https://api.limitry.com/v1/limitsThe response’s X-Environment header names the environment the request
used. An environment that doesn’t exist fails with 400.
Without X-Workspace the request fails with 400. A workspace you’re
not a member of, one the token wasn’t created for, or a scope the token
doesn’t have, fails with 403. Workspace API keys ignore X-Workspace,
because a key already is its workspace, and they’re never accepted on
/v1/user/*. A key always acts in its own environment: an
X-Environment header that names the other one fails with 403.
Like API keys, we show tokens once, and you can revoke them from the same page. They stop working at once if they expire or your account is suspended.
Apps and AI agents (OAuth)
Section titled “Apps and AI agents (OAuth)”Apps, including AI agents connecting their tools, can act for a person without ever holding a key, because the product is an OAuth 2.1 authorization server. The app sends the person to sign in. They choose a workspace and approve what the app may do, and the app gets a short-lived access token for the API.
- Discovery:
https://api.limitry.com/.well-known/oauth-authorization-server/authlists every endpoint. Apps can register themselves (dynamic client registration); registering grants nothing until a person approves. - Scopes: an app asks for the same scopes, such as
workspace.audit:read, plusoffline_accessfor a refresh token. The person can give it fewer. - One person, one workspace: a token acts for one person in one
workspace, with that person’s role, so it needs no
X-Workspaceheader. Request it for the resourcehttps://api.limitry.com/v1. - Environment: like a personal access token, it works in test
unless a request sends
X-Environment: live. - Disconnecting: the person can disconnect the app at any time under Account → Connected apps. Its tokens stop working on the next request.
When authentication fails
Section titled “When authentication fails”A missing, malformed, invalid or revoked credential gets a 401 with
the standard error envelope:
{ "error": { "code": "unauthorized", "message": "Unauthorized", "requestId": "…" }}The response is the same whatever the cause, so it gives nothing away
to someone guessing keys. Keys from before test and live existed, which
start with sk_limitry_, get this response too. Browser session cookies are never accepted on
the public API.