This document is for an older version of Kazoo (version 4.3) that is no longer supported. You should upgrade and read the current documentation.

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 _read_only key (to avoid accident document update).

Schema

Schema for conferences

KeyDescriptionTypeDefaultRequiredSupport Level
bridge_passwordthe password used for a conference bridgestring()false
bridge_usernamethe username used for a conference bridgestring()false
caller_controlscaller controls (config settings)string()false
conference_numbers.[]string()false
conference_numbersDefines conference numbers that can be used by members or moderatorsarray(string())[]false
controlscontrolsobject()false
domaindomainstring()false
flags.[]string()falsesupported
flagsFlags set by external applicationsarray(string())falsesupported
focusThis is a read-only property indicating the media server hosting the conferencestring()false
languagePrompt language to play in the conferencestring()false
max_members_mediaMedia to play when the conference is fullstring()false
max_participantsThe maximum number of participants that can joininteger()false
member.join_deafDetermines if a member will join deafboolean()falsefalsesupported
member.join_mutedDetermines if a member will join mutedboolean()truefalsesupported
member.numbers.[]string()false
member.numbersDefines the conference (call in) number(s) for membersarray(string())[]false
member.pins.[]string()false
member.pinsDefines the pin number(s) for membersarray(string())[]false
member.play_entry_promptWhether to play the entry prompt on member joinboolean()false
memberDefines the discovery (call in) properties for a memberobject(){}false
moderator.join_deafDetermines if a moderator will join deafboolean()falsefalse
moderator.join_mutedDetermines if a moderator will join mutedboolean()falsefalse
moderator.numbers.[]string()false
moderator.numbersDefines the conference (call in) number(s) for moderatorsarray(string())[]false
moderator.pins.[]string()false
moderator.pinsDefines the pin number(s) for moderatorsarray(string())[]false
moderatorDefines the discovery (call in) properties for a moderatorobject(){}false
moderator_controlsprofile on the switch for controlling the conference as a moderatorstring()false
nameA friendly name for the conferencestring(1..128)falsesupported
owner_idThe user ID who manages this conferencestring(32)falsesupported
play_entry_toneWhether to play an entry tone, or the entry tone to play`boolean()string()`false
play_exit_toneWhether to play an exit tone, or the exit tone to play`boolean()string()`false
play_nameDo we need to announce new conference members?boolean()falsefalse
play_welcomeWhether to play the welcome promptboolean()false
profileProfile configurationobject()false
profile_nameconference profile namestring()false
require_moderatordoes the conference require a moderatorboolean()false
wait_for_moderatorshould members wait for a moderator before joining the conferenceboolean()false

conferences.profile

Schema for conference profiles

KeyDescriptionTypeDefaultRequiredSupport Level
alone-soundAudio that plays while you are alone in the conferencestring()false
announce-countPlay member count to conference when above this thresholdinteger()false
caller-controlsName of the caller control groupstring()false
comfort-noiseThe volume level of background white noiseinteger()false
energy-levelEnergy level required for audio to be sent to other usersinteger()false
enter-soundAudio to play when entering a conferencestring()false
exit-soundAudio to play when exiting a conferencestring()false
intervalMilliseconds per frameinteger()false
locked-soundAudio to play when the conference is lockedstring()false
max-membersSet the maximum number of members in the conferenceinteger()false
max-members-soundIf max-members has been reached, audio to play to caller instead of joining the conferencestring()false
moderator-controlsName of the moderator control group to usestring()false
moh-soundAudio to play, on a loop, while participant count is 1string()false
muted-soundAudio to play when mutedstring()false
rateAudio sample rateinteger()false
unmuted-soundAudio to play when unmutedstring()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}
ActionDescription
lockLock the conference; no new participants may join
unlockUnlock the conference; new participants may join
dialDial an endpoint (user/device/DID)
playPlay media to the conference (all participants)
recordStart/stop the recording of 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}

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

