Configuring Conferences
About Conferences
Conference documents are enriched with real-time information along side their configuration, namely showing the number of members, number of moderators, duration of the conference, conference locked status.
The real-time information (if available) is added to conference document under the _read_only
key (to avoid accidental document update).
Schema
Schema for conferences
Key | Description | Type | Default | Required | Support Level |
---|---|---|---|---|---|
allow_shareable_link | Indicates if the conference is reachable using a public link | boolean() | false | false | |
base_profile_name | name of base profile | string() | false | ||
bridge_password | the password used for a conference bridge | string() | false | ||
bridge_username | the username used for a conference bridge | string() | false | ||
caller_controls | caller controls (config settings) | string() | false | ||
conference_numbers.[] | string() | false | |||
conference_numbers | Defines conference numbers that can be used by members or moderators | array(string()) | [] | false | |
controls | controls | object() | false | ||
domain | domain | string() | false | ||
flags.[] | string() | false | supported | ||
flags | Flags set by external applications | array(string()) | false | supported | |
focus | This is a read-only property indicating the media server hosting the conference | string() | false | ||
language | Prompt language to play in the conference | string() | false | ||
max_members_media | Media to play when the conference is full | string() | false | ||
max_participants | The maximum number of participants that can join | integer() | false | ||
member.join_deaf | Determines if a member will join deaf | boolean() | false | false | supported |
member.join_muted | Determines if a member will join muted | boolean() | true | false | supported |
member.numbers.[] | string() | false | |||
member.numbers | Defines the conference (call in) number(s) for members | array(string()) | [] | false | |
member.pins.[] | string() | false | |||
member.pins | Defines the pin number(s) for members | array(string()) | [] | false | |
member.play_entry_prompt | Whether to play the entry prompt on member join | boolean() | false | ||
member | Defines the discovery (call in) properties for a member | object() | {} | false | |
moderator.join_deaf | Determines if a moderator will join deaf | boolean() | false | false | |
moderator.join_muted | Determines if a moderator will join muted | boolean() | false | false | |
moderator.numbers.[] | string() | false | |||
moderator.numbers | Defines the conference (call in) number(s) for moderators | array(string()) | [] | false | |
moderator.pins.[] | string() | false | |||
moderator.pins | Defines the pin number(s) for moderators | array(string()) | [] | false | |
moderator | Defines the discovery (call in) properties for a moderator | object() | {} | false | |
moderator_controls | profile on the switch for controlling the conference as a moderator | string() | false | ||
name | A friendly name for the conference | string(1..128) | true | supported | |
owner_id | The user ID who manages this conference | string(32) | false | supported | |
play_entry_tone | Whether to play an entry tone, or the entry tone to play | `boolean() | string()` | false | |
play_exit_tone | Whether to play an exit tone, or the exit tone to play | `boolean() | string()` | false | |
play_name | Do we need to announce new conference members? | boolean() | false | false | |
play_welcome | Whether to play the welcome prompt | boolean() | false | ||
profile | Profile configuration | object() | false | ||
profile_name | conference profile name | string() | false | ||
require_moderator | does the conference require a moderator | boolean() | false | ||
video | If false, video participants will join with video muted | boolean() | false | ||
wait_for_moderator | should members wait for a moderator before joining the conference | boolean() | false |
conferences.profile
Schema for conference profiles
Key | Description | Type | Default | Required | Support Level |
---|---|---|---|---|---|
alone-sound | Audio that plays while you are alone in the conference | string() | false | ||
announce-count | Play member count to conference when above this threshold | integer() | false | ||
caller-controls | Name of the caller control group | string() | false | ||
comfort-noise | The volume level of background white noise | integer(0..10000) | false | ||
energy-level | Energy level required for audio to be sent to other users | integer(0..1800) | false | ||
enter-sound | Audio to play when entering a conference | string() | false | ||
exit-sound | Audio to play when exiting a conference | string() | false | ||
interval | Milliseconds per frame | integer(10..120) | false | ||
locked-sound | Audio to play when the conference is locked | string() | false | ||
max-members | Set the maximum number of members in the conference | integer(2..) | false | ||
max-members-sound | If max-members has been reached, audio to play to caller instead of joining the conference | string() | false | ||
moderator-controls | Name of the moderator control group to use | string() | false | ||
moh-sound | Audio to play, on a loop, while participant count is 1 | string() | false | ||
muted-sound | Audio to play when muted | string() | false | ||
rate | Audio sample rate | integer() | false | ||
unmuted-sound | Audio to play when unmuted | string() | false |
Keys under development
require_moderator
wait_for_moderator
Perform an action on a conference
PUT /v2/accounts/{ACCOUNT_ID}/conferences/{CONFERENCE_ID}
curl -v -X PUT \
-d '{"action": "{CONFERENCE_ACTION}", "data": {"ACTION":"DATA"}}' \
-H "X-Auth-Token: {AUTH_TOKEN}" \
http://{SERVER}:8000/v2/accounts/{ACCOUNT_ID}/conferences/{CONFERENCE_ID}
Action | Description |
---|---|
lock | Lock the conference; no new participants may join |
unlock | Unlock the conference; new participants may join |
dial | Dial an endpoint (user/device/DID) |
play | Play media to the conference (all participants) |
record | Start/stop the recording of the conference |
vars | Put custom conference variables on the conference |
Lock / unlock
Lock and unlock take no additional data.
curl -v -X PUT \
-d '{"action": "lock", "data": {}}' \
-H "X-Auth-Token: {AUTH_TOKEN}" \
http://{SERVER}:8000/v2/accounts/{ACCOUNT_ID}/conferences/{CONFERENCE_ID}
Play media into a conference
The play
action takes the media ID to play into the conference.
curl -v -X PUT \
-d '{"action": "play", "data": {"media_id":"{MEDIA_TO_PLAY}"}}' \
-H "X-Auth-Token: {AUTH_TOKEN}" \
http://{SERVER}:8000/v2/accounts/{ACCOUNT_ID}/conferences/{CONFERENCE_ID}
Start/Stop recording the conference
The record
action takes a toggle of “start” or “stop”:
curl -v -X PUT \
-d '{"action": "record", "data": {"action":"start"}}' \
-H "X-Auth-Token: {AUTH_TOKEN}" \
http://{SERVER}:8000/v2/accounts/{ACCOUNT_ID}/conferences/{CONFERENCE_ID}
Set custom conference variables
This action allows the client to associate custom conference variables on a running (active) conference. No effect if the conference isn’t running.
Optionally, a SIP NOTIFY can be sent to participants with the X-Conference-Vars
header where the key/value pairs will be encoded X-Conference-Vars: key=value;key-value
curl -v -X PUT \
-d '{"action":"vars","data":{"custom_conference_vars":{"key_the_first":"value_the_first"}}}'
-H "X-Auth-Token: {AUTH_TOKEN}" \
http://{SERVER}:8000/v2/accounts/{ACCOUNT_ID}/conferences/{CONFERENCE_ID}
When the conference config is fetched, custom conference variables will appear in the metadata
top-level key.
Dialing an endpoint
Sometimes you want to dial out from a conference to an endpoint (versus waiting for the caller to dial into the conference). Similar to how the group
callflow works, you can include device and user IDs; unlike groups, you can include DIDs as well (similar to quickcall/click2call).
Schema
Schema for conferences
Key | Description | Type | Default | Required | Support Level |
---|---|---|---|---|---|
allow_shareable_link | Indicates if the conference is reachable using a public link | boolean() | false | false | |
base_profile_name | name of base profile | string() | false | ||
bridge_password | the password used for a conference bridge | string() | false | ||
bridge_username | the username used for a conference bridge | string() | false | ||
caller_controls | caller controls (config settings) | string() | false | ||
conference_numbers.[] | string() | false | |||
conference_numbers | Defines conference numbers that can be used by members or moderators | array(string()) | [] | false | |
controls | controls | object() | false | ||
domain | domain | string() | false | ||
flags.[] | string() | false | supported | ||
flags | Flags set by external applications | array(string()) | false | supported | |
focus | This is a read-only property indicating the media server hosting the conference | string() | false | ||
language | Prompt language to play in the conference | string() | false | ||
max_members_media | Media to play when the conference is full | string() | false | ||
max_participants | The maximum number of participants that can join | integer() | false | ||
member.join_deaf | Determines if a member will join deaf | boolean() | false | false | supported |
member.join_muted | Determines if a member will join muted | boolean() | true | false | supported |
member.numbers.[] | string() | false | |||
member.numbers | Defines the conference (call in) number(s) for members | array(string()) | [] | false | |
member.pins.[] | string() | false | |||
member.pins | Defines the pin number(s) for members | array(string()) | [] | false | |
member.play_entry_prompt | Whether to play the entry prompt on member join | boolean() | false | ||
member | Defines the discovery (call in) properties for a member | object() | {} | false | |
moderator.join_deaf | Determines if a moderator will join deaf | boolean() | false | false | |
moderator.join_muted | Determines if a moderator will join muted | boolean() | false | false | |
moderator.numbers.[] | string() | false | |||
moderator.numbers | Defines the conference (call in) number(s) for moderators | array(string()) | [] | false | |
moderator.pins.[] | string() | false | |||
moderator.pins | Defines the pin number(s) for moderators | array(string()) | [] | false | |
moderator | Defines the discovery (call in) properties for a moderator | object() | {} | false | |
moderator_controls | profile on the switch for controlling the conference as a moderator | string() | false | ||
name | A friendly name for the conference | string(1..128) | true | supported | |
owner_id | The user ID who manages this conference | string(32) | false | supported | |
play_entry_tone | Whether to play an entry tone, or the entry tone to play | `boolean() | string()` | false | |
play_exit_tone | Whether to play an exit tone, or the exit tone to play | `boolean() | string()` | false | |
play_name | Do we need to announce new conference members? | boolean() | false | false | |
play_welcome | Whether to play the welcome prompt | boolean() | false | ||
profile | Profile configuration | object() | false | ||
profile_name | conference profile name | string() | false | ||
require_moderator | does the conference require a moderator | boolean() | false | ||
video | If false, video participants will join with video muted | boolean() | false | ||
wait_for_moderator | should members wait for a moderator before joining the conference | boolean() | false |
conferences.profile
Schema for conference profiles
Key | Description | Type | Default | Required | Support Level |
---|---|---|---|---|---|
alone-sound | Audio that plays while you are alone in the conference | string() | false | ||
announce-count | Play member count to conference when above this threshold | integer() | false | ||
caller-controls | Name of the caller control group | string() | false | ||
comfort-noise | The volume level of background white noise | integer(0..10000) | false | ||
energy-level | Energy level required for audio to be sent to other users | integer(0..1800) | false | ||
enter-sound | Audio to play when entering a conference | string() | false | ||
exit-sound | Audio to play when exiting a conference | string() | false | ||
interval | Milliseconds per frame | integer(10..120) | false | ||
locked-sound | Audio to play when the conference is locked | string() | false | ||
max-members | Set the maximum number of members in the conference | integer(2..) | false | ||
max-members-sound | If max-members has been reached, audio to play to caller instead of joining the conference | string() | false | ||
moderator-controls | Name of the moderator control group to use | string() | false | ||
moh-sound | Audio to play, on a loop, while participant count is 1 | string() | false | ||
muted-sound | Audio to play when muted | string() | false | ||
rate | Audio sample rate | integer() | false | ||
unmuted-sound | Audio to play when unmuted | string() | false |
Endpoints
Dial-able endpoints are
- Devices (by device id or device JSON)
- Users (by user id)
- Phone Numbers
- SIP URIs (
sip:user@realm
)
Note: Phone numbers will involve some internal legs being generated (loopback legs) to process the number as if it was a call coming in for the desired number. This means billing and limits will be applied just the same as if a user dialed the number from their device.
Dial schema
Schema for conference dial API command
Key | Description | Type | Default | Required | Support Level |
---|---|---|---|---|---|
caller_id_name | Caller ID Name to use when dialing out to endpoints | string() | false | ||
caller_id_number | Caller ID Number to use when dialing out to endpoints | string() | false | ||
endpoints.[] | `string() | #/definitions/devices` | |||
endpoints | Endpoints to dial out to and join to the conference | array() | true | ||
participant_flags.[] | `string(‘mute' | 'deaf' | 'distribute_dtmf' | 'is_moderator' | |
participant_flags | Participant flags applied to each endpoint when it joins the conference | `array(string(‘mute' | 'deaf' | 'distribute_dtmf' | 'is_moderator' |
profile_name | The profile name to use for configuration | string() | false | ||
target_call_id | Existing UUID to use as a hint for where to start the conference | string() | false | ||
timeout | How long to try to reach the endpoint(s) | integer() | false |
Example payloads
{
"action":"dial"
,"data":{
"data":{
"endpoints":["{DEVICE_ID}","{USER_ID}","{NUMBER}","sip:{URI}"],
"caller_id_name":"Conference XYZ",
"caller_id_number":"5551212"
}
}
}
As when making QuickCalls, you can include custom_application_vars
:
{
"action":"dial"
,"data":{
"custom_application_vars":{
"foo":"bar"
}
,"data":{
"endpoints":["{DEVICE_ID}","{USER_ID}","{NUMBER}","sip:{URI}"],
"caller_id_name":"Conference XYZ",
"caller_id_number":"5551212"
}
}
}
You can also include the outbound call id you’d like the leg to use:
{
"action":"dial"
,"data":{
"custom_application_vars":{
"foo":"bar"
}
,"data":{
"endpoints":["{DEVICE_ID}","{USER_ID}","{NUMBER}","sip:{URI}"],
"caller_id_name":"Conference XYZ",
"caller_id_number":"5551212",
"outbound_call_id":"xyz-abc"
}
}
}
Participant Flags
You can specify how a participant will enter a conference with a list of attributes:
Value | Description |
---|---|
deaf | Participant joins unable to hear conference audio |
disable_moh | Disable music on hold when the participant is the only one in the conference |
distribute_dtmf | Send DTMF from participant’s leg to all other participants |
ghost | Uncounted in conference membership total |
is_moderator | Participant will join as a moderator |
join_existing | Participant may only join a running conference (won’t start a conference) |
mute | Participant joins muted |
video_mute | Participant joins with video stream muted |
{
"action":"dial"
,"data":{
"data":{
"endpoints":["{DEVICE_ID}","{USER_ID}","{NUMBER}","sip:{URI}"],
"caller_id_name":"Conference XYZ",
"caller_id_number":"5551212",
"participant_flags":["deaf", "mute"]
}
}
}
Dialing out to a dynamic conference
Sometimes you want to create ad-hoc conferences and put a participant in there. You can PUT
a conference and the endpoints to dial out to create a temporary conference. The {CONFERENCE_ID}
you supply will be used to name the conference and any conference schema parameters in the request will be used when creating the conference. For example:
{
"action":"dial"
,"data":{
"data":{
"endpoints":["{DEVICE_ID}","{USER_ID}","{NUMBER}","sip:{URI}"],
"caller_id_name":"Conference XYZ",
"caller_id_number":"5551212",
"play_entry_tone": true,
"play_exit_tone": true,
"play_name": false
}
}
}
These properties will be merged into a “default” conference document and then executed the same as if the conference was preconfigured.
The API response
{
"data": {
"endpoint_responses": [
{
"call_id": "{CALL_ID}",
"endpoint_id": "{ENDPOINT_FROM_REQUEST}",
"job_id": "{JOB_ID}",
"message": "dial resulted in call id {CALL_ID}",
"status": "success"
}
]
}
,...
}
Playing media to a conference
Playing a media file to everyone in a conference:
{
"action":"play",
"data": {
"data":{"media_id":"{MEDIA_ID}"}
}
}
{MEDIA_ID}
can be a pre-uploaded media ID or a URL to fetch media from.
Perform an action on participants
PUT /v2/accounts/{ACCOUNT_ID}/conferences/{CONFERENCE_ID}/participants
curl -v -X PUT \
-d '{"data": {"action": {PARTICIPANTS_ACTION}}}' \
-H "X-Auth-Token: {AUTH_TOKEN}" \
http://{SERVER}:8000/v2/accounts/{ACCOUNT_ID}/conferences/{CONFERENCE_ID}/participants
Action | Description |
---|---|
mute | Mute all the participants that are currently unmuted |
unmute | Unmute all the participants that are currently muted |
deaf | Stop sending conference audio to all participants |
undeaf | Start sending conference audio to all participants |
kick | Kick all the participants from the conference |
relate | Relate two participants |
Relate participants
The relate
action takes a data
object:
{
"data":{
"action":"relate"
,"data":{
"participant_id":{ID}
,"other_participant":{ID}
,"relationship":"{RELATIONSHIP}"
}
}
}
Schema
Relate two participants to each other in a conference
Key | Description | Type | Default | Required | Support Level |
---|---|---|---|---|---|
conference_id | The ID of the conference | string() | true | ||
other_participant | The other participant ID to relate | `string() | integer()` | true | |
participant_id | The participant ID to relate | `string() | integer()` | true | |
relationship | The relationship to establish between the two participants | `string(‘deaf' | 'clear' | 'mute’)` | clear |
API example
curl -v -X PUT \
-H "X-Auth-Token: $AUTH_TOKEN" \
"http://{SERVER}:8000/v2/accounts/{ACCOUNT_ID}/conferences/{CONFERENCE_ID}/participants" \
-d'{"data":{"action":"relate","data":{"participant_id":23, "other_participant":24}}}'
{
"auth_token": "{AUTH_TOKEN}",
"data": "relating participants",
"node": "{NODE}",
"request_id": "{REQUEST_ID}",
"revision": "1-100475067fa624422c9a21bd976c7b84",
"status": "success",
"timestamp": "{TIMESTAMP}",
"version": "4.2.2"
}
Perform an action on participant
PUT /v2/accounts/{ACCOUNT_ID}/conferences/{CONFERENCE_ID}/participants/{PARTICIPANT_ID}
curl -v -X PUT \
-d '{"data": {"action": {PARTICIPANT_ACTION}}}' \
-H "X-Auth-Token: {AUTH_TOKEN}" \
http://{SERVER}:8000/v2/accounts/{ACCOUNT_ID}/conferences/{CONFERENCE_ID}/participants/{PARTICIPANT_ID}
Sometimes you may get a HTTP/1.1 304 Not Modified response from crossbar for similar API calls. If you do, add a random string filter to the end of the call to ensure the request is viewed as ‘unique’. For example:
curl -v -X PUT \
-d '{"data": {"action": {PARTICIPANT_ACTION}}}' \
-H "X-Auth-Token: {AUTH_TOKEN}" \
http://{SERVER}:8000/v2/accounts/{ACCOUNT_ID}/conferences/{CONFERENCE_ID}/participants/{PARTICIPANT_ID}?random={RANDOM_BIT}
Action | Description |
---|---|
mute | Mute the participant |
unmute | Unmute the participant |
deaf | Stop sending conference audio to the participant |
undeaf | Start sending conference audio to the participant |
kick | Kick the participant from the conference |
play | Play media to a single participant |
Playing media to a conference
Playing a media file to everyone in a conference:
{"data":{
"action":"play",
"data":{"media_id":"{MEDIA_ID}"}
}
}
{MEDIA_ID}
can be a pare-uploaded media ID or a URL to fetch media from.
List of conferences example
[
{
"id": "",
"name": "",
"owner_id": "",
"member": {
"join_muted": false,
"join_deaf": false,
"numbers": [],
"pins": []
},
"moderator": {
"join_deaf": false,
"join_muted": false,
"numbers": [],
"pins": []
},
"members": 0,
"admins": 0,
"duration": 0,
"is_locked": false
},
...
]
Conference document
{
"name": "Conf",
"id": "",
"owner_id": "",
"play_entry_tone": true,
"play_exit_tone": true,
"play_name": false,
"conference_numbers": [],
"member": {
"join_muted": false,
"join_deaf": false,
"numbers": [],
"pins": []
},
"ui_metadata": {
"ui": "kazoo-ui"
},
"moderator": {
"join_deaf": false,
"join_muted": false,
"numbers": [],
"pins": []
},
"_read_only": {
"members": 0,
"admins": 0,
"duration": 0,
"is_locked": false,
"participants": [
{
"call_id": "",
"conference_name": "",
"conference_uuid": "",
"switch_hostname": "",
"floor": false,
"hear": true,
"speak": true,
"talking": false,
"mute_detect": false,
"participant_id": 1,
"energy_level": 20,
"current_energy": 0,
"video": false,
"is_moderator": false,
"join_time": 63635217275,
"duration": 10
},
...
]
}
}
join_time
is participant’s join time as epoch, duration is number of seconds participant participate in conference.
Here we can see values set up for a Member, then for a Moderator.
The last field, play_entry_tone
, is at the root of the document: meaning this field applies to everyone in the conference.
Available fields
- play_entry_tone and play_exit_tone: can be either a boolean or a non-empty string.
true
means play the default tone when someone joins (or leaves) the conferencefalse
disables the tone from being played- A string like a tone string or a URI to a media file can be inputted.
Web-socket events
A client may subscribe to conference event using websocket connection. Participant events are published as
amqp conference.event.{conference_id}.{call_id}
, where call_id is participant”s call.
The list of published events is determined by publish_participant_event
parameter of ecallmgr configuration,
if parameter is unset, then all events are published.
Participant events
add-member
del-member
stop-talking
start-talking
mute-member
unmute-member
deaf-member
undeaf-member
Example event
{
"custom_channel_vars": {
"account_id": "{ACCOUNT_ID}",
"authorizing_id": "{AUTHZ_ID}",
"authorizing_type": "device",
"owner_id": "{OWNER_ID}",
"presence_id": "1000@kamailio.kazoo",
"fetch_id": "{FETCH_ID}",
"bridge_id": "{BRIDGE_ID}",
"precedence": 5,
"realm": "kamailio.kazoo",
"username": "sip1",
"call_interaction_id": "{INTERACTION_ID}"
},
"channel_presence_id": "1000@kamailio.kazoo",
"caller_id_number": "sip1",
"caller_id_name": "sip1",
"mute_detect": false,
"video": false,
"energy_level": 20,
"current_energy": 0,
"talking": false,
"speak": true,
"hear": true,
"floor": false,
"participant_id": 20,
"instance_id": "{INSTANCE_ID}",
"conference_id": "{CONFERENCE_ID}",
"focus": "freeswitch@freeswitch.kazoo",
"call_id": "{CALL_ID}",
"event": "add-member",
"node": "kazoo_apps@kazoo.kazoo",
"msg_id": "{MSG_ID}",
"event_name": "participant_event",
"event_category": "conference",
"app_version": "4.0.0",
"app_name": "ecallmgr",
"routing_key": "participant_event"
}
Email Invite
conferences.email_invite
Schema for conference email_invite
Key | Description | Type | Default | Required | Support Level |
---|---|---|---|---|---|
conference_link | Link to join the conference | string() | true | supported | |
guests.[] | string() | true | supported | ||
guests | List of email recipients to be invited to the conference | array(string()) | true | supported | |
invite_message | Invite message | string() | true | supported |
Send Invite
PUT /v2/accounts/{ACCOUNT_ID}/conferences/{CONFERENCE_ID}/email_invite
curl -v -X PUT \
-H "X-Auth-Token: {AUTH_TOKEN}" \
-d '{"data": {"conference_link": "http://link.to/my-conference", \
"invite_message": "invite message", \
"guests": ["email1@domain.com", "email2@domain.com"]}}' \
http://{SERVER}:8000/v2/accounts/{ACCOUNT_ID}/conferences/{CONFERENCE_ID}/email_invite
{
"version": "{VSN}",
"timestamp": "2021-04-22T15:10:33Z",
"node": "{NODE}",
"request_id": "{REQUEST_ID}",
"tokens": {
"consumed": 1,
"remaining": 100
},
"auth_token": "{AUTH_TOKEN}",
"data": "request accepted",
"status": "success"
}