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

# Authentication

> Create API keys and authenticate requests to the Calseta REST API and MCP server.

Calseta uses API key authentication. Both the REST API and MCP server accept the same keys.

## API Key Format

All keys use the `cai_` prefix followed by a 32-character URL-safe random string:

```
cai_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6
```

Keys are stored as bcrypt hashes. The full key is shown **once** on creation and cannot be retrieved again.

## Creating an API Key

### Via CLI (recommended for first key)

```bash theme={null}
python -m app.cli.create_api_key \
  --name "My Agent" \
  --scopes "alerts:read,alerts:write,enrichments:read,workflows:read,workflows:execute"
```

### Via API

```bash theme={null}
curl -X POST http://localhost:8000/v1/api-keys \
  -H "Authorization: Bearer cai_your_admin_key" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "My Agent Key",
    "scopes": ["alerts:read", "alerts:write", "enrichments:read", "workflows:read"],
    "key_type": "agent",
    "expires_at": "2026-01-01T00:00:00Z"
  }'
```

<Warning>
  Save the returned API key immediately. It cannot be retrieved after creation.
</Warning>

## Key Types

Every API key has a `key_type` — either `"human"` (default) or `"agent"`:

| Type    | Purpose                              | Workflow behavior                                                                                                                                                     |
| ------- | ------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `human` | Human operators, dashboards, scripts | Workflows triggered as `trigger_source: human`. Bypasses `agent_only` approval gates.                                                                                 |
| `agent` | AI agents, automated systems         | Workflows triggered as `trigger_source: agent`. Must provide `reason` and `confidence` when executing workflows. Subject to `agent_only` and `always` approval gates. |

The `trigger_source` for workflow execution is derived **server-side** from the API key's `key_type` — it is not a request body field. This ensures agents cannot bypass approval gates by claiming to be human.

<Tip>
  Create separate keys for human operators and AI agents. This gives you audit clarity and lets approval gates distinguish between human and agent triggers automatically.
</Tip>

## Using API Keys

Include the key in the `Authorization` header with the `Bearer` prefix:

```bash theme={null}
curl -X GET http://localhost:8000/v1/alerts \
  -H "Authorization: Bearer cai_your_api_key"
```

The MCP server uses the same header format.

## Scopes

Each API key has one or more scopes that control access:

| Scope               | Grants access to                                                                     |
| ------------------- | ------------------------------------------------------------------------------------ |
| `alerts:read`       | Read alerts, indicators, activity, context                                           |
| `alerts:write`      | Update alert status, post findings                                                   |
| `enrichments:read`  | Read and trigger enrichment, read field extractions                                  |
| `workflows:read`    | Read workflows and workflow runs                                                     |
| `workflows:execute` | Execute workflows                                                                    |
| `approvals:write`   | Approve or reject workflow approval requests                                         |
| `agents:read`       | Read agent registrations                                                             |
| `agents:write`      | Register, update, delete agents                                                      |
| `admin`             | Full access (API keys, source integrations, enrichment providers, field extractions) |

<Tip>
  Follow the principle of least privilege. An agent that only reads alerts and posts findings needs `alerts:read` and `alerts:write` — not `admin`.
</Tip>

## Key Prefix Display

For display and audit purposes, only the key prefix (first 8 characters, e.g., `cai_a1b2`) is stored. This identifies which key was used in logs without exposing the full secret.

## Rate Limiting

All endpoints are rate-limited. Authenticated requests are limited by API key prefix. Unauthenticated requests are limited by IP address. When rate-limited, the response includes a `Retry-After` header.

## Allowed Sources

API keys can optionally restrict which alert sources they can ingest from:

```json theme={null}
{
  "name": "Sentinel-only key",
  "scopes": ["alerts:write"],
  "allowed_sources": ["sentinel"]
}
```

When `allowed_sources` is `null` (default), the key can ingest from any source.
