Callbacks

With callbacks, our system calls one party and if they accept the call, calls a second party and connects then together.

A callback is initiated by a call to our telecoms.callback.create API function.

Example scenario

The call can optionally be recorded, and emailed to you if you wish.

There is also the option of having webhooks sent to a URL supplied in the API call so that you can see realtime progress of the call (eg when calling, when ringing, when answered etc).

Contents

telecoms.callback.create introduction

In a callback call, there are two parties. A "party" is a person being called / participant in the call. The system calls the first party, and upon successful connection, calls the second party and connects them together so that they may have a conversation.

zz

The parties are defined in the party1 and party2 arguments. These are sub-objects/arrays that define the destination (typically a phone number but can be other things) as well as other options, if required.

For simplicity, if party1 is just a phone number (which may optionally include an extension) then this can instead be defined in the destnumber1 argument, which just takes a string containing the phone number (and optional extension).

Similarly, destnumber2 can be submitted as an alternative argument to party2 if there is no need for additional features for this party.

Basic example

In the simplest case, a user is browsing your site and wants to speak to an agent. They key in their phone number in a form on your site and click a button to request a call.

Your agent's phone number is 02079460987 (see number-formatting)
The user's phone number is 02079460123 (see number-formatting).

You want the agent's phone to ring, and upon answer, the user to be called, giving the agent no option to accept or reject (besides hang up their phone).

JSON example request:

POST https://live.apicontrol.co.uk/1/json
{
   "auth" : {
      "username" : YOURUSERNAME,
      "password" : YOURPASSWORD,
   },
   "func" : "telecoms.callback.create",
   "args" : {
      "destnumber1" : "02079460987",
      "destnumber2" : "02079460123"
   }
}

JSON example response:

{
    "success": 1,
    "results": {
        "callbackUID": "67d32019.7dbad.8e5c.1696c2"
    }
}

You may wish to store the callbackUID value returned. This callbackUID value will be available in the extra_params field in CDRs (see telecoms.calldata.detail.get) and will also be a field in realtime webhooks. Using this you can associate your callback request with call data and call status.

Navigating remote menus

You may specify an extension if, for example, your agent can only be reached after selecting an option in a remote menu. For example, if the first party's phone system invites the caller to enter an extension number if they know it, and the agent is on extension 4455, then you could specify that as an extension to their phone number:

JSON example request:

POST https://live.apicontrol.co.uk/1/json
{
   "auth" : {
      "username" : YOURUSERNAME,
      "password" : YOURPASSWORD,
   },
   "func" : "telecoms.callback.create",
   "args" : {
      "destnumber1" : "02079460987,4455",
      "destnumber2" : "02079460123"
   }
}

See ddi-extensions for more information and options on how to use this feature.

Extended options for call parties

You may wish to use extended options if you wish to do any of these things with either party of the call:

Clearly, some combinations of the above would have little or no practical use (eg routing party1 to an IVR menu on your account as this would get stuck until something timed out) but the flexibiliy is there for you to exploit whichever options are suitable.*

* routing party2 (or destnumber2) to an IVR menu may have a practical use, however, if you wish to encourage party1 to go through the IVR menu which they have somehow failed to call themselves so that they actually do end up renewing their car insurance or whatever.

If you wish to have additional options for either party in the callback, you may supply a "party" argument instead of a "argument" for the appropriate party, ie instead of destnumber1 you can specify party1, and instead of destnumber2 you can specify party2. Both substitutions are optional, and substituting one does not require you to substitute the other. In other words, you may specify any of these combinations:

Calling number presentation

By default, the callbacks come from a withheld number. This can be overridden with the presentCLI argument, in which you specify the number that each party will see as the number that is calling them.

The number you give this argument must be either a number on the account you have with us, or a number that we don't host ourselves but have validated to be yours (eg your mobile number or office number).

JSON example request:

POST https://live.apicontrol.co.uk/1/json
{
   "auth" : {
      "username" : YOURUSERNAME,
      "password" : YOURPASSWORD,
   },
   "func" : "telecoms.callback.create",
   "args" : {
      "destnumber1" : "02079460987",
      "destnumber2" : "02079460123",
      "presentCLI" : "02079460555",
   }
}
However, if you specify a number that is not on your account or validated to be yours, you would receive an error like the one below. Note the errordiags/info returned:

JSON example response:

{
   "error" : "presentCLI not found within account",
   "errordiags" : {
      "child_arg" : "presentCLI",
      "child_val" : "02079460555",
      "errclass" : "illegal",
      "errtype" : "perm",
      "info" : "number not owned, validated or associated with this account",
      "parent_account_arg" : 12345,
      "parent_account_val" : "(API user)"
   },
   "errornum" : "5.2.18",
   "results" : {},
   "success" : 0
}
If you wish to present a different calling number to each party, then you must use at least one of party1 or party2 instead of destnumber1 or destnumber2 respectively, eg:

JSON example request:

