Introduction

This platform prioritizes an API-first approach to development; Application Programming Interfaces (APIs) are central to nearly every feature. Features and capabilities are designed as APIs, fostering a development environment where features can be utilized as originally intended while also enabling innovative and unforeseen use cases.


For example, an AI feature can transcribe and summarize call recordings. While the user interface for this feature is a simple icon in a detail report, the API-first approach allows for other activation methods. A button could be added to an agent's wrap-up screen, or customers could call the API directly.


Furthermore, the individual steps within the feature are also available as independent APIs. For instance, the transcription function is a standalone API that can transcribe any call recording. This allows transcription to be added to the voicemail system without the developer needing knowledge of the transcription technology.


API Structure

Platform APIs are categorized as either native (CLR) APIs or flow APIs. 


Native APIs, developed by internal developers, necessitate a software update for deployment. These APIs form the fundamental components of the platform's features and are designed with a focus on generality. 


Flow APIs, on the other hand, are created using the Flow Designer interface. This interface empowers internal developers, Professional Services, partners, third parties, and customers to expand the platform's capabilities. A key advantage of flow APIs is their immediate availability upon creation, eliminating the need for traditional deployment processes. 


Note: For the API consumer there is no obvious difference between a native API and a flow API. The framework abstracts the API implementation so that all APIs can be consumed the same way.


The Flow Designer allows construction of APIs but is also the tool we use when building call flows and chatbots, among other things. It makes this possible by supporting two types of flow design: visual flows and text flows. 


A visual flow is a graphical flowchart where the logic is represented through the use of icons and connecting lines. A text flow is a conventionally structured program using syntax resembling C#, Java, or Javascript. Both visual flows and text flows support the same capabilities, and APIs and IVRs can be built through either style.


A basic set of low-level native APIs have been developed which expose all sorts of capabilities. Built on top, the solution has added numerous mid-level APIs built in flows that augment the low-level APIs. Much of these APIs are exposed to partners and tenants to reuse how they see fit. The combination of native APIs and flow APIs results in a rich library that exposes nearly all of the solutions features. 


API Library

Since APIs can be authored by different users of the platform, depending on what account you are logged in to, you will only see a subset of the overall selection of APIs. All the APIs provided are visible when logged into the System account. However, if you are strictly a partner or customer, you will only see APIs that are shared by the system or are authored in your own contact center.


To view the list of APIs available you must be a System Administrator (a user with the SysAdmin role):


  1. Log into the contact center as a system administrator.

  2. Navigate to System Administration, followed by API Management and finally Browse APIs.


This will display the API Browser in which you can see all the private and shared APIs available to your contact center. The list initially shows only top-level namespaces. A namespace is a hierarchical grouping of APIs. The namespace itself is made up of one or more parts separated by a period. For example, one namespace that has been defined is Platform.AI.Transcription. The top-level is Platform. If you navigate your way down, once you expand the Transcription level, you'll see a single API called TranscribeFile. Clicking it will reveal the API documentation for that API.


The URL defined for the transcription API discussed above is:


GET 

Apps/AI/Transcription/TranscribeFile


Note that this API can be called by an authorized user via HTTP, over a web socket, or from a flow. If invoking from a flow, you will reference it by the fully qualified name. In this case, it would look like this:


Platform.AI.Transcription.TranscribeFile("<featureId>", "recording.wav","en-us",null,$Current);


Or, if using the visual designer, it would appear like this (showing the properties to the left):



Note: One advantage of the visual designer is that you get help for certain fields. In the above example, the FeatureId argument has a dropdown. So you are able to pick from the available list of features without needing to know the cryptic Id.


The results of the API depend upon the particular API. However, a vast majority of APIs return their responses in Javascript Object Notation format (JSON). This is the most flexible format as the JSON object can hold any value in a structured way.


When invoking the transcription API from the API Browser, you might get a response like this:


