# Realtime

Real-time speech-to-text transcription over WebSocket.

```
wss://api.reson8.dev/v1/speech-to-text/realtime
```

## Request

### Headers

| Header                   | Value                                         |
|--------------------------|-----------------------------------------------|
| Authorization            | `ApiKey <api_key>` or `Bearer <access_token>` |
| Sec-WebSocket-Protocol   | `bearer, <access_token>`                      |

See [Authentication](../../documentation/general/authentication.md) for which header to use in different situations.

### Query Parameters

| Parameter               | Type    | Default | Description                                                |
|-------------------------|---------|---------|------------------------------------------------------------|
| `encoding`              | string  | `auto`  | Audio encoding: `auto` or `pcm_s16le`                      |
| `sample_rate`           | number  | `16000` | Sample rate in Hz (only used depending on encoding)        |
| `channels`              | number  | `1`     | Number of audio channels (only used depending on encoding) |
| `language`              | string  |         | Language to transcribe. Recommended for best quality. When omitted, the server auto-detects each utterance independently. See [Languages](../../documentation/speech-to-text/languages.md) for supported codes |
| `custom_model_id`       | string  |         | Optional. ID of a [custom model](../custom-model/create.md) to bias transcription. Overrides the model configured on the API client |
| `include_timestamps`    | boolean | `false` | Include `start_ms` and `duration_ms` on transcripts and words |
| `include_words`         | boolean | `false` | Include word-level detail on transcripts                   |
| `include_confidence`    | boolean | `false` | Include `confidence` on words                              |
| `include_interim`       | boolean | `false` | Include interim (partial) results and the `is_final` flag  |

### Example

=== "Python"

    ```python
    import asyncio
    import websockets

    async def transcribe():
        url = "wss://api.reson8.dev/v1/speech-to-text/realtime"
        headers = {"Authorization": "ApiKey <your_api_key>"}

        async with websockets.connect(url, additional_headers=headers) as ws:
            # Send audio data and control messages...

            async for message in ws:
                print(message)

    asyncio.run(transcribe())
    ```

=== "JavaScript (Browser)"

    ```javascript
    const token = "<your_access_token>";
    const url = "wss://api.reson8.dev/v1/speech-to-text/realtime";

    // Passes token via Sec-WebSocket-Protocol header
    const ws = new WebSocket(url, ["bearer", token]);

    ws.onopen = () => {
      // Send audio data and control messages...
    };

    ws.onmessage = (event) => {
      console.log(event.data);
    };
    ```

## Sending Messages

### Audio

Binary WebSocket frame containing audio data.

### Flush Request

Force the server to finalize any buffered audio and return a transcript.

```json
{
  "type": "flush_request",
  "id": "abc123"
}
```

| Field | Type   | Required | Description                                                       |
|-------|--------|----------|-------------------------------------------------------------------|
| `id`  | string | No       | Optional identifier, returned in the flush corresponding response |

## Receiving Messages

### Transcript

Returned when speech is recognized. By default, only final results are returned. When `include_interim=true`, interim (partial) results are also returned — these may change as more audio is processed.

=== "Default"

    ```json
    {
      "type": "transcript",
      "text": "the patient presented with chest pain"
    }
    ```

=== "Everything Included"

    ```json
    {
      "type": "transcript",
      "text": "the patient presented with chest pain",
      "is_final": true,
      "start_ms": 1200,
      "duration_ms": 2400,
      "words": [
        { "text": "the", "start_ms": 1200, "duration_ms": 200, "confidence": -0.010 },
        { "text": "patient", "start_ms": 1410, "duration_ms": 450, "confidence": -0.020 },
        { "text": "presented", "start_ms": 1880, "duration_ms": 500, "confidence": -0.030 },
        { "text": "with", "start_ms": 2400, "duration_ms": 200, "confidence": -0.010 },
        { "text": "chest", "start_ms": 2620, "duration_ms": 350, "confidence": -0.041 },
        { "text": "pain", "start_ms": 3000, "duration_ms": 600, "confidence": -0.030 }
      ]
    }
    ```

| Field         | Type    | Included                         | Description                           |
|---------------|---------|----------------------------------|---------------------------------------|
| `text`        | string  | Always                           | The recognized text                   |
| `is_final`    | boolean | When `include_interim=true`      | `true` for final, `false` for interim |
| `start_ms`    | number  | When `include_timestamps=true`   | Start time in milliseconds            |
| `duration_ms` | number  | When `include_timestamps=true`   | Duration in milliseconds              |
| `words`       | array   | When `include_words=true`        | Word-level detail                     |

Each word contains:

| Field         | Type   | Included                         | Description                |
|---------------|--------|----------------------------------|----------------------------|
| `text`        | string | Always                           | The recognized word        |
| `start_ms`    | number | When `include_timestamps=true`     | Start time in milliseconds |
| `duration_ms` | number | When `include_timestamps=true`  | Duration in milliseconds   |
| `confidence`  | number | When `include_confidence=true`   | Natural log-probability (≤ 0); apply `exp` for probability in `(0, 1]` |

### Flush Confirmation

Sent after a flush request has been processed. Includes the `id` if one was provided in the request.

```json
{
  "type": "flush_confirmation",
  "id": "abc123"
}
```

| Field | Type   | Included | Description                                            |
|-------|--------|----------|--------------------------------------------------------|
| `id`  | string | Always   | The identifier from the corresponding flush request, or `null` if none was provided |

## Errors

| Status | Code              | Description                   |
|--------|-------------------|-------------------------------|
| 400    | `INVALID_REQUEST` | Missing or invalid parameters |
| 401    | `UNAUTHORIZED`    | Invalid or expired credentials |
| 500    | `INTERNAL_ERROR`  | Unexpected server error       |
