> ## Documentation Index
> Fetch the complete documentation index at: https://docs.aurous-labs.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Authentication

> API keys, scopes, rotation, and the 24h grace window.

## API keys

All requests authenticate via the `X-Api-Key` header. Keys look like `al_live_<64-hex>`:

```bash theme={null}
curl https://api.aurous-labs.com/v1/team \
  -H "X-Api-Key: al_live_8jKpQ4nVmR..."
```

Keys are minted in the [dashboard](https://app.aurous-labs.com/dashboard/api-keys). The full plaintext is shown **once** at creation — store it in a secret manager. The dashboard preview thereafter shows only the first 14 characters (e.g. `al_live_8jKpQ4`); the platform stores a one-way hash, so we cannot recover the plaintext for you.

The `Authorization: Bearer <key>` form is also accepted as an alias, but `X-Api-Key` is the documented contract — pick one and stay consistent.

## Scopes

Every key has one of three scopes. Pick the narrowest scope that meets your integration's needs.

| Scope   | Allows                                                                                                                                                            |
| ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `read`  | All `GET` requests (loras, balance, team, usage, generation status, pricing)                                                                                      |
| `write` | All `read` access plus `POST /v1/images`, `POST /v1/videos`, `POST /v1/files`, `POST /v1/webhook_endpoints`, and per-resource `cancel` / `test` / `rotate_secret` |
| `full`  | All operations including reading and rotating other API keys via the dashboard                                                                                    |

A key without sufficient scope returns `403 insufficient_scope`. Most integrations only need `write` — reserve `full` for management tooling.

## Rotation — the 24h grace window

Rotate from `Settings → API keys → Rotate`. The platform mints a new key (returned **once**) and atomically marks the old key with `deactivate_at = now() + 24h`. Both keys validate during the grace window so deployments can roll without downtime; after 24h, the old key starts returning `401 invalid_api_key` automatically — no manual revoke required.

Workflow:

1. Click **Rotate** in the dashboard. Copy the new plaintext immediately.
2. Roll the new key through your secret store and redeploy.
3. Wait out the 24h grace window — your old deploys keep working until they're replaced.
4. After 24h the old key auto-deactivates. No further action.

If a key is **suspected compromised**, hit **Revoke** instead of rotate. Revocation is immediate (no grace), all in-flight requests with the revoked key return `401 invalid_api_key` within seconds.

## Per-team rate limits

Rate limits are per-team — multiple keys on the same team share the bucket. Burst capacity is 120 for `POST /v1/images` / `POST /v1/videos` and 1200 for reads, with sustained rates of 60/min and 600/min respectively. See [Rate limits](/rate-limits) for the full table and `429` recovery contract.

## Versioning

Pin a contract version with the `Aurous-Version: YYYY-MM-DD` request header so deploys downstream of yours can't break you. Every response echoes the applied version in the `Aurous-Version` response header. Without the request header, we use your team's `default_api_version` (set at signup). See the [Changelog](/changelog) for what each date-pin contains.

## Security checklist

* **Never** embed an API key in client-side bundles, mobile apps, or browser-side JS — proxy via your own backend.
* **Never** check a key into git, even on a private repo. Use a secret manager (Doppler, 1Password, AWS Secrets Manager, etc.).
* **Never** pass the key in a URL query string — query strings get logged by intermediate proxies and CDNs. Always use the `X-Api-Key` header. The platform refuses query-string keys explicitly.
* **Treat the key like a password** — anyone with the plaintext can spend your team's credits.
* **Tighten the scope on production keys** to `write` (or `read` for read-only integrations) so a leak can't escalate to key management.
* **Rotate quarterly** as a hygiene baseline; rotate **immediately** if you suspect any compromise.

## Error responses

| Status | Code                 | When                                                      |
| ------ | -------------------- | --------------------------------------------------------- |
| `401`  | `missing_api_key`    | `X-Api-Key` header is absent.                             |
| `401`  | `invalid_api_key`    | Key is unknown, revoked, or past its 24h `deactivate_at`. |
| `403`  | `insufficient_scope` | Key authenticated but its scope doesn't permit the route. |

Every error returns the standard envelope — see [Errors](/errors) for the shape and `request_id` workflow for support.
