Skip to content

Authentication

The public API accepts a workspace API key in the standard Bearer header:

Authorization: Bearer YOUR_API_KEY
Terminal window
curl \
-H "Authorization: Bearer YOUR_API_KEY" \
https://api.limitry.com/v1/workspace

The response names the workspace the key belongs to:

{ "id": "…", "name": "Example 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.

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.

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.

  1. Give it a name that says where it’s used, such as production-backend.
  2. Choose what it may do (see Access). A new key starts at Check limits, what most integrations need.
  3. 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.

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:

  1. Create a new key.
  2. Switch your integration to it.
  3. Revoke the old key.

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.

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 adds limits: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 adds workspace.approvals:write.

Developers

  • Webhooks: View is workspace.webhooks:read; View and change adds workspace.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.

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-events is 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:
Terminal window
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:

Terminal window
curl \
-H "Authorization: Bearer YOUR_PERSONAL_ACCESS_TOKEN" \
-H "X-Workspace: example" \
https://api.limitry.com/v1/workspace

A personal access token works in test unless the request says otherwise. To act in live, add X-Environment: live:

Terminal window
curl \
-H "Authorization: Bearer YOUR_PERSONAL_ACCESS_TOKEN" \
-H "X-Workspace: example" \
-H "X-Environment: live" \
https://api.limitry.com/v1/limits

The 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, 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/auth lists 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, plus offline_access for 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-Workspace header. Request it for the resource https://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.

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.