Room events
Room events cover room lifecycle, member management, and playback control within rooms.
Ordering note: Room lifecycle events (room.created, command.room.delete.accepted, room.deleted) and room playback events are not associated with a session_uuid. They have no ordering guarantee relative to session-scoped events.
Envelope: Like every webhook, each room event also carries a timestamp field (emission time as an RFC 3339 / ISO 8601 UTC string, e.g. "2026-06-28T14:30:00.000Z") in addition to the fields listed below. Treat it as event-time metadata, not as a guaranteed total-order key; room events do not have the per-session delivery-order guarantee. Delivery requests carry W3C trace context in headers. The example payloads omit these envelope fields for brevity.
room.created
Fired when a new room is created via POST /api/v1/rooms.
command.room.delete.accepted
Fired immediately when a room delete is requested via DELETE /api/v1/rooms/{room_id}. The delete endpoint returns 202 Accepted with body {"room_id": "...", "status": "deleting"}, acknowledging the request before teardown completes. A later room.deleted event confirms the room has actually been torn down.
room.deleted
Fired when a room has been torn down following a delete request. It is emitted on confirmation that the room is gone (reason: "closed"), or after a timeout if confirmation never arrives (reason: "timeout"). The reason field is always present and is one of these two values.
room.member.joined
Fired when a call joins a room. This event confirms the member has actually joined. The join is asynchronous: POST /api/v1/rooms/{room_id}/members returns 202 Accepted with status "joining" only as an acknowledgment that the request was accepted, while room.member.joined fires later, once the underlying system confirms the member is in the room.
Room membership is identified by session_uuid; the caller number is available on the inbound call.created or outbound command.call.dial.accepted webhook for that session.
room.member.left
Fired when a call leaves a room, whether by DELETE /api/v1/rooms/{room_id}/members/{uuid}, being kicked, or hanging up.
Room membership is identified by session_uuid; the caller number is available on the inbound call.created or outbound command.call.dial.accepted webhook for that session.
room.member.muted
Fired when a room member is muted via the room/mute command.
Room membership is identified by session_uuid; the caller number is available on the inbound call.created or outbound command.call.dial.accepted webhook for that session.
room.member.unmuted
Fired when a room member is unmuted via the room/unmute command.
Room membership is identified by session_uuid; the caller number is available on the inbound call.created or outbound command.call.dial.accepted webhook for that session.
room.member.voice_activity_changed
Fired each time a room member’s voice activity detection (VAD) state changes. talking: true marks speech onset; talking: false marks the return to silence. Expect a high-frequency stream during an active conversation and debounce events on your side.
VAD state is delivered via this webhook. The member object returned by GET /api/v1/rooms/{room_id}/members/{uuid} contains only {uuid, muted}.
Room membership is identified by session_uuid; the caller number is available on the inbound call.created or outbound command.call.dial.accepted webhook for that session.
command.room.member.volume.accepted
Fired immediately when a member’s volume is changed via the room/volume command. This is a per-member session command, distinct from the room-level command.room.playback.volume.accepted event.
Room membership is identified by session_uuid; the caller number is available on the inbound call.created or outbound command.call.dial.accepted webhook for that session.
command.room.playback.start.accepted
Fired immediately after room playback is dispatched via POST /api/v1/rooms/{room_id}/playback/play. This event acknowledges dispatch; it does not prove that audio began. If start is not confirmed within the validation window, a later room.playback.failed event reports error: "playback_timeout".
command.room.playback.pause.accepted
Fired when the room playback pause toggle is accepted and the pause command is
dispatched. The gateway reads the room’s prior playback_status before
toggling: if it was "playing", this event fires; if it was "paused",
command.room.playback.resume.accepted fires
instead. Neither event independently confirms the resulting media-layer state.
command.room.playback.resume.accepted
Fired when the room playback pause toggle is accepted and a resume command is
dispatched while the prior playback_status was "paused". The same endpoint
emits either command.room.playback.pause.accepted
or this event depending on prior state; it does not independently confirm the
resulting media-layer state.
command.room.playback.stop.accepted
Fired when a room playback stop command is accepted and dispatched. It does not
independently confirm that the media layer has stopped. Its operation_uuid
identifies the stop request; the resulting
room.playback.ended event retains the operation UUID of
the original play request.
command.room.playback.volume.accepted
Fired when a room playback volume-change command is accepted and dispatched.
The volume field is the requested target; the event does not independently
confirm that the media layer applied it.
room.playback.ended
Terminal event fired exactly once when room playback completes naturally or is stopped through the API. A multi-source playlist emits one event after every source completes, rather than one event per source. Playback failures and start-confirmation timeouts emit room.playback.failed instead.
room.playback.failed
Fired when room playback fails: either the platform reports a playback failure, any source in a multi-source playlist fails, or the gateway does not receive confirmation within 10 seconds that a dispatched play actually started. A failure of any source fails the whole operation. A playback that is confirmed within that window does not fail merely because it runs for more than 10 seconds. The event resets playback_status to "stopped" so the room can accept a new play.
Triggered by
These events are produced by the following endpoints:
room.created— POST /rooms.command.room.delete.accepted— DELETE /rooms/{room_id} (fires immediately; endpoint returns202 Accepted).room.deleted— automatic: fires on confirmed teardown after acommand.room.delete.accepted(reason: "closed"), or withreason: "timeout"if confirmation never arrives.room.member.joined— POST /rooms/{room_id}/members (asynchronous).room.member.left— DELETE /rooms/{room_id}/members/{uuid}, or automatic on hangup.room.member.muted— room/mute.room.member.unmuted— room/unmute.room.member.voice_activity_changed— automatic: VAD state change.command.room.member.volume.accepted— room/volume (immediate).command.room.playback.start.accepted— POST /rooms/{room_id}/playback/play.command.room.playback.pause.accepted— POST /rooms/{room_id}/playback/pause (when prior state wasplaying).command.room.playback.resume.accepted— POST /rooms/{room_id}/playback/pause (when prior state waspaused).command.room.playback.stop.accepted— POST /rooms/{room_id}/playback/stop.command.room.playback.volume.accepted— POST /rooms/{room_id}/playback/volume.room.playback.ended— terminal: fires once when playback completes naturally or is stopped through the API.room.playback.failed— automatic: fires on a playback failure or when the playback watchdog times out.