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

# Realtime WebSocket events

> Client and server event contracts for the Realtime WebSocket API.

The Realtime WebSocket API creates a real-time speech translation session over a single WebSocket connection. The client sends a session configuration first, then streams microphone audio with JSON events that contain base64-encoded audio. The server responds with session lifecycle events, transcripts, translated text, and translated audio.

For the interactive WebSocket playground, see [Realtime (WebSocket)](/api-reference/websockets/realtime).

## Endpoint

```http theme={null}
GET /v1/realtime?model=lilac
Host: realtime.camb.ai
x-api-key: <YOUR_API_KEY>
```

The request upgrades to a WebSocket connection. The `model` query parameter is optional.

| Model    | Notes                     |
| -------- | ------------------------- |
| `lilac`  | Default model.            |
| `violet` | Supported realtime model. |
| `iris`   | Supported realtime model. |
| `orchid` | Supported realtime model. |

<Info>
  If `session.update.session.model` is omitted, the server uses the `model` query parameter. If both are omitted, the server uses `lilac`.
</Info>

## Session lifecycle

<Steps>
  <Step title="Open the WebSocket">
    Connect to `wss://realtime.camb.ai/v1/realtime`. Send your API key in the `x-api-key` request header when your WebSocket client supports custom headers.
  </Step>

  <Step title="Send `session.update` first">
    The first WebSocket message must be a JSON `session.update` event. The server waits up to 10 seconds for this initial event.
  </Step>

  <Step title="Wait for session activation">
    After authorization and activation, the server sends `session.created`, followed by `session.updated`.
  </Step>

  <Step title="Stream microphone audio">
    Send base64-encoded audio chunks with `input_audio_buffer.append`. The server forwards decoded audio bytes into the realtime pipeline.
  </Step>

  <Step title="Read realtime output">
    The server emits completed input transcripts, translated text deltas, final translated text, translated audio chunks, and audio completion events.
  </Step>
</Steps>

Only text WebSocket messages are parsed as realtime events. Binary messages and Pong frames are ignored. Ping frames receive Pong replies.

## Authentication

Prefer the `x-api-key` WebSocket request header.

```http theme={null}
x-api-key: <YOUR_API_KEY>
```

You can also send credentials in the initial `session.update` event.

<CodeGroup>
  ```json API key auth theme={null}
  {
    "type": "session.update",
    "session": {
      "model": "lilac",
      "source_language": "en-US",
      "target_language": "de-DE",
      "output_modalities": ["text", "audio"]
    },
    "auth": {
      "api_key": "<YOUR_API_KEY>"
    }
  }
  ```
</CodeGroup>

<Info>
  If the request header and `auth` object are both present, the request header credential is used.
</Info>

## Limits

| Limit                                                         | Value                      |
| ------------------------------------------------------------- | -------------------------- |
| Initial `session.update` timeout                              | 10 seconds                 |
| Maximum client event text size                                | 1 MiB                      |
| Maximum decoded audio payload per `input_audio_buffer.append` | 256 KiB                    |
| Audio encoding in `input_audio_buffer.append.audio`           | Base64-encoded audio bytes |

## Session configuration

Send the active session settings in `session.update.session`.

```json theme={null}
{
  "model": "lilac",
  "source_language": "en-US",
  "target_language": "de-DE",
  "output_modalities": ["text", "audio"]
}
```

| Field               | Type      | Required | Notes                                                                                                         |
| ------------------- | --------- | -------- | ------------------------------------------------------------------------------------------------------------- |
| `model`             | string    | No       | Defaults to the `model` query parameter, then `lilac`. Must be one of `lilac`, `violet`, `iris`, or `orchid`. |
| `source_language`   | string    | Yes      | Source language tag, for example `en-US`.                                                                     |
| `target_language`   | string    | Yes      | Target language tag, for example `de-DE`.                                                                     |
| `output_modalities` | string\[] | No       | Defaults to `["text", "audio"]`.                                                                              |

## Client events

| Event                       | When to send it                  | Support                      |
| --------------------------- | -------------------------------- | ---------------------------- |
| `session.update`            | First message on the connection. | Required for activation.     |
| `input_audio_buffer.append` | After the session is active.     | Supported.                   |
| `input_audio_buffer.clear`  | Not available in this version.   | Recognized, returns `error`. |
| `input_audio_buffer.commit` | Not available in this version.   | Recognized, returns `error`. |
| `response.cancel`           | Not available in this version.   | Recognized, returns `error`. |

### `session.update`

Initializes the realtime session. This must be the first client event.

```json theme={null}
{
  "type": "session.update",
  "session": {
    "model": "lilac",
    "source_language": "en-US",
    "target_language": "de-DE",
    "output_modalities": ["text", "audio"]
  }
}
```

After activation, sending another `session.update` is recognized but not supported. The server responds with an `error` event.

```json theme={null}
{
  "type": "error",
  "error": {
    "message": "session.update after activation is not supported in this version"
  }
}
```

### `input_audio_buffer.append`

Appends audio bytes to the realtime input stream.

```json theme={null}
{
  "type": "input_audio_buffer.append",
  "audio": "<base64_audio_bytes>"
}
```

The server base64-decodes `audio` and forwards the decoded bytes into the realtime pipeline. Each decoded payload can be up to 256 KiB.

### Unsupported client events

These events are recognized so clients can receive a structured error instead of silent failure.

