Version 1.0 of the CCM Programmable Connect (Private Beta) should not be integrated henceforth as we will be deprecating it soon. Please use version 1.1 of CCM Programmable Connect (Beta)

Short video:

CCM programmable connect is our call centre version of connecting customers with agents by returning the agent id or phone number dynamically via a webhook. Using CCM programmable connect will ensure your agents are marked busy while they are on a call such that no other call (incoming or outgoing) is routed to them until they are free. Such agents (users) need to be created on Exotel via the dashboard or using APIs, or else the dial to non-agents would fail. If you are looking for a generic programmable connect without agent state management, refer here.

If this feature is enabled for your account you would see the option as shown above.

You can choose to configure the Connect applet parameters using the flow builder itself or control it dynamically through a URL. However, you'll need to configure the transitions (next applet) while building the flow irrespective.

If you choose to configure the parameters dynamically using your application URL, you can set a ‘Primary URL’ for handling the requests. You can also set a ‘Fallback URL’ (optional) which will be contacted in case something goes wrong with your ‘Primary URL’. 


If an application URL is set for Connect applet, Exotel will make a GET request to the URL with the call details as URL-encoded HTTP query parameters.

The following are the parameters of the GET request. Note that only some of this list may be passed to your application - depending on what stage of the flow you have placed the Connect applet.



This value will indicate the version of connecting applet parameters against which your endpoint’s response will be validated.

Current Version: 1.0

Query Parameters:

Parameter Name



Unique identifier of the call


The direction of the call. Possible values: ‘incoming’ or ‘outbound-dial’


Timestamp when the call is created (format: yyyy-mm-dd hh:mm: ss)


Value in seconds from the time call is triggered to the second leg of the call till it is over (including conversation time). This value can be set to zero depending on the previous applet and if there’s no second leg in the call flow.


Timestamp when the call is started (format: yyyy-mm-dd hh:mm:ss)


Shows the number of the agent who was dialed at last


In the case of an incoming call, it is the number of the caller. In the case of an outgoing call, it is the number of the first leg of the call.


 In the case of an incoming call, it is the ExoPhone into which the call came. In the case of an outgoing call, it is the number to which the call was made.


Current server time (format: yyyy-mm-dd hh:mm:ss)

*These parameters will be passed if certain conditions are met as described below:

Parameter Name                



This will denote what happened with the second leg of the call if the previous applet was “connect”.

Possible values: 'completed', 'busy', 'no-answer', 'failed', 'canceled'


‘digits’ will be passed if there was a 'Gather' or ‘IVR’ applet before this applet and will be equal to the input digits that were entered. NOTE: This parameter comes with a double quote (") before and after the number. You'll have to trim() this parameter for double quotes (") to get the actual digits.


This will be populated if the previous applet was "voicemail". It will contain the URL of the voicemail recording. There could be a delay before the recording can be accessed depending on the length of the recording file.


This is the response Exotel will expect to the GET request from your Connect Application URL. The response will decide what parameters will be set while executing Connect during the call flow.

Response Header:




