Heartbeat Subscription Beta

Heartbeat API notifies the ‘health’ of an Exophone in real time based on which actions can be taken at your end. To subscribe to Heartbeat, you need to put a working HTTP URL (it should return 200 OK on POST request) in the Notifications Settings of your Dashboard along with frequency mentioned in minutes. The URL endpoint will receive heartbeat notifications continously at the frequency you set.

Heartbeat Webhook Beta

This webhook (HTTP Push API) will ping information about your ExoPhone health every nth minute as configured. If some ExoPhones are facing connectivity issues, we will provide details about those ExoPhones alone. You can use the Get ExoPhone Details API described in next section for further connectivity information about an ExoPhone.

Description of parameters which will be set in heartbeat requests to your endpoint:

Parameter Name



This denotes the time when a particular heartbeat request was generated in our system.
Date Time Format: RFC 3339
Example: 2018-08-22T15:19:23Z


This will provide an overall state of all your ExoPhones combined. Possible values

  • OK - This denotes that all your ExoPhones are healthy and there is no connectivity issue identified by our system
  • WARNING - One or more ExoPhones' health is affected in either incoming/outgoing or both.
  • CRITICAL - All your ExoPhones health is affected in either incoming/outgoing or both
  • PAYLOAD_TOO_LARGE - It indicates that the maximum payload size limit (10MB) this method supports has breached. You may observe this error if you have signficantly large quantity of ExoPhones in your account. In case you observe this, you can use Get Exophone Details to know your ExoPhones health.


Array; List of unique SIDs denoting ExoPhone(s) for which incoming call connectivity is affected


Array; List of unique SIDs denoting ExoPhone(s) for which outgoing call connectivity is affected


This block contains comma separated nested JSON blocks denoting information per ExoPhone which is having connectivity issues as mentioned in incoming_affected or outgoing_affected array.

phone_number_sid (key): Unique string which identifies the ExoPhone owned by you. This may not always be same as your phone number. You can find out your ExoPhone SID by triggering a GET request using your auth credentials on https://api.exotel.com/v2/accounts/<account_sid>/incoming-phone-numbers

It’s value will be a nested JSON containing below:

phone_number - Denoting the phone_number of the ExoPhone in E.164 format. This can be different than the SID of the phone number.

For example, 02030090005 denotes the phone_number_sid (key) and phone_number is present as parameter within it in E.164 format.


    "phone_number": "+912030090005"


Note: There could be multiple blocks depending on numbers present in incoming_affected and outgoing_affected list.

Example webhook payload with possible scenarios:

Scenario #1

If everything is working fine i.e. all ExoPhones are healthy (OK):

    "timestamp": "2018-08-22T15:19:23Z",	
    "status_type": "OK",
    "incoming_affected": null,
    "outgoing_affected": null,
    "data": {}

Scenario #2

If some ExoPhones connectivity is affected (WARNING):

   "timestamp": "2018-08-22T15:19:23Z>",
   "outgoing_affected": null,
         "phone_number": "+917930061010",

Scenario #3

If all ExoPhones connectivity is affected (CRITICAL):

   "timestamp": "2018-08-22T15:19:23Z",
         "phone_number": "+917930061010",
          "phone_number": "+918030752522",

Responding to a heartbeat request

The HTTP Response for acknowledging the heartbeat webhook request should be 200 OK. All other non-2XX HTTP codes or if your server is unable to respond timely will indicate that you have not received the heartbeat and we will retry. In such retry cases, your server should be able to handle subsequent requests of the same heartbeat and the timestamp field in the heartbeat payload can be used to uniquely identify the most recent heartbeat.

Retries and timeouts

If your server needs to perform any complex logic, or make internal network calls, it is possible that the heartbeat webhook request might time out. For that reason, you might want to have your webhook endpoint immediately acknowledge receipt by returning a 2XX HTTP status code, and then perform the rest of its operations.

Guidelines on usage

You should consume Heartbeat Webhook to continuously be aware of your ExoPhones health status and take necessary actions. In case any of your ExoPhone faces an issue as reported by webhook, you can query the GET ExoPhone Details for fetching further details. The GET endpoint can also be used to pull status per ExoPhone in case the webhook is not consumed by your servers (Exotel not being able to send or because your server is unable to process). As a best practice, polling the GET endpoint is not recommended. Exotel will throttle requests to GET ExoPhone Details endpoint with HTTP Code 429.

Get Details of an ExoPhone Beta

To get the details of a specific ExoPhone in your account including connectivity information, make an HTTP GET request to:



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

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

