Skip to content

Conference

Create and manage conference rooms, control room-level playback, and manage individual participant sessions (join, leave, mute, unmute). Conference endpoints are split into two groups: room-level endpoints and session-level commands.

All conference endpoints require App authentication via X-App-ID and X-API-Key headers.

Room-level endpoints (GET, DELETE, play, pause, stop, volume) additionally require room ownership validation: the room must exist and its app_id must match your X-App-ID.

Session-level conference commands (join, leave, mute, unmute) require session ownership: the session must exist and belong to your application.

POST /api/v1/conferences

Create a new conference room. The gateway picks a source node, generates a unique room_id, and checks for duplicate names within your application.

Request body

FieldTypeRequiredDescriptionValidations
namestringrequiredConference name. Used as a human-readable identifier.Alphanumeric, hyphens, underscores only. Must start with alphanumeric. Max 64 chars.

Response — 201 Created

{
"room_id": "acW68-room-550e8400-e29b-41d4-a716-446655440000"
}

Error — 409 Conflict. If the conference name is already taken for your app, the existing room_id is returned under detail so the caller can reuse it:

{
"success": false,
"error": "Conference name already taken for this application",
"detail": { "room_id": "acW68-room-existing-uuid-here" }
}
POST /api/v1/conferences
curl -X POST https://gateway.example.com/api/v1/conferences \
  -H "X-App-ID: YOUR_APP_ID" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "weekly-standup"}'

Triggered webhooks

  • conference.created — immediate; includes room_id and name.

GET /api/v1/conferences

List conference rooms owned by the authenticated app. The filter is implicit — only rooms whose app_id matches the authenticated app are returned. Apps cannot enumerate other apps’ rooms.

Query parameters

FieldTypeRequiredDescriptionValidations
limitintegeroptionalMaximum rooms to return.Positive integer. Default 50, clamped to 200.
cursorstringoptionalOpaque pagination cursor from a previous response.Pass through unchanged. Do not parse or persist across deploys.

Response — 200 OK

{
"conferences": [
{
"room_id": "acW68-room-550e8400-e29b-41d4-a716-446655440000",
"name": "team-standup",
"members": 3,
"created_at": "2026-05-06T12:34:56Z"
}
],
"cursor": ""
}

Iterate by passing the previous response’s cursor back as ?cursor=. When the response’s cursor is empty (or absent), iteration is complete.

Errors: 400 invalid limit/cursor; 401 missing or invalid auth. Read-only — no webhooks.

GET /api/v1/conferences/{room_id}

Retrieve the current status of a conference room, including member count, playback state, and volume.

{
"room_id": "acW68-room-550e8400-e29b-41d4-a716-446655440000",
"name": "weekly-standup",
"created_at": "1711036800",
"members": 5,
"playback_status": "stopped",
"playback_volume": 0,
"playback_urls": [],
"playback_operation_id": ""
}

Read-only — no webhooks.

GET /api/v1/conferences/{room_id}/members

Return active sessions joined to the conference room, paginated via an opaque cursor.

Query parameters

FieldTypeRequiredDescriptionValidations
limitintegeroptionalMaximum members to return per page.Positive integer. Default 50, clamped to 1000.
cursorstringoptionalOpaque pagination cursor from a previous response.Pass through unchanged. Do not parse or persist across deploys.

Response — 200 OK

{
"room_id": "acW68-room-...",
"members": [
{ "uuid": "acW68-...", "did": "747713001", "caller_id": "527121102", "muted": false }
],
"cursor": ""
}

Errors: 400 invalid limit/cursor; 401 missing or invalid auth; 404 room not found or owned by a different app.

DELETE /api/v1/conferences/{room_id}

Destroy a conference room. Stops any active recording, kicks all members, tears down bridges, and removes room data.

{
"room_id": "acW68-room-550e8400-e29b-41d4-a716-446655440000"
}

Triggered webhooks

  • conference.destroyed — immediate; includes room_id.

POST /api/v1/conferences/{room_id}/play

Start playing audio URLs into the conference room. Each URL is dispatched as a separate conference play command.

Request body

FieldTypeRequiredDescriptionValidations
urlsstring[]requiredHTTP/HTTPS URLs of audio files to play into the room.Max 128 files.

Rate limitconf_play group, 2 s cooldown per room.

Response — 202 Accepted

{
"operation_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"status": "in_progress"
}
POST /api/v1/conferences/{room_id}/play
curl -X POST https://gateway.example.com/api/v1/conferences/{room_id}/play \
  -H "X-App-ID: YOUR_APP_ID" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"urls": ["https://cdn.example.com/announcement.wav"]}'

