×

To make a call connecting a user to a customer, you will need to make a HTTP POST request to

POST

https://<your_api_key>:<your_api_token>@<subdomain>/v3/accounts/<your_sid>/calls

Example (For Singapore Stamp)-

POST

https://<your_api_key>:<your_api_token>@ccm-api.exotel.com/v3/accounts/<your_sid>/calls

Example (For Mumbai Stamp)

POST

https://<your_api_key>:<your_api_token>@ccm-api.in.exotel.com/v3/accounts/<your_sid>/calls

  • Replace <your_api_key> and <your_api_token> with the API key and token created by you OR use Basic Authentication.
  • Replace <your_sid> with your “Account sid”
  • Replace <subdomain> with the region of your account
    1. <subdomain> of Singapore cluster is @ccm-api.exotel.com
    2. <subdomain> of Mumbai cluster is @ccm-api.in.exotel.com

<your_api_key> , <your_api_token> and <your_sid> are available in the API settings page of your Exotel Dashboard

The following are the POST parameters supported with Content-Type: application/json set in the header

Parameter

Mandatory/

Optional

Value/Description

from

Mandatory

JSON block indicating the number to be dialed first (leg1). This should be your user/agent number. Currently it has two attributes:

  • contact_uri - Phone Number preferably in E.164 format or the SIP URI if VOIP calling is enabled. 
  • state_management- Allows the state management to be done on the ‘from’ number. Can be:
    • false (default) - Number will not be checked for busy status before allowing calls on that number
    • true - Number will be checked for busy status before allowing calls on that number

If the contact_uri is already added to the Exotel dashboard as a user number, state_management will be ‘true’ by default.

Example- 

{
  "from": {
    "contact_uri": "+9199XXXXXXX",
    "state_management": "true"
  }
}

If not set in E.164 format, our system will try to match it with a country and make a call. If landline number, prefix it with STD code; Ex: 080XXXX2400

to

Mandatory

JSON block containing the phone number of the customer (leg2) to be connected after the ‘from’ number is connected.

  • contact_uri- Phone number in E.164 format which will be dialed if the leg 1 of the call is picked up

Example -

 
{
  "to": {
    "contact_uri": "+9199XXXXXXX"
  }
}

virtual_number

Mandatory

ExoPhone (Virtual Number) present in your account in E.164 format or local format for Indian virtual numbers. This will be the number that will be used to make the call to both ‘from’ and ‘to’ numbers.

recording

Optional

JSON block containing the recording related attributes. Currently these are record, channels and the ormat.

  • record: Record the conversation of your call. The recording url will be sent to the status_callback URL if this is set to 'true' and the call conversation happens. Can be:
  • true - Call conversation will be recorded
  • false (default) - Call conversation will not be recorded
  • channels: Number of audio channels to be present in the final recording
    • single- Record both legs of the call in a single channel of the recording file
    • dual - Record the caller and the callee into separate channels of the recording file
  • format: Quality of the audio recording.
    • mp3- Standard bitrate recording
    • mp3-hq- Higher bitrate (32 kbps/channel) recording. Mp3-hq option is an on-demand feature.

Please reach out to hello@exotel.com to get it enabled for your account before using this option.

Example-

{
  "recording": {
    "record": "true",
    "channels": "single",
    "format": "mp3-hq"
  }
}

wait_audio_url

Optional

String; Play this audio to the caller. When the first leg (from) has to wait for the other leg (to) to pick up the call, the audio file specified in this parameter will be played.

Please refer to this article to understand the format specifications of the audio file to be played (wav is only supported).

Guidelines on usage:

  • The audio file size is recommended to be less than 2MB. Please note, Exotel will cache the wav file. During the first few call attempts of setting this parameter, the user might hear normal ringing tone for the first 5 seconds (for a ~2MB file). This is only temporary for initial few calls and once the audio file is cached, audio will be played out smoothly
  • In case you decide to change the audio file later, the WaitUrl should be different (as Exotel will cache audio files based on URL). You can do so by hosting the audio file with a different name
  • When using this parameter, it is recommended to set the TimeOut parameter as well

Example: "http://{your_hosted_endpoint}/{audio file name}.wav"

max_time_limit

Optional

Integer; The time limit (in seconds) that you want this call to last. The call will be cut after this time

Default: 4 hours

attempt_time_out

Optional

Integer; The time (in seconds) to ring the called parties (both first and second call leg)

Default: 30 seconds.

custom_field

Optional

String; Any application specific value like order id that will be passed back as a parameter in status_callback

status_callback

Optional

Array: An HTTP request will be made to the specified URLs based on the subscribed events and methods. Currently the supported attributes are: 

  • event: Call events for which we will send details to the URL as set in the url attribute. 'event' becomes mandatory if you have specified a url for the status_callback. terminal/answered or both events could be subscribed to:
    • terminal - This will be triggered once the call is over
    • answered - This will be triggered for each of the legs (From and To) if and when they answer the call
  • url: An HTTP request will be made to this URL depending on what event is subscribed to using the ‘event’ attribute.

