# AtmoRouter — API keys

Source: https://atmorouter.dev/docs/api-keys

Only endpoints that intentionally differ from the standard API carry a chip; the chip links to the note that explains the difference.

Two credentials for two surfaces. Inference takes a Bearer `ar-` key (or `x-api-key` header); the dashboard takes a session cookie. An `ar-` key never acts as a session, and a session cookie never authenticates inference.

`/api/dashboard/keys` `/api/dashboard/keys/{id}`

## Key lifecycle without support

Create keys with `POST /api/dashboard/keys` under your session. The key secret is shown in full exactly once at creation (prefixed with `ar-` followed by 48 hex characters) — save it immediately. Listing keys with `GET /api/dashboard/keys` returns a 12-character preview only. Revoking with `DELETE /api/dashboard/keys/{id}` immediately and permanently deletes the key.

Only the SHA-256 digest and the non-usable display prefix are stored — the plaintext is not stored, so a database dump, backup, or replica never yields a usable key. Authentication looks up the digest; list and export read the prefix verbatim.

No rotation, revoke and recreate. There is no key-rotation endpoint: rotation with a grace window is not available on Atmo today. You revoke the old key (`DELETE /api/dashboard/keys/{id}`) and create a new one; the old key stops working immediately, with no grace window. There is no read-only or config key kind — every user key is a full inference key. Grace rotation and read-only keys are not available today; treat them as roadmap, not as features, and rotate with manual overlap.

## Lifecycle operations

| Action | Endpoint | Auth | Effect |
| --- | --- | --- | --- |
| Create | POST /api/dashboard/keys | Session | 201; full ar- key shown exactly once |
| List | GET /api/dashboard/keys | Session | Key entries with a prefix-only preview, never the full secret |
| Revoke | DELETE /api/dashboard/keys/{id} | Session | Immediate hard delete |
| Revoke, bad id | DELETE /api/dashboard/keys/{id} | Session | 400 invalid key id |
| Revoke, unknown id | DELETE /api/dashboard/keys/{id} | Session | 404 key not found |

## Key properties

| Field | Meaning |
| --- | --- |
| name | Your label for the key. |
| rate_limit | Requests per minute for your whole account (all keys combined). Absent: 500/min. Explicit: 1..1000 — anything else (including 0 and negatives) is rejected with 400. |
| allowed_models | Optional allowlist of model IDs. Calls to any model outside the list are rejected with 403. |
| enabled | Keys carry no toggle: revoking deletes the key immediately, and subsequent calls return 401. |
| requests, last_used, created_at | Read-only telemetry returned by list. |

## Set price limits for one key

Create a key, store its secret, then follow Set price budget beside the new key or Manage price budgets in [API Keys](https://atmorouter.dev/dashboard/keys). Budgets opens with that key selected. Choose All models for coverage across eligible paid models, or choose a family or exact model for narrower coverage, set a minimum discount, and save. Creating a key does not create a budget automatically.

The key summary counts account limits and that key’s limits separately, including percentage rules and fixed model rates. A model-only rule does not cover the rest of the key’s traffic. All matching account and key limits intersect; the strictest input and output ceilings win. With no saved rules, catalogue price limits still apply. Budgets limit token rates, not total spend; the paid-request minimum still applies.

The session-authenticated Playground uses account rules only. It does not exercise a particular API key’s budgets. Test key-specific behavior through your client using that key. Read [Budgets](https://atmorouter.dev/docs/budgets) for API examples and [Setup helper](https://atmorouter.dev/docs/helper) for client configuration.

## Roadmap, not features

| Capability | Status | Operation today |
| --- | --- | --- |
| Grace-window rotation | Absent — delete is immediate and hard | Manual overlap: create new key, shift traffic, then delete old key |
| Read-only / config-scoped keys | Absent — only allowed_models exists | Separate keys per app, narrow each allowlist |
| Automated balance-check + key-creation snippets | Not yet offered | Use the dashboard, or adapt the curl examples on this page |
