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

# API keys

> Mint, scope, rotate, and revoke API keys for your tenant.

API keys are how programmatic clients authenticate to Agnes. Each key
belongs to exactly one tenant; the tenant is inferred from the key on
every request.

This page covers the lifecycle. The wire-level details
(`Authorization: Bearer …`, `Agnes-Version` pinning) live on
[Authentication](/get-started/authentication).

## Live vs sandbox keys

| Prefix                | Bills? | Calls upstream models?                   | Use for                                   |
| --------------------- | ------ | ---------------------------------------- | ----------------------------------------- |
| `ak_…` (live)         | Yes    | Yes                                      | Production traffic.                       |
| `ak_test_…` (sandbox) | No     | No, returns deterministic canned results | Tests, CI, example apps, MCP scaffolding. |

Sandbox keys behave exactly like live keys on every public endpoint —
same schemas, same headers, same idempotency semantics — but every
analyzer output comes from a deterministic stub. See
[Sandbox mode](/testing/sandbox-mode).

## Minting a key

1. Sign in to [`agnes.lasscyber.com`](https://agnes.lasscyber.com).
2. Open **Settings → Keys** (or
   [`agnes.lasscyber.com/keys`](https://agnes.lasscyber.com/keys)).
3. Click **Create API key**.
4. Choose:
   * **Description.** Human-readable name. Appears in the audit log.
   * **Test mode.** Toggle on to mint an `ak_test_…` sandbox key.
   * **Scopes.** The set of scopes the key may exercise. The picker
     disables any scope you do not have yourself; see
     [Roles & permissions](/administration/roles-and-permissions).
   * **Rate-limit override** (optional, owner / admin only). Lower
     the per-key minute / hour ceiling below the tenant default if
     you want to throttle a noisy workload.
5. Click **Create**. Copy the **full key value**. It is shown
   exactly once and never recoverable; if you lose it, delete the key
   and mint a new one.

Required role: owners and admins. Members can read keys but cannot
mint, rotate, or delete them.

## Storing a key

* **Never** commit a key to source control.
* **Never** put a key in browser-side code or a mobile app bundle.
* Use a secret manager (GCP Secret Manager, AWS Secrets Manager,
  Doppler, 1Password Secrets Automation, etc.).
* For local development, environment variables in a `.env` that is
  gitignored is fine.

The official SDKs read `AGNES_API_KEY` from the environment by
default; that is the path of least resistance.

## Recommended scope bundles

| Use case                    | Scopes                                                                                             |
| --------------------------- | -------------------------------------------------------------------------------------------------- |
| Production analyzer key     | `analyzer:run`, all `*:analyze`, `analyzer_logs:read`                                              |
| CI sandbox key              | Same as above                                                                                      |
| Read-only dashboard / audit | All `*:read` scopes                                                                                |
| Admin / automation          | Production analyzer scopes + the policy / YARA / SDP / safety create-update-delete scopes you need |

The full scope vocabulary is on
[Roles & permissions](/administration/roles-and-permissions#scopes-advanced).

## Rotation

Agnes does not have a single-call "rotate in place" operation. The
rotation pattern is **mint-then-delete**:

1. Mint a new key with the same description / scopes / rate-limit
   overrides.
2. Roll the new key out to your callers.
3. Watch its usage in the dashboard until you are confident traffic
   has migrated.
4. Delete the old key.

Both create and delete operations write to the audit log so you have a
record of every issuance.

## Per-key usage

The dashboard shows per-key usage — calls, tokens, last used, last IP.
Useful for confirming that an old key is no longer in use before you
delete it.

Programmatic access via
`GET /api/v1/api-keys/{key_id}/usage`. Required scope:
`api_key:read_usage`.

## Revoking compromised keys

If a key is compromised:

1. Delete it immediately from the dashboard. Authentication starts
   failing on the next request.
2. Mint a replacement.
3. Audit access. The audit log records every key creation / deletion;
   the analyzer log records every analyze call with `request_id` so
   you can scope the blast radius.

There is no "soft delete" or "expired but readable" state — deletion
is immediate and permanent.

## Programmatic CRUD

The full surface lives at `/api/v1/api-keys/`:

* `POST /api/v1/api-keys/` — mint a new key. Returns the full key
  value once.
* `GET /api/v1/api-keys/` — list keys (no values, only metadata).
* `GET /api/v1/api-keys/{id}` — fetch metadata for one key.
* `PUT /api/v1/api-keys/{id}` — update description, scopes, or
  rate-limit override.
* `DELETE /api/v1/api-keys/{id}` — revoke.
* `GET /api/v1/api-keys/scopes` — enumerate the available scope
  vocabulary.
* `GET /api/v1/api-keys/{id}/usage` — usage stats.

See the auto-generated [API reference](/api-reference/overview) for
schemas. Use [`Idempotency-Key`](/api-reference/idempotency) on
mints to make retries safe.

## SDKs

Both SDKs expose the API key namespace:

```python theme={null}
agnes = Agnes()

scopes = agnes.api_keys.scopes()
new_key = agnes.api_keys.create(description="ci", scopes=["analyzer:run"])
print(new_key["api_key"])           # full value, shown once

for key in agnes.api_keys.list():
    print(key["description"], key["last_used_at"])
```

```ts theme={null}
const scopes = await agnes.apiKeys.scopes();
const newKey = await agnes.apiKeys.create({
  description: "ci",
  scopes: ["analyzer:run"],
});
console.log(newKey.apiKey);          // full value, shown once

for await (const key of agnes.apiKeys.list()) {
  console.log(key.description, key.lastUsedAt);
}
```

## Sandbox key lifecycle

Sandbox keys do not expire by default when minted from the dashboard
under your own tenant. Sandbox tenants minted via
`POST /api/v1/test-tenants` (operator endpoint) carry a TTL; the keys
inside them stop authenticating when the tenant is reaped. See
[Sandbox mode](/testing/sandbox-mode#getting-a-sandbox-key).

## Next

* [Authentication](/get-started/authentication)
* [Roles & permissions](/administration/roles-and-permissions) —
  scope vocabulary.
* [Sandbox mode](/testing/sandbox-mode)
