> For complete lifecycle-event payload schemas and examples, use the canonical overview: Session /api/sessions; Room lifecycle, members, and room playback /api/rooms; Session playback /api/playback; Recording /api/recording; DTMF /api/keypad-input; Messages /api/messages; WebSocket Session /api/web-socket. Use /api/event-delivery for transport behavior. Endpoint pages name relevant events, but these overviews are the canonical references.

# WebSocket overview

> Complete WebSocket Session connection and lifecycle-event reference.

A WebSocket Session is a media-only participant backed by a
connection to your WebSocket server. Create one with [`POST
/v1/sessions:connectWebsocket`](/api/sessions/connect-websocket) when your
application needs to exchange live audio without creating a phone call.

## When to use

Use WebSocket to connect a real-time voice application, such as a voice agent
or live transcription service, to a conversation.

## Use the Session in a Room

Add the WebSocket Session and one or more phone Sessions to a
[Room](/api/rooms) to build a bidirectional voice agent. Your server receives
audio from the WebSocket Session and sends audio back through the same
connection. The Room connects that media to the other participants.

## Connection lifecycle

The create request returns a Session in the `connecting` state while the
platform opens the WebSocket connection. The Session becomes `answered` after
your server accepts the connection. If the connection fails or closes, the
WebSocket Session ends.

Follow the lifecycle events on this page to observe connection success,
connection failure, disconnection, and completion of buffered audio playback.
Follow [Session lifecycle events](/api/sessions#lifecycle-events) for the
complete WebSocket Session lifecycle.

## Audio format

The Session exchanges raw mono audio in binary WebSocket messages without a
WAV header. The required `media_format` object configures each direction from
the Session's perspective:

* `from_session` describes audio that the platform sends from the Session to
  your WebSocket server.
* `to_session` describes audio that your WebSocket server sends to the Session.

Each direction independently accepts signed 16-bit little-endian PCM at a
supported multiple of 8 kHz, or G.711 mu-law at 8 kHz. The two directions can
use different formats. See [WebSocket audio formats](/formats#websocket-audio)
for the supported matrix and [`POST
/v1/sessions:connectWebsocket`](/api/sessions/connect-websocket) for the complete
request schema.

The platform exchanges raw audio only. It does not implement Twilio Media
Streams JSON envelopes, base64 payloads, or control messages.

## Lifecycle events

These events report the WebSocket connection owned by a
`type: "websocket"` Session created through [`POST
/v1/sessions:connectWebsocket`](/api/sessions/connect-websocket). The wire event
names use the `websocket.*` namespace.

All webhook deliveries are signed. See [Verifying
signatures](/api/event-delivery#signature-verification) before processing an event.

Every event contains these fields. `operation_uuid` is optional; all other
fields are required.

| Field            | Type   | Description                                                                        |
| ---------------- | ------ | ---------------------------------------------------------------------------------- |
| `aud`            | string | Application UUID that identifies the intended recipient.                           |
| `event`          | string | Exact event name documented in the corresponding section.                          |
| `session_uuid`   | string | WebSocket Session identifier.                                                      |
| `operation_uuid` | string | Originating WebSocket operation identifier. Present when correlation is available. |
| `timestamp`      | string | RFC 3339 UTC event time with a `Z` suffix.                                         |

## websocket.connected

Fires when the WebSocket server accepts the connection. The WebSocket Session
then advances from `connecting` to `answered` without emitting
`session.answered`.

```json
{
  "aud": "app_3f9c0b2a-7d41-4e8b-9f12-2a6c5d0e7b34",
  "event": "websocket.connected",
  "session_uuid": "acW68-f47ac10b-58cc-4372-a567-0e02b2c3d479",
  "operation_uuid": "550e8400-e29b-41d4-a716-446655440000",
  "timestamp": "2026-08-23T08:53:20.000Z"
}
```

## websocket.disconnected

Fires when an established connection closes unexpectedly or the WebSocket
server initiates the close. The event also contains:

| Field    | Type    | Description                                                       |
| -------- | ------- | ----------------------------------------------------------------- |
| `code`   | integer | WebSocket close code, or `0` when unavailable.                    |
| `reason` | string  | Human-readable close reason, or an empty string when unavailable. |

```json
{
  "aud": "app_3f9c0b2a-7d41-4e8b-9f12-2a6c5d0e7b34",
  "event": "websocket.disconnected",
  "session_uuid": "acW68-f47ac10b-58cc-4372-a567-0e02b2c3d479",
  "operation_uuid": "550e8400-e29b-41d4-a716-446655440000",
  "code": 1000,
  "reason": "bye",
  "timestamp": "2026-08-23T08:54:20.000Z"
}
```

The WebSocket Session ends after this event, and a
[`session.ended`](/api/sessions#sessionended) event follows.

## websocket.failed

Fires when the connection cannot become usable. The event also contains:

| Field         | Type    | Description                                                                                                                                     |
| ------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| `error`       | string  | Sanitized category: `handshake_failed` or `connection_failed`.                                                                                  |
| `http_status` | integer | WebSocket handshake response status, or `0` when no response was available.                                                                     |
| `reason`      | string  | Stable reason: `session_codec_unsupported`, `destination_unreachable`, `tls_failed`, `handshake_rejected`, or `connection_precondition_failed`. |

```json
{
  "aud": "app_3f9c0b2a-7d41-4e8b-9f12-2a6c5d0e7b34",
  "event": "websocket.failed",
  "session_uuid": "acW68-f47ac10b-58cc-4372-a567-0e02b2c3d479",
  "operation_uuid": "550e8400-e29b-41d4-a716-446655440000",
  "error": "handshake_failed",
  "http_status": 403,
  "reason": "handshake_rejected",
  "timestamp": "2026-08-23T08:53:20.000Z"
}
```

The WebSocket Session ends after this event, and a
[`session.ended`](/api/sessions#sessionended) event follows.

## websocket.audio\_playback\_completed

Fires when the platform reports that all buffered audio received from the
WebSocket server has played and the buffer is idle. The event also contains:

| Field       | Type    | Description                                                               |
| ----------- | ------- | ------------------------------------------------------------------------- |
| `played_ms` | integer | Milliseconds of server audio reported as played, or `0` when unavailable. |

```json
{
  "aud": "app_3f9c0b2a-7d41-4e8b-9f12-2a6c5d0e7b34",
  "event": "websocket.audio_playback_completed",
  "session_uuid": "acW68-f47ac10b-58cc-4372-a567-0e02b2c3d479",
  "operation_uuid": "550e8400-e29b-41d4-a716-446655440000",
  "played_ms": 1840,
  "timestamp": "2026-08-23T08:54:22.000Z"
}
```

Treat this as a lifecycle signal from the platform. A successful WebSocket
connection or this event alone does not prove that another participant received
non-silent audio.