Conference Calling
Host multi-party calls where participants join a named conference room. Conferences support moderators, mute control, hold music, and recording — ideal for team standups, support escalations, and webinars.
🧭 How It Works
A conference is a named room (conversation). Each call leg that joins the same room name is bridged together. Create the room, then route calls into it via an NCCO conversation action.
🏗️ Create a Conference
POST /v1/voice/conference
curl -X POST https://api.afriroute.ai/api/v1/voice/conference \
-H "Authorization: Bearer $AFRIROUTE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "team-standup",
"record": true,
"max_participants": 20,
"wait_music": "https://yourapp.com/audio/hold.mp3"
}'
Parameters
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Unique room name participants join |
record | boolean | No | Record the whole conference |
max_participants | number | No | Cap on simultaneous legs (default 50) |
wait_music | string | No | URL of hold music until moderator joins |
start_on_enter | boolean | No | Start when a moderator enters (default true) |
end_on_exit | boolean | No | End when the moderator leaves |
Response
{
"conference_id": "conf_abc123",
"name": "team-standup",
"status": "created",
"created_at": "2026-05-28T10:30:00Z"
}
📥 Add Participants
Dial out and place each answered call into the room with a conversation NCCO action:
app.post('/voice/answer', (req, res) => {
res.json([
{ action: 'talk', text: 'Joining the team standup now.' },
{
action: 'conversation',
name: 'team-standup',
startOnEnter: false, // participants wait for moderator
endOnExit: false,
musicOnHoldUrl: ['https://yourapp.com/audio/hold.mp3']
}
]);
});
The moderator leg uses startOnEnter: true and typically endOnExit: true.
🎛️ Manage Participants
import requests
# Mute a participant
requests.post(
'https://api.afriroute.ai/api/v1/voice/conference/conf_abc123/mute',
headers={'Authorization': 'Bearer $AFRIROUTE_API_KEY'},
json={'call_id': 'call_def456'}
)
# Remove a participant
requests.post(
'https://api.afriroute.ai/api/v1/voice/conference/conf_abc123/kick',
headers={'Authorization': 'Bearer $AFRIROUTE_API_KEY'},
json={'call_id': 'call_def456'}
)
Available actions: mute, unmute, hold, unhold, kick.
🔔 Conference Events
app.post('/voice/conference-events', (req, res) => {
const { conference_id, event, call_id } = req.body;
// event: participant_joined | participant_left | conference_ended
console.log(`${conference_id}: ${event} (${call_id ?? ''})`);
res.sendStatus(200);
});
| Event | Description |
|---|---|
participant_joined | A leg entered the room |
participant_left | A leg left the room |
conference_started | First moderator joined |
conference_ended | Room closed |
💡 Best Practices
- Use
startOnEnter: falsefor attendees so they hear hold music until the host arrives. - Set
end_on_exiton the moderator leg to close the room automatically. - Cap
max_participantsto control cost and audio quality. - Enable recording with consent and announce it at join time.
- Mute on entry for large conferences to avoid background noise.
⚠️ Error Handling
| Code | Description | Solution |
|---|---|---|
CONFERENCE_NOT_FOUND | Room ended or invalid name | Recreate the conference |
CONFERENCE_FULL | max_participants reached | Raise the cap or wait |
PARTICIPANT_NOT_FOUND | Bad call_id on action | Verify the leg is connected |
📚 Related Resources
Need help? Contact Support → | Last Updated: May 2026