You can take a look at the blog below, which uses Human Detection
(alternatives to AMD) to intelligently handle the dialed party's voicemail.
Outsmart Voice Mail with Human Detection Using Keypress Prompts
You cannot use your current approach with parallel forking, since it cannot account for Voicemail.
You will need to build the sequential dialing logic. Below is some Twilio Function code that may be useful, but you will need to adapt it to meet your needs
Main Function (where you point your Twilio Telephone Number to) is shown first:
Replace:
let phoneTreeUrl = "https://YOUR_FUNTION/PATH";
With your unique Function URL and path (this varies for each Twilio customer). Also update the phoneNumbers to be the phone numbers you want to call. You can pass the Timeout as a variable when you call the function from your Twilio phone number or change it in the code below (it defaults to 30 seconds).
Update the PLACE_HOLDER URL with the other Function you will create in the next step further below.
/*
* Example: Strictly Linear Phone Tree
* This example shows how you might iterate through a list of numbers.
* Each will be tried for 10 seconds before moving on to the next.
*/
exports.handler = function(context, event, callback) {
// REQUIRED - URL to this Function
let phoneTreeUrl = "https://YOUR_FUNTION/PATH";
// Timeout - The amount of time we want to dial before giving up
let timeout = event.Timeout || 30;
// Attempt - The position in the list we are currently at
let attempt = parseInt(event.Attempt) || 0;
console.log(attempt);
// DialCallStatus - Returned by <Dial> action
let DialCallStatus = event.DialCallStatus || null;
console.log(DialCallStatus);
// Phone Numbers - The list of numbers to cycle through
let phoneNumbers = [
"+14073601234", "+16787851234"
];
// generate the TwiML to tell Twilio how to forward this call
let twiml = new Twilio.twiml.VoiceResponse();
// If we have successfully contacted a number, then exit Function
if (DialCallStatus === "completed" || DialCallStatus === "answered") {
twiml.hangup();
callback(null, twiml);
}
// If we have exhausted all numbers end the attempts
if (attempt >= phoneNumbers.length) {
twiml.say("Sorry, we could not find someone to take your call. Please try again later");
callback(null, twiml);
}
// Build the state for our Twiml response
let target = phoneNumbers[attempt];
let nextAttempt = attempt + 1;
let nextAttemptUrl = phoneTreeUrl + "?Attempt=" + nextAttempt;
twiml.dial({ timeout: timeout, action: nextAttemptUrl})
.number({url: "https://PLACE_HOLDER/humandetect?Detection=required"}, target);
callback(null, twiml);
};
Human Detection Function:
Give this new function the path /humandetect
Update the code below, THIS_FUNCTION, to the unique URL for this FUNCTION (with the path of /humandetect)
exports.handler = function(context, event, callback) {
let twiml = new Twilio.twiml.VoiceResponse();
// REQUIRED - URL to this Function
let phoneTreeUrl = "https://THIS_FUNCTION/humandetect";
let detection = event.Detection || null;
if (detection === "required") {
twiml.gather({timeout: 5, numDigits: 1, action: phoneTreeUrl})
.say("Press any key to hear an important message about your appointment.");
twiml.hangup();
}
callback(null, twiml);
};