WebSocket Messages
All media-stream traffic is JSON over the WebSocket. Two message types flow in (Teler → your bridge) and three flow out (your bridge → Teler).
Incoming (Teler → your bridge)
Section titled “Incoming (Teler → your bridge)”The first message on every connection. Contains stream metadata. Use it to
correlate the WebSocket with a call_id and to check the audio format Teler
is using.
{ "type": "start", "account_id": "<uuid>", "call_app_id": "<uuid>", "call_id": "<uuid>", "stream_id": "<uuid>", "message_id": 1, "data": { "encoding": "audio/l16", "sample_rate": 8000, "channels": 1 }}| Field | Type | Description |
|---|---|---|
type | string | Always "start". |
account_id | UUID | Your Teler account ID. |
call_app_id | UUID | The Voice App ID this call belongs to. |
call_id | UUID | The active call’s ID. Matches call_id in webhooks. |
stream_id | UUID | This media stream’s ID. Use it for correlation. |
message_id | integer | Monotonic per-stream message counter. start is 1. |
data.encoding | enum | Currently always "audio/l16". |
data.sample_rate | integer | Currently always 8000, even when the Stream flow is configured "16k". |
data.channels | integer | Always 1 (mono). |
Repeated for the lifetime of the call. Each message carries one chunk of caller audio, base64-encoded.
{ "type": "audio", "stream_id": "<uuid>", "message_id": 2, "data": { "audio_b64": "<BASE64_ENCODED_AUDIO_CHUNK>" }}| Field | Type | Description |
|---|---|---|
type | string | Always "audio". |
stream_id | UUID | Same as in the start message. |
message_id | integer | Monotonic per-stream counter. |
data.audio_b64 | string | Base64-encoded PCM chunk. Decode → 16-bit linear PCM at the negotiated sample rate. |
The duration of each chunk equals the chunk_size from your Stream flow
(default 400 ms). At 16 kHz mono, that’s chunk_size_ms × 16 × 2 bytes per
chunk after decoding.
Outgoing (your bridge → Teler)
Section titled “Outgoing (your bridge → Teler)”Queue an audio chunk for playback into the call.
{ "type": "audio", "audio_b64": "<BASE64_ENCODED_AUDIO_CHUNK>", "chunk_id": "123"}| Field | Type | Required | Description |
|---|---|---|---|
type | string | yes | Always "audio". |
audio_b64 | string | yes | Base64-encoded 16-bit linear PCM at the negotiated sample rate. |
chunk_id | string | yes | Your identifier for this chunk. Used by interrupt. Must be unique per stream. |
interrupt
Section titled “interrupt”Stop playback of a specific queued chunk and any chunks queued after it. Use this to implement barge-in when the caller starts speaking over the agent.
{ "type": "interrupt", "chunk_id": "123"}| Field | Type | Required | Description |
|---|---|---|---|
type | string | yes | Always "interrupt". |
chunk_id | string | yes | The chunk_id from the outgoing audio message you want to stop. |
Drop all queued audio chunks immediately. Use when the conversation context changes (e.g., the model decides to start over).
{ "type": "clear"}| Field | Type | Required | Description |
|---|---|---|---|
type | string | yes | Always "clear". |
Connection lifecycle
Section titled “Connection lifecycle”| Event | Cause |
|---|---|
| WebSocket opens | Teler connects to your ws_url after a stream Call Flow. |
| First message in | Teler sends start. |
| Connection close (clean) | Caller hangs up, or Teler sends final audio and closes. A stream.completed webhook fires. |
| Connection close (error) | Network failure or your bridge closes. Teler tears down the stream connection. A call.failed webhook may follow only if the underlying call itself fails. |