Twilio outgoing call to recipient with call screening (Google voice) - twilio

I have a working service, where we do outgoing calls something like this.
$sid = getenv("TWILIO_ACCOUNT_SID");
$token = getenv("TWILIO_AUTH_TOKEN");
$twilio = new Client($sid, $token);
$call = $twilio->calls
->create("+14155551212", // to
"+14155551212", // from
["url" => "http://demo.twilio.com/docs/classic.mp3"]
);
print($call->sid);
The issue is when the recipient has call screening, the callback to the URL parameter is done as soon as the screening starts (with callbackstatus "in-progress"!), which means we have to add a pause in the response.
<Response>
<Pause length="10"/>
<Say>
This is an important message
</Say>
<Gather action="https://xxx" method="GET" timeout="15" speechTimeout="auto" numDigits="1" input="dtmf speech">
<Say>Please press 1 followed by the pound sign or say confirm to confirm your appointment</Say>
</Gather>
<Redirect method="GET">https://xxx</Redirect>
</Response>
Is there some way to bypass the screening or have the system not start the response in screening?
EDIT:
I've added the AMD options and it seems to be correctly somewhat working. Right now the only issue that remains is when calling in to Google Voice, when there's call screening, my added voice recording start reading before the recipient actually answers
$call = $client->calls->create(
$to, $from,
array(
"url" => $url,
"statusCallback" => $statusURL,
"statusCallbackMethod" => 'POST',
"machineDetection" => "DetectMessageEnd",
"machineDetectionTimeout" => 5
)
);

You are looking for answering machine detection (AMD).
You can make a call with AMD enabled by setting the MachineDetection parameter to Enable or DetectMessageEnd.
$call = $twilio->calls
->create("+14155551212", // to
"+14155551212", // from
[
"url" => "http://demo.twilio.com/docs/classic.mp3",
"machineDetection" => "Enabled"
]
);
When you use the MachineDetection parameter the request to your url will include an AnsweredBy parameter. From the docs:
Use Enable if you would like Twilio to return an AnsweredBy value as soon as it identifies the called party. This is useful if you would like to take a specific action — for example, connect to an agent, play a message) — for a human but hang up on a machine.
If you would like to leave a voicemail on an answering machine, specify DetectMessageEnd. In this case, Twilio will return an AnsweredBy immediately when a human is detected but for an answering machine, AnsweredBy is returned only once the end of the greeting is reached, usually indicated by a beep.
There is also an option for asynchronous AMD. With asynchronous detection your url is called immediately as if a normal call, but once Twilio has performed the detection an asynchronous webhook is made to a different URL and you can use the callback data to decide whether to update the call.

Related

How to make a customable message in Twilio Voice call

i've successfully make a voice call with twilio like this:
$call = $client->calls->create(
$toNumber, $fromNumber,
array("url" => "http://demo.twilio.com/docs/voice.xml")
);
the above code will call to the $toNumber with twilio demo message, when i try to use TwiML to create the dynamic message like this:
$response = new TwiML();
$response->say('Votre otp est 2234', ['voice' => 'woman', 'language' => 'fr']);
$call = $client->calls->create(
$toNumber, $fromNumber,
$response
);
i got an error like this:
[HTTP 400] Unable to create record: Url parameter is required. For
more information, see http://www.twilio.com/docs/api/twiml
Twilio developer evangelist here.
You can't send the TwiML to Twilio when you make a call like that. You need to send a URL that Twilio will send an HTTP request to when the call connects (like in the original example). So, to fix your code you should replace the demo URL with your own URL.
$call = $client->calls->create(
$toNumber, $fromNumber,
array("url" => $YOUR_URL_HERE)
);
That URL can be your own application, or something like a TwiML Bin or Twilio Function. Check out this article to see how to respond with TwiML to a request from Twilio.
I notice that you are building something for one time passwords too. You might be interested in checking out the Authy API that can implement and deliver OTP codes via calls, SMS and app.

How can I capture a dtmf code on for a call sent out of twilio?