{

    "Successful": true,

    "Duration": 22.650001525878906,

    "FullTranscript": "Welcome to the voice mail system. This is a complimentary voice message to demonstrate the features of the voice mail system. While listening to this message, you can use the keys on your phone at any time to pause, rewind, or skip ahead. Use the star key to activate the main menu. For more information about how to configure your mailbox, please log on to your account. Have a nice day.",

    "Language": "",

    "Summary": null,

    "Entities": [],

    "Paragraphs": [],

    "WordList": [

        "welcome",

        "to",

        "the",

        "voice",

        "mail",

        ...

}


In this example, the transcript contains more information than just the plain text. The full response has been truncated for readability.


Namespace categorization

The four top-level namespaces are:


  • Integrations

  • Platform

  • System

  • User


Beneath each top level namespace are sub-namespaces and individual APIs. 


The APIs nested under the Integrations namespace are largely used to integrate with third-parties, some examples: Telnyx sub-namespace APIs for purchasing telephone numbers; BYODB sub-namespace APIs to write data to external databases; Route53API sub-namespace APIs to communicate with Amazon Route 53.


The APIs nested under the Platform, System and User namespaces are a combination of native and flow APIs that drive the contact center.


Note: The User namespace is the default namespace for all custom private APIs built within the contact center; no system or platform APIs are published to the User namespace.


Use keywords in the System Administration > API Management > Browse APIs page to find the APIs that are used to implement any feature.


Consuming APIs

The platform is built in a modern service-oriented architecture. This means that different components of the system potentially exist on different physical servers. To allow distributed services to communicate with one another, we have a message broker sitting in the middle. This broker allows any service within the platform to communicate with any other service. Native APIs are often implemented on specific servers that have access to hardware or network services not generally available. When a feature or consumer needs to invoke a given API in the platform, a message is constructed and sent to the message broker where it is routed to the appropriate physical server to fulfill the request.


Internally, this is how native APIs execute. APIs implemented as flows are executed on a service that knows how to compile and execute flow code. Then, as the flow is executing, it may also need to invoke an API. If the API is native, it may marshal the API via the message broker to another physical server to execute it.


Initiating the execution of an API can therefore happen from a currently running flow API. But a high percentage of APIs also support a mechanism of invocation via the web. Two flavors of web invocation exist: HTTP and WebSocket.


In order for an API to be invoked from the web, an API template must be defined. This involves designating a URL pattern for the API. Examples of a URL pattern include:


PUT Apps/Files/PutFile/{*filename}

GET Apps/Reporting/CDR/{sessionId}


Each API that requires web access has its own URL pattern. The pattern includes a path as well as placeholders for parameters.


APIs that are invoked via HTTP must include authorization information in the request in order for the security layer to permit execution. This is accomplished by creating an API key in the contact center Admin Portal. Only a System Administrator can create an API key.


  1. Log into the contact center as a system administrator.

  2. Navigate to System Administration, followed by API Management and finally Keys.

  3. Click Create New.

  4. In the New API Key tab:

    1. Use Description to define a verbose description of the intended use for the key.

    2. Leave Type as Customer.

    3. Leave User unchanged (i.e. blank).

    4. OPTIONAL Use Permissions to define permission based limitations for the key.

      1. Click Add Another +.

      2. Use the text input to define the namespace and sub-namespace(s) under which the key grants permission. Dot separated (i.e. namespace.sub-namespace.sub-namespace) each namespace and sub-namespace to the required level.

        For example, Platform.DialerLists would permit the key to authenticate requests for APIs that exist under the Platform.DialerLists namespace and sub-namespace.

      3. OPTIONAL Repeat steps i and ii to define additional permissions.

    5. OPTIONAL Use Expiration to specify a date and time when the key will stop authenticating requests. Leave with no expiration date / time to allow the key to authenticate forever.

    6. Click Save.


After the API key is created, it can be included in the request's authorization header as a key-value pair, where the key is "apikey" and the value is the API key itself. 


APIs can be made private, shared, or public. A private API is only able to be invoked by the owner (owner refers to the contact center, or specifically, a user authorized to login to the contact center). A shared API is able to be invoked by the owner or another contact center as long as they are authenticated properly. A public API is a non-secure API that anyone can invoke.


APIs can also be invoked over a web socket. When establishing a web socket connection, the authentication occurs up front. Once established, APIs can be invoked over the same web socket without re-authenticating. To invoke an API over a web socket requires that an object be constructed that identifies the URL of the API. In this way, an API invoked from a web socket looks very similar to an API invoked through HTTP.


Examples

CreateUsersJSON

When you first come to the platform you might want to bulk create users in the contact center.


The Platform namespace CreateUsersJSON API takes a JSON array of users and creates them locally within the contact center using a POST method with the JSON array passed as the body of the request.


Example - the following PHP request to add John and Jane Example:


<?php

require_once 'HTTP/Request2.php';

$request = new HTTP_Request2();

$request->setUrl('https://<your platform API URL>/Apps/BulkUserCreation/CreateUsersJSON');

$request->setMethod(HTTP_Request2::METHOD_POST);

$request->setConfig(array(

  'follow_redirects' => TRUE

));

$request->setHeader(array(

  'Content-Type' => 'application/json',

  'apikey' => '<your authenticating API Key>',

  'Cookie' => '<your cookie>'

));

$request->setBody('[

\n  {

\n    "First Name": "John",

\n    "Last Name": "Example",

\n    "Timezone": "Greenwich Mean Time",

\n    "Username": "JohnExample",

\n    "Roles": ["ACD","Author","Admin","PBX","Manager"],

\n    "Password": "rOoR0pVeYGPSa+2+",

\n    "Profile Template": "Default",

\n    "Idle Logout Opt In": "NO",

\n    "Enable Debugging": "NO",

\n    "Locale": "en_gb",

\n    "Email Address": "johnexample@email.com",

\n    "Phone Number (Mobile)": "+11112223333",

\n    "Ask to Reset": "YES",

\n    "Password Expires": "YES"

\n  },

\n  {

\n    "First Name": "Jane",

\n    "Last Name": "Example",

\n    "Timezone": "Mountain Standard Time",

\n    "Username": "JaneExample",

\n    "Roles": ["Admin","SysAdmin"],

\n    "Password": "EH5Q?XhTLXH&Q0PE",

\n    "Profile Template": "Default",

\n    "Idle Logout Opt In": "NO",

\n    "Enable Debugging": "NO",

\n    "Locale": "en_us",

\n    "Email Address": "janeexample@email.com",

\n    "Phone Number (Mobile)": "+11112223333",

\n    "Ask to Reset": "YES",

\n    "Password Expires": "YES"

\n  }

\n]');

try {

  $response = $request->send();

  if ($response->getStatus() == 200) {

    echo $response->getBody();

  }

  else {

    echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .

    $response->getReasonPhrase();

  }

}

catch(HTTP_Request2_Exception $e) {

  echo 'Error: ' . $e->getMessage();

}


Would return the following response where Jane was created, but John was not due to an unrecognized time zone ‘Greenwich Mean Time’.


{

    "Result": {

        "UsersCreated"1,

        "RowsSkipped"1,

        "UserId_LoginId": [

            {

                "UserId""c75a74cc-1189-4589-a9d1-0e7a46a441ed",

                "LoginId""JaneExample"

            }

        ],

        "CreationErrors": [

            {

                "First Name""John",

                "Last Name""Example",

                "Timezone""Greenwich Mean Time",

                "Username""JohnExample",

                "Roles": [

                    "ACD",

                    "Author",

                    "Admin",

                    "PBX",

                    "Manager"

                ],

                "Password""rOoR0pVeYGPSa+2+",

                "Profile Template""Default",

                "Idle Logout Opt In""NO",

                "Enable Debugging""NO",

                "Locale""en_gb",

                "Email Address""johnexample@email.com",

                "Phone Number (Mobile)""+11112223333",

                "Ask to Reset""YES",

                "Password Expires""YES",

                "Error""Unrecognized timezone"

            }

        ]

    }

}


InQueueCount

To ensure you can achieve service level agreements you might want to query the number of contacts currently waiting in a queue for agents to become available.


The Platform namespace InQueueCount API takes the name of a queue and returns a count of waiting contacts.


Platform/ACDExt/v2/InQueueCount uses a GET method with one mandatory input parameter, QueueName.


  • QueueName - a mandatory parameter, the Name that identifies the queue.


Example - the following C# request for a queue with name Gold Service:


var client = new HttpClient();

var request = new HttpRequestMessage(HttpMethod.Get, "https://<your platform API URL>/Apps/ACDExt/v2/InQueueCount?QueueName=Gold Service");

request.Headers.Add("apikey""<your authenticating API Key");

request.Headers.Add("Cookie""<your cookie>");

var response = await client.SendAsync(request);

response.EnsureSuccessStatusCode();

Console.WriteLine(await response.Content.ReadAsStringAsync());


Returns the following when 7 contacts are waiting in queue:


{

    "Result"7

}


UserLoggedInAndReadyCount

In conjunction with the previous InQueueCount, at times of heavy traffic you might want to query a particularly busy queue to assess how many agents are needed to achieve service level agreement.


The Platform namespace UserLoggedInAndReadyCount API takes the name of a queue and returns the number of agents logged into the Agent Experience and in a Ready state who have the queue associated with their ACD User Profile (i.e. can handle traffic from the queue). 


Platform/ACDExt/v2/UserLoggedInAndReadyCount uses a GET method with one mandatory input parameter to return the current count of logged in and ready agents with the queue associated with their ACD User Profile.


  • QueueName - a mandatory parameter, the Name that identifies the queue.


Example - the following jQuery request for a queue with name Gold Service:


var settings = {

  "url""https://<your platform API URL>/Apps/ACDExt/v2/UserLoggedInAndReadyCount?QueueName=Gold Service",

  "method""GET",

  "timeout"0,

  "headers": {

    "apikey""<your authenticating API Key>",

    "Cookie""<your cookie>"

  },

};


$.ajax(settings).done(function (response) {

  console.log(response);

});


Returns the following when 3 agents match the criteria:


{

    "Result"3

}


ClickToDial

The ClickToDial API is most likely going to be used in a system like a Customer Relationship Management (CRM) tool that is used alongside the contact center. Once implemented, agents are able to click a telephone number in a CRM record to initiate an outbound telephone call in their Agent Experience.


The key is identifying the agent in the contact center that should be making the call when a CRM user clicks the telephone number in the CRM. This can be achieved by matching contact center agents to CRM users using the Platform/Apps/GetCustomerUsers API to retrieve a JSON array of contact center user details (including their UserID) and querying by CRM user to find the appropriate UserID).