Triggered webhooks

  • conference.play.started — immediate; includes room_id, urls, operation_id.
  • conference.play.finished — deferred; fires when playback completes.

POST /api/v1/conferences/{room_id}/pause

Toggle pause/resume of conference room playback. No request body required.

Rate limitconference_control group, 200 ms cooldown per room. Shared with stop and volume.

Triggered webhooks

  • conference.play.paused — immediate; includes room_id and operation_id.

POST /api/v1/conferences/{room_id}/stop

Stop all conference room playback. No request body required.

Rate limitconference_control group, 200 ms cooldown per room. Shared with pause and volume.

Triggered webhooks

  • conference.play.stopped — immediate; includes room_id and operation_id.

POST /api/v1/conferences/{room_id}/volume

Set the conference room playback volume.

Request body

FieldTypeRequiredDescriptionValidations
volumeintegerrequiredVolume level for conference playback.Range -50 to 7. Negative values attenuate; positive amplify.

Rate limitconference_control group, 200 ms cooldown per room. Shared with pause and stop.

POST /api/v1/conferences/{room_id}/volume
curl -X POST https://gateway.example.com/api/v1/conferences/{room_id}/volume \
  -H "X-App-ID: YOUR_APP_ID" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"volume": 2}'

Triggered webhooks

  • conference.play.volume_changed — immediate; includes room_id, volume, operation_id.

These commands are sent to individual call sessions to manage their conference membership. They use the standard session command path.

POST /api/v1/sessions/{uuid}/commands/conference/join

Join a call session to a conference room. All members join muted by default. The join is confirmed asynchronously via a conference.member.joined webhook.

Request body

FieldTypeRequiredDescriptionValidations
room_idstringrequiredThe conference room ID to join.Format {5-char-prefix}-room-{uuid}. Room must exist and belong to same app.

Rate limitconference group, 2 s cooldown per session. Shared with conference/leave.

Responses

StatusConditionBody
202Successfully initiated join{"status": "joining", "room_id": "..."}
200Already in the same room (idempotent){"status": "already_joined", "room_id": "..."}
409Session is in a different room{"success": false, "error": "Session is already in a different conference room. Use conference/leave first."}
POST /api/v1/sessions/{uuid}/commands/conference/join
curl -X POST https://gateway.example.com/api/v1/sessions/{uuid}/commands/conference/join \
  -H "X-App-ID: YOUR_APP_ID" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"room_id": "acW68-room-550e8400-e29b-41d4-a716-446655440000"}'

Triggered webhooks

  • conference.member.joined — deferred; fires when the join is confirmed.

POST /api/v1/sessions/{uuid}/commands/conference/leave

Remove a call session from its current conference room. No additional fields beyond the optional command_uid.

Rate limitconference group, 2 s cooldown per session. Shared with conference/join.

Response — 202 Accepted

{
"status": "leaving",
"room_id": "acW68-room-550e8400-e29b-41d4-a716-446655440000"
}

Errors: 404 session not in any conference; 409 session still joining (no member_id yet).

Triggered webhooks

  • conference.member.left — deferred; fires when the removal is confirmed.

POST /api/v1/sessions/{uuid}/commands/conference/mute

Mute a conference member. No additional fields beyond the optional command_uid.

Rate limitconference_mute group, 2 s cooldown per session. Shared with conference/unmute.

Response — 202 Accepted{"status": "muted", "room_id": "..."}

Errors: 404 session not in any conference; 409 already muted, or still joining.

Triggered webhooks

  • conference.member.muted — deferred; fires when mute is confirmed.

POST /api/v1/sessions/{uuid}/commands/conference/unmute

Unmute a conference member. No additional fields beyond the optional command_uid.

Rate limitconference_mute group, 2 s cooldown per session. Shared with conference/mute.

Response — 202 Accepted{"status": "unmuted", "room_id": "..."}

Errors: 404 session not in any conference; 409 already unmuted, or still joining.

Triggered webhooks

  • conference.member.unmuted — deferred; fires when unmute is confirmed.

See the Rate limits guide for cooldown windows and 429 retry semantics.

StatusCondition
400Invalid name, room_id format, volume range, or malformed JSON.
401Missing or invalid X-API-Key.
403Room or session belongs to a different application.
404Room not found, session not found, or session not in a conference.
409Conference name already taken, session in different room, already muted/unmuted, or still joining.
429Rate limit exceeded (global or per-command/room cooldown).