I send calls out by building an html file that contains twiml markup, and use the php lib to place the call to the outgoing number (see e.g.)
$tw_call = $twilio_client->calls->create(
"+1".$recipient['address'], "+1".$org['twilio_number'],
array(
'Url' => VOICE_CALL_LINK.'/'.$file, (this contains the SAY verbs and text)
'Timeout' => '30',
'StatusCallback' => CALLBACK_LINK.'/voice_call_handler.php',
'StatusCallbackEvent' => array('initiated', 'ringing', 'answered', 'completed')
)
I want to know if it is possible to record a dtmf code from the call recipient via the method I am using for placing the call?
Can an additional callback url be placed in the text file? If so how would I capture which call the was coming back? Would the call sid be available to the possible callback url within the text file?
Ok I must be missing something. I tried the following:
<Response>
<Pause length='1'/>
<Say voice='alice'>$intro</Say>
<Pause length='1'/>
<Say voice='alice'>$msg_body</Say>
<Pause length='1'/>
<Gather action='absolute html path' numDigits='1'>
<Say Please respond by selecting 1 for I can come. Select 2 for I cannot come.</Say>
</Gather>
</Response>";
I get back from Twilio "an application error has occurred". If I remove the Gather tags and the Say tag within the Gather tags, I receive a perfect call.
Same error occurs if I leave the tags and remove the action and path.
Can you gather responses on outbound calls? I ask because all twilio docs refer to inbound call.
Twilio developer evangelist here.
In order to capture DTMF tones from a call you can use the <Gather> TwiML verb. This would probably go in the file which contains your <Say> that you point to in the code above. <Say> can be nested within <Gather> in order to allow you to ask the user for input and start taking it as soon as they start typing.
The TwiML might look like this:
<Response>
<Gather action="/gather_result.php" numDigits="1">
<Say>Welcome to the free beer hotline, dial 1 for free beer, dial 2 for other beverages.</Say>
</Gather>
</Response>
Then, when the user dials the number (you can control how many numbers with the numDigits attribute) Twilio will make a request to the URL in the action attribute. Within that request will be a Digits parameter which will contain the numbers the user pressed. The call SID would also be among the parameters.
Let me know if that helps at all.
I had similar issue where Gather TwiML was not capturing the user dtmf input from a call sent out of twilio. For some reasons, it failed to capture my input digit. I did press 1#, but the voice message keep playing and repeating the same message. Sometimes it works and twilio able to get the digit that I inputted, but more than 80% of the times I tried, it failed to capture the inputted digit. Below is the TwiML in node js looks like:
var promise = new Parse.Promise();
twilioClient.calls.create({
to: phoneNumber,
from:'+6598124124',
url: hosturl + '/gather_user_dial',
body: callParam,
statusCallback: hosturl + '/callback_user',
statusCallbackMethod: 'POST',
statusCallbackEvent: ["completed", "busy", "no-answer", "canceled", "failed"]
}).then(function(call) {
if (res) res.success(call);
promise.resolve(call);
}, function(error) {
console.error('Call failed! Reason: ' + error.message);
if (res) res.error(error);
promise.reject(error);
});
app.post('/gather_user_dial', (request, response) => {
const twiml = new VoiceResponse();
const gather = twiml.gather({
numDigits: 1,
timeout: 5,
actionOnEmptyResult: true,
action: '/gather',
});
gather.say('You are receiving a call from company A because you press the emergency button. Press 1 if you are okay or Press 9 if you need help, followed by the pound sign.');
twiml.redirect('/gather_user_dial');
response.type('text/xml');
response.send(twiml.toString());
});
app.post('/gather', (request, response) => {
const twiml = new VoiceResponse();
if (request.body.Digits) {
switch (request.body.Digits) {
case '1':
twiml.say('User has been notified!');
userPressOne(request.body.Called);
break;
case '9':
twiml.say('User has been notified!');
userPressNine(request.body.Called);
break;
default:
twiml.say("Sorry, I don't understand that choice.").pause();
twiml.redirect('/gather_user_dial');
break;
}
} else {
twiml.redirect('/gather_user_dial');
}
response.type('text/xml');
response.send(twiml.toString());
});

Unable to transfer twilio call to new number

We have small twilio application which we use to calls any customer number from website. Now we are trying to add transfer call functionality in our application.
But we are unable to transfer call using php api.
Here is what we are using :
We dial number from website, JS returns callid
We have another number on which we need to transfer call after few minutes
So we have "Transfer" button which makes ajax call to php file
which have following code :
<?php
$existing_call_sid = $_REQUEST['CallSid'];
$new_number = $_REQUEST['new_number'];
$call = $client->calls($existing_call_sid)->update(
array(
"url" => "transfer_xml_main.php?new_number=".$new_number,
"method" => "POST"
)
);
echo $call->to;
?>
transfer_xml_main.php contains :
<Response>
<Dial><?php echo $_GET['new_number'];?></Dial>
<Say>Please be on line we are transferring your call</Say>
</Response>
But when this request happens existing call is dropping and no call to new number.
also $call->to is blank
Am i doing anything wrong?
Update
After implementing answer of philnash i am getting following fatal error :
<b>Fatal error</b>: Uncaught exception 'Twilio\Exceptions\RestException' with message '[HTTP 400] Unable to update record: No 'To' number is specified' in /twilo/twillo_php_master_new/Twilio/Version.php:85
Stack trace:
#0 /twilo/twillo_php_master_new/Twilio/Version.php(127): Twilio\Version->exception(Object(Twilio\Http\Response), 'Unable to updat...')
#1 /twilo/twillo_php_master_new/Twilio/Rest/Api/V2010/Account/CallContext.php(109): Twilio\Version->update('POST', '/Accounts/AC618...', Array, Array)
#2 /twilo/twilo_call_transfer.php(26): Twilio\Rest\Api\V2010\Account\CallContext->update(Array)
#3 {main}
thrown in <b>/twilo/twillo_php_master_new/Twilio/Version.php</b> on line <b>85</b><br />
However i am getting parent call id correctly and in $child_calls i am getting to and from correctly which is one who called first and one whom user is called. Still anything wrong ?
And yes we want exactly like you said :
1. User1 (agent) called one number (customer A) from twilio JS Client
2. Now User1 (agent) want to transfer call to another number which can be agent or some other number.
Also there is no errors in debugger
Twilio developer evangelist here.
I'm surprised that no call is happening. Are there any errors in your Twilio debugger?
I can see some issues though.
The CallSid you get from the JS when you dial out is the Sid of the dialling leg, the one owned by your agent. But, I'm guessing you want to transfer the person that is called to a new number. If that is the case then you need to get the Sid of the receiving leg of the call. The dialling Sid is the parent Sid for the calls, so you can look up the other leg by listing child legs, like this:
<?php
$parent_call_sid = $_REQUEST['CallSid'];
$child_calls = $this->client->calls->read(array("ParentCallSid" => $parent_call_sid));
$child_call_sid = $childCalls[0]->sid;
$new_number = $_REQUEST['new_number'];
$call = $client->calls($child_call_sid)->update(
array(
"url" => "transfer_xml_main.php?new_number=".$new_number,
"method" => "POST"
)
);
echo $call->to;
?>
Secondly, your TwiML you return is the wrong way round. If you want the message to come before you start dialling, then you need to put the <Say> first.
<Response>
<Say>Please be on line we are transferring your call</Say>
<Dial><?php echo $_GET['new_number'];?></Dial>
</Response>
When you do all of this, your original dialler will get cut off as the call is transferred. You may want this, though you may find that a warm transfer is a better experience. There is a good tutorial on how to perform a warm transfer using PHP and Laravel which might help.
Let me know if that helps at all.
In your PHP you use the POST method, but in your XML you use $_GET. You're not passing the variables.
<?php
$parent_call_sid = $_REQUEST['CallSid'];
$child_calls = $this->client->calls->read(array("ParentCallSid" => $parent_call_sid));
$child_call_sid = $childCalls[0]->sid;
$new_number = $_REQUEST['new_number'];
$call = $client->calls($child_call_sid)->update(
array(
"url" => "transfer_xml_main.php?new_number=".$new_number,
"method" => "POST" // <---NOTICE THE POST
)
);
echo $call->to;
?>
Change $_GET to $_POST
<Response>
<Dial><?php echo $_POST['new_number'];?></Dial>
<Say>Please be on line we are transferring your call</Say>
</Response>

Dial a Number Twilio Number to Trigger TWILM Bin

We are attempting to create a workflow that will ultimately connect a lead from a contact form, with a business owner.
The workflow is as follows:
1) Lead fills in contact form
2) Using Stamplay integration with Unbounce, the lead receives a text asking them if they wanted to be contacted "Now", or "Later".
Let's go with lead says "Now"
3) Lead says "Now", which will access a webhook URL to decide on what to do next.
In this particular case, saying "Now", will trigger a TWIML bin to dial the business owner. If the business owner doesn't pick up/busy, then we send a text to the lead asking them to send a follow-up text with a 'name' and 'date/time'.
4) The lead replies with a text with this information, and then both the business owner and lead receive separate notifications about the appointment.
I have been able to successfully go through this whole workflow when a user directly dials the Twilio number (not programatically with keywords yet, which is where I need help).
When a call comes in -> TWIML bin
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Pause length="4"/>
<Say>Please hold, while I connect your call.</Say>
<Pause length="4"/>
<Dial timeout="10"> business owner number </Dial>
<Pause length="4"/>
<Sms>I am currently unavailable. If you'd like me to get in touch, pls reply back with your name, and a time that would work best for you. Thanks, Adam</Sms>
</Response>
When a SMS is received -> webhook URL
<?php
// Require the bundled autoload file - the path may need to change
// based on where you downloaded and unzipped the SDK
require __DIR__ . '/twilio-php-master/Twilio/autoload.php';
// Use the REST API Client to make requests to the Twilio REST API
use Twilio\Rest\Client;
// Your Account SID and Auth Token from twilio.com/console
$sid = 'xyz';
$token = 'xyz';
$client = new Client($sid, $token);
$number = $_POST['From'];
$body = $_POST['Body'];
//Sends a message to the owner
$sms = $client->account->messages->create(
// Cell of owner
'12345',
array(
// A Twilio phone number you purchased at twilio.com/console
'from' => "78900",
// Lead's reply sent to owner asNotification
'body' => "Hi <name>. You have a new lead. The information for this lead is: $body. You can contact them at $number"
)
);
//Sends a message to the lead
$sms = $client->account->messages->create(
// Cell of Lead
$number,
array(
// A Twilio phone number you purchased at twilio.com/console
'from' => "78900",
// Notification Message sent to Lead
'body' => "This is a confirmation that I have received your information, and will be in contact with you soon. Thanks, <name>."
)
);
Where I am encountering issues is having the lead text "Now", to trigger a phone call between the business owner and lead.
This is the code that I have been attempting to use, except that I have been receiving 11200- HTTP retrieval failure non-stop. I have also attempted to use $client->account->calls->create, as that's what I used to successfully send messages.
// Read TwiML at this URL when a call connects (attempt to connect to owner)
$call = $client->calls->create(
'lead-number', // Call this number
'78900', // From a valid Twilio number
array(
'url' => TWIML Bin of Interest
)
);
Anyone have any idea what I could do?
Check out the example of creating a dynamic response:
<?php
// Get the PHP helper library from twilio.com/docs/php/install
require_once '/path/to/vendor/autoload.php'; // Loads the library
use Twilio\Twiml;
$response = new Twiml;
$body = $_REQUEST['Body'];
if( $body == 'hello' ){
$response->message('Hi!');
}else if( $body == 'bye' ){
$response->message('Goodbye');
}
print $response;
In your case you'll modify for if "now" is in the $body you can create the call which your code looks fine for.
$call = $client->calls->create(
"+1415XXXXXXX", "+1415XXXXXXX",
array("url" => "link_to_twiml_bin")
);
In regards to the 11200 HTTP retrieval error, take a look at the possible solutions here especially:
Make sure your web server allows HTTP POST requests to static
resources (if the URL refers to .xml or .html files)

