POST

https://<your_api_key>:<your_api_token><subdomain>/v2/accounts/<your_sid>/campaigns

  • 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

The following are the POST parameters:

Parameter Name   Mandatory/Optional Value
from Mandatory Comma seperated list of phone numbers that will be called. Preferably in E.164 format. If not set, our system will try to match it with a country and make a call. If landline number, prefix it with STD code; Ex: 0XXXXXX2400. Default is 1 and Max is 5000
lists Optional

Array of listSid. Up to 5 listSid can be part of one single campaign. Either 'from' parameter or 'lists' parameter should be present in the API request

caller_id Mandatory This is your ExoPhone (pick one from here)
url Mandatory http://my.exotel.com/{your_sid}/exoml/start_voice/{app_id} where app_id is the identifier of the flow (or applet) that you want to connect to once the from number picks up the call. You can get the app_id from your Exotel Dashboard
name Optional

It's an optional parameter in the request but mandatory in the response. It is used to define the name of the campaign. It should be greater than 3 characters and if not passed, its default value will be created using the 'AccountSID CurrentDate CurrentTime' and passed in the response.

Example: exotel 2021-06-04 11:11:10

type Optional

It's an optional parameter in the request but mandatory in the response. It's allowed (and default) value is 'trans'. If not passed in the request, we will create campaign as type 'trans' and pass this parameter in the API response. As per regulations, we support only transactional type of campaigns.

call_duplicate_numbers

Optional

Type: boolean

Allowed Values: 'true' & 'false'

Default Value: 'false'

If 'true', Campaign will try calling the duplicate numbers present in the list(s). If 'false', Campaign will call any number in the list(s) only once. It is independent of the 'retry' functionality.

retries Optional

Object;Retry logic in case the calls are not successful.

  • number_of_retries - The number of times a call to a phone number should be attempted. Default is 0 and max is 3.
  • interval_mins - The time interval between retries in mins. Mandatory when number_of_retries is specified
  • mechanism - either "Linear" or "Exponential". If the retry should be equally spaced or exponentially. Default is linear.
  • on_status - Array; Determines when should campaign treat a call as an unsuccessful attempt. Could be "busy", "no-answer", "failed"
schedule Optional

Array;Determines when to start and end a campaign in RFC 3339 date-time

  • send_at - Time when the campaign should start. Default is to start now.
  • end_at - Time when the campaign should end even if all calls are not attempted as part of the campaign. Default +30 days from now or send_at time. This time is always strictly adhered to even there are calls pending to be made
call_status_callback Optional

When the call completes, an HTTP POST will be made to the provided URL with the following four parameters:

  • campaign_sid - an alpha-numeric unique identifier of this campaign
  • call_sid - an alpha-numeric unique identifier of this call
  • date_created - time when the resource was created
  • date_updated - time when the was updated
  • number - number to which the call was made
  • status - one of: completed, no-answer, busy, failed
call_schedule_callback Optional

When all calls to a number were completed including retries, an HTTP POST will be made to the provided URL with the following four parameters:

  • campaign_sid - an alpha-numeric unique identifier of this campaign
  • to - the number to which the call was made
  • from - the Exophone used in the campaign
  • date_created - time when the resource was created
  • date_updated - time when the resource was updated
  • call_sids - Object; includes all the call_sids and status of the calls that were made as part of this schedule
  • status - one of completed, busy, no-answer, failed
status_callback Optional

When the call campaign starts or ends, an HTTP POST will be made to the provided URL with the following four parameters:

  • campaign_sid - an alpha-numeric unique identifier of this campaign
  • date_created - time when the campaign resource was created
  • date_updated - time when the campaign was updated
  • date_started - time when the campaign started
  • status - one of: in-progress, completed, failed, canceled
  • reports - link to the campaign reports
custom_field Optional Any application specific value that will be passed back as a parameter while doing a GET request to the URL mentioned in your Passthru Applet or Greetings Applet.It is also provided as part of the campaigns report
curl -X POST https://<your_api_key>:<your_api_token><subdomain>/v2/accounts/<your_sid>/campaigns \
-H 'Content-Type: application/json' \
-d '{
  "campaigns": [
    {
    "name": "diwali_campaign",
    "type":"trans",
    "call_duplicate_numbers": true,
    "caller_id": "0XXXX720616",
    "url": "http://my.exotel.com/<your_sid>/exoml/start_voice/<app_id>",
    "lists": ["68f443cd3e764ad1ae7d82ad27f0af72"],
    "retries": {
      "number_of_retries": 3,
      "interval_mins": 2,
      "mechanism": "Exponential",
      "on_status": ["failed"]
    },
    "schedule": {
      "send_at": "2019-01-20T21:15:00+05:30",
      "end_at": "2019-01-20T21:16:00+05:30"
    },
    "status_callback": "https://mycallback.sampledomain.in/1gvta9f1",
    "call_status_callback": "https://mycallback.sampledomain.in/1gvta9f1",
    "call_schedule_callback": "https://mycallback.sampledomain.in/1gvta9f1",
    "custom_field": "{\"field\": \"value\"}"
    }
  ]
}'
var request = require("request");
var accountSid = "XXXXXXXXX";
var accountToken = "YYYYYYYYY";
var authKey = "ZZZZZZZZZZ";

