When to use
Use this when you need to bridge three or more parties into a single named room, or when you need programmatic control over who is muted, on hold, coaching, or dialed in mid-call. Twilio conferences are created by placing callers into <Dial><Conference> with a shared room name; you then add, remove, and modify participants through the REST API.
Not for: simple two-party call bridging (use <Dial><Number> directly); AI voice agents (see twilio-voice-conversation-relay); or recording detail — conference recording is covered here at a high level but PCI pause, dual-channel, and media retrieval live in twilio-call-recordings.
Method
- Return TwiML that drops the caller into a named room:
<Dial><Conference>ROOM</Conference></Dial>. Everyone who joins the same name on the same account lands in the same conference.
- Decision point — lifecycle: set
startConferenceOnEnter on the moderator so the room does not begin until they arrive, and endConferenceOnExit on the moderator so it tears down when they leave. Regular participants get startConferenceOnEnter="false".
- Set wait behavior with
waitUrl (TwiML/MP3 hold music) and beep for join/leave tones.
- To add a participant programmatically, POST to the Participants resource with
From and To; Twilio dials them and joins them on answer.
- To mute, hold, or coach an existing participant, POST an update to that participant's resource (
Muted, Hold, Coaching, CallSidToCoach).
- Decision point — coaching: a coach hears the conference and can whisper to one target (
CallSidToCoach) without the rest of the room hearing.
- Remove a participant by DELETE on their resource, or end the whole room by updating the Conference
Status to completed.
- Wire
statusCallback (conference-level) and per-participant callbacks to track participant-join, participant-leave, start, end, mute, hold.
- To record, set
record="record-from-start" on the <Conference> — then hand off to twilio-call-recordings for media retrieval and compliance.
Example
TwiML for the moderator:
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Dial>
<Conference startConferenceOnEnter="true"
endConferenceOnExit="true"
beep="true"
waitUrl="https://example.com/hold.mp3"
record="record-from-start"
statusCallback="https://example.com/conf-events"
statusCallbackEvent="start end join leave mute hold">
standup-room
</Conference>
</Dial>
</Response>
Dial a new participant into that room and mute another (Python):
from twilio.rest import Client
client = Client(account_sid, auth_token)
# Add a participant by phone number
client.conferences("standup-room").participants.create(
from_="+15551112222", to="+15553334444", beep="onEnter")
# Mute an existing participant
client.conferences("standup-room") \
.participants("CA_call_sid_here").update(muted=True)
# Put someone on hold with hold music
client.conferences("standup-room") \
.participants("CA_call_sid_here").update(hold=True, hold_url="https://example.com/hold.mp3")
Pitfalls
- If no one has
startConferenceOnEnter="true", everyone waits on hold music forever.
endConferenceOnExit on the wrong participant tears down the room when a normal caller hangs up. Reserve it for the moderator.
- The Participants API is keyed by the participant's Call SID, not the phone number; capture the SID from the join callback.
- Conference names are scoped per account and case-sensitive; a typo silently creates a second, empty room.
- Default
maxParticipants is 250; conferences do not auto-scale beyond it and creation fails once full.
waitUrl TwiML may only contain <Play>, <Say>, and <Redirect> — other verbs are ignored.
Output format
TwiML places callers in the room. REST calls return JSON participant/conference resources (SIDs prefixed CF for conferences, CA for the participant call). Status callbacks POST form-encoded events (StatusCallbackEvent, ConferenceSid, CallSid, Muted, Hold) to your URL.
Reference
- TwiML:
<Dial><Conference>. Attributes: startConferenceOnEnter, endConferenceOnExit, muted, beep (true/false/onEnter/onExit), waitUrl, waitMethod, maxParticipants (default 250), record (do-not-record | record-from-start), recordingStatusCallback, statusCallback, statusCallbackEvent (start end join leave mute hold speaker), coach, region, trim.
- REST base:
https://api.twilio.com/2010-04-01/Accounts/{AccountSid}.
- Add participant:
POST /Conferences/{ConferenceSid}/Participants.json (params From, To, Muted, Beep, EarlyMedia, Coaching, CallSidToCoach).
- Update participant:
POST /Conferences/{ConferenceSid}/Participants/{CallSid}.json (Muted, Hold, HoldUrl, Coaching, AnnounceUrl).
- Remove:
DELETE /Conferences/{ConferenceSid}/Participants/{CallSid}.json.
- List/inspect:
GET /Conferences.json (filter by FriendlyName, Status, DateCreated); end a room via POST /Conferences/{ConferenceSid}.json with Status=completed.
- Common errors: 21470 (invalid
waitUrl), 21472 (conference not found for participant op), 21226/21211 (invalid To/From). Conference recording media is fetched via the Recordings resource — see twilio-call-recordings.
1---2name: twilio-conference-calls3description: Build and control multi-party Twilio conference calls with TwiML and the Participants REST API, including mute, hold, coaching, wait music, and status callbacks.4---56## When to use78Use this when you need to bridge three or more parties into a single named room, or when you need programmatic control over who is muted, on hold, coaching, or dialed in mid-call. Twilio conferences are created by placing callers into `<Dial><Conference>` with a shared room name; you then add, remove, and modify participants through the REST API.910**Not for:** simple two-party call bridging (use `<Dial><Number>` directly); AI voice agents (see twilio-voice-conversation-relay); or recording detail — conference recording is covered here at a high level but PCI pause, dual-channel, and media retrieval live in twilio-call-recordings.1112## Method13141. Return TwiML that drops the caller into a named room: `<Dial><Conference>ROOM</Conference></Dial>`. Everyone who joins the same name on the same account lands in the same conference.152. Decision point — lifecycle: set `startConferenceOnEnter` on the moderator so the room does not begin until they arrive, and `endConferenceOnExit` on the moderator so it tears down when they leave. Regular participants get `startConferenceOnEnter="false"`.163. Set wait behavior with `waitUrl` (TwiML/MP3 hold music) and `beep` for join/leave tones.174. To add a participant programmatically, POST to the Participants resource with `From` and `To`; Twilio dials them and joins them on answer.185. To mute, hold, or coach an existing participant, POST an update to that participant's resource (`Muted`, `Hold`, `Coaching`, `CallSidToCoach`).196. Decision point — coaching: a coach hears the conference and can whisper to one target (`CallSidToCoach`) without the rest of the room hearing.207. Remove a participant by DELETE on their resource, or end the whole room by updating the Conference `Status` to `completed`.218. Wire `statusCallback` (conference-level) and per-participant callbacks to track `participant-join`, `participant-leave`, `start`, `end`, `mute`, `hold`.229. To record, set `record="record-from-start"` on the `<Conference>` — then hand off to twilio-call-recordings for media retrieval and compliance.2324## Example2526TwiML for the moderator:2728```xml29<?xml version="1.0" encoding="UTF-8"?>30<Response>31 <Dial>32 <Conference startConferenceOnEnter="true"33 endConferenceOnExit="true"34 beep="true"35 waitUrl="https://example.com/hold.mp3"36 record="record-from-start"37 statusCallback="https://example.com/conf-events"38 statusCallbackEvent="start end join leave mute hold">39 standup-room40 </Conference>41 </Dial>42</Response>43```4445Dial a new participant into that room and mute another (Python):4647```python48from twilio.rest import Client49client = Client(account_sid, auth_token)5051# Add a participant by phone number52client.conferences("standup-room").participants.create(53 from_="+15551112222", to="+15553334444", beep="onEnter")5455# Mute an existing participant56client.conferences("standup-room") \57 .participants("CA_call_sid_here").update(muted=True)5859# Put someone on hold with hold music60client.conferences("standup-room") \61 .participants("CA_call_sid_here").update(hold=True, hold_url="https://example.com/hold.mp3")62```6364## Pitfalls6566- If no one has `startConferenceOnEnter="true"`, everyone waits on hold music forever.67- `endConferenceOnExit` on the wrong participant tears down the room when a normal caller hangs up. Reserve it for the moderator.68- The Participants API is keyed by the participant's Call SID, not the phone number; capture the SID from the join callback.69- Conference names are scoped per account and case-sensitive; a typo silently creates a second, empty room.70- Default `maxParticipants` is 250; conferences do not auto-scale beyond it and creation fails once full.71- `waitUrl` TwiML may only contain `<Play>`, `<Say>`, and `<Redirect>` — other verbs are ignored.7273## Output format7475TwiML places callers in the room. REST calls return JSON participant/conference resources (SIDs prefixed `CF` for conferences, `CA` for the participant call). Status callbacks POST form-encoded events (`StatusCallbackEvent`, `ConferenceSid`, `CallSid`, `Muted`, `Hold`) to your URL.7677## Reference7879- TwiML: `<Dial><Conference>`. Attributes: `startConferenceOnEnter`, `endConferenceOnExit`, `muted`, `beep` (`true`/`false`/`onEnter`/`onExit`), `waitUrl`, `waitMethod`, `maxParticipants` (default 250), `record` (`do-not-record` | `record-from-start`), `recordingStatusCallback`, `statusCallback`, `statusCallbackEvent` (`start end join leave mute hold speaker`), `coach`, `region`, `trim`.80- REST base: `https://api.twilio.com/2010-04-01/Accounts/{AccountSid}`.81 - Add participant: `POST /Conferences/{ConferenceSid}/Participants.json` (params `From`, `To`, `Muted`, `Beep`, `EarlyMedia`, `Coaching`, `CallSidToCoach`).82 - Update participant: `POST /Conferences/{ConferenceSid}/Participants/{CallSid}.json` (`Muted`, `Hold`, `HoldUrl`, `Coaching`, `AnnounceUrl`).83 - Remove: `DELETE /Conferences/{ConferenceSid}/Participants/{CallSid}.json`.84 - List/inspect: `GET /Conferences.json` (filter by `FriendlyName`, `Status`, `DateCreated`); end a room via `POST /Conferences/{ConferenceSid}.json` with `Status=completed`.85- Common errors: 21470 (invalid `waitUrl`), 21472 (conference not found for participant op), 21226/21211 (invalid `To`/`From`). Conference recording media is fetched via the Recordings resource — see twilio-call-recordings.