JSONP API Guide - Desktop Connect Unified Agent
1 Introduction
This document describes the technical details and intended use of the Unified Agent JSONP API, with a focus on the Javascript implementation of the client, and instructions on how to implement in other languages.
The UA JSONP API is a web service, and has a javascript library that helps third parties send requests to and receive events from the Unified Agent server. Each instance of the API client is associated with one web client instance: it will receive the same events that WebClient does, and requests are made on behalf of the agent using that WebClient. The JS lib connects to a servlet that accepts http queries and returns JavaScript Object Notation strings wrapped in a call-back function (Padded). Using jQuery, this allows cross-domain requests to be sent.
The Unified Agent server(s) and its dependencies are assumed to be deployed and configured. Refer to the Unified Agent Implementation Guide for details; they won’t be discussed here unless a configuration entry is specific to the JSONP API.
This document references both the APC Agent API documentation and the JTAPI documentation; it is recommended to read these first if not already familiar with the concepts.
2 Initializing the API
Include jQuery (jquery-1.9.0.min.js), the JSON library (json2.js), and the UA JSONP API (ua.js) in the header of your page. All functions and variables mentioned here are in the com.geomant.ua.client object in ua.js
Set the javascript variable com.geomant.ua.client.uaserver to the server you want to connect to (e.g.: “http://127.0.0.1:8080/GeoCCIWebClient).
Register your event handlers by calling RegisterEventHandler(event, function). The first argument is a string that identifies the event type, the second is a reference to your event handler function. The function should expect a single javascript object as an argument. See the Events reference for details.
Start the event queue by calling GetEvent(). This function will call itself each time the request it generates returns with an event. The server won’t respond until an event is available. If the 10 second timeout expires the server returns a pseudo-event, and the client will call GetEvent() again.
Clients (browser sessions) are identified by a globally unique identifier (GUID) generated by the server. If the Unified Agent WebClient is embedded in a frame inside your application, you will need to navigate it to include the GUID in the URL parameters. The UA server you connected to may also redirect the API to another server, overriding the uaserver variable. If your application is embedded in the Unified Agent WebClient instead, you should set the ”Guid” variable to the one passed to you in the URL parameters before starting the event queue. See the “queuestarted” event for details.
By default, the API event queue will receive every event the WebClient does. You can set a filter (to reduce network traffic) by calling SubscribeToEvents(filter), where “filter” is a list of event type strings, separated by the ‘|’ character (e.g. “LOGIN_RESP|RINGING|CONNECTED”). Only these events will be sent to the API. UnsubscribeFromEvents(filter) removes the event subscriptions specified. Use “all” instead to subscribe to/unsubscribe from all events.
Alternatively, by setting "noclient" to true, the API client can be used in a standalone mode, without associating it to a web client instance. This would mean the API client would have to implement procedures normally performed by the web client (e.g. logging in as a PAB agent involves a client side logic that is not easy to replicate). In theory, this can be used to completely replace the UA web client with your implementation.
3 General API properties and methods
All found in “com.geomant.ua.client” in ua.js, functions / variables intended for internal use only are not included.
Properties
version: API version, should match the WebClient version (e.g. v2.2.1)
uaserver: the UA server URL, used in every request
defaultTimeout: the number of milliseconds before a request is considered failed by the client. Default is 15000. If the server is not available, request will return an HTTP error code. This value will almost never affect functionality and should not be overridden.
Guid: the Globally Unique Identifier assigned to this client. It will be included in every request sent to the server.
Extension: if an agent is logged in, the extension number of the station used by that agent
NoClient: if set to true, the server won’t assume there is WebClient associated to this API instance. This is mainly used for testing.
Methods
GetEvent(): implements the long-polling event queue. Sends a request to retrieve an event from the server. Calls itself recursively. Should be called externally only when initializing the API, or to handle an error.
SubscribeToEvents(filter): call with list of event type strings to only receive those events, or “all” to restore default behaviour and receive all events
UnsubscribeFromEvents(filter): call with list of event type strings to stop receiving those events. Use “all” to stop events from being sent to the API. Removing all the subscribed events without using “all” will restore default behaviour
RegisterEventHandler(eventid, handler): register an event handler function to this event type. Note that only a single function can be registered to each event. If your event handlers start communication with your server, they should use asynchronous methods. Due to javascript being single threaded, you will only receive the next event after your handler stopped executing.
4 CTI methods
Found in com.geomant.ua.client.CTI: this object holds all CTI (Computer Telephony Integration, here: CM/AES) related functions. All functions are assumed to be done on the station the agent logged in on, unless noted otherwise. In the request, the "system" field is "cti". The JS implementation adds the "extension" (For all call related requests) field, based on the login response, and the guid. Don't forget to add these in custom implementations. The request name is what the "request" field is set to, note the differences in capitalisation.
CTI.Agent holds the agent ID of the agent after logging in.
JS method | args | description | request name |
---|---|---|---|
Login | agentid, password, extension |
Logs the agent in to ACD on the specified station | login |
Answer | ucid | Answers the alerting call with the matching Unique Call ID | answer |
CompleteTransfer | ucid1, ucid2 | Transfers a call to another call; last step of a “consultative” transfer. One call should be active, the other held. | completeConference |
CompleteConference | ucid1, ucid2 | Merges two calls to become a conference call; the last step of a “consultative” conference. One call should be active, the other held. | completeConference |
QuickTransfer | destination, uui | Transfers the active call to the destination with the specified UUI attached to the call. The second call will be started, and the transfer is completed automatically. | doTransfer |
QuickConference | destination, uui, timeout | Established a conference using the active call and a second call made to the destination, with the specified UUI attached to the call. The second call will be started, and the conference completed automatically. Timeout is the number of milliseconds UA will wait for the second call to be answered. | ssconference |
Hold | ucid | Puts the call with the matching UCID on hold. | hold |
UnHold | ucid | Retrieves the call with the matching UCID from hold. | unhold |
SetAgentState | state, reason | Sets the agent state to “state” with the reason code specified. Valid values for state: “aux”, “acw”, “auto” (ready/auto-in), “man” (ready/manual-in). The actual request has two fields: "state" and "mode", use the following values instead of the shorthands above if sending the request manually from a custom implementation: aux: "state" = "3" (mode is ignored) |
setAgentState |
SendDTMF | dtmf | Sends the DTMF on the active call. Valid values are numbers 1-9, *, and # ("hash" when sent in the request) | sendDTMF |
RemoveParty | party | Removes the party (identified based on CLI) from the active conference | removeParty |
MakeCall | destination, uui | Calls the destination number, with the UUI attached to the call. | makecall |
Drop | ucid | drops the call with the matching UCID | drop |
SnapShotDevice | - | Requests call information from the server. Use this if you suspect your state machine for handling call states is out of synch. Note that you will get this information each time the WebClient sends the same requests, so calling it here is redundant most of the time. | snapshotdevice |
QueryAgentState | - | Requests agent state information. Use this if you suspect your state machine for handling agent states is out of synch. Note that you will get this information each time the WebClient sends the same requests, so calling it here is redundant most of the time. | queryagentstate |
LoginAgent | agentid, password, extension, workmode | Same as Login except no monitor is started on the station. This means that you won’t receive any telephony events. Not supported by the WebClient, this should only be used for NoClient=true API instances. Workmode accepts the same values as "setAgentState". For custom implementations, "state" and "mode" fields need to be set the same way too. | acd_login |
LogoutAgent | agentid, extension |
Logout agent from ACD, that was logged in by sending LoginAgent (acd_login) | acd_logout |
StartRecording / StopRecording | - | Starts / stops recording the call using a RecorderProxy component (only implemented for ComputerTel recorders [TTL specific]) | startrecording / stoprecording |
5 APC methods
All found in com.geomant.ua.client.APC: this javascript object holds all APC (Avaya Proactive Contact) related functions.
The JSONP API exposes the Agent API provided by Proactive Contact directly for most commands. The requests are formatted by the server to include the proper headers, but otherwise, there is very little difference in usage: read the Agent API documentation for more information on how to use these functions.
Some requests are handled differently by the server, most of the time for performance reasons, e.g. the JSONP client / WebClient won’t ever send “SetDataField”: the server will generate request for each of the fields extracted from the screen definition, instead of the web application requesting them individually. These exceptions are explained here in detail.
It should be noted that technically, any request starting with “AGT” will get accepted by the server, the header and arguments one through three (arg1,arg2,arg3) will get inserted correctly, but using this to send commands not implemented for external use by this API is not recommended. If you want to use additional commands, please consult Geomant first.
JS method | args | description | request name |
---|---|---|---|
Login | agent, password, extension, workclass, acdswitch | Logs the agent in. This includes opening the secure socket and sending several APC commands, in order: AGTLogin, AGTReserveHeadset, AGTConnHeadset or AGTLogonAcd (for PAB agents) Additionally AGTLogIoStart is sent if UA is configured to do so. If any of the above returns with an error, AGTLogoff is called and the socket is closed. The event message will be sent as a response to the specific failed command even though the API exposes them as a single command (see the APC Events section). Finally, SetWorkClass is sent. If acdswitch is set to a number, the agent will be logged in as a PAB (blended) agent. Leave it empty or null to log in as a regular agent. See Agent API docs for valid workclass values and their meanings. UA may be configured to work with more than one dialler; in this case E50100 for AGTLogon is handled internally. | login |
AdjustHeadset | device, volume | Device is either M (mouth) or E (ear) to set volume on the mic or the speakers, respectively. Only works for DirectConnect headsets. | AGTAdjustHeadset |
AttachJob | jobname, jobtype | Attaches the job, gets the list of keys and the call-back format, gets the screen(s) and parses them, sets the data fields based on the screen(s), and sends AvailWork. Expect an AGTGetScreen, two AGTListKeys, and an AGTAvailWork response and nothing else, unless one of the other commands (AGTAttachJob, AGTSetDataField or AGTListScreens) returns with an error. | attachjob |
AvailWork | - | also called automatically once after joining a job. | AGTAvailWork |
ChangePassword | agent, old, new | Changes the agents password. | AGTSetPassword |
ConnectHeadset | - | Reconnect the headset if it got disconnected (i.e. the agent hung up the APC call). Called automatically to start the first long call to the agent after login. | AGTConnHeadset |
DetachJob | - | Exits the job, provided the agent is in the NoFurtherWork state. | AGTDetachJob |
DoNotCall | - | Marks the current record as DNC. | AGTDoNotCall |
FinishItem | completion code | Finishes the work item with the code specified. | AGTFinishedItem |
ForceQuit | - | Not a single APC command. Initiates a state machine to log out the agent and close the APC connection, regardless of what state the agent is in. It tries to send the following commands: NoFurtherWork, FinishItem, DetachJob, and Logoff. FinishItem uses code 49: OPDIED, “operator ended session abnormally”. The UA server uses the same mechanism to disconnect agents whose WebClient lost connection for too long. You can use this to properly close sessions in case an irrecoverable outage prevents agents from continuing work. | forcequit |
GetHeadsetVol | - | Returns the volume settings of the DirectConnect headset | AGTGetHeadsetVol |
HoldCall | - | Puts the call on hold. | AGTHoldCall |
HangupCall | Hangs up the customer call, but keeps the line, which can be then used to start manual calls. | AGTHangupCall | |
HookflashLine | destination | Starts the transfer using hookflash, if the dialer is configured for it (it rarely is) | AGTHookflashLine |
ListJobs | - | Lists active jobs | AGTListJobs |
ListState | - | Request agent state information. Not used internally by UA. | AGTListState |
ManagedCall | - | In preview state, starts the call | AGTManagedCall |
ManualCall | destination | Starts a manual call to the destination number | AGTManualCall |
NoFurtherWork | - | Agent requests a break. May have to complete one or more calls before it is granted. | AGTNoFurtherWork |
ReadyNextItem | - | The agent is ready for the next call. Called automatically by the WebClient after FinishItem (unless a break is pending) | AGTReadyNextItem |
ReleaseLine | script, message | Releases the line and runs the script or plays the message if one of them is specified. | AGTReleaseLine |
SendDTMF | dtmf | Sends the DTMF (1-9,#,*). # is sent as "hash" and translated by the server. | AGTDialDigit |
SendMessage | msg | Sends a message to the supervisor. Limit is 59 characters. | AGTSendMessage |
SetCallback | time, phoneid, alt_name, alt_phone | Sets a call-back. “time” is a Unix timestamp (ms since epoch, like Date.getTime()), the UA server will account for server-dialler timezone differences when converting to a date-time string. “phoneid” is the index number of the phone field used. | setcallback |
SetWorkClass | workclass | Sets the workclass. | AGTSetWorkClass |
SetUnit | unit | Set the unit (after joining a unitworklist job) | AGTSetUnit |
TransferBlind | job | Alias for AGTMoFlashBlind. If job is null, it transfers to the default job instead. | AGTMoFlashBlind |
TransferCall | destination | starts or completes a voice-only transfer. | AGTTransferCall |
TransferSupervised | job | Alias for AGTMoFlashSupv. If job is null, it transfers to the default job instead. | AGTMoFlashSupv |
UnholdCall | - | retrieves the call | AGTUnholdCall |
UpdateField | screentype, fieldname, fieldvalue | updates a single field in the record | |
UpdateRecord | fields | updates several fields in the record. Parameter is a list of triples separated by semicolons ‘;’ . Type / Field /value triples are separated by ‘|’. E.g.: “O|phone1|123;O|title|Mrs;O|Name|Smith” would update all three fields with one command. |
6 About events in general
All UA events are collections of key-value pairs. On the client side (the API and the WebClient) these are represented as javascript objects, as parsed back from the JSON string the server sent.
Almost all events have these fields (technically javascript object properties):
- the “event” field identifies the event type. A “MAKECALL_RESP event” is a (javascript) object with the “event” field set to “MAKECALL_RESP”
- the “result” field indicates either the subtype of the event (for APC some events) or the general success / failure of the command it is sent in response to. CTI telephony events are unsolicited and thus have no “result” field. The few APC events that are unsolicited still have a “result” field, either because it indicates a subtype (OnCallNotify has “Data” and “Completed”) or because the event is an error event (AGTSytemError, AGTHeadsetConnBroken)
- the “system” field shows which Avaya system (“apc” or “cti”), other system UA can connect to (“ldap”, “db”) or internal UA subsystem/servlet (Language, Config, JSONP) the event is from/about. JSONP related technical events (timeout, format errors, etc.) are the only events without a “system” field.
Some events may contain arrays or other longer data in a field. These are usually concatenated to a single string using ‘;’ as the top level and ‘|’ as the lower level separator (e.g. aux code labels). Exceptions to this are the APC events that carry data sent by the dialler “as is”, without additional formatting: GetScreen, AORNotify, OnPreviewRecord, etc. These are put in the “data” field and should be interpreted as described in the Agent API docs. These use the "\u001e" character for separators.
Fields should always be confirmed to exist before de-referencing them. Even in the same type of event, the fields included may vary.
7 CTI Events
The UA server generates two kinds of events related to CTI: response events (these end with “_RESP”) and (unsolicited) telephony events.
For example, after a call to CTI.MakeCall, the server will send a “MAKECALL_RESP” event. If the result in this event does not indicate an error, it means that the makecall request was well-formatted, and no known conditions prevents UA from forwarding to the AES, in this case, no other calls are active on the station. It does not mean that the call already started, just that the JTAPI method was called and it threw no exceptions. Starting the actual call may still fail if the called number is not a valid one, the remote number is busy, etc. Telephony events will indicate changes in the state of the phone and calls. In this case, an INITIATED event will signal a dial tone was received, “TALKING” the call started, and a “RINGING” event when the call starts ringing.
With a few exceptions, response events should only be checked for to see if error handling is needed. Exceptions to this are: QUERYAGENTSTATE_RESP, and SNAPSHOTDEVICE_RESP: these carry the information requested.
Telephony events are generated from JTAPI events. They will contain multiple fields, not just a result. You can identify a CTI event (system = “cti”) belongs to this group quickly by checking for the existence of the result field. If it’s missing, it’s a telephony event, and the event will carry information about call and/or agent states, or state transitions.
7.1. Response events
List of events where result “1” means success, “0” means error:
ANSWER_RESP, MAKECALL_RESP, COMPLETECONFERENCE_RESP, COMPLETETRANSFER_RESP, DOTRANSFER_RESP (quick transfer), CONFERENCE_RESP (quick conference), HOLD_RESP, UNHOLD_RESP, SENDDTMF_RESP, DROP_RESP, REMOVEPARTY_RESP
Response events with an irregular result field, and possible result values (and explanation for those values):
LOGIN_RESP: see table
“result” field value |
Additional field name |
Value |
Description |
OK |
n/a |
n/a |
Successful login |
error |
errormsg |
“too many agents” |
License limit reached |
LICENSE_LIMIT_REACHED |
n/a |
n/a |
License limit reached on GeoCCI but not UA. This should not happen |
ERROR |
n/a |
n/a |
Unexpected CTI exception (malformed request etc. |
ALREADY_MONITORED |
agent |
"monitor-only agent" |
No-agent-login on extension |
ALREADY_MONITORED |
agent |
“agent [agentid]” |
[agentid] is already logged in on extension |
ALREADY_MONITORED |
[none] |
|
GeoCCI internal error |
UNABLE_TO_MONITOR |
n/a |
n/a |
Exception while starting monitor |
“No telephony provider” |
n/a |
n/a |
AES connectiron is down |
“There is already an Agent logged on at the station" |
n/a |
n/a |
An agent with a different agent id used external means (i.e. FACs) to log in using this extension |
“Failed to login agent” |
n/a |
n/a |
Misc. JTAPI error |
“Check if station is logged in!” |
n/a |
n/a |
A generic error happened but there is no agent logged in on the station. |
LOGOUT_RESP: “true” (success), anything else is an error (rare)
LOGIN_ACD_RESP (LoginAgent response) and LOGOUT_ACD_RESP (LogoutAgent response): “OK”, “CTI_EXCEPTION”, “NO_CTI_CONN”, “INVALID_ARGS”, “INVALIX_EXT”, “OTHER_AGENT” (already logged in on station),
MONITOR_RESP: “MONITOR_STARTED” (success), “ALREADY_MONITORED” (also has “agent” field; [2.5.0] not sent to client because of a bug), “UNABLE_TO_MONITOR” (general failure: invalid extension, extension not logged in, etc.), “LICENSE_LIMIT_REACHED”
STOPMONITOR_RESP: “OK” (success), “NOT_MONITORED” (wasn’t monitored before)
SETAGENTSTATE_RESP: “0” (success), “1” (error) – opposite of most events
queryagentstateresponse (all lowercase): only sent for if an error (unexpected exception) occurred
7.2. Telephony events
QUERYAGENTSTATE_RESP: has the _RESP ending only because of the way it is generated, but like telephony events, it holds information and not just a result. Its fields and values for those fields (see TSAPI docs LucentV6AgentStateInfoEx for more info, this event is based on that object):
- “state”: the state of the agent
- “3” : not ready (a.k.a. AUX)
- “4” : ready (manual-in or auto-in)
- “5”: work not ready (a.k.a. ACW)
- “7”: busy (in a call)
- “0”: unknown (not used)
- “1”: login (not used)
- “2”: logout (not used)
- “6”: work ready (not used)
- “agentid”: agent logged in on the station
- “reasoncode”: the reasoncode selected for the state
- “pendingstate”: a state requested while busy will be set after all calls ended
- “pendingreasoncode”: reasoncode for a state requested while busy
- “lucentWorkMode”: only used for the ready state
- “1”: AUX (not used, state field has the same info)
- “2”: ACW (not used, state field has the same info)
- “3”: Auto-in
- “4”: Manual-in
- “connections”: not agent state related; this is the number of lines with a call
- “ucid.0” – “ucid.[connections – 1]”: the ucids for the active calls, provided there are any. Use this to determine if SnapshotDevice is needed to synchronize.
SNAPSHOTDEVICE_RESP: one for each call is sent. It includes virtually all information about the call state: Call state, Connection state, TerminalConnection state, and CallControlTerminalConnection state. The most common combinations for these are explained here, for more information, see the JTAPI documentation about these classes. All possible values are listed, these are strings with the same value as the variable names in the enum classes.
- “CONN.CALLSTATE”: the call state
- “ACTIVE”
- “IDLE”
- “INVALID”
- “CONN.STATE”: the connection state
- “ALERTING”
- “CONNECTED”
- “DISCONNECTED”
- “FAILED”
- “IDLE”
- “INPROGRESS”
- “UNKNOWN”
- “TERMCONN.STATE”: the terminal connection state
- “ACTIVE”
- “DROPPED”
- “IDLE”
- “PASSIVE”
- “RINGING”
- “UNKNOWN”
- “CALLCTL.STATE”: state of the call as a CallControlTerminalConnection
- “ACTIVE”
- “BRIDGED”
- “DROPPED”
- “HELD”
- “IDLE”
- “INUSE”
- “PASSIVE”
- “RINGING”
- “TALKING”
Call state combinations used by the UA WebClient (in most use cases, it is sufficient to check for these):
CALLCTL.STATE is “ACTIVE” or “TALKING”: active call
CALLCTL.STATE is “HELD”: call is on hold
CALLCTL.STATE is “RINGING” and CONN.STATE is “ALTERTING”: ringing inbound call,
CONN.STATE is not alerting: ringing outbound call
CONN.STATE is “FAILED”: the call failed but is not dropped yet
The following events are call state change related and may contain details about the call. These fields are found in most call state events:
- “UCID”: universal call ID. Used internally to keep track of calls, this must be enabled on the CM
- “CALLID”: some external applications may not use the UCID, so this is included as a separate field too
- “DEVICE”: the device this event occurred on, same as the station’s extension
- “CALLED”: the called number, as returned by CallControlCall.getCalledAddress().getName() in JTAPI
- “CALLING”: the calling number, as returned by CallControlCall.getCallingAddress().getName() in JTAPI
- “UUI”: user to user info. Encoded Base64 if binary data and not already a string
- “LASTREDIR”: address (extension) of the last redirecting device, if applicable
- “DIGITS”: user entered code
- “COLLECTVDN”: the VDN that collected the user entered code
- “DELIVERINGACD”: delivering ACD address (extension)
- “DISTRIBUTINGADDRESS”: distributing VDN’s address
- “DISTRIBUTINGVDN”: directory name of the distributing VDN
- “PARTIES”: number of connections on the call (that is, if more than two, it is a conference)
- “CONN.0” – “CONN.[PARTIES – 1]”: Extensions of the parties in the call
- “CODE”: sometimes included to clarify the cause/type of the event. Possible values are: “CALL_TRANSFERRING” and “OLD_REMOVED”
DROPPED: Generated from “CallCtlConnDisconnectedEv”, “TermConnDroppedEv”and some other transfer or conference related events, provided both agents involved in the transfer/conference are monitored by UA. It contains the field “REMOVEDPARTY” - unique to this event – that has the extension of the party that dropped from the call. If this is the same as “DEVICE” – the extension (station) of the agent this event was sent to – the call really ended for that agent. Otherwise, it could mean a participant of a conference disconnecting, but the conference may still be live if others remain in it.
CONNECTED: Generated from “CallCtlConnEstablishedEv” (“CONFERENCED” is generated from the same JTAPI event, see below). After a ringing call is answered by the remote party a CONNECTED event will be sent.
CONFERENCED: Generated from “CallCtlConnEstablishedEv” if the meta code is “META_CALL_MERGING”), that is, a new party is being added to an existing call). Note that only the initiating agent will receive this after CompleteConference. The other agent will only get a “CONNECTED” event with the UCID of the conference.
FAILED: Generated from “CallCtlConnFailedEv”, means the call failed after dialling the number. “reasoncode”, a field unique to this event will include the reason the call failed. Values (and TSAPI name in brackets): “busy” (CAUSE_BUSY), “noanswer” (CAUSE_CALL_NOT_ANSWERED), “reorder” (CAUSE_REORDER_TONE), “trunksbusy” (CAUSE_TRUNKS_BUSY), “destnotobtainable” (CAUSE_DEST_NOT_OBTAINABLE), or if none of the above applies “cccause[n]” where [n] is the integer in the CallCtlEv enum for the reason.
HELD: Generated from “CallCtlTermConnHeldEv”, it means the agent put the call on hold. “TALKING” will be sent when the call is retrieved.
INITIATED: Generated from “CallCtlConnInitiatedEv”, this event signals that a line is off-hook, but nothing else happened yet. Received after a MakeCall request or when picking up the handset manually. Use this to determine if the call is outbound or inbound: if you received this before RINGING, it is outbound, if not, it is inbound.
RINGING: Generated from “CallCtlConnAlertingEv” and sometimes from “CallCtlConnNetworkReachedEv”. It means the call started ringing. It is the event most often used for screen pops, although when on the receiving end of a transfer or conference, CONNECTED may have to be used to get data about the customer call instead (the first ringing call has the other agent’s info).
TALKING: Generated from “CallCtlTermConnTalkingEv”. The name is a bit misleading: it does not always indicate that you are actually talking with the other end on the line: a “TALKING” event is also sent after “INITIATED” if a dial tone was received. The most common use of this event is to signal that a previously held line is active again.
TRANSFERRED: Generated from “ConnCreatedEv”, only used to notify the agent that the change in call state signalled by previous events was caused by a transfer being completed.
UPDATE: Generated from “ConnConnectedEv”, usually means something about the call changed. Can be ignored, as following events will have the actual information about the change.
Agent state related events are sent only if the hunt group the agent is in is also monitored by UA. These are used only to detect external/manual changes of the agent state, something agents should avoid and use UA methods instead. These are:
AGENT_LOGON: the agent logged in on the monitored station
AGENT_LOGOFF: the agent logged off from the monitored station (not using UA to do so).
AGENT_BUSY: the agent is now busy. Unused, telephony events indicate a call starting anyway.
Finally, MONITOR_ENDED is the event sent when the agent’s device stops being monitored by UA. This usually happens on regular logout.
8 APC Events
Most Agent API messages are sent to the client without any processing by the server other than basic parsing/formatting. The general event format, except where fields are added or modified, or where the server handles events internally are discussed here; for other details (possible return values / error codes, use cases, etc.), please see the APC Agent API documentation.
APC event IDs start with the “AGT” prefix. This prefix is removed, otherwise, the event names are unchanged (AGTCallNotify becomes a CallNotify UA event).
An APC events have a return value (e.g. M00000 for “Completed”, E28947 for “invalid completion code” etc.). In the UA event, this will be the in the “result” field.
Some APC events have additional data attached (not just “M00001”/”Data” events, sometimes “Completed” or certain error messages will have additional data too). This information is put in the “data” field of the UA event, usually without any processing, i.e. same separators and data structure, as described by the Agent API. Exceptions will be discussed here.
An event may be sent in multiple parts by the dialler. UA waits for all the fragments to arrive, and parses them as one message. For example, if the dialler sends a large screen definition, you will only get one GetScreen event, and the “data” field will contain the whole screen.
Pending type messages will only be forwarded to the clients if it is not of return value “S28833” (“Pending”), which is just a confirmation that a command has been received by the dialler. The type of the message (R, D, N, P, and B) is not included in the UA event, they can be inferred from the return value (e.g. M0000 and errors are always R, M00001 is always D). If the type is B (Busy), the return code B00000 is generated. This means APC can’t process the (otherwise valid) command. This is extremely rare. First one to send UA logs with a legit B00000 message to mkormos@geomant.com gets a beer (any beer, any bar in Budapest).
For reference, this is the list of events that get modified/processed by the server beyond the general rule described above (all others are sent “as is”):
AttachJob, CallNotify, ConnHeadset, DisconnHeadset, FinishItem, FreeHeadset, GetScreen, ListCallbackFmt, ListJobs, ListKeys, ListScreens, ListUnits, LogIoStart, Logon, LogonAcd, NoFurtherWork, PreviewRecord, ReserveHeadset, SetDataField, SetUnit, SetWorkClass, START, UpdateField
The “Completed” message is often not forwarded for these if a “Data” event is expected after it. This is not noted separately.
AttachJob: not forwarded to client, unless an error occurs.
CallNotify: two data messages are sent by APC. An additional field is added for clarity: “first” will be “true” for the first data message and “false” for the second
ConnHeadset: an additional field “login” is added: “true” if this was received as part of the normal login process, and “false” otherwise (headset got reconnected). If “login” is “true”, this means logging in was successful, and three additional fields are added: “agent”, “extension” and “type” for the agent ID, station and work class, respectively. Save this information if the login request was sent the WebClient and not you.
DisconnHeadset: not forwarded to the client, unless an error occurred. Part of normal logoff state machine.
FinishItem: the completion code is appended by the server in the “code” field.
FreeHeadset: not forwarded to the client, unless an error occurred. Part of normal logoff state machine.
GetScreen: requested as a part of the state machine initiated by sending an AttachJob request, expect one or more GetScreen responses before AvailWork.
ListCallbackFmt: not forwarded to the client, unless an error occurred. Used to format SetCallback requests, the client only sends ms timestamps
ListJobs: only the active jobs are sent, inactive jobs are filtered out.
ListKeys: requested as part of the state machine initiated by AttachJob. Although not described in the Agent API documentation (as of v5.1), this command returns the whole key file, not just the completion codes and labels, if called with an arbitrary argument. The UA WebClient uses both, so except two ListKeys responses. An additional field “first” is added: “true” for the response that has all the keys, “false” for the one that has the list of completion codes. Use the first one to enable/disable features.
ListScreens: not forwarded to clients.
ListUnits: requested as part of the state machine initiated by AttachJob. Only sent if non-empty
LogIoStart: not forwarded to clients.
Logon: not forwarded to clients, unless an error occurs.
LogonAcd: not forwarded to clients, unless an error occurs.
NoFurtherWork: unlike other events, a “Pending” (S28833) result is forwarded to clients because it actually means something for NoFurtherWork: the request for a break has been processed by the dialler, but not yet granted. The agent has to finish one or more calls first.
PreviewRecord: same as CallNotify, the field “first” is added (“true”/”false”)
ReserveHeadset: not forwarded to clients, unless an error occurs.
SetDataField: not forwarded to clients, unless an error occurs.
SetUnit: not forwarded to clients, unless an error occurs; instead, AvailWork is requested by the server
SetWorkClass: if part of the normal login process, not forwarded to clients. If requested after login is completed, it is forwarded.
START: not forwarded, part of the normal login process
UpdateField: only sent once if multiple fields are updated with one API command (UpdateRecord). If an error occurred in one of the updates, the return value will be the return value of the most recent unsuccessful response message. Usually, if more than one UpdateField fails, they fail with the same error.
9 Code samples
Implementing the API in a language other than javascript can prove challanging: synchronization can become an issue, things done by jQuery may not have a direct translation, etc. To help with basic tasks these Java code samples are provided.
Sending a request
public String sendRequest(HashMap<String, String> req) { String url = _server + "/proc.json?jsoncallback=a"; for (Map.Entry<String, String> e : req.entrySet()) { url = url + "&" + e.getKey() + "=" + e.getValue(); //assumes values //have been sanitized for sending over HTTP previously, if not, use //URLEncoder here (plus post processing to correct "+" to "%20" etc.) } log.log(Level.DEBUG, "UARequest:sendRequest:url=" + url); String ret = ""; URLConnection urlConnection; BufferedReader in = null; try { urlConnection = new URL(url).openConnection(); in = new BufferedReader(new InputStreamReader(urlConnection.getInputStream())); String inputLine; while ((inputLine = in.readLine()) != null) { ret = ret + inputLine; } } catch (Exception ex) { log.log(Level.ERROR, "UARequest:EX:req=" + req.toString() + ":" + ex.getMessage(), ex); ret = "error"; } finally { try { in.close(); } catch (Exception ex2) { } }
//since most events are asynchronous, you can ignore most return values other than "error" if the request wasnt "getevent" return ret;}
Sending a GetEvent request, and parsing the return value
public HashMap<String, String> getEvent() { HashMap<String, String> ret = new HashMap<String, String>(); HashMap<String, String> request = new HashMap<String, String>(); request.put("guid", _guid); request.put("request", "GetEvent"); String reply = sendRequest(request); try { if (!reply.equals("")) { reply = reply.substring(2, reply.length() - 2); //the reply will be in the form of
Note how the request string constructed by sendRequest has no parameters
in this case: the guid never changes (unless the connection to the
server breaks and you have to restart the queue), so this can be
optimized by including the code from sendRequest in this method, but
using a static string built when the queue starts. Run this on a new thread. The queuestarted event also includes a field
("server") with the IP:port of the server, but this is only relevant in
HA / load balanced implementations.Starting the event queue
@Overridepublic void run() { HashMap<String, String> ev = getEvent(); if (ev != null && !ev.isEmpty() && "queuestarted".equals(ev.get("event")) { //the first response to getEvent() - sent without a guid - should be a queuestarted event log.log(Level.INFO, "EventQueue:run:queuestarted:ev=" + ev.toString()); _guid = ev.get("client"); //the event includes the guid assigned to this API client uaRequest.init(server, clientID); //every other request is going to use this info try { this.url = new URL(server + "/proc.json?jsoncallback=a&request=GetEvent&guid=" + _guid); } catch (MalformedURLException ex) { //this should never happen log.log(Level.ERROR, "EventQueue:run:EX:" + ex.getMessage(), ex); uajc.showError("Event queue failed to start! The application is closing."); try { Thread.sleep(5000); } catch (InterruptedException ex2) { } uajc.exit(); } } else { log.log(Level.ERROR, "EventQueue:run:ERROR:BAD_START_MESSAGE:" + ev); uajc.showError("Event queue failed to start! The application is closing."); try { Thread.sleep(5000); } catch (InterruptedException ex) { } uajc.exit(); } while (running) { ev = getEvent(); //after if (ev == null || ev.isEmpty()) { //error handling, waiting a few seconds, possibly restarting the queue, etc.
} else { //handling the event. Events must be processed in the order they arrive. //If you want to run blocking methods in this, it may be necessary to queue these events on the client side processEvent(ev); } }}