2. Custom callouts and Answering Machine Detection
Note:
The code presented on this page is complete and needs no modifications to function. We are providing it for educational purposes and to highlight how it works and what it's doing. You may modify the code to customize the behavior if you want, but this tutorial assumes the code remains as-is to complete successfully and behave as documented.
The lead qualification process starts with calling a phone number.
To make a call out to a phone number, we need to make what we call a callout. And because we're using Answering Machine Detection (or AMD), we need to make a custom callout.Custom callouts use SVAML to create their own call events, depending on what's needed. In this case, we're using a custom callout to make an Incoming Call Event (or ICE) to connect your Sinch number to a phone number on the telephone network. We also specify that AMD is enabled, so when the call is picked up (or not), the service determines whether the call was picked up a human or by an answering machine and reports back either way.
The code that does that is displayed here on this page, but we want to call attention to a few important sections:
The callouts service
The Java SDK sends callouts to the Voice API using thecallouts
service. The callouts
service has a number of methods, and the one we're using here is the custom()
method.var response =
calloutsService.custom(
CalloutRequestParametersCustom.builder()
.setIce(
SVAMLControl.builder()
.setAction(
ActionConnectPstn.builder()
.setNumber(phoneNumber)
.setCli(sinchNumber)
.setAnsweringMachineDetection(
AnsweringMachineDetection.builder().setEnabled(true).build())
.build())
.build())
.build());
SVAMLControl
object. This object is configured with an ConnectPstn
action that sets the phone number to call and also enables AMD.Validating phone numbers
Callouts can only be placed to valid phone numbers in E.164 format. The Java SDK has a very useful function calledE164PhoneNumber.validate()
that accepts a string as an argument and returns true or false if the number is valid or not. We highly recommend using this type of check in your applications, which is why we've included it in the code for this application.private E164PhoneNumber promptPhoneNumber() {
String input;
boolean valid;
do {
input = prompt("\nEnter the phone number you want to call");
valid = E164PhoneNumber.validate(input);
if (!valid) {
echo("Invalid number '%s'", input);
}
} while (!valid);
return E164PhoneNumber.valueOf(input);
}
Answering Machine Detection
The real magic of this solution happens once the AMD service has determined that a human answers the phone. TheServerBusinessLogic.java
file (which we'll explore in in more detail in the next section) contains the logic which parses all incoming callback events from the Sinch servers. The AMD service reports back whether a human answers or not in an Answered Call Event (or ACE). This ACE has an AMD status that we can parse. Using if
statements we can have different code execute depending on the status.public SVAMLControl answeredCallEvent(AnsweredCallEvent event) {
var amdResult = event.getAmd();
if (amdResult.getStatus() == AmdAnswerStatusType.MACHINE) {
return machineResponse();
}
if (amdResult.getStatus() == AmdAnswerStatusType.HUMAN) {
return humanResponse();
}
throw new IllegalStateException("Unexpected value: " + event);
}
If a machine answers, since a machine can't decide an option to pick in an IVR, we just want a simple message to play for the answering machine to record. If a human answers, we want to play an Interactive Voice Response menu for them. But more on that in the next section.
Next steps
Now that you know how to make a callout and enable AMD, we can go over how to configure the Interactive Voice Response system.