POST https://live.apicontrol.co.uk/1/json
{
   "auth" : {
      "username" : YOURUSERNAME,
      "password" : YOURPASSWORD,
   },
   "func" : "telecoms.callback.create",
   "args" : {
      "party1" : {
         "dest_type" : "number",
         "destnumber" : "02079460987",
         "presentCLI" : "02079460555"
      },
      "party2" : {
         "dest_type" : "number",
         "destnumber" : "02079460123",
         "presentCLI" : "02079460666"
      }
   }
}

Accepting, deferring or rejecting the callback

You may wish one of the call parties (typically party1) the option of accepting, deferring or rejecting the call by entering their choice on their phone keypad after hearing a brief message. This uses our callee verify feature (which also has a use in routeplans/huntgroups).

JSON example request:

POST https://live.apicontrol.co.uk/1/json
{
   "auth" : {
      "username" : YOURUSERNAME,
      "password" : YOURPASSWORD,
   },
   "func" : "telecoms.callback.create",
   "args" : {
      "party1" : {
         "dest_type" : "number",
         "destnumber" : "02079460987",
         "presentCLI" : "02079460555",
         "callee_verify" : {
            "prompt_soundclipURL" : "https://example.com/test-sounds/worf.captain-incoming-message.mp3",
            "default_action" : "defer",
            "acceptkeys": ["1"],
            "deferkeys": ["2"],
            "rejectkeys": ["9"]
         }
      },
      "party2" : {
         "dest_type" : "number",
         "destnumber" : "02079460123",
         "presentCLI" : "02079460666"
      },
      "defer_dur":600
   }
}

In the above example, upon answering the phone, party1 will be played the sound prompt that is at the URL in the example and then will be able to press "1" to accept, "2" to defer or "9" to reject the callback. defer_dur is set to 600 (seconds, ie 10 minutes), so if the agent chooses to defer the call (or indeed presses nothing because the default action is defined as defer as well), then the system will re-attempt the callback 10 minutes later. If the defer_dur argument is not specified, the system will assume a deferral duration of 5 minutes.

You could if you wished also specify callee verify for party 2, but that is likely to lead to a poor user experience for party1 if the second party doesn't accept the call, so you may not want to do that.

If you don't have a suitable endpoint for serving sound files, you can upload a sound file via the telecoms.soundclip.create function instead, or use the portal. If you use the API function, it will return a soundclipID to you. However, if you don't have the soundclipID you can call telecoms.soundclip.list to get a list of your soundclips and IDs.

You would then specify the soundclipID instead of the URL when creating the endpoint. This is actually a more reliable approach as it doesn't have to rely on a successful connection to your file serving endpoint (and the downloaded file being in a usable format).

JSON example request:

POST https://live.apicontrol.co.uk/1/json
{
   "auth" : {
      "username" : YOURUSERNAME,
      "password" : YOURPASSWORD,
   },
   "func" : "telecoms.callback.create",
   "args" : {
      "party1" : {
         "dest_type" : "number",
         "destnumber" : "02079460987",
         "presentCLI" : "02079460555",
         "callee_verify" : {
            "prompt_soundclipID" : 2911,
            "default_action" : "defer",
            "acceptkeys": ["1"],
            "deferkeys": ["2"],
            "rejectkeys": ["9"]
         }
      },
      "party2" : {
         "dest_type" : "number",
         "destnumber" : "02079460123",
         "presentCLI" : "02079460666"
      },
      "defer_dur":600
   }
}

Handling failures

Unless both parties answer (and if callee verify is enabled, accept the call), then the callback is considered to have failed. by default, if this happens, the callback will be deferred by the deferral duration and will be re-attempted after that time has passed.

It is not desirable for the system to keep re-attempting a callback indefinitely, so there are limits in place so that a persistently failing callback is eventually aborted. If desired, the system will send notification of this abort either via a webhook, via email, or both.

The arguments for defining how failures are handled are as follows:

JSON example request:

POST https://live.apicontrol.co.uk/1/json
{
   "auth" : {
      "username" : YOURUSERNAME,
      "password" : YOURPASSWORD,
   },
   "func" : "telecoms.callback.create",
   "args" : {
      "party1" : {
         "dest_type" : "number",
         "destnumber" : "02079460987",
         "presentCLI" : "02079460555",
         "callee_verify" : {
            "prompt_soundclipURL" : "https://example.com/test-sounds/worf.captain-incoming-message.mp3",
            "default_action" : "defer",
            "acceptkeys": ["1"],
            "deferkeys": ["2"],
            "rejectkeys": ["9"]
         }
      },
      "party2" : {
         "dest_type" : "number",
         "destnumber" : "02079460123",
         "presentCLI" : "02079460666"
      },
      "defer_dur":600,

      "abort_after_dur" : 7200,
      "abort_after_failures" : 10,
      "abort_notify_URL" : "https://example.com/notifications/callback-abort",
      "abort_notify_email" : "fred@example.com"
   }
}

Requesting webhooks

