Call Routing via APIs
Introduction
Suppose you have a Sales representative that's been engaged in conversations with a prospect for the past month for a giant deal. Wouldn't it be great if when the prospect calls back on the company mainline, the call goes directly to the representative instead of sending them through an IVR? Along with showing the prospect that they're being given extra attention, it would also help the sales continue conversations with ease.
Dialpad's Routing APIs allow you to do just that! With these APIs, you can have total control over where each inbound call is routed, whether it's though our standard routing mechanisms in a Department or Call Centre, or whether it's sent through directly to a User. This document describes the basics of call routers, the steps needed to setup these call routers and the expected responses.
How Call Routing Works
The above diagram illustrates the working of a call router. Once a router is setup, call information is published to a specified URL. The third party then uses that data to generate routing information for that call. The call is then routed to the appropriate user or department or call centre. In the above example, the call was routed to a user. However, the system is flexible to route calls to a department or call centre depending on the call.
Creating the Call Router
To create a call router, invoke the POST callrouters
method.
Field | Type | Required? | Description |
---|---|---|---|
name | string | true | Specify a name for the call router |
routing_url | string (URL) | true | The URL that should be consulted to route calls |
secret | string | false | A JWT secret to be used |
office_id | string | true | The office to which the call router belongs |
default_target_id | string | true | The fallback target to be used in case of client server unavailability |
default_target_type | string | true | The type associated with the default_target_id (i.e. office, department, callcenter, or user) |
enabled | boolean | false | Set to true as default. If set as false , the call router will act as pass through to the office mainline |
e.g.
import requests
url = "https://dialpad.com/api/v2/callrouters"
payload = '''{
"default_target_id": "123456",
"default_target_type": "callcenter",
"name": "Hello Router",
"office_id": "223456",
"routing_url": "https://yourroutingservice.com/routecall",
}'''
headers = {
'accept': "application/json",
'content-type': "application/json"
}
response = requests.request("POST", url, data=payload, headers=headers)
Upon successful creation of the call router, the following response is sent
{
“id”: “generated id”,
“name”: “name”,
“routing_url”: “routing_url”,
“office_id”: “office_id”,
“default_target_id”: “12341234”,
“default_target_type”: “callcenter”,
“enabled”: true,
“phone_numbers”: [“e164 number”, ...],
“signature”: {
“type”: “jwt”,
“algo”: “HS256”,
“secret”: “secret”
}
}
To set a phone number for the call router, invoke the POST callrouters/id/assign_number
method. This number should be provided to your customers. Please ensure the office has available Additional Number
licenses for phone numbers to be assigned.
e.g.
import requests
url = "https://dialpad.com/api/v2/callrouters/323456/assign_number"
headers = {
'accept': "application/json",
'content-type': "application/json"
}
response = requests.request("POST", url, headers=headers)
Providing Routing Information to the Call Router
Once a call comes into the number assigned to the call router, a JWT will be POST-ed to the routing_url
. The JSON content of the JWT will be of the form:
{
“date_started”: <ms_since_epoch>,
“call_id”: <call_id>,
“external_number”: “<e164 number>”,
“internal_number”: “<e164 number>”,
“contact_id”: <contact_id>,
“contact_type”: <contact_type>,
}
The external_number
will contain the number of the caller.
Allowed Actions
Based on the information provided to the URL, you can instruct the call router to take one of three actions. By default the action is assumed to be the route
action, so to trigger a different action you must specify the desired action in the action
field of the response payload.
Field | Type | Required? |
---|---|---|
action | One of: "route" , "ask" , "end" | false |
Route Action
The Route action will route the call to the specified target.
Field | Type | Required? | Description |
---|---|---|---|
target_id | integer | true | The ID of the Dialpad target that should receive the call |
target_type | string | true | The type associated with the target_id (i.e. office, department, callcenter, or user) |
Ask Action
In some scenarios, the ideal routing behaviour may be more complex than just dynamically forwarding a call. It may be desirable to ask the caller to choose between several options and make additional routing decision based on their response. It may also be desirable to play an audio clip to the caller and end the call (e.g. "Our office is currently closed. Please call back between 9 to 5 on a weekday"). This can be achieved using the ask
action.
An ask
action will ask the caller a specified question via a synthesized text-to-speech audio clip. The caller will be allowed to enter a response via their number pad. After an ask
action is completed, your routing endpoint will receive an additional request to allow it to take an additional action based on the caller's response. That information will be included in the post-ask
routing request in the form of a string containing the keys that the caller pressed. The hint_name
you provide will be the field in which the caller's response will appear in the post-ask
routing request.
Field | Type | Required? | Description |
---|---|---|---|
message | string or array | true | The message that should be played to the caller via text-to-speech *see additional considerations section |
hint_name | string | true | The field name in which to insert the caller's response in the subsequent routing request (more details below) |
finish_on_key | string | false | The key the caller should press to signal that they are finished inputting digits (by default, the input will conclude when the caller has pressed the number of digits specified in num_digits ) |
num_digits | integer | false | The number of digits that the caller should enter (defaults to 99 ) |
valid_digits | string | false | A string containing all keypad values that the caller can include in their response (defaults to "0123456789*#" )(the default is the full set of possible digits) |
retries | integer | false | The number of times the audio prompt should be repeated to the caller if they don't press any buttons on their keypad (defaults to 10 ) |
timeout | integer | false | The number of seconds to wait for the caller to press a button before repeating the prompt (defaults to 5 ) |
Using ask
actions increases the potential complexity of your routing logic, especially if the routing flow contains multiple ask
actions. A new request will be hitting the same routing endpoint for every step of the routing flow, which can be logistically challenging. Making good use of the hint_name
field can significantly simplify the logistical challenge. If you use a distinct hint_name
for each ask
action in your routing flow, then you will be able to distinguish between the post-ask
requests without needing any information other than the request itself. Choosing human-readable names can also improve debugging by making it easier to read and comprehend a series of routing requests.
For very complex flows, it may even be helpful to break up the routing process into several parts, and handle each part with a different router. For example, one call router could serve as a single entry point for all the calls within a country, and could redirect the calls to region-specific call routers based on the area code of the caller. Since each router can specify its own routing URL, this strategy can be used to turn a single hard-to-understand routing endpoint into several easier-to-understand routing endpoints.
The caller's response to ask
actions will only be included in the routing request immediately after that action, rather than being carrying forward into every subsequent routing request for that call. If the message repeats retries
times without any response from the caller, the call will simply end, and there will be no subsequent routing request.
End Action
An end
action will play a synthesized text-to-speech audio clip and then hang up the call.
Field | Type | Required? | Description |
---|---|---|---|
message | string or array | true | The message that should be played to the caller via text-to-speech *see additional considerations section |
Deleting Call Routers
Call routers can be deleted by calling the DELETE callrouters/id
method. Note that deletion takes effect immediately and would place the number assigned to the call router in reserve.
Error Handling
If the endpoint takes more than 5 seconds to respond or if there are more than 10 failures in an hour, then the call router will be automatically disabled, and an email will be sent to the office admin. In order to rejuvenate the call router, it must be re-enabled via the PATCH callrouters/id
method. In this situation, the first step will be to investigate and correct the underlying issue in your routing endpoint.
Uniform Errors
In many cases the issue will have a consistent source, and the error may be completely resolved once the issue is addressed. In this situation, the call router can simply be re-enabled the call router by setting the enabled
property to true
via the PATCH
endpoint.
Inconsistent Errors
In some situations (such as performance issues that occasionally result in request latency greater than 5-seconds), your routing endpoint may still have occasional routing errors after applying a fix. In this situation, it may be desirable to re-enable the router in addition to resetting the internal error count. To accomplish this, you can make a PATCH
request that includes "reset_error_count": true, "enabled": true
.
Additional Notes
Text-to-speech
For best results with text-to-speech fields (i.e. the message
field), the value should either be a single short string, or an array of short strings. When the Dialpad backend receives an end
or ask
action, it needs to take the message, synthesize it into an audio file, and then play that audio file to the caller. Text-to-speech is a computationally expensive operation, and in this context it needs to happen as quickly as possible. By allowing the input to be a list of strings, we can process each string into an audio file independently. This means that playback can begin as soon as the first string has been processed, rather than blocking on processing the whole message.
There is also a caching mechanism that helps reduce the playback latency. If Dialpad has seen a particular string before, then it likely already has an audio file in the cache that it can retrieve immediately.
To leverage these mechanisms most effectively:
- The message should be split into small pieces whenever possible
- The first string in a list of messages is the most important, since playback cannot begin until that string is processed.
- If the first string is always the same, Dialpad can make use of the audio file cache, so any dynamic strings should ideally come after an initial static string, where the processing time is much less likely to matter.
Call routers can be assigned multiple numbers.
Using multiple numbers may be useful for assessing the efficacy of an ad campaign or providing separate numbers for support and sales. Your routing endpoint can use this information to make routing decisions, since the internal_number
will indicate which number the caller dialed.
Call routers can be configured to send JWT payloads for additional security.
In order to verify that a routing request is genuine, you can set the secret
property on the call router by using the POST
or PATCH
endpoints. If a call router is given a secret
, then it will use that secret to send a signed JWT payload to your endpoint, rather than a raw JSON payload.
Updated about 3 years ago