method: Default: POST

Allowed: GET and POST

content_type: The HTTP header ‘Content-Type’ using which the status_callback webhook will be triggered to your URL. Can be:

  • multipart/form-data
  • application/json  (default)

Example:

{
  "status_callback": [
    {
      "event": "answered",
      "url": "",
      "method": "POST",
      "content_type": "application/json"
    },
    {
      "event": "terminal",
      "url": "",
      "method": "GET",
      "content_type": "application/json"
    }
  ]
}

playback

Optional

Array: Contains the playback related attributes. Currently, the supported attributes are:

  • event: When should the party (Callee or Both) listen to the playback. Can be:
    • start: At the start of the call
  • to: The party that should listen to the playback. Audio to be listened by the user or both customer and user based on the event. Can be:
    • callee (default) - Playback audio will be played to callee only
    • both - Playback audio will be played to both caller and callee
  • value: URL for the audio to be played just before the call gets connected

Example:

{
  "playback": [
    {
      "event": "start",
      "to": "both",
      "value": ""
    }
}

streaming

Optional

JSON block containing the streaming related attributes. Currently, these are:

  • url: url that supports webSocket where audio will be streamed
  • begin: Describes the beginning of audio streaming- from the point when first user connection is established or once both the users’ connections are established. Can be:
    • from_leg_connect
    • to_leg_connect

Example:

{
  "streaming": {
    "url": "",
    "begin": "from_leg_connect"
  }
}

 

{
  "from": {
    "contact_uri": "8516043026",
    "state_management": true
  },
  "to": {
    "contact_uri": "7987616844"
  },
  "recording": {
    "record": true,
    "channels": "single"
  },
  "virtual_number": "+912241499102",
  "max_time_limit": 4000,
  "attempt_time_out": 45,
  "custom_field": "bilbo_test_call",
  "status_callback": [
    {
      "event": "terminal",
      "url": "https://webhook.site/aecd85dc-f959-48b5-abaf-d45189037e09"
    }
  ]
}

 

HTTP Response:

  • On success, the HTTP response status code will be 200. Please note that a 200 OK isn’t a confirmation of a call being successfully placed/answered. Refer to the StatusCallBack or the GET Call Details API to understand the status of the call.

 

Response parameter description:

Parameter Name

Type & Value

request_id

This indicates the unique id of the request. Useful for debugging and tracing purposes.

method

This indicates the HTTP method for the request such as GET/POST/PUT etc.

http_code

This indicates the HTTP code for the request such as 200, 400, 500 etc.

response

Response block contains the user device record matching the request URI. The block contains

  • code - This indicates the http code for the particular record in the response array like 200, 400 etc.
  • error_data - This block will be null if there is no error else contain error information for the response with following fields
    • code - This would be the error code useful for Exotel's team to debug and can be highlighted in case of unexpected errors.
    • description - This describes the details of the error.
    • message - This is the error message corresponding to the error code useful for Exotel's team to debug and can be highlighted in case of unexpected errors.
  • status - This field would indicate status of the response (success/failure).
  • call_details - This block will contain the information corresponding to the response array element and will contain the fields for a user record as explained below. 

 

Description of parameters under 'call_details' block:

 

Parameter

Value/Description

sid

string; an alpha-numeric unique identifier of the call

direction

  • inbound - Incoming call
  • outbound-dial - Outbound calls from Exotel dashboard
  • outbound-api - All other Outbound calls (API, campaign etc.)

virtual_number

This is your ExoPhone/Exotel Virtual Number

state

  • active: call is not yet over OR post call processing data is yet to be processed
  • terminal: call is over and data is processed against it

status

Overall call status, could be one of:

  • completed: The call was answered and has ended normally
  • from_leg_unanswered: User (From leg) was unanswered due to various reasons such as switched off, not reachable, no-answer, busy, connection failed etc.
  • to_leg_unanswered: Customer (To leg) was unanswered due to various reasons such as switched off, not reachable, no-answer, busy, connection failed etc.
  • from_leg_cancelled - User (From leg) canceled the call while the customer was dialed. This could happen during ringing, blank calls or during an operator message such as switched off, no-answer, busy etc.
  • to_leg_no_dial - There was no dial initiated to customer (rare scenario)
  • from_leg_no_dial - There was no dial initiated to user (rare scenario)

legs

This URL can be used as a GET API to fetch the legs information of a given call_sid

created_time

Time in format YYYY-MM-DD HH:mm:ss+|–hh:mm; Date and time (along with the offset) at which the user initiated the API

updated_time

Time in format YYYY-MM-DD HH:mm:ss+|–hh:mm; Date and time (along with the offset) at which the status of the call was last updated in our system

start_time

Time in format YYYY-MM-DD HH:mm:ss+|–hh:mm; Date and time (along with the offset) when the call request was initiated to the operator

end_time

Time in format YYYY-MM-DD HH:mm:ss+|–hh:mm; Date and time (along with the offset) when the call was completed

total_duration

Total call duration in seconds (From start_time to end_time)

total_talk _time

Total time a customer was on call. If there were more than one conversation, it would be the sum of all conversations.

Eg- User 1 spoke to Customer for 5 minutes and transferred to User 2 and spoke to customer for 10 minutes, total_talk_time for the call would be 15 minutes

custom_field

The value that was passed in the custom_field parameter of the API (if set during the request) will be populated here.

app_id

Flow ID which was used at the start of the call. Null if flow was not used.

app_name

Flow Name which was used at the start of the call. Null if flow was not used

digits

DTMF digits pressed during the call separated by “-” for different applets. Similar to how it is represented in Call Reports

recordings

Array; It will contain all recordings associated with the call. Each array will contain

  • url - This will represent the playable URL for the corresponding recording

*Some of the above parameters can be null for POST response as they'll be not set immediately after call creation

{
  "request_id": "1e2acb77c0f84db4821e765510fdecff",
  "method": "POST",
  "http_code": 200,
  "metadata": null,
  "response": {
    "code": 200,
    "error_data": null,
    "status": "success",
    "call_details": {
      "sid": "3f3fedf8f0928550a60bfa6302dc16b2",
      "direction": "outbound",
      "virtual_number": "02241499102",
      "state": "active",
      "status": null,
      "legs": "/v3/accounts/Exotel/calls/3f3fedf8f0928550a60bfa6302dc16b2/legs",
      "created_time": "2022-11-02 23:49:51+05:30",
      "updated_time": "2022-11-02 23:49:52+05:30",
      "start_time": "2022-11-02 23:49:52+05:30",
      "end_time": null,
      "total_duration": null,
      "total_talk_time": null,
      "custom_field": "bilbo_test_call",
      "app_id": null,
      "app_name": null,
      "digits": null,
      "recordings": null
    }
  }
}

 

Status Call Back

Exotel will perform an asynchronous HTTP request to the status_callback URL you have specified in your request (if any) based on the status_callback event type and the request method opted for. List of parameters which will be sent as part of status_callback. 

Parameter

Value/Description

event_details

JSON block containing the status callback event related attributes. Currently, these are:

  • event_type- Type of the event subscribed to. Can be:
    • answered- This will be triggered for each leg of the call, if and when the leg is answered
    • terminal- This will be triggered once the call is over

call_details

This block will contain the information corresponding to the response array element and will contain the fields for a user record as explained under the 'call_details' block.

{
  "event_details": {
    "event_type": "terminal"
  },
  "call_details": {
    "sid": "0ed3bd4755078e1f9f64d2de75ce16b3",
    "direction": "outbound",
    "virtual_number": "+912241499102",
    "state": "terminal",
    "status": "completed",
    "legs": "/v3/accounts/Exotel/calls/0ed3bd4755078e1f9f64d2de75ce16b3/legs",
    "created_time": "2022-11-03 00:18:32+05:30",
    "updated_time": "2022-11-03 00:19:02+05:30",
    "start_time": "2022-11-03 00:18:38+05:30",
    "end_time": "2022-11-03 00:19:02+05:30",
    "total_duration": null,
    "total_talk_time": 11,
    "custom_field": "bilbo_test_call",
    "app_id": null,
    "app_name": null,
    "digits": null,
    "recordings": [
      {
        "url": "https://s3-ap-south-1.amazonaws.com/exotel-mum1-recordings/Exotel/0ed3bd4755078e1f9f64d2de75ce16b3.mp3"
      }
    ]
  }
}

 

Possible error scenarios in case of this POST API

HttpCode Code Description
401 1010
Authentication failed
404 10731
User not found
409 1012
User device is unavailable
409 10705
User device is unverified
409 10706
User device is currently busy
404 10806
No device found for user
404 1017
AccountSid not found
404 10702
User Device not found
409 10705
User device is unverified
404 1021
Call not found / unsupported in this API
404 1022
Call not found / unsupported in this API
400 1001
account_sid is mandatory
400 1002
Valid values for RecordingChannels are single, dual
500 1100
Internal Server Error
500 1101
Internal Server Error
500 1200
Internal Server Error
404 10703
Device is currently unavailable (turned off)
500 1203
Internal Server Error
500 1300
Internal Server Error
405 10712
VOIP calls are not allowed
500 1500
Internal Server Error
500 1600
Internal Server Error
500 1601
Internal Server Error
500 1800
Internal Server Error
500 3040
Internal Server Error
500 3042
Internal Server Error
404 3043
Call not found / unsupported in this API
404 3044
Call not found / unsupported in this API
404 3045
Call not found / unsupported in this API
500 3046
Internal Server Error
500 3075
Internal Server Error
500 3080
Internal Server Error
500 4060
Internal Server Error
404 10716
Given virtual_number not found
404 10706
User device is currently busy
*These will be populated under the `error_data` block of response