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

# Stream transcription

> WebSocket protocol reference for real-time PCM audio streaming and transcription.

`wss://api.typelessapi.com/v1/transcribe/stream`

WebSocket endpoint for streaming PCM audio; authentication and all options are passed as query parameters at handshake time.

## Query parameters

<ParamField query="token" type="string" required>
  Your API key. See [Authentication](/authentication).
</ParamField>

<ParamField query="model" type="string" required>
  Model tier. One of `typeless-1.0-lite`, `typeless-1.0-pro`, `typeless-1.0-max`. See [Models & Pricing](/models-pricing).
</ParamField>

<ParamField query="sample_rate" type="integer" default="16000">
  PCM sample rate in Hz. Allowed range: 8000–48000.
</ParamField>

<ParamField query="channels" type="integer" default="1">
  Number of audio channels. 1 or 2.
</ParamField>

<ParamField query="encoding" type="string" default="pcm16">
  Audio encoding. Only `pcm16` (16-bit little-endian PCM) is supported.
</ParamField>

<ParamField query="language" type="string">
  Optional ISO 639-1 language hint. When omitted — or when an unsupported/unrecognized code is supplied — the language is detected automatically.
</ParamField>

## Client → server messages

**Binary frames**: send raw little-endian `pcm16` audio bytes as WebSocket binary frames; the server buffers and processes them in the order received.

**keep\_alive** — resets the 60-second idle timer; does **not** extend the 10-second first-frame deadline.

```json theme={null}
{"type": "keep_alive"}
```

**close\_stream** — signals no more audio; the server finalizes and returns the result.

```json theme={null}
{"type": "close_stream"}
```

## Server → client messages

**result** — sent once after finalization; the server closes the connection immediately after.

```json theme={null}
{
  "type": "result",
  "status": "success",
  "result": {
    "transcript": "Let's move the launch to next Thursday and loop in the design team early.",
    "detected_language": "en",
    "duration_seconds": 42.5
  },
  "usage": {
    "billed_audio_seconds": 42.5,
    "output_token_count": 128
  },
  "request_id": "01JXXXXXXXXXXXXXXXXXXXXXXX"
}
```

**error** — sent when a fatal error occurs; after an `error` message the server closes the connection.

```json theme={null}
{
  "type": "error",
  "status": "error",
  "error": {
    "code": "SERVICE_UNAVAILABLE",
    "message": "Service temporarily unavailable"
  },
  "request_id": "01JXXXXXXXXXXXXXXXXXXXXXXX"
}
```

## Timeouts

| Timer             | Value                               | Behavior                                                                                    |
| ----------------- | ----------------------------------- | ------------------------------------------------------------------------------------------- |
| First audio frame | 10 s from connect                   | Connection closes if no binary frame arrives; `keep_alive` does not extend this deadline    |
| Idle              | 60 s                                | Reset by any audio frame or `keep_alive`; connection closes on expiry                       |
| Finalization      | typically seconds, up to \~1 minute | After `close_stream`, the server drains remaining audio and refinement, then sends `result` |

## Connection close semantics

* **Normal**: server sends `result`, then closes.
* **Error**: server sends `error`, then closes.
* **Client disconnect**: if transcription has already started, you are billed for the audio sent (15-second minimum).

## Endpoint-specific errors

| Code                        | When                                                                        |
| --------------------------- | --------------------------------------------------------------------------- |
| `CONCURRENT_LIMIT_EXCEEDED` | Handshake rejected — too many open connections (429)                        |
| `INVALID_REQUEST`           | Invalid handshake parameters, or missing/unknown `model`                    |
| `CLIENT_DISCONNECTED`       | You disconnected mid-stream — recorded in usage logs, not sent as a message |

See the full table in [Errors](/reference/errors).

## Concurrency

Each account allows 10 concurrent connections by default; exceeding it fails the handshake with `CONCURRENT_LIMIT_EXCEEDED` — see [Rate limits](/reference/rate-limits).