Pass Inbound call between twilio clients

i have several twilio client users
Sky - Kevin - Paul
A twilio registered number connects to callsky.xml by default / that code looking like.
<Response>
<Dial>
<Agent>sky</Agent>
</Dial>
</Response>
a call comes in and goes to sky, she then wants to pass that call over to Kevin or Paul.
how is this possible ?
tried:
$caid = $_REQUEST["CallSID"];
$client = new Services_Twilio($sid, $token);
$call = $client->account->calls->get($caid);
$url = 'http://thesite.com/twiml.xml';
$call->update(
'Url' => $url,
'Method' => "GET",
);
This is executed through Ajax, when sky presses a button with the destination users name on it.
<button onclick="divert('kevin')">Kevin</button>
Also: Oddly, the update command shows as a syntax error in my IDE.
Twilio evangelist here.
The update method takes an array, so that might be causing the syntax error:
https://www.twilio.com/docs/api/rest/change-call-state
I'd also recommened checking out the AppMonitor (https://www.twilio.com/user/account/developer-tools/app-monitor) to see if Twilio is logging and errors when trying to retreive the TwiML from your URL.
The URL you point the call at can return static XML, or you ca ndynamically generate it using the PHP helper library. Here is an example of using the <Dial> verb to dial a Client instance:
$response = new Services_Twilio_Twiml;
$dial = $response->dial(NULL, array(
'callerId' => '+14152223333'
));
$dial->client('client-id');
print $response;
This will output TwiML that looks like:
<Response>
<Dial callerId="+14152223333">
<Client>client-id</Client>
</Dial>
</Response>
Hope that helps.

Resources