var encoding = Buffer.from(authKey + ':' + accountToken).toString('base64');
var options = { method: 'POST',
  url: 'https://api.exotel.com/v2/accounts/'+ accountSid + '/campaigns',
  headers: 
   { 
     Authorization: 'Basic ' + encoding,
     'Content-Type': 'application/json' },
  body: 
   { campaigns: 
      [ { caller_id: '0XXXXXXXXX1',
          name: 'diwali_campaign',
          type:'trans',
          call_duplicate_numbers: true,
          url: 'http://my.exotel.com/<your_sid>/exoml/start_voice/<app_id>',
          lists: { include_lists : ["list_sid_1"], exclude_lists : ["list_sid_2"] },
          schedule: { send_at: '2018-11-08T14:20:00+05:30' },
          status_callback: 'https://mycallback.sampledomain.in/1gvta9f1',
          call_status_callback: 'https://mycallback.sampledomain.in/1gvta9f1' } ] },
  json: true };

request(options, function (error, response, body) {

  if (error) throw new Error(error);
  console.log(body.error_data);
  console.log(body);
});
<?php

$curl = curl_init();
$accountSid = "XXXXXXXXXX";
$accountToken = "YYYYYYYYYY";
$authKey = "ZZZZZZZZZZ";

$encoding = base64_encode($authKey .":". $accountToken);
curl_setopt_array($curl, array(
  CURLOPT_URL => "https://api.exotel.com/v2/accounts/".$accountSid."/campaigns",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => "",
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 30,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_POSTFIELDS => '{
    "campaigns": [{
    "name": "diwali_campaign",
    "type":"trans",
    "call_duplicate_numbers": true,
    "caller_id": "0XXXXXXXXX1",
    "url": "http://my.exotel.com/<your_sid>/exoml/start_voice/<app_id>",
    "lists": [ListSid2],
    "schedule": {"send_at": "2018-11-08T14:20:00+05:30"},
    "status_callback": "https://mycallback.sampledomain.in/1gvta9f1",
    "call_status_callback": "https://mycallback.sampledomain.in/1gvta9f1"}]}',
  CURLOPT_HTTPHEADER => array(
    "Authorization: Basic ".$encoding,
    "Content-Type: application/json"
  ),
));

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
  echo "cURL Error #:" . $err;
} else {
  echo $response;
}
import requests, base64, json
accountSid = "XXXXXXXXX"
authToken = "YYYYYYYYY"
authKey = "ZZZZZZZZZZ"

encoding = base64.b64encode(authKey + ":" + authToken)

url = "https://api.exotel.com/v2/accounts/"+accountSid+"/campaigns"

payload = json.dumps({ "campaigns": [{ 
          "caller_id": "0XXXXXXXXX1", 
          "name": "diwali_campaign",
          "type":"trans",
          "call_duplicate_numbers": true,
          "url": "http://my.exotel.com/<your_sid>/exoml/start_voice/<app_id>", 
          "lists": ["list_sid_1"],
          "status_callback": "https://mycallback.sampledomain.in/1gvta9f1", 
          "call_status_callback": "https://mycallback.sampledomain.in/1gvta9f1"}]
        })
headers = {
    'Content-Type': "application/json",
    'Authorization': "Basic " + encoding
    }

response = requests.request("POST", url, data=payload, headers=headers)

print(response.text)
print(json.dumps(json.loads(response.text), indent = 4, sort_keys = True))
package main

import (
	b64 "encoding/base64"
	"fmt"
	"io/ioutil"
	"net/http"
	"strings"
)

