# Authentication

> API keys plus your Account ID on every request.

The Agent API uses **API keys** created in the [Console](https://console.clatterlabs.com/api-keys). Each request carries two headers:

<ParamField header="Authorization" type="string" required>
`Bearer clsk_...`: your API key.
</ParamField>
<ParamField header="X-Clatter-Account" type="string" required>
The Account ID that owns the key, like `CL-7K2M9QXA` (Console › Settings). Matching is case-insensitive.
</ParamField>

```bash
curl https://api.agent.clatterlabs.xyz/agent-config \
  -H "Authorization: Bearer $CLATTER_API_KEY" \
  -H "X-Clatter-Account: $CLATTER_ACCOUNT_ID"
```

## Why two headers

A key alone isn't enough: the request must also name the account that owns it. A key that leaks without its Account ID can't be used, and a key sent with someone else's Account ID is refused.

| Situation | Response |
| --- | --- |
| No `X-Clatter-Account` | `401 missing_account_id` |
| Account ID doesn't own the key | `401 account_mismatch` |
| Key wrong or revoked | `401 invalid_api_key` |
| Key lacks the permission | `403 insufficient_scope` |

## Permissions

| Permission | Endpoints |
| --- | --- |
| `runs:write` | `POST /v1/runs`, `POST /v1/runs/{id}/cancel` |
| `runs:read` | `GET /v1/runs`, `GET /v1/runs/{id}`, `GET /v1/runs/{id}/events` |
| `account:read` | `GET /v1/account` |

`GET /agent-config` needs no key; with one it also describes the key.

## CORS

The API allows cross-origin requests, which is what makes **Try it** work. That doesn't make it safe to put keys in front-end code: call the API from your server.