"destination_type": "user",
"destination": [{"device_contact_uri": "+91995312XXXX"}],
"dial_passthru_event_url": "",
"record": true,
"music_on_hold": {
"start_call_playback": {
"value":"This text would be spoken out to the callee"






default = false

This parameter will indicate if, after each unsuccessful dial attempt within connect, the parameters should be fetched again including destination numbers.

`false` will indicate, a dial attempt happen based on the initial response. No subsequent hits to the URL.

`true` will indicate if connect parameters including a number to dial should be fetched again (hit the configured URL again) if the dial attempt is unsuccessful.

NOTE: If 2 subsequent fetch results contain exactly the same set of destination numbers, Exotel will not make any subsequent attempts even if fetch_after_attempt is set to true.

GET /<customer-url>

Apart from standard request params, it’ll include <connect> params from previous dial attempts.

<Same as above>

destination_typeMandatoryPossible values
  • user - If the destination to be dialed belongs to an agent (user) created on Exotel. Users would be marked busy in such a case.
  • external_number - If the destination to be dialed is a number not belonging to an agent. State management will not happen in this case (the user would not be marked busy/free in such a case).



An array of objects (JSON blocks). 

Possible values:

If, destination_type = user

  • id - UUID of the user
  • device_contact_uri - Phone Number of the user in EE.164 format OR SIP URI of the user. 

If, destination_type = external_number,

  • contact_uri - Phone Number of the user in EE.164 format (No agent state management would be done). DND checks would apply as applicable by platform.

NOTE 1: Currently dial to only one user or external_number is allowed at a time. To dial multiple users/external_number, use fetch_after_attempt to provide different users/external_number for same connect attempt.

NOTE 2: The dial will happen in the order they appear in the array. 


default = Incoming ExoPhone

ExoPhone is to be used for dialing out in E.164 format.


  • The ExoPhone added should be present in your account.

  • Restrictions will depend on telecom regulations i.e. another call can only be dial-ed out from the same telecom circle/region. For example, outgoing ExoPhone cannot be set to Delhi whereas Incoming ExoPhone is in Bangalore.

NOTE: If ExoPhone is not present in your account ExoPhone is unable to dial out i.e. if the above validation fails, then the call would be dial-ed out using the same ExoPhone as the first leg (where the incoming call landed).


default = false

true/false; Record the call or not



default = single

To record the caller and callee in separate channels in the recording file.

Possible values:

  • single

  • dual



default = 30

Value in seconds to limit the ringing duration. This can be increased up to 60 seconds.



default = 900 (15 minutes)

Value in seconds to limit the conversation duration. This can be increased up to 75 minutes (4500 s).



default = default_tone

Possible Values:

  • default_tone: Exotel default music on hold as present here.

  • operator_tone: Audio returned by the operator on the dialing channel as is.

  • custom_tone: Audio URL as provided in the response.

Sample Values:


“type”: “default_tone”



“type”: “operator_tone”



"type": "custom_tone",

"value": "<audio_url>"



Use this option to dial the numbers in parallel (simultaneously). This will dial all the numbers returned under the destination parameter.

"parallel_ringing": {

       "activate": true,

       "max_parallel_attempts": 5


max_parallel_attempts value can be between 1-10. Default: 5

*Please note this feature is chargeable and consult with your Account Manager or email before using this parameter.

The URL passed here will be requested for dial start and dial end events. For more details on request, refer to this.

You can also subscribe to an answered event on this URL (currently available to be enabled for select accounts via


Play a recording to the number that is being called


“type”: “audio_url”,

“value”: “http://...mp3”




“type”: “text”,

“value”: “hello, this is a sample text”


Configuration for audio files supported in this playback are:

Sample Rate = 8 kHz

Bit depth = 16 bit

Bit rate = 128 kbps

Channel = mono

File Format = wav

Note: If the file name returned in the case of `audio_url` is the same, it will be cached by our servers. Kindly, provide dynamic file names if the audio to be played is different each time.

Cases, where the Fallback URL will be triggered, are:

  • The primary URL does not return HTTP 200 OK

  • The primary URL doesn’t return within the timeout period (5 seconds)

  • Primary URL returns invalid response:

    • Content-Type should be application/JSON

    • Mandatory parameters are present

    • audio_url / text should be HTTP/HTTPS and returns 200 HTTP code

Transition to the next applet

The below transitions are to be set in the call flow builder to decide what to execute next.


  • After the call conversation ends: The applet set here will be triggered if a conversation occurs.

  • If nobody answers: The applet set here will be triggered if we dial the number and a conversation doesn’t occur. If no applet is present in "we didn't dial anyone", it will fall back to this.

  • We didn’t dial anyone: The applet set here will be triggered if we don’t dial. Cases when this can occur:

    • If both the Primary and Fallback URL endpoint times out or returns a non-2xx response code. 

    • If both the Primary and Fallback URL endpoint doesn’t return a valid payload.

    • If the number to dial returned is in invalid format.

    • If an empty number (destination) is returned in the response

    • Invalid user UUID or phone number of a user which doesn't exist
    • The user device is unverified
    • The user device is OFF (available = false) on Exotel
    • The user is busy on another call (Incoming or Outgoing)

If you have any questions or concerns, please connect with us using the chat widget on your Exotel Dashboard or Whatsapp us on 08088919888.