Rooms

Last updated April 16, 2026

Multi-party audio conference rooms

# GET /rooms

List all rooms with participants

Responses

200 Array of rooms
# POST /rooms

Create a room

Request Body

FieldTypeDescription
idstringrequiredCustom room ID (auto-generated UUID if omitted)
webhook_urlstring(uri)optionalRoute all events for this room exclusively to this URL instead of global webhooks.
webhook_secretstringoptionalHMAC-SHA256 signing secret for the per-room webhook.

Responses

201 Room created
FieldTypeDescription
instance_idstringoptionalInstance identifier
idstringrequiredRoom identifier
participantsarray[object]requiredLegs currently in this room
409 Room ID already exists
FieldTypeDescription
instance_idstringoptionalInstance identifier
errorstringrequiredError message
# GET /rooms/{id}

Get a room with participants

Parameters

NameInTypeDescription
idpathstringrequiredRoom ID

Responses

200 Room details
FieldTypeDescription
instance_idstringoptionalInstance identifier
idstringrequiredRoom identifier
participantsarray[object]requiredLegs currently in this room
404 Room not found
FieldTypeDescription
instance_idstringoptionalInstance identifier
errorstringrequiredError message
# DELETE /rooms/{id}

Delete a room

Parameters

NameInTypeDescription
idpathstringrequiredRoom ID

Responses

200 Room deleted
FieldTypeDescription
instance_idstringoptionalInstance identifier
statusstringrequired
404 Room not found
FieldTypeDescription
instance_idstringoptionalInstance identifier
errorstringrequiredError message
# POST /rooms/{id}/legs

Add or move a leg to a room