func main() {

	// Please provide accountSid, authToken from your Exotel account
	accountSid := "XXXXXXXXX"
	authToken := "YYYYYYYY"
	authKey := "ZZZZZZZZZZ"

	// Encoding the accountSid and authToken, used in Authorization header
	encoding := b64.StdEncoding.EncodeToString([]byte(authKey + ":" + authToken))

	url := "https://api.exotel.com/v2/accounts/" + accountSid + "/campaigns"

	payload := strings.NewReader(`{ 
  "campaigns": [{ 
    "caller_id": "0XXXXXXXXX1", 
	"name": "diwali_campaign",
    "type":"trans",
    "url": "http://my.exotel.com/<your_sid>/exoml/start_voice/<app_id>", 
    "lists": ["listSid1"]
    "retries": {
      "number_of_retries": 1,
      "interval_mins": 1,
      "mechanism": "Exponential",
      "on_status": [
          "failed",
          "busy"
      ]
  },
    "status_callback": "https://mycallback.sampledomain/1gvta9f1", 
    "call_status_callback": "https://mycallback.sampledomain.in/1gvta9f1"
    }]
  }`)

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("Content-Type", "application/json")
	req.Header.Add("Authorization", "Basic "+encoding)

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := ioutil.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}

HTTP Response:

  • On success, the HTTP response status code will be 200
  • The id is the unique identifier of the campaign, and it will be useful to log this for future debugging
  • HTTP body will contain an JSON similar to the one below
{
    "request_id": "745d624f47004b71bf72e6cb7d58a25b",
    "method": "POST",
    "http_code": 200,
    "response": [
        {
            "code": 200,
            "error_data": null,
            "status": "success",
            "data": {
                "name": "diwali_campaign",
                "type": "trans",
                "id": "909d2a2ba53ce07f3784668b938eb44914bo",
                "account_sid": "<your_sid>",
                "caller_id": "0XXXX720616",
                "lists": [
                    "68f443cd3e764ad1ae7d82ad27f0af72"
                ],
                "url": "http://my.exotel.com/<your_sid>/exoml/start_voice/<app_id>",
                "retries": {
                    "number_of_retries": 3,
                    "interval_mins": 2,
                    "mechanism": "Exponential",
                    "on_status": [
                        "failed"
                    ]
                },
                "schedule": {
                    "send_at": "2019-01-20T21:15:00+05:30",
                    "end_at": "2019-01-20T21:16:00+05:30"
                },
                "status_callback": "https://mycallback.sampledomain.in/1gvta9f1",
                "call_status_callback": "https://mycallback.sampledomain.in/1gvta9f1",
                "call_schedule_callback": "https://mycallback.sampledomain.in/1gvta9f1",
                "date_created": "2019-01-20T21:10:00+05:30",
                "date_updated": "2019-01-20T21:10:00+05:30",
                "custom_field": "{\"field\": \"value\"}",
                "status": "Created",
                "call_status_callback_params": null,
                "call_duplicate_numbers": true,
                "stats": {
                    "created": 0,
                    "in-progress": 0,
                    "retry": 0,
                    "retrying": 0,
                    "failed": 0,
                    "failed-dnd": 0,
                    "invalid": 0,
                    "paused": 0,
                    "failed-no-attempt": 0,
                    "completed": 0
                }
            },
            "summary": {
                "campaign_sid": "75ccf890dd85a87c138396b8abfec9251579",
                "call_scheduled": 0,
                "call_initialized": 0,
                "call_completed": 0,
                "call_failed": 0,
                "call_inprogress": 0,
                "DateCreated": "2019-01-20T21:10:00+05:30"
            }
        }
    ]
}

Description of parameters mentioned in the above response:

Parameter Name Type & Value
request_id string; Random string to uniquely identify the request
method string; HTTP request method (GET, POST, PUT, DELETE)
http_code string; HTTP response code for your request
response

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 POST on Campaigns API. Please note, this field can be null also in case of failures like 404.
id Campaigns identifier
account_sid Exotel account SID
from Array; phone numbers that we will be attempted as part of this campaign
caller_id The Exophone that is used to initiate calls for this campaign
url Identifier of the flow (or applet) that you want to connect to once the from number picks up the call
retries

JSON; The retries that were configured as part of this campaign:

  • number_of_retries - The number of times a call to a phone number should be attempted.
  • interval_mins - The time interval between retries in mins.
  • mechanism - Either "linear" or "exponential". If the retry should be equally spaced or exponentially.
  • on_status - Array; When should campaign treat a call as an unsuccesful attempt. Could be "busy", "no-answer", "failed"
schedule

JSON; The start and end time that were configured for this campaign:

  • send_at - Time when the campaign should start. Default is to start now.
  • end_at - Time when the campaign should end even if all calls are not attempted as part of the campaign. Default +30 days from now or send_at time. This time is always stricktly adhered to even there are calls pending to be made
status_callback URL to which an HTTP POST will be made upon completion of the campaign
call_status_callback URL to which an HTTP POST will be made upon completion of a call in the campaign
call_schedule_callback URL to which an HTTP POST will be made upon completion of one call schedule which includes retries
custom_field Application specific value that was be passed back as a parameter to the campaign creation
date_created Time in format: RFC 3339; Date and time at which the resource was created in the system
date_updated Time in format: RFC 3339; Date and time at which the resource was updated in the system
status