Once that list is in the CRM, the Platform/Apps/ClickToDial/Dial API is used to instruct the contact center to initiate the outbound call for the identified user.


Note: Agents must be logged into the Agent Experience (ready or not ready) for the ClickToDial instruction to succeed.


Platform/Apps/GetCustomerUsers uses a GET method with no parameters to retrieve a JSON array of all contact center user details.


Platform/Apps/ClickToDial/Dial uses a POST method with four parameters to instruct the contact center to make an outbound telephone call. 


  • UserId - an optional parameter identifying the agent with whom the call is associated; passing no UserId results in the call being made for the user associated with the API Key that is used to authenticate the request. 

  • Destination - a mandatory parameter detailing the telephone number (E.164 format) to dial.

  • FromNumber - an optional parameter identifying the telephone number to be used as the CLID / ANI for the outbound call. Where FromQueue is passed instead of FromNumber the first telephone number associated with the queue specified is used.

  • FromQueue - an optional parameter identifying the queue to be used for the outbound call.

Note: At least one of the FromNumber or FromQueue parameters must be passed.


Example - the following jQuery request would initiate an outbound dial for the user with UserID 56b5e934-deec-416a-ab52-7e767e7e11d5, to the UK number 03069990000, with the CLID / ANI +18556296664 and the queue Gold Service.