Add a leg to a room (auto-creates room if it doesn't exist). If the leg is already in a different room, it is atomically moved to the target room. A ringing inbound SIP leg is automatically answered before being added.

Parameters

NameInTypeDescription
idpathstringrequiredRoom ID

Request Body

FieldTypeDescription
leg_idstringrequiredID of the leg to add
mutebooleanoptionalIf set, apply this mute state to the leg atomically before it joins the mixer (no race where un-muted audio enters the mix). Omit to leave current state untouched (useful when moving between rooms).
deafbooleanoptionalIf set, apply this deaf state to the leg atomically before it joins the mixer. Omit to leave current state untouched.
accept_dtmfbooleanoptionalIf set, control whether this leg receives DTMF digits broadcast from other legs in the same room. Omit to leave current state untouched (default for new legs is true).

Responses

200 Leg added or moved
FieldTypeDescription
instance_idstringoptionalInstance identifier
statusstringrequired
400 Invalid JSON, leg not found, or leg not connected
FieldTypeDescription
instance_idstringoptionalInstance identifier
errorstringrequiredError message
# DELETE /rooms/{id}/legs/{legID}

Remove a leg from a room

Parameters

NameInTypeDescription
idpathstringrequiredRoom ID
legIDpathstringrequiredLeg ID

Responses

200 Leg removed
FieldTypeDescription
instance_idstringoptionalInstance identifier
statusstringrequired
400 Room or leg not found
FieldTypeDescription
instance_idstringoptionalInstance identifier
errorstringrequiredError message
# POST /rooms/{id}/play

Play audio to a room

Parameters

NameInTypeDescription
idpathstringrequiredRoom ID

Request Body

FieldTypeDescription
urlstring(uri)requiredURL of the audio file (mutually exclusive with tone)
tonestringrequiredBuilt-in telephone tone name. Format: {country}_{type} or bare {type} (defaults to US). Types: ringback, busy, dial, congestion. Countries: us, gb, de, fr, au, jp, it, in, br, pl, ru. Examples: us_ringback, gb_busy, dial.
mime_typestringrequiredMIME type (e.g. audio/wav). Required when using url.
repeatintegerrequiredNumber of times to repeat playback (url only) 0
volumeintegerrequiredVolume adjustment in dB (-8 to 8) 0

Responses

200 Playback started
FieldTypeDescription
instance_idstringoptionalInstance identifier
statusstringrequired
400 Invalid JSON or volume out of range
FieldTypeDescription
instance_idstringoptionalInstance identifier
errorstringrequiredError message
404 Room not found
FieldTypeDescription
instance_idstringoptionalInstance identifier
errorstringrequiredError message
409 Room has no participants
FieldTypeDescription
instance_idstringoptionalInstance identifier
errorstringrequiredError message
# PATCH /rooms/{id}/play/{playbackID}

Change the volume of an active room playback

Parameters

NameInTypeDescription
idpathstringrequiredRoom ID
playbackIDpathstringrequiredPlayback ID

Request Body

FieldTypeDescription
volumeintegerrequiredVolume adjustment (-8 to 8, ~3dB per step, 0 = unchanged)

Responses

200 Volume updated
FieldTypeDescription
instance_idstringoptionalInstance identifier
statusstringrequired
400 Invalid JSON or volume out of range
FieldTypeDescription
instance_idstringoptionalInstance identifier
errorstringrequiredError message
404 Playback not found
FieldTypeDescription
instance_idstringoptionalInstance identifier
errorstringrequiredError message
# DELETE /rooms/{id}/play/{playbackID}

Stop room playback

Parameters

NameInTypeDescription
idpathstringrequiredRoom ID
playbackIDpathstringrequiredPlayback ID

Responses

200 Playback stopped
FieldTypeDescription
instance_idstringoptionalInstance identifier
statusstringrequired
404 No playback in progress
FieldTypeDescription
instance_idstringoptionalInstance identifier
errorstringrequiredError message
# POST /rooms/{id}/tts

Synthesize speech and play it into a room

Synthesizes the provided text using the configured TTS provider and plays the audio into the room. When TTS_CACHE_ENABLED=true, identical requests (same text, voice, model, language, and prompt) are stored on disk in TTS_CACHE_DIR and persist across restarts, without calling the external provider.

Parameters

NameInTypeDescription
idpathstringrequiredRoom ID

Request Body

FieldTypeDescription
textstringrequiredText to synthesize
voicestringrequiredProvider-specific voice identifier. ElevenLabs: voice name or ID. AWS Polly: voice ID (e.g. Joanna, Matthew). Google Cloud: voice name — either full format (e.g. en-US-Neural2-F) or short name for Gemini models (e.g. Achernar, Kore). Deepgram: model name (e.g. aura-2-asteria-en).
model_idstringrequiredProvider-specific model/engine. ElevenLabs: model ID. AWS Polly: engine (standard, neural, long-form, generative; default neural). Google Cloud: model name (e.g. gemini-2.5-pro-tts, chirp3-hd).
languagestringoptionalLanguage code (e.g. "en-US", "pl-pl"). Required for Google Gemini TTS voices that use short names (e.g. Achernar). Auto-extracted from full voice names like en-US-Neural2-F.
promptstringoptionalStyle/tone instruction for promptable voice models (Google Gemini TTS only). E.g. "Read aloud in a warm, welcoming tone."
volumeintegerrequiredVolume adjustment in dB (-8 to 8) 0
providerenumoptionalTTS provider: "elevenlabs" (default), "aws", "google", or "deepgram"
Values: elevenlabs, aws, google, deepgram
api_keystringoptionalElevenLabs: API key override (falls back to ELEVENLABS_API_KEY env var). AWS: optional ACCESS_KEY:SECRET_KEY override (falls back to default AWS credential chain). Google Cloud: optional API key override (falls back to Application Default Credentials). Deepgram: API key override (falls back to DEEPGRAM_API_KEY env var).

Responses

200 TTS playback started
FieldTypeDescription
instance_idstringoptionalInstance identifier
statusstringrequired
400 Invalid JSON, missing text/voice, or volume out of range
FieldTypeDescription
instance_idstringoptionalInstance identifier
errorstringrequiredError message
404 Room not found
FieldTypeDescription
instance_idstringoptionalInstance identifier
errorstringrequiredError message
409 Room has no participants
FieldTypeDescription
instance_idstringoptionalInstance identifier
errorstringrequiredError message
503 No API key provided for the selected provider
FieldTypeDescription
instance_idstringoptionalInstance identifier
errorstringrequiredError message
# POST /rooms/{id}/record

Start recording the room mix to a WAV file

Records the full room mix at 16kHz, 16-bit, mono.

Parameters

NameInTypeDescription
idpathstringrequiredRoom ID

Request Body

FieldTypeDescription
storageenumrequired"file" (default) — local disk, "s3" — upload to S3 after recording stops
Values: file, s3
multi_channelbooleanrequiredWhen true, record each participant to a separate mono WAV file in addition to the full mix. Only applies to room recordings. false
s3_bucketstringrequiredS3 bucket name. Overrides S3_BUCKET env var. Required if env var is not set.
s3_regionstringrequiredAWS region. Overrides S3_REGION env var. Default us-east-1.
s3_endpointstringrequiredCustom S3 endpoint (MinIO, etc.). Overrides S3_ENDPOINT env var.
s3_prefixstringrequiredKey prefix (e.g. recordings/). Overrides S3_PREFIX env var.
s3_access_keystringrequiredAWS access key ID. Overrides default credential chain.
s3_secret_keystringrequiredAWS secret access key. Must be set together with s3_access_key.

Responses

200 Recording started
FieldTypeDescription
instance_idstringoptionalInstance identifier
statusstringrequired
400 Invalid storage type, S3 not configured, or invalid S3 credentials
FieldTypeDescription
instance_idstringoptionalInstance identifier
errorstringrequiredError message
404 Room not found
FieldTypeDescription
instance_idstringoptionalInstance identifier
errorstringrequiredError message
409 Room has no participants
FieldTypeDescription
instance_idstringoptionalInstance identifier
errorstringrequiredError message
500 Failed to create recording file
FieldTypeDescription
instance_idstringoptionalInstance identifier
errorstringrequiredError message
# DELETE /rooms/{id}/record

Stop room recording

Parameters

NameInTypeDescription
idpathstringrequiredRoom ID

Responses

200 Recording stopped
FieldTypeDescription
instance_idstringoptionalInstance identifier
statusstringrequired
404 No recording in progress
FieldTypeDescription
instance_idstringoptionalInstance identifier
errorstringrequiredError message
# POST /rooms/{id}/record/pause

Pause a room recording

Replaces the room mix with silence on the active recording until /record/resume is called. When multi-channel recording is active, every per-participant track is paused too (including tracks for participants who join while paused). Idempotent: returns status: already_paused when already paused.

Parameters

NameInTypeDescription
idpathstringrequiredRoom ID

Responses

200 Recording paused (or already paused)
FieldTypeDescription
instance_idstringoptionalInstance identifier
statusstringrequired
404 No recording in progress
FieldTypeDescription
instance_idstringoptionalInstance identifier
errorstringrequiredError message
# POST /rooms/{id}/record/resume

Resume a paused room recording

Resumes writing real audio after a prior /record/pause. Resumes every per-participant track if multi-channel recording is active. Idempotent.

Parameters

NameInTypeDescription
idpathstringrequiredRoom ID

Responses

200 Recording resumed (or was not paused)
FieldTypeDescription
instance_idstringoptionalInstance identifier
statusstringrequired
404 No recording in progress
FieldTypeDescription
instance_idstringoptionalInstance identifier
errorstringrequiredError message
# POST /rooms/{id}/stt

Start speech-to-text on all room participants

Parameters

NameInTypeDescription
idpathstringrequiredRoom ID

Request Body

FieldTypeDescription
languagestringrequiredLanguage code (e.g. "en", "es")
partialbooleanrequiredEmit partial (non-final) transcripts false
providerenumoptionalSTT provider: "elevenlabs" (default) or "deepgram"
Values: elevenlabs, deepgram
api_keystringoptionalAPI key override (falls back to ELEVENLABS_API_KEY or DEEPGRAM_API_KEY env var depending on provider)

Responses

200 STT started
FieldTypeDescription
instance_idstringoptionalInstance identifier
statusstringrequired
404 Room not found
FieldTypeDescription
instance_idstringoptionalInstance identifier
errorstringrequiredError message
409 STT already running or room has no participants
FieldTypeDescription
instance_idstringoptionalInstance identifier
errorstringrequiredError message
503 No ElevenLabs API key provided
FieldTypeDescription
instance_idstringoptionalInstance identifier
errorstringrequiredError message
# DELETE /rooms/{id}/stt

Stop speech-to-text on a room

Parameters

NameInTypeDescription
idpathstringrequiredRoom ID

Responses

200 STT stopped
FieldTypeDescription
instance_idstringoptionalInstance identifier
statusstringrequired
404 No STT in progress
FieldTypeDescription
instance_idstringoptionalInstance identifier
errorstringrequiredError message
# POST /rooms/{id}/agent/elevenlabs

Attach an ElevenLabs ConvAI agent to a room

The agent joins as a virtual participant, hearing all participants (mixed-minus-self) and speaking to everyone.

Parameters

NameInTypeDescription
idpathstringrequiredRoom ID

Request Body

FieldTypeDescription
agent_idstringrequiredElevenLabs agent ID
first_messagestringoptionalOverride the agent's first message
languagestringoptionalLanguage code (e.g. "en", "es")
dynamic_variablesobjectoptionalKey-value pairs passed to the agent as dynamic variables
api_keystringoptionalAPI key override (falls back to ELEVENLABS_API_KEY env var)

Responses

200 Agent started
FieldTypeDescription
instance_idstringoptionalInstance identifier
statusstringrequired
400 Invalid JSON or missing agent_id
FieldTypeDescription
instance_idstringoptionalInstance identifier
errorstringrequiredError message
404 Room not found
FieldTypeDescription
instance_idstringoptionalInstance identifier
errorstringrequiredError message
409 Agent already attached to this room
FieldTypeDescription
instance_idstringoptionalInstance identifier
errorstringrequiredError message
503 No ElevenLabs API key provided
FieldTypeDescription
instance_idstringoptionalInstance identifier
errorstringrequiredError message
# POST /rooms/{id}/agent/vapi

Attach a VAPI agent to a room

The agent joins as a virtual participant, hearing all participants (mixed-minus-self) and speaking to everyone.

Parameters

NameInTypeDescription
idpathstringrequiredRoom ID

Request Body

FieldTypeDescription
assistant_idstringrequiredVAPI assistant ID
first_messagestringoptionalOverride the agent's first message
variable_valuesobjectoptionalKey-value pairs passed as VAPI variable values (assistantOverrides.variableValues)
api_keystringoptionalAPI key override (falls back to VAPI_API_KEY env var)

Responses

200 Agent started
FieldTypeDescription
instance_idstringoptionalInstance identifier
statusstringrequired
400 Invalid JSON or missing assistant_id
FieldTypeDescription
instance_idstringoptionalInstance identifier
errorstringrequiredError message
404 Room not found
FieldTypeDescription
instance_idstringoptionalInstance identifier
errorstringrequiredError message
409 Agent already attached to this room
FieldTypeDescription
instance_idstringoptionalInstance identifier
errorstringrequiredError message
503 No VAPI API key provided
FieldTypeDescription
instance_idstringoptionalInstance identifier
errorstringrequiredError message
# POST /rooms/{id}/agent/pipecat

Attach a Pipecat bot to a room

The bot joins as a virtual participant via WebSocket, hearing all participants (mixed-minus-self) and speaking to everyone.

Parameters

NameInTypeDescription
idpathstringrequiredRoom ID

Request Body

FieldTypeDescription
websocket_urlstring(uri)requiredWebSocket URL of the Pipecat bot (e.g. ws://my-bot:8765)

Responses

200 Agent started
FieldTypeDescription
instance_idstringoptionalInstance identifier
statusstringrequired
400 Invalid JSON or missing websocket_url
FieldTypeDescription
instance_idstringoptionalInstance identifier
errorstringrequiredError message
404 Room not found
FieldTypeDescription
instance_idstringoptionalInstance identifier
errorstringrequiredError message
409 Agent already attached to this room
FieldTypeDescription
instance_idstringoptionalInstance identifier
errorstringrequiredError message
# POST /rooms/{id}/agent/deepgram

Attach a Deepgram Voice Agent to a room

The agent joins as a virtual participant, hearing all participants (mixed-minus-self) and speaking to everyone.

Parameters

NameInTypeDescription
idpathstringrequiredRoom ID

Request Body

FieldTypeDescription
settingsobjectoptionalFull Deepgram agent settings object (agent.listen, agent.think, agent.speak, etc.). When omitted, sensible defaults are used (nova-3 STT, gpt-4o-mini LLM, aura-2-asteria-en TTS).
greetingstringoptionalAgent greeting message
languagestringoptionalLanguage code (e.g. "en", "es")
api_keystringoptionalAPI key override (falls back to DEEPGRAM_API_KEY env var)

Responses

200 Agent started
FieldTypeDescription
instance_idstringoptionalInstance identifier
statusstringrequired
400 Invalid JSON
FieldTypeDescription
instance_idstringoptionalInstance identifier
errorstringrequiredError message
404 Room not found
FieldTypeDescription
instance_idstringoptionalInstance identifier
errorstringrequiredError message
409 Agent already attached to this room
FieldTypeDescription
instance_idstringoptionalInstance identifier
errorstringrequiredError message
503 No Deepgram API key provided
FieldTypeDescription
instance_idstringoptionalInstance identifier
errorstringrequiredError message
# POST /rooms/{id}/agent/message

Inject a message into a running agent session on a room

Sends a context message or instruction to the running agent. Supported by Deepgram (InjectAgentMessage), Pipecat (TextFrame), and VAPI (control URL). Returns 501 for ElevenLabs.

Parameters

NameInTypeDescription
idpathstringrequiredRoom ID

Request Body

FieldTypeDescription
messagestringrequiredContext or instruction to inject into the running agent session

Responses

200 Message sent
FieldTypeDescription
instance_idstringoptionalInstance identifier
statusstringrequired
400 Invalid JSON or missing message
FieldTypeDescription
instance_idstringoptionalInstance identifier
errorstringrequiredError message
404 No agent attached to this room
FieldTypeDescription
instance_idstringoptionalInstance identifier
errorstringrequiredError message
409 Agent session not running
FieldTypeDescription
instance_idstringoptionalInstance identifier
errorstringrequiredError message
501 Provider does not support message injection
FieldTypeDescription
instance_idstringoptionalInstance identifier
errorstringrequiredError message
# DELETE /rooms/{id}/agent

Detach the agent from a room

Parameters

NameInTypeDescription
idpathstringrequiredRoom ID

Responses

200 Agent stopped
FieldTypeDescription
instance_idstringoptionalInstance identifier
statusstringrequired
404 No agent attached to this room
FieldTypeDescription
instance_idstringoptionalInstance identifier
errorstringrequiredError message
# GET /rooms/{id}/ws

WebSocket audio stream for a room

Upgrades to a WebSocket connection and joins the room as a bidirectional audio participant. The client sends and receives 16kHz 16-bit signed little-endian PCM audio (mono), base64-encoded in JSON text frames. Each audio frame is 640 bytes (20ms).

Parameters

NameInTypeDescription
idpathstringrequiredRoom ID

Responses

101 WebSocket upgrade successful. Server sends a `connected` message followed by mixed-minus-self audio frames.
404 Room not found
FieldTypeDescription
instance_idstringoptionalInstance identifier
errorstringrequiredError message