KeyDescriptionTypeDefaultRequiredSupport Level
bridge_passwordthe password used for a conference bridgestring()false
bridge_usernamethe username used for a conference bridgestring()false
caller_controlscaller controls (config settings)string()false
conference_numbers.[]string()false
conference_numbersDefines conference numbers that can be used by members or moderatorsarray(string())[]false
controlscontrolsobject()false
domaindomainstring()false
flags.[]string()falsesupported
flagsFlags set by external applicationsarray(string())falsesupported
focusThis is a read-only property indicating the media server hosting the conferencestring()false
languagePrompt language to play in the conferencestring()false
max_members_mediaMedia to play when the conference is fullstring()false
max_participantsThe maximum number of participants that can joininteger()false
member.join_deafDetermines if a member will join deafboolean()falsefalsesupported
member.join_mutedDetermines if a member will join mutedboolean()truefalsesupported
member.numbers.[]string()false
member.numbersDefines the conference (call in) number(s) for membersarray(string())[]false
member.pins.[]string()false
member.pinsDefines the pin number(s) for membersarray(string())[]false
member.play_entry_promptWhether to play the entry prompt on member joinboolean()false
memberDefines the discovery (call in) properties for a memberobject(){}false
moderator.join_deafDetermines if a moderator will join deafboolean()falsefalse
moderator.join_mutedDetermines if a moderator will join mutedboolean()falsefalse
moderator.numbers.[]string()false
moderator.numbersDefines the conference (call in) number(s) for moderatorsarray(string())[]false
moderator.pins.[]string()false
moderator.pinsDefines the pin number(s) for moderatorsarray(string())[]false
moderatorDefines the discovery (call in) properties for a moderatorobject(){}false
moderator_controlsprofile on the switch for controlling the conference as a moderatorstring()false
nameA friendly name for the conferencestring(1..128)falsesupported
owner_idThe user ID who manages this conferencestring(32)falsesupported
play_entry_toneWhether to play an entry tone, or the entry tone to play`boolean()string()`false
play_exit_toneWhether to play an exit tone, or the exit tone to play`boolean()string()`false
play_nameDo we need to announce new conference members?boolean()falsefalse
play_welcomeWhether to play the welcome promptboolean()false
profileProfile configurationobject()false
profile_nameconference profile namestring()false
require_moderatordoes the conference require a moderatorboolean()false
wait_for_moderatorshould members wait for a moderator before joining the conferenceboolean()false

conferences.profile

Schema for conference profiles

KeyDescriptionTypeDefaultRequiredSupport Level
alone-soundAudio that plays while you are alone in the conferencestring()false
announce-countPlay member count to conference when above this thresholdinteger()false
caller-controlsName of the caller control groupstring()false
comfort-noiseThe volume level of background white noiseinteger()false
energy-levelEnergy level required for audio to be sent to other usersinteger()false
enter-soundAudio to play when entering a conferencestring()false
exit-soundAudio to play when exiting a conferencestring()false
intervalMilliseconds per frameinteger()false
locked-soundAudio to play when the conference is lockedstring()false
max-membersSet the maximum number of members in the conferenceinteger()false
max-members-soundIf max-members has been reached, audio to play to caller instead of joining the conferencestring()false
moderator-controlsName of the moderator control group to usestring()false
moh-soundAudio to play, on a loop, while participant count is 1string()false
muted-soundAudio to play when mutedstring()false
rateAudio sample rateinteger()false
unmuted-soundAudio to play when unmutedstring()false

Endpoints

Dial-able endpoints are

  1. Devices (by device id or device JSON)
  2. Users (by user id)
  3. Phone Numbers
  4. 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.

Examples

{
    "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:

ValueDescription
deafParticipant joins unable to hear conference audio
disable_mohDisable music on hold when the participant is the only one in the conference
distribute_dtmfSend DTMF from participant’s leg to all other participants
ghostUncounted in conference membership total
is_moderatorParticipant will join as a moderator
join_existingParticipant may only join a running conference (won’t start a conference)
muteParticipant joins muted
video_muteParticipant 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": "522bb682-da03-11e7-8ce9-5364ba916f96",
                "endpoint_id": "{ENDPOINT_FROM_REQUEST}",
                "job_id": "137b1e9e-d9fb-11e7-8cad-5364ba916f96",
                "message": "dial resulted in call id 522bb682-da03-11e7-8ce9-5364ba916f96",
                "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
ActionDescription
muteMute all the participants that are currently unmuted
unmuteUnmute all the participants that are currently muted
deafStop sending conference audio to all participants
undeafStart sending conference audio to all participants
kickKick all the participants from the conference
relateRelate 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

KeyDescriptionTypeDefaultRequiredSupport Level
conference_idThe ID of the conferencestring()true
other_participantThe other participant ID to relate`string()integer()`true
participant_idThe participant ID to relate`string()integer()`true
relationshipThe 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}
ActionDescription
muteMute the participant
unmuteUnmute the participant
deafStop sending conference audio to the participant
undeafStart sending conference audio to the participant
kickKick the participant from the conference
playPlay 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 conference
    • false 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": "9d351ad7ffd6f846313af9eed3bb7b85",
        "authorizing_id": "6507f40b09a61fbb8b025dbad9316eb5",
        "authorizing_type": "device",
        "owner_id": "32d8788da9506b4b1991d5bb86d27b0a",
        "presence_id": "1000@kamailio.kazoo",
        "fetch_id": "56507071-a216-4e0a-a28f-ff3bd9c86ac3",
        "bridge_id": "934800819",
        "precedence": 5,
        "realm": "kamailio.kazoo",
        "username": "sip1",
        "call_interaction_id": "63635497023-3e247b2e"
    },
    "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": "d5765180-53d5-4104-860e-b352f3f8e6b1",
    "conference_id": "5edbfdd3b825314a71b0a05957392edb",
    "focus": "freeswitch@freeswitch.kazoo",
    "call_id": "934800819",
    "event": "add-member",
    "node": "kazoo_apps@jh460",
    "msg_id": "a6fbbf034b5cd3af",
    "event_name": "participant_event",
    "event_category": "conference",
    "app_version": "4.0.0",
    "app_name": "ecallmgr",
    "routing_key": "participant_event"
}