curl -X GET https://<your_api_key>:<your_api_token><subdomain>/v2/accounts/<your_sid>/incoming-phone-numbers/<exophone_sid>
var request = require('request');
var options = {
    url: 'https://<your_api_key>:<your_api_token><subdomain>/v2/accounts/<your_sid>/incoming-phone-numbers/<exophone_sid>'
function callback(error, response, body) {
    if (!error && response.statusCode == 200) {
request(options, callback);
$headers = array();
$response = Requests::get('https://<your_api_key>:<your_api_token><subdomain>/v2/accounts/<your_sid>/incoming-phone-numbers/<exophone_sid>', $headers);
import requests
require 'net/http'
require 'uri'
uri = URI.parse("https://<your_api_key>:<your_api_token><subdomain>/v2/accounts/<your_sid>/incoming-phone-numbers/<exophone_sid>")
response = Net::HTTP.get_response(uri)
# response.code
# response.body

HTTP Response:

  • On success, the HTTP response status code will be 200
  • The sid is the unique identifier of the number
  • the HTTP body will contain an JSON similar to the one below:
  "request_id": "0f403dff8d854ca08c570a94717aa7d9",
  "method": "GET",
  "http_code": 200,
  "metadata": {
    "page_size": 1,
    "page": 0
  "response": [
      "code": 200,
      "error_data": null,
      "status": "success",
      "data": {
        "sid": "01139585476",
        "date_created": "2018-08-22T12:22:49Z",
        "date_updated": "2018-08-24T11:25:49Z",
        "friendly_name": "01139585476",
        "account_sid": "Exotel",
        "phone_number": "+911139585476",
        "capabilities": {
          "voice": true
        "country": "IN",
        "region": "DL",
        "one_time_price": "0.000000",
        "rental_price": "499.000000",
        "incoming_rate": "0.000000",
        "incoming_pulse": "60",
        "currency": "INR",
        "number_type": "Landline",
        "vanity_number": false,
        "voice_url": "https://my.exotel.com/Exotel/exoml/start_voice/XXX",
        "sms_url": "https://my.exotel.com/Exotel/exoml/start_sms/XXX",
        "uri": "/v2/accounts/Exotel/incoming-phone-numbers/01139585476",
        "connectivity": {
          "incoming_call": {
            "status": "active",
            "last_check_time": "2018-08-24T11:25:49Z",
            "alternate_exophone": null
          "outgoing_call": {
            "status": "active",
            "last_check_time": "2018-08-24T11:25:49Z",
            "alternate_exophone": null

Description of Parameters:

Parameter Name



Random string to uniquely identify the request


HTTP request method (GET, POST, PUT, DELETE)


HTTP response code for your request like 200, 404, 429, 500 etc.


To provide metadata about the response. In case of GET for pagination (bulk), it'll contain:

  • page_size - total number of items in a page
  • page - denotes page number


JSON array representing the response and contains below parameters:

  • code - response code of the block in the response array, can be different from the overall http code, like in case of partial success (207)
  • error_data - To be populated in case of errors like below
"error_data": {
  "code": 1000,
  "description": "Not Found",
  "message": "Not Found"

In case of no errors, it’ll be null.

  • status - success or failure, depicting the status of the block in the response array
  • data - This will contain the data part of the block of the response array depending on the API, below table describes what will be populated in case of GET IPN. Please note, this field can be null also in case of failures like 404.


String; An alpha-numeric unique identifier of the ExoPhone. This can be different than the ExoPhone itself.


Time in format: RFC 3339; Date and time at which the ExoPhone was added to the account


Time in format: RFC 3339; Date and time at which the details of the ExoPhone was last updated


Exotel account SID


The phone number value of the ExoPhone in E.164 format like +911139585476


A freindly name that can be used to identify the ExoPhone


These are the capabilities that are supported on this ExoPhone:

  • voice - Boolean that indicates if incoming voice calls are supported on the ExoPhone
  • sms - Boolean that indicates if incoming SMS is supported on the ExoPhone


ISO Country Code to which this ExoPhone belongs to


The telecom circle this ExoPhone belongs to. Refer here for list of possible telecom circles.


One time cost incurred while adding this ExoPhone to your account


Double; Recurring monthly rental associated with this ExoPhone


Double; The per pulse cost for incoming calls


Double; The duration of one pulse in seconds


Double; The currency in which this ExoPhone is billed


Double; The type of the ExoPhone


Boolean; Indicates if this ExoPhone is a vanity number


string; The Url to the flow to which incoming calls are connected to


string; The Url to the flow to which incoming SMS are connected to


string; The Url to the flow to which incoming calls are connected to


JSON block representing connectivity information about the ExoPhone. It contains incoming_call, outgoing_call blocks which represent connectivity information for incoming call and outgoing call respectively.

Description of 'connectivity' parameters:

Parameter Name



It represents the connectivity status for that functionality (incoming call or outgoing call). Possible values are

  • active: ExoPhone is healthy as per our monitoring system
  • major_outage: ExoPhone is inactive and calls are not connecting as per our monitoring system
  • partial_network_outage: ExoPhone is working partially and is down from/towards one or more operator connectivities. This would be populated once operator level connectivity monitoring information is exposed (yet to be released)


Format: RFC 3339; timestamp representing when this number was checked last for connectivity


If available, this will provide alternate ExoPhones in JSON array format which can be used if the given ExoPhone is down. If there are no alternate ExoPhones available it will be populated as null