<AccordionGroup>
  <Accordion title="input_audio_buffer.clear">
    ```json theme={null}
    {
      "type": "input_audio_buffer.clear"
    }
    ```

    Server response:

    ```json theme={null}
    {
      "type": "error",
      "error": {
        "message": "input_audio_buffer.clear is not supported in this version"
      }
    }
    ```
  </Accordion>

  <Accordion title="input_audio_buffer.commit">
    ```json theme={null}
    {
      "type": "input_audio_buffer.commit"
    }
    ```

    Server response:

    ```json theme={null}
    {
      "type": "error",
      "error": {
        "message": "input_audio_buffer.commit is not supported in this version"
      }
    }
    ```
  </Accordion>

  <Accordion title="response.cancel">
    ```json theme={null}
    {
      "type": "response.cancel"
    }
    ```

    Server response:

    ```json theme={null}
    {
      "type": "error",
      "error": {
        "message": "response.cancel is not supported in this version"
      }
    }
    ```
  </Accordion>
</AccordionGroup>

## Server events

| Event                                                   | Description                                                                                    |
| ------------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
| `session.created`                                       | Sent after the server authorizes, starts, and activates the realtime session.                  |
| `session.updated`                                       | Sent immediately after `session.created` with the active session configuration.                |
| `conversation.item.input_audio_transcription.completed` | Sent when the pipeline produces a completed user transcript.                                   |
| `response.text.delta`                                   | Sent for incremental assistant translation text. Deltas are additive for the current response. |
| `response.text.done`                                    | Sent when the final assistant translation text is available.                                   |
| `response.audio.delta`                                  | Sent when synthesized output audio bytes are available.                                        |
| `response.audio.done`                                   | Sent when the current assistant audio response is complete.                                    |
| `error`                                                 | Sent for recognized unsupported client events and billing stop decisions.                      |

### Session events

`session.created` includes the durable realtime session ID.

```json theme={null}
{
  "type": "session.created",
  "session": {
    "id": "2a4d3cb0-ff62-4e02-a37c-9fcf4e49c8cc",
    "model": "lilac",
    "source_language": "en-US",
    "target_language": "de-DE",
    "output_modalities": ["text", "audio"]
  }
}
```

`session.updated` confirms the active session configuration.

```json theme={null}
{
  "type": "session.updated",
  "session": {
    "model": "lilac",
    "source_language": "en-US",
    "target_language": "de-DE",
    "output_modalities": ["text", "audio"]
  }
}
```

| Field                       | Type        | Notes                                                      |
| --------------------------- | ----------- | ---------------------------------------------------------- |
| `session.id`                | UUID string | Durable realtime session ID. Present on `session.created`. |
| `session.model`             | string      | Active realtime model.                                     |
| `session.source_language`   | string      | Source language tag.                                       |
| `session.target_language`   | string      | Target language tag.                                       |
| `session.output_modalities` | string\[]   | Active output modalities.                                  |

### Transcript and response events

```json theme={null}
{
  "type": "conversation.item.input_audio_transcription.completed",
  "transcript": "Hello, how are you?"
}
```

```json theme={null}
{
  "type": "response.text.delta",
  "delta": "Guten"
}
```

```json theme={null}
{
  "type": "response.text.done",
  "text": "Guten Tag, wie geht es Ihnen?"
}
```

```json theme={null}
{
  "type": "response.audio.delta",
  "delta": "<base64_audio_bytes>"
}
```

```json theme={null}
{
  "type": "response.audio.done"
}
```

### Errors and billing stops

The server sends `error` for recognized but unsupported client events.

```json theme={null}
{
  "type": "error",
  "error": {
    "message": "input_audio_buffer.commit is not supported in this version"
  }
}
```

Billing can also stop a session. In that case, the server sends an `error` event whose `error.message` is the billing close reason, then ends the realtime loop. Active sessions are charged in billing windows and finalized on close, failure, or billing stop.

## Example message flow

<CodeGroup>
  ```json Client: session.update theme={null}
  {
    "type": "session.update",
    "session": {
      "model": "lilac",
      "source_language": "en-US",
      "target_language": "de-DE",
      "output_modalities": ["text", "audio"]
    }
  }
  ```

  ```json Server: session.created theme={null}
  {
    "type": "session.created",
    "session": {
      "id": "2a4d3cb0-ff62-4e02-a37c-9fcf4e49c8cc",
      "model": "lilac",
      "source_language": "en-US",
      "target_language": "de-DE",
      "output_modalities": ["text", "audio"]
    }
  }
  ```

  ```json Server: session.updated theme={null}
  {
    "type": "session.updated",
    "session": {
      "model": "lilac",
      "source_language": "en-US",
      "target_language": "de-DE",
      "output_modalities": ["text", "audio"]
    }
  }
  ```

  ```json Client: append audio theme={null}
  {
    "type": "input_audio_buffer.append",
    "audio": "<base64_audio_bytes>"
  }
  ```

  ```json Server: transcript theme={null}
  {
    "type": "conversation.item.input_audio_transcription.completed",
    "transcript": "Hello, how are you?"
  }
  ```

  ```json Server: text delta theme={null}
  {
    "type": "response.text.delta",
    "delta": "Guten Tag"
  }
  ```

  ```json Server: text done theme={null}
  {
    "type": "response.text.done",
    "text": "Guten Tag, wie geht es Ihnen?"
  }
  ```

  ```json Server: audio delta theme={null}
  {
    "type": "response.audio.delta",
    "delta": "<base64_audio_bytes>"
  }
  ```

  ```json Server: audio done theme={null}
  {
    "type": "response.audio.done"
  }
  ```
</CodeGroup>