var settings = {

  "url": "https://<your platform API URL>/Apps/ClickToDial/Dial",

  "method": "POST",

  "timeout": 0,

  "headers": {

    "Content-Type": "application/json",

    "apikey": "<your authenticating API Key>",

    "Cookie": "<your cookie>"

  },

  "data": JSON.stringify({

    "UserId": "56b5e934-deec-416a-ab52-7e767e7e11d5",

    "Destination": "+443069990000",

    "FromNumber": "+18556296664",

    "FromQueue": "Gold Service"

  }),

};


$.ajax(settings).done(function (response) {

  console.log(response);

});


KillContact

The Platform namespace KillContact API allows you to prevent contacts from being dialed if they are members of preview dialer lists. It might be that a customer has requested no further contact be made with them; in this scenario you have to be sure that they will no longer be dialed. KillContact can be used to find and kill any further dials from taking place to them.


Platform/DialerLists/KillContact uses a POST method with four parameters (one mandatory, three optional) to find and kill telephone numbers in preview dialer campaign lists:

  • TelNumbers - a mandatory JSON array of E.164 telephone numbers to be killed; where only TelNumbers is included in the request the numbers are killed in ALL dialer lists.

  • CampaignIds - an optional JSON array of campaign Ids in which you want to check for telephone numbers to kill.

  • CampaignListIds - an optional JSON array of dialer list Ids in which you want to check for telephone numbers to kill.

  • ColRequirements - an optional set of column requirements, defined as Header / Value pairings, that must be satisfied for telephone numbers to be killed.


Example - the following cURL POST request:


curl --location 'https://<your platform API URL>/Apps/Platform/DialerLists/KillContact?apikey=<your authenticating API Key>' \

--header 'Content-Type: application/javascript' \

--data '{

"CampaignListIds":["34cee200-740d-4208-9110-1620a2b12d30","8a276336-3a0d-4174-a521-937f64385d01"],

"TelNumbers":["+18556296664","+15552368"],

"ColRequirements":[{"Header":"State","Value":"Texas"},{"Header":"City","Value":"Dallas"}]

}'


Results in the number +18556296664 being killed in dialer lists with Ids matching the two defined IF the associated State is Texas AND City is Dallas.


Note: In this example the CampaignIds parameter is not used.