# Authentication

API key headers, key management, and authentication errors.

## Auth headers

Every authenticated request carries your API key in a header. Both conventions are accepted everywhere, on every endpoint. Use whichever your client library already sends:

```
curl https://api.kenpathlabs.com/v1/audio/speech \
  -H "Authorization: Bearer $SVARA_API_KEY" \
  ...
```

```
curl https://api.kenpathlabs.com/v1/audio/speech \
  -H "xi-api-key: $SVARA_API_KEY" \
  ...
```

WebSocket connections authenticate the same way: send the header on the upgrade request. Discovery endpoints (`/v1/voices`, `/v1/languages`, `/v1/models`) are public and need no key.

> API keys are server-side credentials. Don’t embed them in web or mobile clients. Proxy TTS calls through your backend, or scope a low-limit key per environment.

## Managing keys

Keys are created and revoked in the [console under API keys](https://platform.kenpathlabs.com/dashboard/keys). Each key:

- is shown in full exactly once, at creation (we store only a hash)
- carries its own plan: concurrency, requests-per-minute, and monthly character limits are per key (see [Rate limits](https://docs.kenpathlabs.com/rate-limits.md))
- reports its own usage; the [usage page](https://platform.kenpathlabs.com/dashboard/usage) breaks down requests, characters, and audio minutes per key
- can be revoked instantly, without affecting your other keys

A common pattern: one key per environment (`prod`, `staging`) or per integration, named accordingly, so usage attribution and revocation stay surgical.

## Auth errors

Authentication failures return `401` with a structured body:

```json
{
  "detail": {
    "status": "invalid_api_key",
    "message": "API key invalid or revoked."
  }
}
```

| Parameter | Type | Default | Description |
|---|---|---|---|
| `missing_api_key` | 401 | - | No key found in either header. Send xi-api-key or Authorization: Bearer. |
| `invalid_api_key` | 401 | - | The key doesn’t exist or has been revoked. |

These shapes match what the official ElevenLabs SDKs expect, so their built-in error handling works unchanged.
