Political Campaign Conducting a Poll
CallFire allows you to conduct different types of polls using phone calls. Our service provides an IVR technology which helps you interact with your clients, ask questions, get answers, record phone calls, etc. Let's see how we can set up a simple survey.
Story
An independent organization conducted a political poll. The results show that there may be a low voter turnout in Colorado, so they intend to increase voter turnout by calling voters to learn what issues matter to them this election cycle. But how can you reach that many people in so short a time? Tom, a volunteer coordinator, proposes to use an IVR. Tom needs to prepare an IVR dialplan, list of recipients, and then create an IVR broadcast. This article shows how to start the broadcast and gather the responses.
IVR dialplan
The term IVR stands for Interactive Voice Response. An IVR allows you to ask questions through pre-recorded or text-to-speech prompts, and receive responses via phone key presses. The CallFire IVR setup uses an XML-based definition. The following IVR XML dialplan first detects if the call is answered by a person, and then asks recipients a few questions. You can also define your questions based on a recipient's previous answers. The following is an example of an IVR political poll:
<dialplan name="Root">
<amd>
<live>
<goto name="goto_Live">Live</goto>
</live>
<machine>
<goto name="goto_Machine">Machine</goto>
</machine>
</amd>
<menu maxDigits="1" timeout="3500" name="Live">
<play type="tts" voice="female1" name="play_Live">Hello.
This is a call for a short political poll for the upcoming election.
Will you vote in the upcoming election?
Press 1 for Yes, or 2 for No..</play>
<keypress pressed="1" name="kp_Vote">
<stash varname="Vote" name="stash_Will_Vote">Yes</stash>
<goto>Question_01</goto>
</keypress>
<keypress pressed="2" name="kp_Will_Not_Vote">
<stash varname="Vote" name="stash_Will_Not_Vote">No</stash>
<play type="tts" voice="female1" name="play_Goodbye_1">Thank you for your time. Goodbye.</play>
<goto>Hangup</goto>
</keypress>
<keypress pressed="default" name="incorrect_Selection">
<play type="tts" voice="female1" name="play_Inorrect_Selection">That is not a valid selection. Please try again.</play>
<goto name="replay_Live">Live</goto>
</keypress>
</menu>
<menu maxDigits="1" timeout="3500" name="Question_01">
<play type="tts" voice="female1" name="play_Question_01">Who will you vote for in the upcoming elections?
Press 1 for Donkeys.
Press 2 for Elephants.
Press 3 for Greenies,
press 4 for Undecided,
or,
press 5 for Decline to state.</play>
<keypress pressed="1-5" name="Selection_Question_01">
<stash varname="Candidate" name="stash_Candidate">${call.lastinput}</stash>
<goto name="goto_Goodbye">Goodbye</goto>
</keypress>
<keypress pressed="default" name="incorrect_Selection_Question_01">
<play type="tts" voice="female1" name="play_Inorrect_Selection_Question_01">
That is not a valid selection. Please try again.
</play>
<goto name="replay_Question_01">Question_01</goto>
</keypress>
</menu>
<play type="tts" voice="female1" name="Goodbye">
Thank you for taking our poll. Please remember to vote in the upcoming election! Thank you for your time. Goodbye.
</play>
<goto name="Goodbye_Hangup">Hangup</goto>
<play type="tts" voice="female1" name="Machine">
Hello. This is a call for a political poll for the upcoming election.
Sorry we missed you. We will try you again later, or,
if you would like to take this short poll, please call 8 5 5,5 5 5,5 5 5 5. Thank you.</play>
<hangup name="Hangup"/>
</dialplan>
This flowchart shows how the IVR dialplan is executed:
You can find more information about the IVR at the CallFire Answers Page and different IVR examples are available on our public Github repository.
Check the CallFire XML page for detailed descriptions of all IVR tags.
Create an IVR Broadcast
IVR Broadcasts send an IVR call to each recipient added to the broadcast. Then you can query the broadcast statistics, like the number of live answers, the billed duration, the number of failed calls, responses, and other information:
[[code-container]] [+curl] request:
#!/usr/bin/env bash
curl -u username:password -H "Content-Type:application/json" -X POST -d '
{
"name": "Political Campaign",
"fromNumber": "12135551189",
"labels": [
"political-poll",
"id-10002"
],
"localTimeRestriction": {
"beginHour": 9,
"beginMinute": 0,
"endHour": 18,
"endMinute": 0
},
"retryConfig": {
"maxAttempts": 2,
"minutesBetweenAttempts": 5,
"retryResults": [
"BUSY",
"NO_ANS"
],
"retryPhoneTypes": [
"MOBILE_PHONE",
"WORK_PHONE"
]
},
"dialplanXml": "<dialplan name=\"Root\"> <amd> <live> <goto name=\"goto_Live\">Live</goto> </live> <machine> <goto name=\"goto_Machine\">Machine</goto> </machine> </amd> <menu maxDigits=\"1\" timeout=\"3500\" name=\"Live\"> <play type=\"tts\" voice=\"female1\" name=\"play_Live\">Hello. This is a call for a short political poll for the upcoming election. Will you vote in the upcoming election? Press 1 for Yes, or 2 for No..</play> <keypress pressed=\"1\" name=\"kp_Vote\"> <stash varname=\"Vote\" name=\"stash_Will_Vote\">Yes</stash> <goto>Question_01</goto> </keypress> <keypress pressed=\"2\" name=\"kp_Will_Not_Vote\"> <stash varname=\"Vote\" name=\"stash_Will_Not_Vote\">No</stash> <play type=\"tts\" voice=\"female1\" name=\"play_Goodbye_1\">Thank you for your time. Goodbye.</play> <goto>Hangup</goto> </keypress> <keypress pressed=\"default\" name=\"incorrect_Selection\"> <play type=\"tts\" voice=\"female1\" name=\"play_Inorrect_Selection\">That is not a valid selection. Please try again.</play> <goto name=\"replay_Live\">Live</goto> </keypress> </menu> <menu maxDigits=\"1\" timeout=\"3500\" name=\"Question_01\"> <play type=\"tts\" voice=\"female1\" name=\"play_Question_01\">Who will you vote for in the upcoming elections? Press 1 for Donkeys. Press 2 for Elephants. Press 3 for Greenies, press 4 for Undecided, or, press 5 for Decline to state.</play> <keypress pressed=\"1-5\" name=\"Selection_Question_01\"> <stash varname=\"Candidate\" name=\"stash_Candidate\">${call.lastinput}</stash> <goto name=\"goto_Goodbye\">Goodbye</goto> </keypress> <keypress pressed=\"default\" name=\"incorrect_Selection_Question_01\"> <play type=\"tts\" voice=\"female1\" name=\"play_Inorrect_Selection_Question_01\"> That is not a valid selection. Please try again. </play> <goto name=\"replay_Question_01\">Question_01</goto> </keypress> </menu> <play type=\"tts\" voice=\"female1\" name=\"Goodbye\"> Thank you for taking our poll. Please remember to vote in the upcoming election! Thank you for your time. Goodbye. </play> <goto name=\"Goodbye_Hangup\">Hangup</goto> <play type=\"tts\" voice=\"female1\" name=\"Machine\"> Hello. This is a call for a political poll for the upcoming election. Sorry we missed you. We will try you again later, or, if you would like to take this short poll, please call 8 5 5,5 5 5,5 5 5 5. Thank you.</play> <hangup name=\"Hangup\"/> </dialplan> "
}' "https://api.callfire.com/v2/calls/broadcasts"
response:
{
"id": 15
}
[-curl]
[+java]
import com.callfire.api.client.CallfireClient;
import com.callfire.api.client.api.campaigns.model.CallBroadcast;
import com.callfire.api.client.api.campaigns.model.LocalTimeRestriction;
import com.callfire.api.client.api.campaigns.model.RetryConfig;
import com.callfire.api.client.api.campaigns.model.RetryConfig.RetryPhoneTypes;
import com.callfire.api.client.api.campaigns.model.RetryConfig.RetryResults;
import com.callfire.api.client.api.common.model.ResourceId;
import java.util.Arrays;
class ApiClientSample {
public static void main(String[] args) {
CallfireClient client = new CallfireClient("api_login", "api_password");
CallBroadcast broadcast = new CallBroadcast();
broadcast.setName("Political Campaign");
// attach custom labels if needed
broadcast.setLabels(Arrays.asList("political-poll", "id-10002"));
// set validated Caller ID number.
broadcast.setFromNumber("12135551189");
// add IVR XML
broadcast.setDialplanXml(buildDialplanXml());
// allow CallFire to dial recipient only between 09:00 - 18:00 depending on
// recipient's number area code timezone
LocalTimeRestriction timeRestriction = new LocalTimeRestriction();
timeRestriction.setBeginHour(10);
timeRestriction.setBeginMinute(0);
timeRestriction.setEndHour(18);
timeRestriction.setEndMinute(0);
broadcast.setLocalTimeRestriction(timeRestriction);
// set retry configuration to attempt a contact's Mobile and Work phone numbers twice in case Call was
// resulted to BUSY or No Answer response. Set 5 minutes between attempts.
RetryConfig retryConfig = new RetryConfig();
retryConfig.setMaxAttempts(2);
retryConfig.setMinutesBetweenAttempts(5);
retryConfig.setRetryResults(Arrays.asList(RetryResults.BUSY, RetryResults.NO_ANS));
retryConfig.setRetryPhoneTypes(Arrays.asList(RetryPhoneTypes.MOBILE_PHONE, RetryPhoneTypes.WORK_PHONE));
broadcast.setRetryConfig(retryConfig);
// create broadcast with 'start' argument = true to start campaign immediately
ResourceId id = client.callBroadcastsApi().create(broadcast);
System.out.println(id);
}
private static String buildDialplanXml() {
return
" <dialplan name=\"Root\"> "
+ " <amd> "
+ " <live> "
+ " <goto name=\"goto_Live\">Live</goto> "
+ " </live> "
+ " <machine> "
+ " <goto name=\"goto_Machine\">Machine</goto> "
+ " </machine> "
+ " </amd> "
+ " <menu maxDigits=\"1\" timeout=\"3500\" name=\"Live\"> "
+ " <play type=\"tts\" voice=\"female1\" name=\"play_Live\">Hello. "
+ " This is a call for a short political poll for the upcoming election. "
+ " Will you vote in the upcoming election? "
+ " Press 1 for Yes, or 2 for No..</play> "
+ " <keypress pressed=\"1\" name=\"kp_Vote\"> "
+ " <stash varname=\"Vote\" name=\"stash_Will_Vote\">Yes</stash> "
+ " <goto>Question_01</goto> "
+ " </keypress> "
+ " <keypress pressed=\"2\" name=\"kp_Will_Not_Vote\"> "
+ " <stash varname=\"Vote\" name=\"stash_Will_Not_Vote\">No</stash> "
+ " <play type=\"tts\" voice=\"female1\" name=\"play_Goodbye_1\">Thank you for your time. Goodbye.</play> "
+ " <goto>Hangup</goto> "
+ " </keypress> "
+ " <keypress pressed=\"default\" name=\"incorrect_Selection\"> "
+ " <play type=\"tts\" voice=\"female1\" name=\"play_Inorrect_Selection\">That is not a valid selection. Please try again.</play>"
+ " <goto name=\"replay_Live\">Live</goto> "
+ " </keypress> "
+ " </menu> "
+ " <menu maxDigits=\"1\" timeout=\"3500\" name=\"Question_01\"> "
+ " <play type=\"tts\" voice=\"female1\" name=\"play_Question_01\">Who will you vote for in the upcoming elections?"
+ " Press 1 for Donkeys. "
+ " Press 2 for Elephants. "
+ " Press 3 for Greenies, "
+ " press 4 for Undecided, "
+ " or, "
+ " press 5 for Decline to state.</play> "
+ " <keypress pressed=\"1-5\" name=\"Selection_Question_01\"> "
+ " <stash varname=\"Candidate\" name=\"stash_Candidate\">${call.lastinput}</stash> "
+ " <goto name=\"goto_Goodbye\">Goodbye</goto> "
+ " </keypress> "
+ " <keypress pressed=\"default\" name=\"incorrect_Selection_Question_01\"> "
+ " <play type=\"tts\" voice=\"female1\" name=\"play_Inorrect_Selection_Question_01\"> "
+ " That is not a valid selection. Please try again. "
+ " </play> "
+ " <goto name=\"replay_Question_01\">Question_01</goto> "
+ " </keypress> "
+ " </menu> "
+ " <play type=\"tts\" voice=\"female1\" name=\"Goodbye\"> "
+ " Thank you for taking our poll. Please remember to vote in the upcoming election! Thank you for your time. Goodbye. "
+ " </play> "
+ " <goto name=\"Goodbye_Hangup\">Hangup</goto> "
+ " <play type=\"tts\" voice=\"female1\" name=\"Machine\"> "
+ " Hello. This is a call for a political poll for the upcoming election. "
+ " Sorry we missed you. We will try you again later, or, "
+ " if you would like to take this short poll, please call 8 5 5,5 5 5,5 5 5 5. Thank you.</play> "
+ " <hangup name=\"Hangup\"/> "
+ " </dialplan> "
+ " ";
}
}
[-java]
[+csharp]
using System.Collections.Generic;
using CallfireApiClient;
using CallfireApiClient.Api.Campaigns.Model;
public class ApiClientSample
{
public static void Main(string[] args)
{
var client = new CallfireClient("api_login", "api_password");
var broadcast = new CallBroadcast
{
Name = "Political Campaign",
// set validated Caller ID number.
FromNumber = "12135551189",
// attach custom labels if needed
Labels = new List<string> {"political-poll", "id-10002"},
// allow CallFire to dial recipient only between 09:00 - 18:00 depending on
// recipient's number area code timezone
LocalTimeRestriction = new LocalTimeRestriction
{
BeginHour = 9,
BeginMinute = 0,
EndHour = 18,
EndMinute = 0
},
// set retry configuration to attempt a contact's Mobile and Work phone numbers twice in case Call was
// resulted to BUSY or No Answer response. Set 5 minutes between attempts.
RetryConfig = new RetryConfig
{
MaxAttempts = 2,
MinutesBetweenAttempts = 5,
RetryResults = new List<RetryResults> {RetryResults.BUSY, RetryResults.NO_ANS},
RetryPhoneTypes = new List<RetryPhoneTypes>
{
RetryPhoneTypes.MOBILE_PHONE,
RetryPhoneTypes.WORK_PHONE
}
},
// set IVR XML
DialplanXml = @"
<dialplan name=""Root"">
<amd>
<live>
<goto name=""goto_Live"">Live</goto>
</live>
<machine>
<goto name=""goto_Machine"">Machine</goto>
</machine>
</amd>
<menu maxDigits=""1"" timeout=""3500"" name=""Live"">
<play type=""tts"" voice=""female1"" name=""play_Live"">Hello.
This is a call for a short political poll for the upcoming election.
Will you vote in the upcoming election?
Press 1 for Yes, or 2 for No..</play>
<keypress pressed=""1"" name=""kp_Vote"">
<stash varname=""Vote"" name=""stash_Will_Vote"">Yes</stash>
<goto>Question_01</goto>
</keypress>
<keypress pressed=""2"" name=""kp_Will_Not_Vote"">
<stash varname=""Vote"" name=""stash_Will_Not_Vote"">No</stash>
<play type=""tts"" voice=""female1"" name=""play_Goodbye_1"">Thank you for your time. Goodbye.</play>
<goto>Hangup</goto>
</keypress>
<keypress pressed=""default"" name=""incorrect_Selection"">
<play type=""tts"" voice=""female1"" name=""play_Inorrect_Selection"">That is not a valid selection. Please try again.</play>
<goto name=""replay_Live"">Live</goto>
</keypress>
</menu>
<menu maxDigits=""1"" timeout=""3500"" name=""Question_01"">
<play type=""tts"" voice=""female1"" name=""play_Question_01"">Who will you vote for in the upcoming elections?
Press 1 for Donkeys.
Press 2 for Elephants.
Press 3 for Greenies,
press 4 for Undecided,
or,
press 5 for Decline to state.</play>
<keypress pressed=""1-5"" name=""Selection_Question_01"">
<stash varname=""Candidate"" name=""stash_Candidate"">${call.lastinput}</stash>
<goto name=""goto_Goodbye"">Goodbye</goto>
</keypress>
<keypress pressed=""default"" name=""incorrect_Selection_Question_01"">
<play type=""tts"" voice=""female1"" name=""play_Inorrect_Selection_Question_01"">
That is not a valid selection. Please try again.
</play>
<goto name=""replay_Question_01"">Question_01</goto>
</keypress>
</menu>
<play type=""tts"" voice=""female1"" name=""Goodbye"">
Thank you for taking our poll. Please remember to vote in the upcoming election! Thank you for your time. Goodbye.
</play>
<goto name=""Goodbye_Hangup"">Hangup</goto>
<play type=""tts"" voice=""female1"" name=""Machine"">
Hello. This is a call for a political poll for the upcoming election.
Sorry we missed you. We will try you again later, or,
if you would like to take this short poll, please call 8 5 5,5 5 5,5 5 5 5. Thank you.</play>
<hangup name=""Hangup""/>
</dialplan>
"
};
// create broadcast with 'start' argument = true to start campaign immediately
var id = client.CallBroadcastsApi.Create(broadcast);
}
}
[-csharp]
[+js]
'strict'
const CallfireClient = require('callfire-api-client-js');
const client = new CallfireClient('api-login', 'api-password');
client.ready(() => {
client.calls.createCallBroadcast({
// set start parameter to run broadcast immediately
// start: true,
body: {
name: 'Political Campaign',
fromNumber: '12135551189',
labels: [
'political-poll',
'id-10002'
],
localTimeRestriction: {
beginHour: 9,
beginMinute: 0,
endHour: 18,
endMinute: 0
},
retryConfig: {
maxAttempts: 2,
minutesBetweenAttempts: 5,
retryResults: [
'BUSY',
'NO_ANS'
],
retryPhoneTypes: [
'MOBILE_PHONE',
'WORK_PHONE'
]
},
dialplanXml: '<dialplan name="Root"> <amd> <live> <goto name="goto_Live">Live</goto> </live> <machine> <goto name="goto_Machine">Machine</goto> </machine> </amd> <menu maxDigits="1" timeout="3500" name="Live"> <play type="tts" voice="female1" name="play_Live">Hello. This is a call for a short political poll for the upcoming election. Will you vote in the upcoming election? Press 1 for Yes, or 2 for No..</play> <keypress pressed="1" name="kp_Vote"> <stash varname="Vote" name="stash_Will_Vote">Yes</stash> <goto>Question_01</goto> </keypress> <keypress pressed="2" name="kp_Will_Not_Vote"> <stash varname="Vote" name="stash_Will_Not_Vote">No</stash> <play type="tts" voice="female1" name="play_Goodbye_1">Thank you for your time. Goodbye.</play> <goto>Hangup</goto> </keypress> <keypress pressed="default" name="incorrect_Selection"> <play type="tts" voice="female1" name="play_Inorrect_Selection">That is not a valid selection. Please try again.</play> <goto name="replay_Live">Live</goto> </keypress> </menu> <menu maxDigits="1" timeout="3500" name="Question_01"> <play type="tts" voice="female1" name="play_Question_01">Who will you vote for in the upcoming elections? Press 1 for Donkeys. Press 2 for Elephants. Press 3 for Greenies, press 4 for Undecided, or, press 5 for Decline to state.</play> <keypress pressed="1-5" name="Selection_Question_01"> <stash varname="Candidate" name="stash_Candidate">${call.lastinput}</stash> <goto name="goto_Goodbye">Goodbye</goto> </keypress> <keypress pressed="default" name="incorrect_Selection_Question_01"> <play type="tts" voice="female1" name="play_Inorrect_Selection_Question_01"> That is not a valid selection. Please try again. </play> <goto name="replay_Question_01">Question_01</goto> </keypress> </menu> <play type="tts" voice="female1" name="Goodbye"> Thank you for taking our poll. Please remember to vote in the upcoming election! Thank you for your time. Goodbye. </play> <goto name="Goodbye_Hangup">Hangup</goto> <play type="tts" voice="female1" name="Machine"> Hello. This is a call for a political poll for the upcoming election. Sorry we missed you. We will try you again later, or, if you would like to take this short poll, please call 8 5 5,5 5 5,5 5 5 5. Thank you.</play> <hangup name="Hangup"/> </dialplan> '
}
})
.then((response) => {
console.log(response.obj);
})
.catch((err) => {
console.log('request error ' + err.data);
});
},
(clientError) => {
console.log('client error ' + clientError);
}
);
[-js]
[+python]
from callfire.client import CallfireClient
client = CallfireClient('api-login', 'api-password')
response = client.calls.createCallBroadcast(
# set start parameter to run broadcast immediately
# start: true,
body={
'name': 'Political Campaign',
'fromNumber': '12135551189',
'labels': [
'political-poll',
'id-10002'
],
'localTimeRestriction': {
'beginHour': 9,
'beginMinute': 0,
'endHour': 18,
'endMinute': 0
},
'retryConfig': {
'maxAttempts': 2,
'minutesBetweenAttempts': 5,
'retryResults': [
'BUSY',
'NO_ANS'
],
'retryPhoneTypes': [
'MOBILE_PHONE',
'WORK_PHONE'
]
},
'dialplanXml': '<dialplan name="Root"> <amd> <live> <goto name="goto_Live">Live</goto> </live> <machine> <goto name="goto_Machine">Machine</goto> </machine> </amd> <menu maxDigits="1" timeout="3500" name="Live"> <play type="tts" voice="female1" name="play_Live">Hello. This is a call for a short political poll for the upcoming election. Will you vote in the upcoming election? Press 1 for Yes, or 2 for No..</play> <keypress pressed="1" name="kp_Vote"> <stash varname="Vote" name="stash_Will_Vote">Yes</stash> <goto>Question_01</goto> </keypress> <keypress pressed="2" name="kp_Will_Not_Vote"> <stash varname="Vote" name="stash_Will_Not_Vote">No</stash> <play type="tts" voice="female1" name="play_Goodbye_1">Thank you for your time. Goodbye.</play> <goto>Hangup</goto> </keypress> <keypress pressed="default" name="incorrect_Selection"> <play type="tts" voice="female1" name="play_Inorrect_Selection">That is not a valid selection. Please try again.</play> <goto name="replay_Live">Live</goto> </keypress> </menu> <menu maxDigits="1" timeout="3500" name="Question_01"> <play type="tts" voice="female1" name="play_Question_01">Who will you vote for in the upcoming elections? Press 1 for Donkeys. Press 2 for Elephants. Press 3 for Greenies, press 4 for Undecided, or, press 5 for Decline to state.</play> <keypress pressed="1-5" name="Selection_Question_01"> <stash varname="Candidate" name="stash_Candidate">${call.lastinput}</stash> <goto name="goto_Goodbye">Goodbye</goto> </keypress> <keypress pressed="default" name="incorrect_Selection_Question_01"> <play type="tts" voice="female1" name="play_Inorrect_Selection_Question_01"> That is not a valid selection. Please try again. </play> <goto name="replay_Question_01">Question_01</goto> </keypress> </menu> <play type="tts" voice="female1" name="Goodbye"> Thank you for taking our poll. Please remember to vote in the upcoming election! Thank you for your time. Goodbye. </play> <goto name="Goodbye_Hangup">Hangup</goto> <play type="tts" voice="female1" name="Machine"> Hello. This is a call for a political poll for the upcoming election. Sorry we missed you. We will try you again later, or, if you would like to take this short poll, please call 8 5 5,5 5 5,5 5 5 5. Thank you.</play> <hangup name="Hangup"/> </dialplan> '
}
).result()
# see sample JSON response for this API
# on 'curl' samples tab
print(response)
[-python]
[+php]
<?php
class ApiClientSample {
public static function main() {
$client = \CallFire\Api\DocumentedClient::createClient("login", "password");
$request = $client->createCallBroadcast();
$body = '{
"name": "Political Campaign",
"fromNumber": "12135551189",
"labels":
[
"political-poll",
"id-10002"
],
"localTimeRestriction":
{
"beginHour": 9,
"beginMinute": 0,
"endHour": 18,
"endMinute": 0
},
"retryConfig":
{
"maxAttempts": 2,
"minutesBetweenAttempts": 5,
"retryResults":
[
"BUSY",
"NO_ANS"
],
"retryPhoneTypes":
[
"MOBILE_PHONE",
"WORK_PHONE"
]
},
"dialplanXml": "<dialplan name=\"Root\"> <amd> <live> <goto name=\"goto_Live\">Live</goto> </live> <machine> <goto name=\"goto_Machine\">Machine</goto> </machine> </amd> <menu maxDigits=\"1\" timeout=\"3500\" name=\"Live\"> <play type=\"tts\" voice=\"female1\" name=\"play_Live\">Hello. This is a call for a short political poll for the upcoming election. Will you vote in the upcoming election? Press 1 for Yes, or 2 for No..</play> <keypress pressed=\"1\" name=\"kp_Vote\"> <stash varname=\"Vote\" name=\"stash_Will_Vote\">Yes</stash> <goto>Question_01</goto> </keypress> <keypress pressed=\"2\" name=\"kp_Will_Not_Vote\"> <stash varname=\"Vote\" name=\"stash_Will_Not_Vote\">No</stash> <play type=\"tts\" voice=\"female1\" name=\"play_Goodbye_1\">Thank you for your time. Goodbye.</play> <goto>Hangup</goto> </keypress> <keypress pressed=\"default\" name=\"incorrect_Selection\"> <play type=\"tts\" voice=\"female1\" name=\"play_Inorrect_Selection\">That is not a valid selection. Please try again.</play> <goto name=\"replay_Live\">Live</goto> </keypress> </menu> <menu maxDigits=\"1\" timeout=\"3500\" name=\"Question_01\"> <play type=\"tts\" voice=\"female1\" name=\"play_Question_01\">Who will you vote for in the upcoming elections? Press 1 for Donkeys. Press 2 for Elephants. Press 3 for Greenies, press 4 for Undecided, or, press 5 for Decline to state.</play> <keypress pressed=\"1-5\" name=\"Selection_Question_01\"> <stash varname=\"Candidate\" name=\"stash_Candidate\">${call.lastinput}</stash> <goto name=\"goto_Goodbye\">Goodbye</goto> </keypress> <keypress pressed=\"default\" name=\"incorrect_Selection_Question_01\"> <play type=\"tts\" voice=\"female1\" name=\"play_Inorrect_Selection_Question_01\"> That is not a valid selection. Please try again. </play> <goto name=\"replay_Question_01\">Question_01</goto> </keypress> </menu> <play type=\"tts\" voice=\"female1\" name=\"Goodbye\"> Thank you for taking our poll. Please remember to vote in the upcoming election! Thank you for your time. Goodbye. </play> <goto name=\"Goodbye_Hangup\">Hangup</goto> <play type=\"tts\" voice=\"female1\" name=\"Machine\"> Hello. This is a call for a political poll for the upcoming election. Sorry we missed you. We will try you again later, or, if you would like to take this short poll, please call 8 5 5,5 5 5,5 5 5 5. Thank you.</play> <hangup name=\"Hangup\"/> </dialplan> "
}';
$request->getOperationConfig()->setBodyParameter($body);
$result = $client->request($request);
$json = json_decode($result->getBody());
}
}
ApiClientSample::main();
[-php]
[[/code-container]]
Check the Create Call Broadcast method for detailed information about request type, accepted parameters, and responses.
Add New Recipients to an IVR Broadcast
You can add only phone numbers to a broadcast, or you can add existing contacts (phone numbers, names, and other identifying informtaion). CallFire creates contacts on the fly from the provided recipients numbers. Check contacts guide for more information on how to manage CallFire Contacts.
Users have two options to add contacts to an existing broadcast:
- Use Add Contact Batch method
- Use Add Recipients method
Imagine you have uploaded a list of contacts into CallFire and received the contact list id. The following examples show how to use the Add Contact Batch API method to add a CallFire contact list to a broadcast:
[[code-container]] [+curl] request:
#!/usr/bin/env bash
curl -u username:password -H "Content-Type:application/json" -X POST -d '
{
"name":"Contact Batch 1",
"contactListId": 300555001,
"scrubDuplicates": true
}' "https://api.callfire.com/v2/calls/broadcasts/11646003/batches"
response:
{
"id": 13
}
[-curl]
[+java]
import com.callfire.api.client.CallfireClient;
import com.callfire.api.client.api.campaigns.model.request.AddBatchRequest;
import com.callfire.api.client.api.common.model.ResourceId;
class ApiClientSample {
public static void main(String[] args) {
CallfireClient callfireClient = new CallfireClient("api_login", "api_password");
AddBatchRequest request = AddBatchRequest.create()
.campaignId(11646003L)
.name("Contacts Batch 1")
// scrub duplicate numbers if any
.scrubDuplicates(true)
// add all contacts from previously created contact list
.contactListId(300555001L)
.build();
ResourceId resourceId = callfireClient.callBroadcastsApi().addBatch(request);
}
}
[-java]
[+csharp]
using CallfireApiClient;
using CallfireApiClient.Api.Campaigns.Model.Request;
public class ApiClientSample
{
public static void Main(string[] args)
{
var client = new CallfireClient("api_login", "api_password");
var request = new AddBatchRequest
{
// your existing campaign id, you can get it via find() operation
CampaignId = 11646003,
Name = "Contacts Batch 1",
// id of contact list that you have added on previous step
ContactListId = 300555001,
ScrubDuplicates = true
};
var id = client.CallBroadcastsApi.AddBatch(request);
}
}
[-csharp]
[+js]
'strict'
const CallfireClient = require('callfire-api-client-js');
const client = new CallfireClient('api-login', 'api-password');
client.ready(() => {
client.calls.addCallBroadcastBatch({
id: 11646003,
body: {
name: 'Contact Batch 1',
contactListId: 300555001,
scrubDuplicates: true
}
})
.then((response) => {
console.log(response.obj);
})
.catch((err) => {
console.log('request error ' + err.data);
});
},
(clientError) => {
console.log('client error ' + clientError);
}
);
[-js]
[+python]
from callfire.client import CallfireClient
client = CallfireClient('api-login', 'api-password')
response = client.calls.addCallBroadcastBatch(
id=11646003,
body={
'name': 'Contact Batch 1',
'contactListId': 300555001,
'scrubDuplicates': True
}
).result()
# see sample JSON response for this API
# on 'curl' samples tab
print(response)
[-python]
[+php]
<?php
class ApiClientSample {
public static function main() {
$client = \CallFire\Api\DocumentedClient::createClient("login", "password");
$request = $client->addCallBroadcastBatch();
$request->getOperationConfig()->setPathParameters(array("id" => 11646003));
$body = '{
"name":"Contact Batch 1",
"contactListId": 300555001,
"scrubDuplicates": true
}';
$request->getOperationConfig()->setBodyParameter($body);
$result = $client->request($request);
$json = json_decode($result->getBody());
}
}
ApiClientSample::main();
[-php]
[[/code-container]]
How to Start a Broadcast
Once you add new recipients to a broadcast, you can start it immediately or schedule it to run in the future. An example of how to start a broadcast:
[[code-container]] [+curl] request:
#!/usr/bin/env bash
curl -u username:password -H "Content-Type:application/json" -X POST "https://api.callfire.com/v2/calls/broadcasts/11646003/start"
response:
200 OK - No Response
[-curl]
[+java]
import com.callfire.api.client.CallfireClient;
class ApiClientSample {
public static void main(String[] args) {
CallfireClient client = new CallfireClient("api_login", "api_password");
client.callBroadcastsApi().start(11646003L);
}
}
[-java]
[+csharp]
using CallfireApiClient;
public class ApiClientSample
{
public static void Main(string[] args)
{
var client = new CallfireClient("api_login", "api_password");
client.CallBroadcastsApi.Start(11646003);
}
}
[-csharp]
[+js]
'strict'
const CallfireClient = require('callfire-api-client-js');
const client = new CallfireClient('api-login', 'api-password');
client.ready(() => {
client.calls.startVoiceBroadcast({id: 11646003})
.then((response) => {
console.log(response.obj);
})
.catch((err) => {
console.log('request error ' + err.data);
});
},
(clientError) => {
console.log('client error ' + clientError);
}
);
[-js]
[+python]
from callfire.client import CallfireClient
client = CallfireClient('api-login', 'api-password')
client.calls.startVoiceBroadcast(id=11646003).result()
[-python]
[+php]
<?php
class ApiClientSample {
public static function main() {
$client = \CallFire\Api\DocumentedClient::createClient("login", "password");
$request = $client->startVoiceBroadcast();
$request->getOperationConfig()->setPathParameters(array("id" => 11646003));
$result = $client->request($request);
$json = json_decode($result->getBody());
}
}
ApiClientSample::main();
[-php]
[[/code-container]]
To schedule a broadcast, you can add scheduling information upon broadcast creation, or invoke Update API on an existing broadcast with the schedule object set. Broadcasts support multiple schedule objects per single instance, so you can make a long-term schedule to start/stop your campaigns.
How to Pull User's Responses
CallFire provides two ways of retrieving a user's data:
- set up a webhook to automatically send the data through an HTTP call to a customer's callback endpoint
- poll CallFire service for call details.
Webhooks are a system of automated notifications indicating that an event has occurred in the CallFire system. They help you to build a bi-directional integration where your service receives HTTP POST notifications from our platform.
Check webhooks guide for more information about CallFire Webhooks.
The following examples show how to query outbound calls, and find a user's data in records.questionResponses array.
[[code-container]] [+curl] request:
#!/usr/bin/env bash
curl -u username:password -H "Content-Type:application/json" -X GET "https://api.callfire.com/v2/calls?id=11646003&id=12646003&id=13776003&campaignId=449060003&batchId=447060003&fromNumber=12135551126&toNumber=12136666123&label=my label&states=READY,FINISHED,INVALID&results=LA&inboubd=true&intervalBegin=1473781817000&intervalEnd=1473781817000&offset=0&limit=10&fields=items(id,fromNumber,toNumber,modified,finalCallResult)"
response:
{
"items": [
{
"id": 13395,
"fromNumber": "12135551189",
"toNumber": "12135551101",
"state": "FINISHED",
"campaignId": 10,
"batchId": 6,
"contact": {
"id": 4097,
"homePhone": "12135551101"
},
"labels": [
"survey 1"
],
"attributes": {
"external_user_id":"45450007002",
"external_route_id":"77770007002"
},
"inbound": false,
"created": 1443373386000,
"modified": 1443373412000,
"finalCallResult": "LA",
"records": [
{
"id": 10306,
"billedAmount": 1.1667,
"finishTime": 1443373425000,
"callResult": "LA",
"questionResponses":[
{
"question":"Do you have a dog",
"response":"Yes"
},
{
"question":"What's your favorite movie",
"response":"StarWars"
}
]
}
],
"agentCall": false
},
{
"id": 13394,
"fromNumber": "12135551189",
"toNumber": "12135551100",
"state": "FINISHED",
"campaignId": 10,
"batchId": 6,
"contact": {
"id": 4096,
"homePhone": "12135551100"
},
"inbound": false,
"created": 1443373382000,
"modified": 1443373412000,
"finalCallResult": "CARRIER_ERROR",
"records": [
{
"id": 10305,
"billedAmount": 0,
"finishTime": 1443373408000,
"callResult": "CARRIER_ERROR"
}
],
"agentCall": false
}
],
"limit": 2,
"offset": 0,
"totalCount": 7160
}
[-curl]
[+java]
import com.callfire.api.client.CallfireClient;
import com.callfire.api.client.api.callstexts.model.Call;
import com.callfire.api.client.api.callstexts.model.request.FindCallsRequest;
import com.callfire.api.client.api.common.model.Page;
import static com.callfire.api.client.api.callstexts.model.Action.State;
import static com.callfire.api.client.api.callstexts.model.Call.CallResult;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
class ApiClientSample {
public static void main(String[] args) throws ParseException {
CallfireClient client = new CallfireClient("api_login", "api_password");
// find all calls made through particular campaign, with exact toNumber and fromNumber
FindCallsRequest request = FindCallsRequest.create()
.id(Arrays.asList(11646003L, 12646003L, 13776003L))
.campaignId(449060003L)
.batchId(447060003L)
.fromNumber("12135551126")
.toNumber("12136666123")
.label("my label")
.states(Arrays.asList(State.READY, State.FINISHED, State.INVALID))
.results(Arrays.asList(CallResult.LA))
.inbound(false)
.intervalBegin(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2016-09-13 15:50:17"))
.intervalEnd(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2016-09-13 15:50:17"))
.offset(0L)
.limit(10L)
.fields("items(id,fromNumber,toNumber,modified,finalCallResult)")
.build();
Page<Call> calls = client.callsApi().find(request);
// check Call.records.questionResponses list for stored data
}
}
[-java]
[+csharp]
using System;
using System.Collections.Generic;
using CallfireApiClient;
using CallfireApiClient.Api.CallsTexts.Model;
using CallfireApiClient.Api.CallsTexts.Model.Request;
using CallfireApiClient.Api.Common.Model;
public class ApiClientSample
{
public static void Main(string[] args)
{
var client = new CallfireClient("api_login", "api_password");
var request = new FindCallsRequest
{
Id = new List<long> { 11646003, 12646003, 13776003 },
CampaignId = 449060003,
BatchId = 447060003,
FromNumber = "12135551126",
ToNumber = "12136666123",
Label = "my label",
States = new List<StateType> { StateType.FINISHED, StateType.READY, StateType.INVALID },
Results = new List<Call.CallResult> { Call.CallResult.LA },
Inbound = true,
IntervalBegin = new DateTime(2016, 9, 13, 15, 50, 17),
IntervalEnd = new DateTime(2016, 9, 13, 15, 50, 17),
Offset = 0,
Limit = 10,
Fields = "items(id,fromNumber,toNumber,modified,finalCallResult)"
};
Page<Call> calls = client.CallsApi.Find(request);
// check Call.records.questionResponses for stored data
}
}
[-csharp]
[+js]
'strict'
const CallfireClient = require('callfire-api-client-js');
const client = new CallfireClient('api-login', 'api-password');
client.ready(() => {
client.calls.findCalls({
// filter by call ids
id: [
11646003,
12646003,
13776003
],
// specify id of a campaign, queries for calls inside a particular campaign.
// do not set to list calls of all campaigns or 0 for a default campaign
campaignId: 449060003,
// queries for calls which are used in the particular contact batch
batchId: 447060003,
// filter by fromNumber
fromNumber: '12135551126',
// filter by toNumber
toNumber: '12136666123',
// filter by label
label: 'my label',
// filter by call state
states: 'READY,FINISHED,INVALID',
// filter by call result
results: 'SENT',
// filter only inbound actions
inbound: false,
// filter by time interval
intervalBegin: 1473781817000,
// filter by time interval
intervalEnd: 1473781817000,
// search offset
offset: 0,
// return 10 items per request
limit: 10,
// return only specific fields
fields: 'items(id,fromNumber,toNumber,modified,finalCallResult)'
})
.then((response) => {
console.log(response.obj);
})
.catch((err) => {
console.log('request error ' + err.data);
});
},
(clientError) => {
console.log('client error ' + clientError);
}
);
[-js]
[+python]
from callfire.client import CallfireClient
client = CallfireClient('api-login', 'api-password')
response = client.calls.findCalls(
# filter by call ids
id=[
11646003,
12646003,
13776003
],
# specify id of a campaign, queries for calls inside a particular campaign.
# do not set to list calls of all campaigns or 0 for a default campaign
campaignId=449060003,
# queries for calls which are used in the particular contact batch
batchId=447060003,
# filter by fromNumber
fromNumber='12135551126',
# filter by toNumber
toNumber='12136666123',
# filter by label
label='my label',
# filter by call state
states='READY,FINISHED,INVALID',
# filter by call result
results='LA',
# filter only inbound actions
inbound=False,
# filter by time interval
intervalBegin=1473781817000,
# filter by time interval
intervalEnd=1473781817000,
# search offset
offset=0,
# return 10 items per request
limit=10,
# return only specific fields
fields='items(id,fromNumber,toNumber,modified,finalCallResult)'
).result()
# see sample JSON response for this API
# on 'curl' samples tab
print(response)
[-python]
[+php]
<?php
class ApiClientSample {
public static function main() {
$client = \CallFire\Api\DocumentedClient::createClient("login", "password");
$request = $client->findCalls();
$request->getOperationConfig()->setQueryParameters(array("id" => 11646003,
"id" => 12646003,
"id" => 13776003,
"campaignId" => 449060003,
"batchId" => 447060003,
"fromNumber" => "12135551126",
"toNumber" => "12136666123",
"label" => "my label",
"states" => "READY,FINISHED,INVALID",
"results" => "LA",
"inbound" => true,
"intervalBegin" => 1473781817000,
"intervalEnd" => 1473781817000,
"offset" => 0,
"limit" => 10,
"fields" => "items(id,fromNumber,toNumber,modified,finalCallResult)"));
$result = $client->request($request);
$json = json_decode($result->getBody());
}
}
[-php]
[[/code-container]]
Check API method reference for detailed information about request type, accepted parameters, responses.