# Authentication

Every connection is tied to your account with an API key. There are two ways to
use it, depending on whether the code runs on **your server** or in an
**untrusted client** (a browser or mobile app).

## Server-side: your secret key

From your own backend, send your secret key in the `Authorization` header when
you open the connection:

```
Authorization: Bearer swaram_your_key_here
```

Your secret key looks like `swaram_…`, is shown once when you create it, and is
stored only as a hash — keep it on your server. **Never put a `swaram_` key in a
browser or app**, where a user could read it.

## Browser / mobile: a short-lived token

Untrusted clients shouldn't hold your secret key. Instead, your backend mints a
short-lived **ephemeral token** (it looks like `swaram_ek_…`) and hands only that
to the client. The token can carry locked settings — model, voice, instructions,
tools — that the client can't change, and it expires after a minute or so.

**1. On your backend**, exchange your secret key for a token:

```python
import httpx

resp = httpx.post(
    "https://api.swaram.live/v1/realtime/client_secrets",
    headers={"Authorization": "Bearer swaram_your_key_here"},
    json={
        "model": "mal-realtime-simple",
        "session": {
            "instructions": "You are a friendly Malayalam assistant.",
            "voice": "mal-female",
        },
    },
)
token = resp.json()["value"]   # a swaram_ek_… token — send THIS to the client
```

**2. In the client**, connect with that token. Browsers can't set headers on a
WebSocket, so pass it as a subprotocol:

```browser
const ws = new WebSocket(
  "wss://api.swaram.live/v1/realtime?model=mal-realtime-simple",
  ["realtime", "openai-insecure-api-key." + token]
);
```

A bad or expired token is rejected and the connection closes (code `4001`).

## How the key is read

The server looks for your credential in this order:

1. `Authorization: Bearer <key>` header — the server-side path.
2. `?api_key=<key>` query parameter.
3. `Sec-WebSocket-Protocol: openai-insecure-api-key.<key>` subprotocol — the browser path.

## Config at creation

Whichever path you use, send your configuration **at the start** — in the token,
or as the first `session.update` right after you connect. It's locked once the
conversation begins. See [Sessions & context](sessions.html) for the details.
