CTI Protocol
Protocol Changelog
The versions below indicate the xivo version followed by the protocol version.
Warning
The CTI server protocol is subject to change without any prior warning. If you are using this protocol in your own tools please be sure to check that the protocol did not change before upgrading XiVO
16.11 - 2.2
the user_id field has been added back to the User status update
16.09 - 2.2
the Register user status update now uses the user_uuid instead of the user_id
the User status update now uses the user_uuid instead of the user_id
16.04 - 2.1
the Chitchat command to and from fields are now a list of two strings, xivo_uuid and user_uuid.
16.01 - 2.0
the lastconnswins field has been removed from the Login capas command
the loginkind field has been removed from the Login capas command
the ipbxcommands and regcommands capakinds have been removed from Login capas command
the Login password command has been modified. The hashedpassword has been replaced by the password field which is now sent verbatim.
15.20 - 1.2
the STARTTLS command has been added
15.19 - 1.2
the Chitchat command to field is now a list of two elements, xivo_uuid and user_id.
the
getlist
command has been removed for the channels listname.many fields have been removed from the
getlist
command.users list
enableclient
profileclient
phones
context
protocol
simultcalls
channels
voicemails
email
fullname
old
waiting
agents
phonenumber
some ipbxcommands have been removed:
mailboxcount
atxfer
transfer
hangup
originate
15.18 - 1.2
add the Attended transfer to voicemail command
add the Blind transfer to voicemail command
the Send fax command now include the size and data field.
the filetransfer command has been removed.
15.16 - 1.2
the Get relations command was added.
the Relations message was added.
15.14 - 1.2
the
people_purge_personal_contacts
message was added.the
people_personal_contacts_purged
message was added.the
people_personal_contact_raw
message was added.the
people_personal_contact_raw_result
message was added.the
people_edit_personal_contact
message was added.the
people_personal_contact_raw_update
message was added.the
people_import_personal_contacts_csv
message was added.the
people_import_personal_contacts_csv_result
message was added.the
people_export_personal_contacts_csv
message was added.the
people_export_personal_contacts_csv_result
message was added.for messages
people_personal_contact_deleted
andpeople_favorite_update
there are no longerdata
sub-key.
15.13 - 1.2
for
channel status update
message:the value of
commstatus
have been changed fromlinked-caller
andlinked-called
tolinked
.the key
direction
have been removed.the key
talkingto_kind
have been removed.
the
people_personal_contacts
message was added.the
people_personal_contacts_result
message was added.the
people_create_personal_contact
message was added.the
people_personal_contact_created
message was added.the
people_delete_personal_contact
message was added.the
people_personal_contact_deleted
message was added.
15.12 - 1.2
people_search_result
has a new key inrelations
:source_entry_id
the
people_favorites
message was added.the
people_favorites_result
message was added.the
people_set_favorite
message was added.the
people_favorite_update
message was added.
15.11 - 1.2
the
fax_progress
message was added.
15.09 - 1.2
for messages of class
history
the client cannot request by mode anymore. The server returns all calls and the mode is now metadata for each call.
14.24 - 1.2
for messages of class
ipbxcommand
, the commandrecord
andsipnotify
have been removed.the
logfromclient
message has been removed
14.22 - 1.2
for messages of class
faxsend
, the stepsfile_decoded
andfile_converted
have been removed.
14.06 - 1.2
the
dial_success
message was added
14.05 - 1.2
the
unhold_switchboard
command was renamedresume_switchboard
.
13.22 - 1.2
the
actionfiche
message was renamedcall_form_result
.
13.17 - 1.2
for messages of class
login_capas
from server to client: the keypresence
has been removed.
13.14 - 1.2
for messages of class
getlist
, listagents
and functionupdatestatus
: the keyavailability
in thestatus
object/dictionary has changed values:deleted values:
on_call_non_acd_incoming
andon_call_non_acd_outgoing
added values: *
on_call_non_acd_incoming_internal
*on_call_non_acd_incoming_external
*on_call_non_acd_outgoing_internal
*on_call_non_acd_outgoing_external
13.12 - 1.2
for messages of class
getlist
, listagents
and functionupdatestatus
: the keyavailability
in thestatus
object/dictionary has changed values:deleted value:
on_call_non_acd
added values:
on_call_non_acd_incoming
andon_call_non_acd_outgoing
13.10 - 1.2
for messages of class
getlist
and functionupdateconfig
, theconfig
object/dictionary does not have arules_order
key anymore.
Commands
Objects have the format: “<type>:<xivoid>/<typeid>”
<type> can take any of the following values: user, agent, queue, phone, group, meetme, …
<xivoid> indicates on which server the object is defined
<typeid> is the object id, type dependant
- e.g.
user:xivo-test/5 I’m looking for the user that has the ID 5 on the xivo-test server.
Here is a non exaustive list of types:
exten
user
vm_consult
voicemail
Agent
Login agent
Client -> Server
{"agentphonenumber": "1000", "class": "ipbxcommand", "command": "agentlogin", "commandid": 733366597}
agentphonenumber is the physical phone set where the agent is going to log on.
Server > Client
Login successfull :
{"function": "updateconfig",
"listname": "queuemembers",
"tipbxid": "xivo",
"timenow": 1362664323.94,
"tid": "Agent/2002,blue",
"config": {"paused": "0",
"penalty": "0",
"membership": "static",
"status": "1",
"lastcall": "",
"interface": "Agent/2002",
"queue_name": "blue",
"callstaken": "0"},
"class": "getlist"}
{"function": "updatestatus",
"listname": "agents",
"tipbxid": "xivo",
"timenow": 1362664323.94,
"status": {"availability_since": 1362664323.94,
"queues": [],
"on_call": false,
"availability": "available",
"channel": null},
"tid": 7,
"class": "getlist"}
The phone number is already used by an other agent :
{"class": "ipbxcommand", "error_string": "agent_login_exten_in_use", "timenow": 1362664158.14}
Logout agent
Client -> Server
{"class": "ipbxcommand", "command": "agentlogout", "commandid": 552759274}
Pause
On all queues
Client -> Server
{"class": "ipbxcommand", "command": "queuepause", "commandid": 859140432, "member": "agent:xivo/1", "queue": "queue:xivo/all"}
Un pause agent
On all queues
Client -> Server
{"class": "ipbxcommand", "command": "queueunpause", "commandid": 822604987, "member": "agent:xivo/1", "queue": "queue:xivo/all"}
Add an agent in a queue
Client -> Server
{"class": "ipbxcommand", "command": "queueadd", "commandid": 542766213, "member": "agent:xivo/3", "queue": "queue:xivo/2"}
Remove an agent from a queue
Client -> Server
{"class": "ipbxcommand", "command": "queueremove", "commandid": 742480296, "member": "agent:xivo/3", "queue": "queue:xivo/2"}
Listen to an agent
Client -> Server
{"class": "ipbxcommand", "command": "listen", "commandid": 1423579492, "destination": "xivo/1", "subcommand": "start"}
Configuration
The following messages are used to retrieve XiVO configuration.
Common fields
class : getlist
function : listid
commandid
tipbxid
listname : Name of the list to be retreived : users, phones, agents, queues, voicemails, queuemembers
{
"class": "getlist",
"commandid": 489035169,
"function": "listid",
"tipbxid": "xivo",
"listname": "........."
}
Users configuration
Return a list of configured user id’s
Client -> Server
{"class": "getlist", "commandid": 489035169, "function": "listid", "listname": "users", "tipbxid": "xivo"}
Server -> Client
{
"class": "getlist",
"function": "listid", "listname": "users",
"list": ["11", "12", "14", "17", "1", "3", "2", "4", "9"],
"tipbxid": "xivo","timenow": 1362735061.17
}
User configuration
Return a user configuration
tid is the userid returned by Users configuration message
Client -> Server
{
"class": "getlist",
"function": "updateconfig",
"listname": "users",
"tid": "17",
"tpbxid": "xivo", "commandid": 5}
Server -> Client
{
"class": "getlist",
"function": "updateconfig",
"listname": "users",
"tid": "17",
"tipbxid": "xivo",
"timenow": 1362741166.4,
"config": {
"enablednd": 0, "destrna": "", "enablerna": 0, "enableunc": 0, "destunc": "", "destbusy": "", "enablebusy": 0, "enablexfer": 1,
"firstname": "Alice", "lastname": "Bouzat", "fullname": "Alice Bouzat",
"voicemailid": null, "incallfilter": 0, "enablevoicemail": 0, "agentid": 2, "linelist": ["7"], "mobilephonenumber": ""}
}
Phones configuration
Client -> Server
{"class": "getlist", "commandid": 495252308, "function": "listid", "listname": "phones", "tipbxid": "xivo"}
Server > Client
{"class": "getlist", "function": "listid", "list": ["1", "3", "2", "5", "14", "7", "6", "9", "8"],
"listname": "phones", "timenow": 1364994093.38, "tipbxid": "xivo"}
Individual phone configuration request:
{"class": "getlist", "commandid": 704096693, "function": "updateconfig", "listname": "phones", "tid": "3", "tipbxid": "xivo"}
Server > Client
{"class": "getlist",
"config": {"allowtransfer": null, "identity": "SIP/ihvbur", "iduserfeatures": 1,
"initialized": null, "number": "1000"},
"function": "updateconfig", "listname": "phones", "tid": "3", "timenow": 1364994093.43, "tipbxid": "xivo"}
Agents configuration
Client -> Server
{"class": "getlist", "commandid": 1431355191, "function": "listid", "listname": "agents", "tipbxid": "xivo"}
Queues configuration
Client -> Server
{"class": "getlist", "commandid": 719950939, "function": "listid", "listname": "queues", "tipbxid": "xivo"}
Server -> Client
{"function": "listid", "listname": "queues", "tipbxid": "xivo",
"list": ["1", "10", "3", "2", "5", "4", "7", "6", "9", "8"], "timenow": 1382704649.64, "class": "getlist"}
Queue configuration
tid is the id returned in the list field of the getlist response message
Client -> Server
{"commandid":7,"class":"getlist","tid":"3","tipbxid":"xivo","function":"updateconfig","listname":"queues"}
Server -> Client
{
"function": "updateconfig", "listname": "queues", "tipbxid": "xivo", "timenow": 1382704649.69, "tid": "3",
"config":
{"displayname": "red", "name": "red", "context": "default", "number": "3002"},
"class": "getlist"}
Voicemails configuration
Client -> Server
{"class": "getlist", "commandid": 1034160761, "function": "listid", "listname": "voicemails", "tipbxid": "xivo"}
Queue members configuration
Client -> Server
{"class": "getlist", "commandid": 964899043, "function": "listid", "listname": "queuemembers", "tipbxid": "xivo"}
Server -> Client
{"function": "listid", "listname": "queuemembers", "tipbxid": "xivo",
"list": ["Agent/2501,blue", "Agent/2500,yellow", "Agent/2002,yellow", "Agent/2003,__switchboard",
"Agent/2003,blue", "Agent/108,blue", "Agent/2002,blue"],
"timenow": 1382717016.23,
"class": "getlist"}
Fax
Send fax
Client -> Server
{"class": "faxsend",
"filename": "contract.pdf",
"destination", 41400,
"size": 100000,
"data": "<base64 of the fax content>"}
Fax status
Server -> Client
pages: number of pages sent (
NULL
if FAILED)status
FAILED: Failed to send fax.
PRESENDFAX: Fax number exist and converting pdf->tiff has been done.
SUCCESS: Fax sent with success.
{"class": "fax_progress", "status": "SUCCESS", "pages": 2 }
Call control commands
Dial
destination can be any number
destination can be a pseudo URL of the form “type:ibpx/id”
Client -> Server
{
"class": "ipbxcommand",
"command": "dial",
"commandid": <commandid>,
"destination": "exten:xivo/<extension>"
}
For example :
{
"class": "ipbxcommand",
"command": "dial",
"commandid": 1683305913,
"destination": "exten:xivo/1202"
}
The server will answer with either an error or a success:
{
"class": "ipbxcommand",
"error_string": "unreachable_extension:1202",
}
{
"class": "dial_success",
"exten": "1202"
}
Attended transfer to voicemail
Transfer the current call to a given voicemail and listen to the message before completing the transfer.
Client -> Server
{
"class": "attended_transfer_voicemail",
"voicemail": "<voicemail number>"
}
Blind transfer to voicemail
Transfer the current call to a given voicemail.
Client -> Server
{
"class": "blind_transfer_voicemail",
"voicemail": "<voicemail number>"
}
Login
Once the network is connected at the socket level, the login process requires three steps. If one of these steps is omitted, the connection is reset by the cti server.
login_id, the username is sent as a login to the cti server, cti server answers by giving a sessionid
login_pass, the password is sent to the cti server, cti server answers by giving a capaid
login_capas, the capaid is returned to the server with the user’s availability, cti server answers with a list of info relevant to the user
{
"commandid": <commandid>,
"class": "login_id",
}
class: defined what class of command use.
commandid : a unique integer number.
Login ID
Client -> Server
{
"class": "login_id",
"commandid": 1092130023,
"company": "default",
"ident": "X11-LE-24079",
"lastlogout-datetime": "2013-02-19T11:13:36",
"lastlogout-stopper": "disconnect",
"userlogin": <userlogin>,
"xivoversion": "<cti protocol version>"
}
Server -> Client
{
"class": "login_id",
"sessionid": "21UaGDfst7",
"timenow": 1361268824.64,
"xivoversion": "<cti protocol version>"
}
Note
sessionid is used to calculate the hashed password in next step
Login password
Client -> Server
{
"class": "login_pass",
"password": "secret",
"commandid": <commandid>
}
Server -> Client
{
"capalist": [
2
],
"class": "login_pass",
"replyid": 1646064863,
"timenow": 1361268824.68
}
If no CTI profile is defined on XiVO for this user, the following message will be sent:
{
"error_string": "capaid_undefined",
"class": "login_pass",
"replyid": 1646064863,
"timenow": 1361268824.68
}
Note
the first element of the capalist is used in the next step login_capas
Login capas
Client -> Server
{
"capaid": 3,
"commandid": <commandid>,
"state": "available",
"class": "login_capas"
}
Server -> Client
First message, describes all the capabilities of the client, configured at the server level
presence : actual presence of the user
userid : the user id, can be used as a reference
- capas
- userstatusa list of available statuses
status name
color
selectionnable status from this status
default action to be done when this status is selected
long name
services : list of availble services
phonestatus : list of available phonestatuses with default colors and descriptive names
capaxlets : List of xlets configured for this profile
appliname
{
"class": "login_capas"
"presence": "available",
"userid": "3",
"ipbxid": "xivo",
"timenow": 1361440830.99,
"replyid": 3,
"capas": {
"preferences": false,
"userstatus": {
"available": { "color": "#08FD20",
"allowed": ["available", "away", "outtolunch", "donotdisturb", "berightback"],
"actions": {"enablednd": "false"}, "longname": "Disponible"
},
"berightback": { "color": "#FFB545",
"allowed": ["available", "away", "outtolunch", "donotdisturb", "berightback"],
"actions": {"enablednd": "false"}, "longname": "Bient\u00f4t de retour"
},
"disconnected": { "color": "#202020",
"actions": {"agentlogoff": ""}, "longname": "D\u00e9connect\u00e9"
},
/* a list of other status depends on the cti server configuration */
},
"services": ["fwdrna", "fwdbusy", "fwdunc", "enablednd"],
"phonestatus": {
"16": {"color": "#F7FF05", "longname": "En Attente"},
"1": {"color": "#FF032D", "longname": "En ligne OU appelle"},
"0": {"color": "#0DFF25", "longname": "Disponible"},
"2": {"color": "#FF0008", "longname": "Occup\u00e9"},
"-1": {"color": "#000000", "longname": "D\u00e9sactiv\u00e9"},
"4": {"color": "#FFFFFF", "longname": "Indisponible"},
"-2": {"color": "#030303", "longname": "Inexistant"},
"9": {"color": "#FF0526", "longname": "(En Ligne OU Appelle) ET Sonne"},
"8": {"color": "#1B0AFF", "longname": "Sonne"}
}
},
"capaxlets": [["identity", "grid"], ["search", "tab"], ["customerinfo", "tab", "1"], ["fax", "tab", "2"], ["dial", "grid", "2"], ["tabber", "grid", "3"], ["history", "tab", "3"], ["remotedirectory", "tab", "4"], ["features", "tab", "5"], ["people", "tab", "6"], ["conference", "tab", "7"]],
"appliname": "Client",
}
Second message describes the current user configuration
{
"function": "updateconfig",
"listname": "users",
"tipbxid": "xivo",
"timenow": 1361440830.99,
"tid": "3",
"config": {"enablednd": false},
"class": "getlist"
}
Third message describes the current user status
{
"function": "updatestatus",
"listname": "users",
"status": {"availstate": "available"},
"tipbxid": "xivo",
"tid": "3",
"class": "getlist",
"timenow": 1361440830.99
}
Others
call_form_result
This message is received when a call form is submitted from a client to the XiVO.
Client -> Server
{
"class": "call_form_result",
"commandid": <commandid>,
"infos": {"buttonname": "saveandclose",
"variables": {"XIVOFORM_varname1": "value1",
"XIVOFORM_varname2": "value2"}}
}
History
size : Size of the list to be sent by the server
Client -> Server
{
"class": "history",
"commandid": <commandid>
"size": "8",
"xuserid": "<xivoid>/<userfeaturesid>",
}
Server > Client
Send back a table of calls :
duration in seconds
extension: caller/destination extension
fullname: caller ID name
mode
0 : sent calls
1 : received calls
2 : missed calls
{
"class": "history",
"history": [
{"calldate": "2013-03-29T08:44:35.273998",
"duration": 30.148765,
"extension": "*844201",
"fullname": "Alice Wonderland",
"mode": 0},
{"calldate": "2013-03-28T16:56:48.071213",
"duration": 58.134744,
"extension": "41400",
"fullname": "41400"}
"mode": 1},
],
"replyid": 529422441,
"timenow": 1364571477.33
}
Chitchat
Client > Server
{
"class": "chitchat",
"alias": "Alice",
"text": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse venenatis velit nibh, ac condimentum felis rutrum id.",
"to": [<xivo_uuid>, <user_uuid>],
"commandid": <commandid>
}
Server > Client
The following message is received by the remote XiVO client
{
"class": "chitchat",
"from": [<xivo_uuid>, <user_uuid>],
"to": [<xivo_uuid>, <user_uuid>]
"alias": "Alice",
"text": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse venenatis velit nibh, ac condimentum felis rutrum id.",
}
Directory
Request directory information, names matching pattern ignore case.
Client -> Server
{
"class": "directory",
"commandid": 1079140548,
"pattern": "pau"
}
Server > Client
{
"class": "directory",
"headers": ["Nom", "Num\u00e9ro", "Mobile", "Autre num\u00e9ro", "E-mail", "Fonction", "Site", "Source"],
"replyid": 1079140548,
"resultlist": ["Claire Mapaurtal;;+33644558899;31256;cmapaurtal@societe.com;;;",
"Paul Salvadier;+33445236988;+33678521430;31406;psalvadier@societe.com;;;"],
"status": "ok",
"timenow": 1378798928.26
}
parking
keepalive
availstate
getipbxlist
{
"class": "getipbxlist",
"commandid": <commandid>
}
People
Get relations
This command will trigger a Relations message.
Client -> Server
{
"class": "get_relations"
}
People headers
Client -> Server
{
"class": "people_headers",
}
Server -> Client
{
"class": "people_headers_result",
"column_headers": ["Status", "Name", "Number"],
"column_types": [null, null, "number"],
}
People Search
Client -> Server
{
"class": "people_search",
"pattern": <pattern>,
}
Server -> Client
{
"class": "people_search_result",
"term": "Bob",
"column_headers": ["Firstname", "Lastname", "Phone number", "Mobile", "Fax", "Email", "Agent"],
"column_types": [null, "name", "number_office", "number_mobile", "fax", "email", "relation_agent"],
"results": [
{
"column_values": ["Bob", "Marley", "5555555", "5556666", "5553333", "mail@example.com", null],
"relations": {
"agent_id": null,
"user_id": null,
"endpoint_id": null,
"source_entry_id": null
},
"source": "my_ldap_directory"
}, {
"column_values": ["Charlie", "Boblin", "5555556", "5554444", "5552222", "mail2@example.com", null],
"relations": {
"agent_id": 12,
"user_id": 34,
"endpoint_id": 56,
"source_entry_id": "34"
},
"source": "internal"
}
]
}
Relations
This message can currently only be received as a response to the Get relations command.
The xivo_uuid is the id of the server
The user_id is the id of the current user.
The endpoint_id is the id of the line of the current user or null.
The agent_id is the id of the agent of the current user or null.
Server -> Client
{
"class": "relations",
"data": {"xivo_uuid": <the xivo uuid>,
"user_id": <the user id>,
"endpoint_id": <the endpoint id>,
"agent_id": <the agent id>}
}
Favorites list
Client -> Server
{
"class": "people_favorites",
}
Server -> Client
{
"class": "people_favorites_result",
"column_headers": ["Firstname", "Lastname", "Phone number", "Mobile", "Fax", "Email", "Agent", "Favorites"],
"column_types": [null, "name", "number_office", "number_mobile", "fax", "email", "relation_agent", "favorite"],
"results": [
{
"column_values": ["Bob", "Marley", "5555555", "5556666", "5553333", "mail@example.com", null, true],
"relations": {
"agent_id": null,
"user_id": null,
"endpoint_id": null,
"source_entry_id": "55"
},
"source": "my_ldap_directory"
}, {
"column_values": ["Charlie", "Boblin", "5555556", "5554444", "5552222", "mail2@example.com", null, true],
"relations": {
"agent_id": 12,
"user_id": 34,
"endpoint_id": 56,
"source_entry_id": "34"
},
"source": "internal"
}
]
}
Set favorite
Client -> Server
{
"class": "people_set_favorite",
"source": "my_ldap_directory"
"source_entry_id": "55"
"favorite": true
}
Server -> Client
{
"class": "people_favorite_update",
"source": "my_ldap_directory"
"source_entry_id": "55"
"favorite": true
}
STARTTLS
The STARTTLS command is used to upgrade a connection to use SSL. Once connected, the server send a starttls offer to the client which can reply with a starttls message including the status field. The server will then send a starttls message back to the client with the same status and start the handshake if the status is true.
Server -> Client
{
"class": "starttls"
}
Client -> Server -> Client
{
"class": "starttls",
"status": true
}
Note
a client which does not reply to the starttls offer will keep it’s unencrypted connection.
Personal contacts list
Client -> Server
{
"class": "people_personal_contacts"
}
Server -> Client
{
"class": "people_personal_contacts_result",
"column_headers": ["Firstname", "Lastname", "Phone number", "Mobile", "Fax", "Email", "Agent", "Favorites", "Personal"],
"column_types": [null, "name", "number_office", "number_mobile", "fax", "email", "relation_agent", "favorite", "personal"],
"results": [
{
"column_values": ["Bob", "Marley", "5555555", "5556666", "5553333", "mail@example.com", null, false, true],
"relations": {
"agent_id": null,
"user_id": null,
"endpoint_id": null,
"source_entry_id": "abcd-12"
},
"source": "personal"
}, {
"column_values": ["Charlie", "Boblin", "5555556", "5554444", "5552222", "mail2@example.com", null, false, true],
"relations": {
"agent_id": null,
"user_id": null,
"endpoint_id": null,
"source_entry_id": "efgh-34"
},
"source": "personal"
}
]
}
Personal contact purge
Client -> Server
{
"class": "people_purge_personal_contacts",
}
Server -> Client
{
"class": "people_personal_contacts_purged",
}
Personal contact raw
Client -> Server
{
"class": "people_personal_contact_raw",
"source": "personal",
"source_entry_id": "abcd-1234"
}
Server -> Client
{
"class": "people_personal_contact_raw_result",
"source": "personal",
"source_entry_id": "abcd-1234",
"contact_infos": {
"firstname": "Bob",
"lastname": "Wonderland"
...
}
}
Create personal contact
Client -> Server
{
"class": "people_create_personal_contact",
"contact_infos": {
"firstname": "Bob",
"lastname": "Wonderland",
...
}
}
Server -> Client
{
"class": "people_personal_contact_created"
}
Delete personal contact
Client -> Server
{
"class": "people_delete_personal_contact",
"source": "personal",
"source_entry_id": "abcd-1234"
}
Server -> Client
{
"class": "people_personal_contact_deleted",
"source": "personal",
"source_entry_id": "abcd-1234"
}
Edit personal contact
Client -> Server
{
"class": "people_edit_personal_contact",
"source": "personal",
"source_entry_id": "abcd-1234",
"contact_infos": {
"firstname": "Bob",
"lastname": "Wonderland",
...
}
}
Server -> Client
{
"class": "people_personal_contact_raw_update",
"source": "personal",
"source_entry_id": "abcd-1234"
}
Import personal contacts
Client -> Server
{
"class": "people_import_personal_contacts_csv",
"csv_contacts": "firstname,lastname\r\nBob,the Builder\r\n,Alice,Wonderland\r\n,BobMissingFields\r\n"
}
Server -> Client
{
"class": "people_import_personal_contacts_csv_result",
"created_count": 2,
"failed": [
{
"line": 3,
"errors": [
"missing fields"
]
}
]
}
Export personal contacts
Client -> Server
{
"class": "people_export_personal_contacts_csv",
}
Server -> Client
{
"class": "people_export_personal_contacts_csv_result",
"csv_contacts": "firstname,lastname\r\nBob,the Builder\r\n,Alice,Wonderland\r\n"
}
Service
class : featuresput
Call Filtering
function : incallfilter
value : true, false activate deactivate filtering
Client -> Server
{"class": "featuresput", "commandid": 1326845972, "function": "incallfilter", "value": true}
Server > Client
{
"class": "getlist",
"config": {"incallfilter": true},
"function": "updateconfig",
"listname": "users",
"tid": "2",
"timenow": 1361456398.52, "tipbxid": "xivo" }
DND
function : enablednd
value : true, false activate deactivate DND
Client -> Server
{"class": "featuresput", "commandid": 1088978942, "function": "enablednd", "value": true}
Server > Client
{
"class": "getlist",
"config": {"enablednd": true},
"function": "updateconfig",
"listname": "users",
"tid": "2",
"timenow": 1361456614.55, "tipbxid": "xivo"}
Recording
function : enablerecording
value : true, false
Activate / deactivate recording for a user, extension call recording has to be activated :
Client -> Server
{"class": "featuresput", "commandid": 1088978942, "function": "enablerecording", "value": true, "target" : "7" }
Server > Client
{
"class": "getlist",
"config": {"enablerecording": true},
"function": "updateconfig",
"listname": "users",
"tid": "7",
"timenow": 1361456614.55, "tipbxid": "xivo"}
Unconditional Forward
Forward the call at any time, call does not reach the user
function : fwd
Client -> Server
{
"class": "featuresput", "commandid": 2082138822, "function": "fwd",
"value": {"destunc": "1002", "enableunc": true}
}
Server > Client
{
"class": "getlist",
"config": {"destunc": "1002", "enableunc": true},
"function": "updateconfig",
"listname": "users",
"tid": "2",
"timenow": 1361456777.98, "tipbxid": "xivo"}
Forward On No Answer
Forward the call to another destination if the user does not answer
function : fwd
Client -> Server
{
"class": "featuresput", "commandid": 1705419982, "function": "fwd",
"value": {"destrna": "1003", "enablerna": true}
}
Server > Client
{
"class": "getlist",
"config": {"destrna": "1003", "enablerna": true},
"function": "updateconfig",
"listname": "users",
"tid": "2",
"timenow": 1361456966.89, "tipbxid": "xivo" }
Forward On Busy
Forward the call to another destination when the user is busy
function : fwd
Client -> Server
{
"class": "featuresput", "commandid": 568274890, "function": "fwd",
"value": {"destbusy": "1009", "enablebusy": true}
}
Server > Client
{
"class": "getlist",
"config": {"destbusy": "1009", "enablebusy": true},
"function": "updateconfig",
"listname": "users",
"tid": "2",
"timenow": 1361457163.77, "tipbxid": "xivo"
}
Statistics
Subscribe to queues stats
This message can be sent from the client to enable statitics update on queues
Client -> Server
{"commandid":36,"class":"subscribetoqueuesstats"}
``Server > Client``
Get queues stats
When statistic update is enable by sending message Subscribe to queues stats.
The first element of the message is the queue id
{"stats": {"10": {"Xivo-LoggedAgents": 0}},
"class": "getqueuesstats", "timenow": 1384509582.88}
{"stats": {"1": {"Xivo-WaitingCalls": 0}},
"class": "getqueuesstats", "timenow": 1384509582.89}
{"stats": {"1": {"Xivo-TalkingAgents": "0", "Xivo-AvailableAgents": "1", "Xivo-EWT": "6"}},
"class": "getqueuesstats", "timenow": 1384512350.25}
Status
These messages can also be received without any request as unsolicited messages.
User status
User status is to manage user presence
Request user status update
Client -> Server
{"class": "getlist", "commandid": 107712156,
"function": "updatestatus",
"listname": "users",
"tid": "14", "tipbxid": "xivo"}
Server > Client
{"class": "getlist",
"function": "updatestatus",
"listname": "users",
"status": {"availstate": "outtolunch", "connection": "yes"},
"tid": "1", "timenow": 1364994093.48, "tipbxid": "xivo"}
Change User status
Client -> Server
{"availstate": "away",
"class": "availstate",
"commandid": 1946092392,
"ipbxid": "xivo",
"userid": "1"}
Server > Client
{"class": "getlist",
"function": "updatestatus",
"listname": "users",
"status": {"availstate": "away"},
"tid": "1", "timenow": 1370523352.6, "tipbxid": "xivo"}
Phone status
tid is the line id, found in linelist from message User configuration
Client -> Server
{"class": "getlist", "commandid": 107712156,
"function": "updatestatus",
"listname": "phones", "tid": "8", "tipbxid": "xivo"}
Server > Client
{"class": "getlist",
"function": "updatestatus",
"listname": "phones",
"status": {"hintstatus": "0"},
"tid": "1",
"timenow": 1364994093.48,
"tipbxid": "xivo"}
Queue status
Client -> Server
{"commandid":17,"class":"getlist","tid":"8","tipbxid":"xivo","function":"updatestatus","listname":"queues"}
Server > Client
{"function": "updatestatus", "listname": "queues", "tipbxid": "xivo", "timenow": 1382710430.54,
"status": {"agentmembers": ["1","5"], "phonemembers": ["8"]},
"tid": "8", "class": "getlist"}
Agent status
tid is the agent id.
Client -> Server
{"class": "getlist",
"commandid": <random_integer>,
"function": "updatestatus",
"listname": "agents",
"tid": "635",
"tipbxid": "xivo"}
Server > Client
{"class": "getlist",
"listname": "agents",
"function": "updatestatus",
"tipbxid": "xivo",
"tid": 635,
"status": {
"availability": "logged_out",
"availability_since": 1370868774.74,
"channel": null,
"groups": [],
"on_call_acd": false,
"on_call_nonacd": false,
"on_wrapup": false,
"phonenumber": null,
"queues": [
"113"
]
}}
availability can take the values:
logged_out
available
unavailable
on_call_nonacd_incoming_internal
on_call_nonacd_incoming_external
on_call_nonacd_outgoing_internal
on_call_nonacd_outgoing_external
availability_since is the timestamp of the last availability change
queues is the list of queue ids from which the agent receives calls
Switchboard
Answer
This allows the switchboard operator to answer an incoming call or unhold a call on-hold.
{"class": "answer", "uniqueid": "12345667.89"}
Unsolicited Messages
These messages are received whenever one of the following corresponding event occurs: sheet message on incoming calls, or updatestatus when a phone status changes.
Sheet
This message is received to display customer information if configured at the server side
{
"timenow": 1361444639.61,
"class": "sheet",
"compressed": true,
"serial": "xml",
"payload": "AAADnnicndPBToNAEAbgV1n3XgFN1AP...................",
"channel": "SIP/e6fhff-00000007"
}
How to decode payload :
>>> b64content = base64.b64decode(<payload content>)
>>> # 4 first cars are the encoded lenght of the xml string (in Big Endian format)
>>> xmllen = struck.unpack('>I',b64content[0:4])
>>> # the rest is a compressed xml string
>>> xmlcontent = zlib.decompress(toto[4:])
>>> print xmlcontent
<?xml version="1.0" encoding="utf-8"?>
<profile>
<user>
<internal name="ipbxid"><![CDATA[xivo]]></internal>
<internal name="where"><![CDATA[dial]]></internal>
<internal name="channel"><![CDATA[SIP/barometrix_jyldev-00000009]]></internal>
<internal name="focus"><![CDATA[no]]></internal>
<internal name="zip"><![CDATA[1]]></internal>
<sheet_qtui order="0010" name="qtui" type="None"><![CDATA[]]></sheet_qtui>
<sheet_info order="0010" name="Nom" type="title"><![CDATA[0230210083]]></sheet_info>
<sheet_info order="0030" name="Origine" type="text"><![CDATA[extern]]></sheet_info>
<sheet_info order="0020" name="Num\xc3\xa9ro" type="text"><![CDATA[0230210083]]></sheet_info>
<systray_info order="0010" name="Nom" type="title"><![CDATA[Maric\xc3\xa9 Sapr\xc3\xaftch\xc3\xa0]]></systray_info>
<systray_info order="0030" name="Origine" type="body"><![CDATA[extern]]></systray_info>
<systray_info order="0020" name="Num\xc3\xa9ro" type="body"><![CDATA[0230210083]]></systray_info>
</user>
</profile>
The xml file content is defined by the following xsd file:
xivo-javactilib/src/main/xsd/sheet.xsd
(online version)
Phone status update
Received when a phone status change
class : getlist
function : updatestatus
listname : phones
{
"class": "getlist",
"function": "updatestatus",
"listname": "phones",
"tipbxid": "xivo",
"timenow": 1361447017.29,
.........
}
tid is the the object identification
Example of phone messages received when a phone is ringing :
{.... "status": {"hintstatus": "0"}, "tid": "3"}
{.... "status": {"hintstatus": "8"}, "tid": "3"}
Update notification
Register agent status update
The register_agent_status_update command is used to register to the status updates of a list of agent. Once registered to a agent’s status, the client will receive all Agent status update events for the registered agents.
This command should be sent when an agent is displayed in the people xlet to be able to update the agent status icon.
The Unregister agent status update command should be used to stop receiving updates.
Client -> Server
{
"class": "register_agent_status_update",
"agent_ids": [["<xivo-uuid>", "<agent-id1>"],
["<xivo-uuid>", "<agent-id2>"],
...,
["<xivo-uuid>", "<agent-idn>"]],
"commandid": <commandid>
}
Unregister agent status update
The unregister_agent_status_update command is used to unregister from the status updates of a list of agent.
Once unregistered, the client will stop receiving the Agent status update events for the specified agents.
Client -> Server
{
"class": "unregister_agent_status_update",
"agent_ids": [["<xivo-uuid>", "<agent-id1>"],
["<xivo-uuid>", "<agent-id2>"],
...,
["<xivo-uuid>", "<agent-idn>"]],
"commandid": <commandid>
}
Agent status update
The agent_status_update event is received when the presence of an agent changes.
To receive this event, the user must first register to the event for a specified agent using the Register agent status update command.
To stop receiving this event, the user must send the Unregister agent status update command.
data, a dictionary containing 3 fields:
agent_id, is an integer containing the ID of the user affected by this status change
xivo_uuid: a string containing the UUID of the XiVO that sent the status update
status: a string containing the new status, “logged_in” or “logged_out”
Server -> Client
{
"class": "agent_status_update",
"data": {
"agent_id": 42,
"xivo_uuid": "<the-xivo-uuid>",
"status": "<status-name>"
}
}
Register endpoint status update
The register_endpoint_status_update command is used to register to the status updates of a list of lines. Once registered to a endpoint’s status, the client will receive all Endpoint status update events for the registered agents.
This command should be sent when a endpoint is displayed in the people xlet to be able to update the agent status icon.
The Unregister endpoint status update command should be used to stop receiving updates.
Client -> Server
{
"class": "register_endpoint_status_update",
"endpoint_ids": [["<xivo-uuid>", "<endpoint-id1>"],
["<xivo-uuid>", "<endpoint-id2>"],
...,
["<xivo-uuid>", "<endpoint-idn>"]],
"commandid": <commandid>
}
Unregister endpoint status update
The unregister_endpoint_status_update command is used to unregister from the status updates of a list of agent.
Once unregistered, the client will stop receiving the Endpoint status update events for the specified agents.
Client -> Server
{
"class": "unregister_endpoint_status_update",
"endpoint_ids": [["<xivo-uuid>", "<endpoint-id1>"],
["<xivo-uuid>", "<endpoint-id2>"],
...,
["<xivo-uuid>", "<endpoint-idn>"]],
"commandid": <commandid>
}
Endpoint status update
The endpoint_status_update event is received when the status of a line changes.
To receive this event, the user must first register to the event for a specified endpoint using the Register endpoint status update command.
To stop receiving this event, the user must send the Unregister endpoint status update command.
data, a dictionary containing 3 fields:
endpoint_id, is an integer containing the ID of the line affected by this status change
xivo_uuid: a string containing the UUID of the XiVO that sent the status update
status: an integer matching an entry in the cti hint configuration
Server -> Client
{
"class": "endpoint_status_update",
"data": {
"endpoint_id": 42,
"xivo_uuid": "<the-xivo-uuid>",
"status": <hint-status>
}
}
Register user status update
The register_user_status_update command is used to register to the status updates of a list of user. Once registered to a user’s status, the client will receive all User status update events for the registered users.
This command should be sent when a user is displayed in the people xlet to be able to update the presence status icon.
The Unregister user status update command should be used to stop receiving updates.
Client -> Server
{
"class": "register_user_status_update",
"user_ids": [["<xivo-uuid>", "<user-uuid1>"],
["<xivo-uuid>", "<user-uuid2>"],
...,
["<xivo-uuid>", "<user-uuidn>"]],
"commandid": <commandid>
}
Unregister user status update
The unregister_user_status_update command is used to unregister from the status updates of a list of user.
Once unregistered, the client will stop receiving the User status update events for the specified users.
Client -> Server
{
"class": "unregister_user_status_update",
"user_ids": [["<xivo-uuid>", "<user-uuid1>"],
["<xivo-uuid>", "<user-uuid2>"],
...,
["<xivo-uuid>", "<user-uuidn>"]],
"commandid": <commandid>
}
User status update
The user_status_update event is received when the presence of a user changes.
To receive this event, the user must first register to the event for a specified user using the Register user status update command.
To stop receiving this event, the user must send the Unregister user status update command.
data, a dictionary containing the following fields:
user_uuid, a string containing the UUID of the user.
user_id, an integer containing the ID of the user.
xivo_uuid: a string containing the UUID of the XiVO that sent the status update
status: a string containing the new status of the user based on the cti profile configuration
Note
When multiple XiVO share user statuses, the cti profile configuration for presences and phone statuses should match on all XiVO to be displayed properly
Server -> Client
{
"class": "user_status_update",
"data": {
"user_uuid": "<the-user-uuid>",
"user_id": <the-user-id>,
"xivo_uuid": "<the-xivo-uuid>",
"status": "<status-name>"
}
}
Warning
The user_id field is DEPRECATED and should not be used. Use the user_uuid field instead.
CTI server implementation
In the git repository https://gitlab.com/xivo.solutions/xivo-ctid
cti_config handles the configuration coming from the WEBI
interfaces/interface_ami, together with asterisk_ami_definitions, amiinterpret and xivo_ami handle the AMI connections (asterisk)
interfaces/interface_info handles the CLI-like connections
interfaces/interface_webi handles the requests and signals coming from the WEBI
interfaces/interface_cti handles the clients’ connections, with the help of client_connection, and it often involves cti_command too
innerdata is meant to be the place where all statuses are computed and stored
The main loop uses select() syscall to dispatch the tasks according to miscellaneous incoming requests.
Requirements for innerdata:
the properties fetched from the WEBI configuration shall be stored in the relevant xod_config structure
the properties fetched from elsewhere shall be stored in the relevant xod_status structure
at least two kinds of objects are not “predefined” (as are the phones or the queues, for instance)
the channels (in the asterisk SIP/345-0x12345678 meaning)
the group and queue members shall be handled in a special way each
The purpose of the ‘relations’ field, in the various structures is to keep track of relations and cross-relations between different objects (a phone logged in as an agent, itself in a queue, itself called by some channels belonging to phones …).
CTI server Message flow
Messages sent from the CTI clients to the server are received by the CTIServer class.
The CTIServer then calls interface_cti.CTI
class manage_connection
method.
The interface_cti
uses his _cti_command_handler
member to parse and run the command.
The CTICommandHandler
get a list of classes that handle this message from the CTICommandFactory
.
Then the the interface_cti.CTI
calls run_commands
on the handler, which returns a list of all commands replies.
To implement a new message in the protocol you have to create a new class that inherits the CTICommand
class.
Your new class should have a static member caller required_fields
which is a list of required fields for this class.
Your class should also have a conditions
static member which is a list of tupples of conditions to detect that
an incoming message matches this class. The __init__
of your class is responsible for the initialization of
it’s fields and should call super(<ClassName>, self).__init__(msg)
. Your class should register itself to the CTICommandFactory
.
from xivo_cti.cti.cti_command import CTICommand
from xivo_cti.cti.cti_command_factory import CTICommandFactory
class InviteConfroom(CTICommand):
required_fields = ['class', 'invitee']
conditions = [('class', 'invite_confroom')]
def __init__(self):
super(InviteConfroom, self).__init__(msg)
self._invitee = msg['invitee']
CTICommandFactory.register_class(InviteConfroom)
Each CTI commands has a callback list that you can register to from anywhere. Each callback function will be called when this message is received with the command as parameter.
Refer to MeetmeList.__init__
for a callback registration example and to MeetmeList.invite
for the implementation of a callback.
from xivo_cti.cti.commands.invite_confroom import InviteConfroom
class MySuperClass(object):
def __init__(self):
InviteConfroom.register_callback(self.invite_confroom_handler)
def invite_confroom_handler(self, invite_confroom_command):
# Do your stuff here.
if ok:
return invite_confroom_command.get_message('Everything is fine')
else:
return invite_confroom_command.get_warning('I don't know you, go away', True)
Note
The client’s connection is injected in the command instance before calling callbacks functions.
The client’s connection is an interface_cti.CTI
instance.