> 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.

# Room

> Complete Room resource and event reference for room lifecycle, members, and room playback.

A `Room` is a shared audio resource identified by `room_id`. The full resource
returned by the get method reflects room playback and a room
[Recording](/api/recording).

## When to use

Use a Room to connect two or more Sessions in one conversation, such as a caller
and an agent or a group call.

## Room lifecycle

Use the events on this page to react to creation, confirmed deletion,
membership changes, and room playback outcomes. Use the get method to reconcile
the latest Room state after a missed event.

## Methods

* [Create a room](api:voice-api:POST/api/v1/rooms)
* [List rooms](api:voice-api:GET/api/v1/rooms)
* [Get room details](api:voice-api:GET/api/v1/rooms/\{room_id})
* [Delete a room](api:voice-api:DELETE/api/v1/rooms/\{room_id})

The list method returns a `RoomSummary` projection for each room. Use the get
method when you need the complete `Room` representation shown below.

## Enable member voice-activity events

Room voice-activity events are opt-in. To receive
[`room.member.voice_activity_changed`](/api/rooms#roommembervoice_activity_changed)
events when members start and stop talking, create the Room with
`voice_activity_events` set to `true`:

```json
{
  "voice_activity_events": true
}
```

If you omit `voice_activity_events` or set it to `false`, the Room does not emit
voice-activity events. The `voice_activity_events` property on the Room resource
reports the value selected when the Room was created.

## Resource representation

### The Room resource

```json
{
  "created_at": "2023-01-01T00:00:00Z",
  "member_count": 0,
  "playback_operation_uuid": "string",
  "playback_status": "stopped",
  "playback_urls": [
    "string"
  ],
  "playback_volume": 0,
  "room_id": "string",
  "voice_activity_events": true
}
```

## Properties

### Schema (`Room`)

```yaml
components:
  schemas:
    RoomPlaybackStatus:
      type: string
      enum:
        - stopped
        - playing
        - paused
      title: RoomPlaybackStatus
    Room:
      type: object
      properties:
        created_at:
          type: string
          format: date-time
        member_count:
          type: integer
          description: Current number of members in the room.
        playback_operation_uuid:
          type: string
        playback_status:
          $ref: '#/components/schemas/RoomPlaybackStatus'
        playback_urls:
          type: array
          items:
            type: string
            format: uri
        playback_volume:
          type: integer
          minimum: 0
          maximum: 200
          default: 0
          description: |-
            Current room playback volume (0-200). A newly created room reports
            `0` until a room playback volume command sets an explicit value.
        room_id:
          type: string
        voice_activity_events:
          type: boolean
          description: Whether member voice activity webhooks are enabled for this room.
      required:
        - created_at
        - member_count
        - playback_operation_uuid
        - playback_status
        - playback_urls
        - playback_volume
        - room_id
        - voice_activity_events
      title: Room
```

## Lifecycle, member, and playback events

Use room events to track room lifecycle, membership, and playback.

**Event ordering:** All `room.*` events for this Room, including events for
different members, are delivered in production order. Failures hold this Room,
not other Rooms. See [Ordering guarantees](/api/event-delivery#ordering-guarantees).

**Event envelope:** Every room event also includes a `timestamp`: the emission
time as an RFC 3339 / ISO 8601 UTC string, such as
`"2026-06-28T14:30:00.000Z"`. Treat this value as event-time metadata, not as a
total-order key.

Delivery requests carry W3C trace context in their headers.

**Member identity:** Room membership events identify a member by `session_uuid`.
For an inbound Session, the caller number is available on its `session.created`
webhook. For an outbound Session, use the caller number from your dial request.

## room.created

The platform emits this event when `POST /api/v1/rooms` creates a room.

| Field      | Type   | Description                                                                                         |
| ---------- | ------ | --------------------------------------------------------------------------------------------------- |
| `event`    | string | Always `"room.created"`. **Required**                                                               |
| `app_uuid` | string | Platform-generated identifier (`app_<uuid-v4>`) of the application that owns the room. **Required** |
| `room_id`  | string | Unique room identifier. **Required**                                                                |

```json
{
  "aud": "app_3f9c0b2a-7d41-4e8b-9f12-2a6c5d0e7b34",
  "event": "room.created",
  "app_uuid": "app_3f9c0b2a-7d41-4e8b-9f12-2a6c5d0e7b34",
  "room_id": "acW68-room-550e8400-e29b-41d4-a716-446655440000",
  "timestamp": "2026-06-28T14:30:00.000Z"
}
```

## room.deleted

The platform emits this event after processing a room deletion request.
`DELETE /api/v1/rooms/{room_id}` first returns `202 Accepted` with
`{"room_id": "...", "status": "deleting"}`. This response only acknowledges
that the request was admitted.

The event arrives when the platform confirms that the room is gone
(`reason: "closed"`) or when that confirmation times out (`reason: "timeout"`).
The `reason` field is always present.

| Field      | Type   | Description                                                                                                                                                                            |
| ---------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `event`    | string | Always `"room.deleted"`. **Required**                                                                                                                                                  |
| `app_uuid` | string | Platform-generated identifier (`app_<uuid-v4>`) of the application that owned the room. **Required**                                                                                   |
| `room_id`  | string | Unique room identifier. **Required**                                                                                                                                                   |
| `reason`   | string | Why the room was torn down. One of `"closed"` (normal confirmed teardown) or `"timeout"` (the room was reaped after teardown confirmation never arrived). Always present. **Required** |

```json
{
  "aud": "app_3f9c0b2a-7d41-4e8b-9f12-2a6c5d0e7b34",
  "event": "room.deleted",
  "app_uuid": "app_3f9c0b2a-7d41-4e8b-9f12-2a6c5d0e7b34",
  "room_id": "acW68-room-550e8400-e29b-41d4-a716-446655440000",
  "reason": "closed",
  "timestamp": "2026-06-28T14:31:00.000Z"
}
```

## room.member.joined

The platform emits this event after a call joins a room. The join is
asynchronous: [`POST /api/v1/rooms/{room_id}/members`](/api/room-members/add)
returns `202 Accepted` with status `"joining"` when it accepts the request. Wait
for `room.member.joined` to confirm that the member is in the room.

| Field          | Type   | Description                                      |
| -------------- | ------ | ------------------------------------------------ |
| `event`        | string | Always `"room.member.joined"`. **Required**      |
| `session_uuid` | string | Session UUID of the joining member. **Required** |
| `room_id`      | string | Room identifier. **Required**                    |

```json
{
  "aud": "app_3f9c0b2a-7d41-4e8b-9f12-2a6c5d0e7b34",
  "event": "room.member.joined",
  "session_uuid": "acW68-f47ac10b-58cc-4372-a567-0e02b2c3d479",
  "room_id": "acW68-room-550e8400-e29b-41d4-a716-446655440000",
  "timestamp": "2026-06-28T14:32:00.000Z"
}
```

## room.member.left

The platform emits this event when a call leaves a room through
[`DELETE /api/v1/rooms/{room_id}/members/{uuid}`](/api/room-members/remove), is
kicked, or hangs up.

The `reason` value identifies how the member left:

* `"hangup"` means the member's channel hung up.
* `"removed"` means an explicit leave or kick through the room leave endpoint.
* `"orphan"` means the platform detected that the member's call had already
  gone away, typically because of a crash or dropped connection, and removed
  the stale membership. Treat this as an abnormal disconnect, not a clean
  leave.

| Field          | Type   | Description                                                                                   |
| -------------- | ------ | --------------------------------------------------------------------------------------------- |
| `event`        | string | Always `"room.member.left"`. **Required**                                                     |
| `session_uuid` | string | Session UUID of the departing member. **Required**                                            |
| `room_id`      | string | Room identifier. **Required**                                                                 |
| `reason`       | string | Departure trigger. Consumers should accept any string for forward compatibility. **Required** |

```json
{
  "aud": "app_3f9c0b2a-7d41-4e8b-9f12-2a6c5d0e7b34",
  "event": "room.member.left",
  "session_uuid": "acW68-f47ac10b-58cc-4372-a567-0e02b2c3d479",
  "room_id": "acW68-room-550e8400-e29b-41d4-a716-446655440000",
  "reason": "hangup",
  "timestamp": "2026-06-28T14:33:00.000Z"
}
```

## room.member.muted

The platform emits this event when the `room/mute` command mutes a member.

| Field          | Type   | Description                                    |
| -------------- | ------ | ---------------------------------------------- |
| `event`        | string | Always `"room.member.muted"`. **Required**     |
| `session_uuid` | string | Session UUID of the muted member. **Required** |
| `room_id`      | string | Room identifier. **Required**                  |

```json
{
  "aud": "app_3f9c0b2a-7d41-4e8b-9f12-2a6c5d0e7b34",
  "event": "room.member.muted",
  "session_uuid": "acW68-f47ac10b-58cc-4372-a567-0e02b2c3d479",
  "room_id": "acW68-room-550e8400-e29b-41d4-a716-446655440000",
  "timestamp": "2026-06-28T14:34:00.000Z"
}
```

## room.member.unmuted

The platform emits this event when the `room/unmute` command unmutes a member.

| Field          | Type   | Description                                      |
| -------------- | ------ | ------------------------------------------------ |
| `event`        | string | Always `"room.member.unmuted"`. **Required**     |
| `session_uuid` | string | Session UUID of the unmuted member. **Required** |
| `room_id`      | string | Room identifier. **Required**                    |

```json
{
  "aud": "app_3f9c0b2a-7d41-4e8b-9f12-2a6c5d0e7b34",
  "event": "room.member.unmuted",
  "session_uuid": "acW68-f47ac10b-58cc-4372-a567-0e02b2c3d479",
  "room_id": "acW68-room-550e8400-e29b-41d4-a716-446655440000",
  "timestamp": "2026-06-28T14:35:00.000Z"
}
```

## room.member.voice\_activity\_changed

The platform emits this event when a room member's
[voice activity detection (VAD)](https://en.wikipedia.org/wiki/Voice_activity_detection)
state changes. `talking: true` marks speech onset, and `talking: false` marks the
return to silence. During an active conversation, expect frequent events and
debounce them in your application.

VAD state is delivered via this webhook. The member object returned by [`GET /api/v1/rooms/{room_id}/members/{uuid}`](/api/room-members/get) contains only `{uuid, muted}`.

| Field          | Type    | Description                                                                     |
| -------------- | ------- | ------------------------------------------------------------------------------- |
| `event`        | string  | Always `"room.member.voice_activity_changed"`. **Required**                     |
| `session_uuid` | string  | Session UUID of the member whose VAD state changed. **Required**                |
| `room_id`      | string  | Room identifier. **Required**                                                   |
| `talking`      | boolean | `true` when the member started talking, `false` when they stopped. **Required** |

```json
{
  "aud": "app_3f9c0b2a-7d41-4e8b-9f12-2a6c5d0e7b34",
  "event": "room.member.voice_activity_changed",
  "session_uuid": "acW68-f47ac10b-58cc-4372-a567-0e02b2c3d479",
  "room_id": "acW68-room-550e8400-e29b-41d4-a716-446655440000",
  "talking": true,
  "timestamp": "2026-06-28T14:36:00.000Z"
}
```

## room.playback.ended

The platform emits this terminal event exactly once when room playback completes
naturally or stops through the API. For a multi-source playlist, the platform
emits one event after every source completes, not one event per source. Playback
failures and start-confirmation timeouts emit `room.playback.failed` instead.

| Field            | Type      | Description                                                                                                                                                                                                  |
| ---------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `event`          | string    | Always `"room.playback.ended"`. **Required**                                                                                                                                                                 |
| `room_id`        | string    | Room identifier. **Required**                                                                                                                                                                                |
| `operation_uuid` | string    | Correlation identifier echoed from the originating [play request](/api/room-playback/play)'s `202 Accepted` response. An API stop does not replace it with the stop command's correlation UUID. **Required** |
| `urls`           | string\[] | The complete original `urls` playlist from the room playback request, in request order. **Required**                                                                                                         |
| `reason`         | string    | Why playback ended: `"completed"` when every source finished naturally, or `"stopped"` when interrupted through the API. **Required**                                                                        |

```json
{
  "aud": "app_3f9c0b2a-7d41-4e8b-9f12-2a6c5d0e7b34",
  "event": "room.playback.ended",
  "room_id": "acW68-room-550e8400-e29b-41d4-a716-446655440000",
  "operation_uuid": "d4e5f6a7-b8c9-4123-8567-89abcdef0123",
  "urls": ["https://cdn.example.com/audio/announcement.wav"],
  "reason": "completed",
  "timestamp": "2026-06-28T14:37:00.000Z"
}
```

## room.playback.failed

The platform emits this event when room playback fails. A failure occurs when
the platform reports a playback error, any source in a multi-source playlist
fails, or the platform does not receive start confirmation within 10 seconds.

One failed source fails the entire operation. Playback that starts within the
10-second window can continue for longer without failing. This event resets
`playback_status` to `"stopped"` so the room can accept a new play.

| Field            | Type      | Description                                                                                                                                                                                  |
| ---------------- | --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `event`          | string    | Always `"room.playback.failed"`. **Required**                                                                                                                                                |
| `room_id`        | string    | Room identifier. **Required**                                                                                                                                                                |
| `operation_uuid` | string    | Non-empty lowercase UUID v4 echoed from the originating [play request](/api/room-playback/play)'s `202 Accepted` response. **Required**                                                      |
| `urls`           | string\[] | The complete original `urls` playlist from the room playback request, in request order. **Required**                                                                                         |
| `error`          | string    | Coarse-grained error bucket. One of `"playback_error"` (the platform reported a playback failure) or `"playback_timeout"` (playback start was not confirmed within 10 seconds). **Required** |

```json
{
  "aud": "app_3f9c0b2a-7d41-4e8b-9f12-2a6c5d0e7b34",
  "event": "room.playback.failed",
  "room_id": "acW68-room-550e8400-e29b-41d4-a716-446655440000",
  "operation_uuid": "d4e5f6a7-b8c9-4123-8567-89abcdef0123",
  "urls": ["https://cdn.example.com/audio/announcement.wav"],
  "error": "playback_timeout",
  "timestamp": "2026-06-28T14:38:00.000Z"
}
```

## Triggered by

These events are produced by the following endpoints:

* [`room.created`](#roomcreated) — [POST /rooms](/api/rooms/create).
* [`room.deleted`](#roomdeleted) — automatic: fires on confirmed teardown after [DELETE /rooms/\{room\_id}](/api/rooms/delete) returns `202 Accepted` (`reason: "closed"`), or with `reason: "timeout"` if confirmation never arrives.
* [`room.member.joined`](#roommemberjoined) — [POST /rooms/\{room\_id}/members](/api/room-members/add) (asynchronous).
* [`room.member.left`](#roommemberleft) — [DELETE /rooms/\{room\_id}/members/\{uuid}](/api/room-members/remove), or automatic on hangup.
* [`room.member.muted`](#roommembermuted) — [room/mute](/api/room-members/mute).
* [`room.member.unmuted`](#roommemberunmuted) — [room/unmute](/api/room-members/unmute).
* [`room.member.voice_activity_changed`](#roommembervoice_activity_changed) — automatic: VAD state change.
* [`room.playback.ended`](#roomplaybackended) — terminal: fires once when playback completes naturally or is stopped through the API.
* [`room.playback.failed`](#roomplaybackfailed) — automatic: fires on a playback failure or when the playback watchdog times out.

For room deletion, member volume, and room playback play, pause, resume, stop,
and volume commands, only the request's `202 Accepted` response acknowledges
admission.