The current status of the campaign. Campaings have both intermediate and final status:

  • Created - A campaign resource was created in the system as a result of a succesful POST request to the campaigns end point
  • InProgress - The campaign is currently in progress
  • completed - The campaign has ended normally
  • Failed - None of the calls were made as part of the campaign (5xx/4xx/invalid numbers etc.). Immediate failures are marked as failed as well
  • Canceled - The campaign was paused but never resumed and end_at time reached or it expired
  • Deleted - The campaign which was deleted before the trigger (scheduled time)
  • Paused - The campaign that was scheduled or is in-progress was paused

Status Callbacks

There are multiple status callbacks that Campaign API serves when specified as part of POST request. Sample responses of each of them are given below

Call Status Callback:

  • On every attempt to call a number, a HTTP POST request is made to the end point specified
  • The campaign_sid is the unique identifier of the campaign, and it will be useful to log this for future debugging
  • the HTTP body will contain an JSON similar to the one below
{
    "request_id": "745d624f47004b71bf72e6cb7d58a25b",
    "method": "POST",
    "http_code": 200,
    "response": [
        {
            "code": 200,
            "error_data": null,
            "status": "success",
            "data": {
                "name": "diwali_campaign",
                "type": "trans",
                "id": "909d2a2ba53ce07f3784668b938eb44914bo",
                "account_sid": "exotel8u3",
                "caller_id": "0XXXX720616",
                "lists": [
                    "68f443cd3e764ad1ae7d82ad27f0af72"
                ],
                "url": "http://my.exotel.com/<your_sid>/exoml/start_voice/<app_id>",
                "retries": {
                    "number_of_retries": 1,
                    "interval_mins": 1,
                    "mechanism": "Exponential",
                    "on_status": [
                        "failed",
                        "busy"
                    ]
                },
                "schedule": {
                    "send_at": "2019-01-20T21:15:00+05:30",
                    "end_at": "2019-01-20T21:16:00+05:30"
                },
                "status_callback": "https://mycallback.sampledomain.in/1gvta9f1",
                "call_status_callback": "https://mycallback.sampledomain.in/1gvta9f1",
                "call_schedule_callback": "https://mycallback.sampledomain.in/1gvta9f1",
                "date_created": "2019-01-20T21:10:00+05:30",
                "date_updated": "2019-01-20T21:10:00+05:30",
                "status": "Created",
                "call_status_callback_params": null,
                "call_duplicate_numbers": true,
                "stats": {
                    "created": 0,
                    "in-progress": 0,
                    "retry": 0,
                    "retrying": 0,
                    "failed": 0,
                    "failed-dnd": 0,
                    "invalid": 0,
                    "paused": 0,
                    "failed-no-attempt": 0,
                    "completed": 0
                }
            },
            "summary": {
                "campaign_sid": "75ccf890dd85a87c138396b8abfec9251579",
                "call_scheduled": 0,
                "call_initialized": 0,
                "call_completed": 0,
                "call_failed": 0,
                "call_inprogress": 0,
                "DateCreated": "2019-01-20T21:10:00+05:30"
            }
        }
    ]
}

Call Schedule Status Callback:

  • After all attempts to call a number (including all retries), a HTTP POST request is made to the end point specified
  • The campaign_sid is the unique identifier of the campaign, and it will be useful to log this for future debugging
  • the HTTP body will contain an JSON similar to the one below
{
   "campaign_sid":"44a89f18b291441786f6be2dacee0366",
   "to": "+91XXXX161323",
   "from": "XXXXXX74100",
   "date_created": "2019-01-10T17:08:00+05:30",
   "date_updcated": "2019-01-10T17:08:00+05:30",
   "call_sids": [
       {
     "call_sid": "73f57c6bccd64a29a0cb4806af05cdbe",
       "status": "completed"
       }
   ],
   "status": "completed"
}

Campaigns Status Callback:

  • After the campaign is completed, a HTTP POST request is made to the end point specified
  • The campaign_sid is the unique identifier of the campaign, and it will be useful to log this for future debugging
  • the HTTP body will contain an JSON similar to the one below
{
   "campaign_sid": "44a89a18b291441786f6be2dfcee0366",
   "date_created": "2019-01-10T17:08:00+05:30",
   "date_updated": "2019-01-10T17:08:00+05:30",
   "date_started": "2019-01-10T17:08:00+05:30",
   "status": "completed",
   "reports": "https://campaigns-reports.s3.ap-southeast-1.amazonaws.com/000d3b00d7651e088e1b42be5d89xxx.csv"
}