Webhooks can be sent to your endpoint to give you realtime updates of call events. To request this, supply the webhookURL argument. There are additional arguments that can change some of the webhook options:

Each webhook contains a number of fields. Note that the callbackUID value returned by a successful API request will appear in every webhook for this callback.

JSON example request:

POST https://live.apicontrol.co.uk/1/json
{
   "auth" : {
      "username" : YOURUSERNAME,
      "password" : YOURPASSWORD,
   },
   "func" : "telecoms.callback.create",
   "args" : {
      "party1" : {
         "dest_type" : "number",
         "destnumber" : "02079460987",
         "presentCLI" : "02079460555",
         "callee_verify" : {
            "prompt_soundclipURL" : "https://example.com/test-sounds/worf.captain-incoming-message.mp3",
            "default_action" : "defer",
            "acceptkeys": ["1"],
            "deferkeys": ["2"],
            "rejectkeys": ["9"]
         }
      },
      "party2" : {
         "dest_type" : "number",
         "destnumber" : "02079460123",
         "presentCLI" : "02079460666"
      },
      "defer_dur":600,

      "abort_after_dur" : 7200,
      "abort_after_failures" : 10,
      "abort_notify_URL" : "https://example.com/notifications/callback-abort",
      "abort_notify_email" : "fred@example.com",

      "webhookURL" : "https://example.com/notifications/callback",
      "webhook_timeout": 5,
      "webhook_retries": 2,
      "webhook_DTMF": "RX"
   }
}

Call recording

If requested, our system will record the conversation and optionally email it to you.

In order to record the conversation, you should set the value of the callrec_party argument to 1 or 2. Normally it would make most sense to set this to 2, as then the recording would only commence once the second party has answered the call and the two parties can hear each other. Setting this argument to 1 would result in the start of the recording hearing party1's experience, including the audio prompt (if specified) and any ringing they hear whilst the system is calling the second party.

If requesting call recording, there are other additional arguments which may be useful:

Note that if you have requested webhooks as well as call recording, as soon as the recording is ready, a webhook declaring "callrec_ready" and including the download URL will be sent to your endpoint.

JSON example request:

POST https://live.apicontrol.co.uk/1/json
{
   "auth" : {
      "username" : YOURUSERNAME,
      "password" : YOURPASSWORD,
   },
   "func" : "telecoms.callback.create",
   "args" : {
      "party1" : {
         "dest_type" : "number",
         "destnumber" : "02079460987",
         "presentCLI" : "02079460555",
         "callee_verify" : {
            "prompt_soundclipURL" : "https://example.com/test-sounds/worf.captain-incoming-message.mp3",
            "default_action" : "defer",
            "acceptkeys": ["1"],
            "deferkeys": ["2"],
            "rejectkeys": ["9"]
         }
      },
      "party2" : {
         "dest_type" : "number",
         "destnumber" : "02079460123",
         "presentCLI" : "02079460666"
      },
      "defer_dur":600,

      "abort_after_dur" : 7200,
      "abort_after_failures" : 10,
      "abort_notify_URL" : "https://example.com/notifications/callback-abort",
      "abort_notify_email" : "fred@example.com",

      "webhookURL" : "https://example.com/notifications/callback",
      "webhook_timeout": 5,
      "webhook_retries": 2,
      "webhook_DTMF": "RX",

      "callrec_party": 2,
      "callrec_stereo": 1
   }
}

Adding a custom call reference

When calling the API to create the callback, you can supply a reference string in the ref argument (max length 45 characters). This ref string will be stored in the CDRs (downloadable with telecoms.calldata.detail.get) and will also appear in every webhook for that call.

JSON example request:

POST https://live.apicontrol.co.uk/1/json
{
   "auth" : {
      "username" : YOURUSERNAME,
      "password" : YOURPASSWORD,
   },
   "func" : "telecoms.callback.create",
   "args" : {
      "party1" : {
         "dest_type" : "number",
         "destnumber" : "02079460987",
         "presentCLI" : "02079460555",
         "callee_verify" : {
            "prompt_soundclipURL" : "https://example.com/test-sounds/worf.captain-incoming-message.mp3",
            "default_action" : "defer",
            "acceptkeys": ["1"],
            "deferkeys": ["2"],
            "rejectkeys": ["9"]
         }
      },
      "party2" : {
         "dest_type" : "number",
         "destnumber" : "02079460123",
         "presentCLI" : "02079460666"
      },
      "defer_dur":600,

      "abort_after_dur" : 7200,
      "abort_after_failures" : 10,
      "abort_notify_URL" : "https://example.com/notifications/callback-abort",
      "abort_notify_email" : "fred@example.com",

      "webhookURL" : "https://example.com/notifications/callback",
      "webhook_timeout": 5,
      "webhook_retries": 2,
      "webhook_DTMF": "RX",

      "callrec_party": 2,
      "callrec_stereo": 1,

      "ref":"AC2-292382-022382"
   }
}