How to Modify Calls in Progress
In this guide we will show you how to modify the BXML for a call already in progress. Please ensure you have followed our earlier guide on how to make an outbound call with Bandwidth. It is recommended to use a request manager like POSTMAN
for this tutorial, but the SDKs are also capable.
Bandwidth's /calls
API provides the capability of modifying the call flow by sending new BXML to an active call. An example of when you may want to modify an active call is an inbound call center application where you place a customer in a “waiting room” by playing hold music while waiting for an agent to become available. Once an agent becomes available you can send replacement BXML for the call to be transferred to the available agent. As an enhancement you could send BXML in the interim to indicate to the caller the estimated time until an agent is available by playing text to speech and resuming the hold music.
Modify a Live Call
You can modify both an inbound or outbound live call by providing a new set of instructions via BXML. Please note that modifying a call will end any verbs currently executing and will skip any subsequent ones.
You will need to interrupt an active call by calling our REST API endpoint. In this example, we will create an outbound call that pauses for 1 minute. This will give you time to copy the callId
and modify the call.
- XML
- Java
- C#
- Ruby
- NodeJS
- Python
- PHP
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Pause duration="60" />
</Response>
Pause pause = new Pause(60.0);
Response response = new Response()
.with(pause);
System.out.println(response.toBXML());
Pause pause = new Pause
{
Duration = 60
};
Response response = new Response();
response.Add(pause);
Console.WriteLine(response.ToBXML());
pause = Bandwidth::Bxml::Pause.new({ duration: 60 })
response = Bandwidth::Bxml::Response.new([pause])
p response.to_bxml
const pause = new Bxml.Pause({
duration: 60
});
const response = new Bxml.Response(pause);
console.log(response.toBxml());
pause = Pause(duration=60)
response = Response()
response.add_verb(pause)
print(response.to_bxml())
$pause = new BandwidthLib\Voice\Bxml\Pause();
$pause->duration(60);
$response = new BandwidthLib\Voice\Bxml\Response();
$response->addVerb($pause);
echo $response->toBxml();
When the outbound call is placed, you will need to make a note of the callId
for this call as it will be used to modify the active call.
API for Call Modification
In this example, the BXML that is in the redirectUrl
will immediately replace all verbs present on the current call with the new text-to-speech sentence.
- Request Payload
- cURL
- Java
- C#
- Ruby
- NodeJS
- Python
- PHP
//Note: remember to add auth for your application if needed!
POST https://voice.bandwidth.com/api/v2/accounts/{YOUR_ACCOUNT_ID}/calls/{THE_CALL_ID}
{
"redirectUrl": "/goodbyeMessage",
}
/goodbyeMessage should serve the following:
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<SpeakSentence>
Thank you for holding! Goodbye!
</SpeakSentence>
</Response>
//Note: remember to add auth for your application if needed!
curl 'https://voice.bandwidth.com/api/v2/accounts/{YOUR_ACCOUNT_ID}/calls/{THE_CALL_ID}' \
-X POST \
-u {BANDWIDTH_USERNAME}:{BANDWIDTH:PASSWORD} \
-H 'Content-Type: application/json' \
-d '{
"redirectUrl": "/goodbyeMessage",
}'
/goodbyeMessage should serve the following:
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<SpeakSentence>
Thank you for holding! Goodbye!
</SpeakSentence>
</Response>
import com.bandwidth.sdk.ApiClient;
import com.bandwidth.sdk.ApiException;
import com.bandwidth.sdk.Configuration;
import com.bandwidth.sdk.auth.*;
import com.bandwidth.sdk.models.*;
import com.bandwidth.sdk.api.CallsApi;
public class Example {
public static void main(String[] args) {
ApiClient defaultClient = Configuration.getDefaultApiClient();
defaultClient.setBasePath("http://localhost");
// Configure HTTP basic authorization: Basic
HttpBasicAuth Basic = (HttpBasicAuth) defaultClient.getAuthentication("Basic");
Basic.setUsername("YOUR USERNAME");
Basic.setPassword("YOUR PASSWORD");
CallsApi apiInstance = new CallsApi(defaultClient);
String accountId = "9900000"; // String | Your Bandwidth Account ID.
String callId = "c-15ac29a2-1331029c-2cb0-4a07-b215-b22865662d85"; // String | Programmable Voice API Call ID.
UpdateCall updateCall = new UpdateCall(); // UpdateCall | JSON object containing information to redirect an existing call to a new BXML document
try {
apiInstance.updateCall(accountId, callId, updateCall);
} catch (ApiException e) {
System.err.println("Exception when calling CallsApi#updateCall");
System.err.println("Status code: " + e.getCode());
System.err.println("Reason: " + e.getResponseBody());
System.err.println("Response headers: " + e.getResponseHeaders());
e.printStackTrace();
}
}
}
/goodbyeMessage should serve the following:
//Note: This application is pseudocoded. Your implementation will look different
@Post /goodbyeMessage endpoint
public String goodbyeMessage() {
SpeakSentence speakSentence = new SpeakSentence("Thank you for holding! Goodbye!");
Response response = new Response()
.with(speakSentence);
return response.toBXML()
}
using System;
using System.Threading.Tasks;
using Bandwidth.Standard;
using Bandwidth.Standard.Exceptions;
using Bandwidth.Standard.Voice.Models;
class Program
{
static async Task Main(string[] args)
{
var username = System.Environment.GetEnvironmentVariable("BW_USERNAME");
var password = System.Environment.GetEnvironmentVariable("BW_PASSWORD");
var accountId = System.Environment.GetEnvironmentVariable("BW_ACCOUNT_ID");
var callId = {CALL_ID}
var client = new BandwidthClient.Builder()
.VoiceBasicAuthCredentials(username, password)
.Build();
var request = new ModifyCallRequest()
{
State = StateEnum.Active,
RedirectUrl = "/goodbyeMessage"
//remember to add auth for your application if needed!
};
try
{
await client.Voice.APIController.ModifyCallAsync(accountId, callId, request);
}
catch (ApiException e)
{
Console.WriteLine(e.Message);
}
}
}
/goodbyeMessage should serve the following:
//Note: This application is pseudocoded. Your implementation will look different
@Post [/goodbyeMessage]
public ActionResult goodbyeMessage() {
SpeakSentence speakSentence = new SpeakSentence
{
Sentence = "Thank you for holding! Goodbye!"
};
Response response = new Response();
response.Add(speakSentence);
return new OkObjectResult(response.ToBXML());
}
require 'bandwidth-sdk'
begin
BW_USERNAME = ENV.fetch('BW_USERNAME')
BW_PASSWORD = ENV.fetch('BW_PASSWORD')
BW_ACCOUNT_ID = ENV.fetch('BW_ACCOUNT_ID')
BW_VOICE_APPLICATION_ID = ENV.fetch('BW_VOICE_APPLICATION_ID')
BW_NUMBER = ENV.fetch('BW_NUMBER')
USER_NUMBER = ENV.fetch('USER_NUMBER')
BASE_CALLBACK_URL = ENV.fetch('BASE_CALLBACK_URL')
CALL_ID = ENV.fetch('CALL_ID')
rescue
p 'Please set the environmental variables defined in the README'
exit(-1)
end
Bandwidth.configure do |config|
config.username = BW_USERNAME
config.password = BW_PASSWORD
end
calls_api_instance = Bandwidth::CallsApi.new
call_body = Bandwidth::UpdateCall.new(
state: 'active',
redirect_url: '/goodbyeMessage'
)
begin
calls_api_instance.update_call(ACCOUNT_ID, CALL_ID, call_body)
rescue Bandwidth::ApiError => e
p e.code
end
/goodbyeMessage should serve the following:
#Note: This application is pseudocoded. Your implementation will look different
post '/goodbyeMessage' do
speak_sentence = Bandwidth::Bxml::SpeakSentence.new('Thank you for holding! Goodbye!')
response = Bandwidth::Bxml::Response.new([speak_sentence])
return response.to_bxml
end
import { CallsApi, Configuration, CallStateEnum } from 'bandwidth-sdk';
const BW_USERNAME = process.env.BW_USERNAME;
const BW_PASSWORD = process.env.BW_PASSWORD;
const BW_ACCOUNT_ID = process.env.BW_ACCOUNT_ID;
const BASE_CALLBACK_URL = process.env.BASE_CALLBACK_URL;
const config = new Configuration({
BW_USERNAME,
BW_PASSWORD
});
const callsApi = new CallsApi(config);
const callId = 'c-abc12345-6defabc1-2345-6def-abc1-23456defabc1';
const updateCallBody = {
state: CallStateEnum.Active,
redirectUrl: `${BASE_CALLBACK_URL}/bxml/pause`
};
const { status: updateStatus } = await callsApi.updateCall(
BW_ACCOUNT_ID,
callId,
updateCallBody
);
/goodbyeMessage should serve the following:
//Note: This application is pseudocoded. Your implementation will look different
@post ['/goodbyeMessage'] (request, request_response) => {
const speakSentence = new Bxml.SpeakSentence('Thank you for holding! Goodbye!');
const response = new Bxml.Response(speakSentence);
console.log(response.toBxml());
request_response.status(200).send(response.toBxml());
}
import os
import bandwidth
configuration = bandwidth.Configuration(
username=os.environ["BW_USERNAME"],
password=os.environ["BW_PASSWORD"]
)
with bandwidth.ApiClient(configuration) as api_client:
api_instance = bandwidth.CallsApi(api_client)
account_id = os.environ["BW_ACCOUNT_ID"]
call_id = 'c-15ac29a2-1331029c-2cb0-4a07-b215-b22865662d85'
update_call = bandwidth.UpdateCall(
redirect_url="/goodbyeMessage"
)
try:
api_instance.update_call(account_id, call_id, update_call)
except Exception as e:
print("Exception when calling CallsApi->update_call: %s\n" % e)
/goodbyeMessage should serve the following:
#Note: This application is pseudocoded. Your implementation will look different
@post '/goodbyeMessage'
def goodbyeMessage():
speak_sentence = SpeakSentence(
text="Thank you for holding! Goodbye!"
)
response = Response()
response.add_verb(speak_sentence)
return response.to_bxml()
require "vendor/autoload.php";
$BW_USERNAME = getenv("BW_USERNAME");
$BW_PASSWORD = getenv("BW_PASSWORD");
$BW_ACCOUNT_ID = getenv("BW_ACCOUNT_ID");
$config = new BandwidthLib\Configuration(
array(
'voiceBasicAuthUserName' => $BW_USERNAME,
'voiceBasicAuthPassword' => $BW_PASSWORD,
)
);
$client = new BandwidthLib\BandwidthClient($config);
$voiceClient = $client->getVoice()->getClient();
$callId = {CALL_ID};
$body = new BandwidthLib\Voice\Models\ModifyCallRequest();
$body->redirectUrl = "/goodbyeMessage";
$body->state = "active";
#remember to add auth for your application if needed!
try {
$voiceClient->modifyCall($BW_ACCOUNT_ID, $callId, $body);
} catch (BandwidthLib\APIException $e) {
print_r($e->getResponseCode());
}
/goodbyeMessage should serve the following:
#Note: This application is pseudocoded. Your implementation will look different
@post('/goodbyeMessage)
function goodbyeMessage(Request $request, Response $response) {
$speakSentence = new BandwidthLib\Voice\Bxml\SpeakSentence("Thank you for holding! Goodbye!");
$response = new BandwidthLib\Voice\Bxml\Response();
$response->addVerb($speakSentence);
return $response->toBxml();
}
Where to next?
Now that you have learnt how to modify existing calls in progress, check out some of the available actions in the following guides: