I've set up a TwiML bin for handling incoming faxes on one of my numbers. The bin looks like (if I remember correctly, there is no dashboard for editing existing fax TwiML bins yet :) )
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Receive action="my/api/endpoint" methods="POST" storeMedia="false"/>
</Response>
I don't believe it is an issue with my TwiML bin, however. Going into the debugger, I see 11200 errors, connection issues with the service. It seems the connection issue is with the TwiML bin handler:
POST https://handler.twilio.com/fax/received
Request message text: "; will retry until 2018-04-20T23:07:25.893Z"
Response body: "HTTP Retrieval Failure"
The issue is on Twilio's side, right?
Anything else I should check?
I had same error.
The error is just because twilio did not get the expected result back from your action endpoint.
First you should return the following XML with action attribute that you are doing correctly
<?xml version="1.0"?>
<Response>
<Receive action="/api/fax/received/file"/>
</Response>
And second you should return 200 OK response on /api/fax/received/file. Meaning you should respond with valid response confirming that you got that fax file to twilio i.e 200 response code.
In your case:
Now you should have <your-domain>/my/api/endpoint active and reachable from twilio as you have action="my/api/endpoint". and when twilio calls this endpoint, you should return 200 OK response confirming that you got the file otherwise twilio will think that there is error "HTTP Retrieval Failure".
check your action="my/api/endpoint"(/fax/received) and make sure you respond back with 200.
If programming language does not matter to you then my code for both endpoint looks like as follows in PHP. First method (Endpoint) is mapped with the phone-number on twilio and second is for action attribute. This is how I got rid of that error.
// this is /api/incoming/fax endpoint and I on twilio i have put this URL on the phone number
// this method will be called via /api/incoming/fax when any incoming fax
public function incomingFax(Request $request){
$twimlResponse = new \SimpleXMLElement("<Response></Response>");
$recieveEl = $twimlResponse->addChild('Receive');
$recieveEl->addAttribute('action', '/api/fax/received/file');
return response($twimlResponse->asXML(), 200)
->header('Content-Type', 'text/xml');
}
// this is /api/fax/received/file endpoint which will be called by twilio
//always return 200
public function receivedFaxFile(Request $request)
{
$inputs = $request->all();
$from = $inputs['From'];
$media_url = $inputs['MediaUrl'];
if(isset($inputs['MediaUrl'])&&isset($inputs['To'])){
$thread = Thread::where(array("out_did"=>$to))->latest()->first();
$slack = new Slack(config("app.slack_access_key"));
$this->sendAttachment($from,$to,$media_url,$thread->thread_ts);
}
return response('', 200); // should return 200
}
Related
Im placing an outbound call, and based on the automated message from whom Twilio is calling, it calls my phone with the connection.
Here is the script that places the phone call.
import os
from twilio.rest import Client
account_sid = "xxxx"
auth_token = "xxxx"
client = Client(account_sid, auth_token)
call = client.calls.create( url='http://myhost.com/rec.php',to='+1234',from_='+9876')
print(call.sid)
The phone call is placed, and the action script sends a TwiML gather response. Here's rec.php
echo '<Response>
<Gather input="speech"
partialResultCallback="http://myhost.com/partial.php"
action="http://myhost.com/finalresult.php">
</Gather>
</Response>
I've got the partial page logging the text. But when I forward a call, my phone rings for one second, then disconnects. There's no errors in the debugger either.
Here's partial.php
if(contains("To continue in English", $_REQUEST['UnstableSpeechResult'])){
echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<Response>
<Dial>+myPhoneNumber</Dial>
</Response>";
}
here is final result, which i think is called when the phone call is complete? im not sure.
if(contains("To continue in English", $_POST['SpeechResult'])){
echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<Response>
<Dial>+myPhoneNumber</Dial>
</Response>";
}
According to the documentation, partialResultCallback doesn't process TwiML.
The webhooks Twilio makes to your partialResultCallback are
asynchronous. They do not accept any TwiML in response. If you want to
take more actions based on this partial result, you need to use the
REST API to modify the call.
Not sure how your phone is ringing given the above. Any more details you can provide will help troubleshoot the issue.
As given in link https://github.com/twilio/voice-quickstart-android#bullet5,
we need to create TwiML application and voice Request url should be set for e.g. https://twiliodev.mycompany.com/makeCall to make call. Then what should be written in makecall function to connect the current call because if we use Dial verb then it make another call.
Note : I am using Twilio programmable voice to connect two Android device using VOIP.
Now the question is what Twiml response should be send in MakeCall function to get call connected, because in following function if I return blank response then call didn't connect.
[HttpPost]
public ActionResult MakeCall()
{
var response = new VoiceResponse();
return TwiML(response);
}
Edit #Alan Thanks to reply.
As I am using c# at server side. I have used Dial Verb as
var dial = response.Dial(callerId: from);
Which Connect call and Immediately disconnect bcoz client verb is missing. Now how to append Client verb in Dial verb, I am using Client verb as
dial.Append(client);
and Twiml response is
<Response>
<Dial callerId="client:21f421792"></Dial>
<Client>2170561
</Client>
</Response>
And Its return schema error bcoz I think correct schema is
<Response>
<Dial callerId="client:21f421792">
<Client>2170561
</Client></Dial>
</Response>
So can you please help how to add Client verb inside Call Verb.
Thanks.
Edit 2
As Suggested by #philnash this c# link is for Browser to client call and in that it uses new Dial client as
var dial = new Dial();
but I am using Android VOIP SDK to make call between two android devices.
For which If I use new Dial object, it will place new Call as child call. Which I don't want to create. And As request by #philnash the complete code for makeCall function is
[HttpPost]
public ActionResult MakeCall()
{
var response = new VoiceResponse();
string from,to;
if (Request.HttpMethod == HttpMethod.Post.Method)
{
from = Request.Form["From"];
to = Request.Form["To"];
}
else
{
from = Request.QueryString["From"];
to = Request.QueryString["To"];
}
var dial = response.Dial(callerId: from);
var client = new Client(to);
dial.Append(client);
return TwiML(response);
}
Edit 3
<?xml version="1.0" encoding="utf-8"?>
<Response>
<Dial>
<Client>2170561
</Client>
</Dial>
</Response>
As I have Noticed for VOIP call if Client xml tag is inside Dial tag then it successfully connect but it counts two legs for each call and charge for two calls. Is it the default behaviour of Twilio to leg two calls in each call when one device want to call to another device or Am I getting wrong ?
Again please note I am talking about two android device VOIP connection via Twiml request url to our server.
If you are trying to connect to Mobile Programmable Voice SDK powered devices together, you would use the Dial verb with Client noun. The Client noun would be the identity/name of the other client you are trying to call.
TwiML™ Voice:
Twilio has a serverless Function that has the example code below used to place a call and based on the To number your client side POSTs to the makeCall end-point, it determines if it is a PSTN phone call or client-to-client phone call, const attr = isAValidPhoneNumber(event.To) ? 'number' : 'client';. That code is copied below.
exports.handler = function(context, event, callback) {
let twiml = new Twilio.twiml.VoiceResponse();
if(event.To) {
// Wrap the phone number or client name in the appropriate TwiML verb
// if is a valid phone number
const attr = isAValidPhoneNumber(event.To) ? 'number' : 'client';
const dial = twiml.dial({
callerId: context.CALLER_ID,
});
dial[attr]({}, event.To);
} else {
twiml.say('Thanks for calling!');
}
callback(null, twiml);
};
/**
* Checks if the given value is valid as phone number
* #param {Number|String} number
* #return {Boolean}
*/
function isAValidPhoneNumber(number) {
return /^[\d\+\-\(\) ]+$/.test(number);
}
I'm trying to create a button on a webpage (on my presonal PHP webserver) that should connect me (either call my cellphone or via the webclient), then call a number, I then want to have an options to either hangup the call, or just disconnect me but play an mp3 to the other person and then hangup.
I'm not sure how to go about it. I created a TwiML, but how do I connect that to the existing call? Or is there a different way to do it?
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Play>https://something-something.twil.io/assets/recording1.mp3</Play>
<Hangup/>
</Response>
Thanks in advance.
Twilio developer evangelist here.
This is an ideal use case for Answering Machine Detection. With Twilio's answer machine detection you can set it to Enabled or DetectMessageEnd which means that you can use Twilio to work out whether a machine has answered the call and wait until the message is over then play it a message. Otherwise you can connect the call to yourself.
With PHP, you can generate the call like this:
use Twilio\Rest\Client;
// Your Account Sid and Auth Token from twilio.com/console
$sid = "YOUR_ACCOUNT_SID";
$token = "YOUR_AUTH_TOKEN";
$client = new Client($sid, $token);
$call = $client->calls->create(
"+14155551212", "+14158675309",
array(
"url" => "http://example.com/calls",
"MachineDetection" => "DetectMessageEnd"
)
);
Then, for your URL, you need to respond to the call depending on what the machine detected. You do that with the AnsweredBy parameter. Something like this, which dials your number if someone answers or speaks a message using <Say> if a machine answers:
<?php
if ($_REQUEST['AnsweredBy'] == "human") {
echo "<Response><Dial><Number>YOUR_NUMBER</Number></Dial></Response>";
} else {
echo "<Response><Say>Hello, this is my message</Say></Response>";
}
Let me know if that helps at all.
Edit
Without Answering Machine Detection
Ok, to do this without Answering Machine Detection I recommend you build yourself a dialler using Twilio Client JS. There is a quickstart guide here, so I won't go through how that works here.
Once you have a dialler you can use it to initiate the phone calls. The issue is then moving the voicemail calls to play the message. I would build two buttons, one that hangs up as if you've completed the call successfully and the other that plays the message instead. The first button is a simple function call to Twilio.Device.activeConnection().disconnect().
The second one needs a couple of things. The idea is that it will make a call to your server to redirect the other call to a new set of TwiML.
First up, you need the SID of the call you created. You can get that from the connection object you receive in response to calling connect.
var connection = Twilio.Device.connect({ number: "+1234567890" });
var callSid = connection.parameters.CallSid;
When you want to hangup and play a message you need to send this to your server. This is the SID of the parent call though, and you need to get the child call, the other leg. So, on your server you need to use the REST API to get the other call, then redirect it.
use Twilio\Rest\Client;
// Your Account Sid and Auth Token from twilio.com/console
$sid = "YOUR_ACCOUNT_SID";
$token = "YOUR_AUTH_TOKEN";
$client = new Client($sid, $token);
$calls = $client->calls->read(
array("ParentCallSid" => $_REQUEST['CallSid'])
);
// Loop over the list of calls, it should only have one call in it, and redirect the call to a URL that has the message TwiML
foreach ($calls as $call) {
$call->update(array(
"url" => "http://example.com/message.xml"
));
}
When you redirect the child call, the parent call will no longer be connected so it will hang up. The URL you redirect the child call to should contain the TwiML required to play the message to the machine using <Say> or <Play>.
I think I get what you're trying to do. You have a list of people you're trying to call. The app will call them and connect you. If you hear an answering machine, you want to press a key then hangup and move on to the next call. But after you hang up, that first outbound call stays online and leaves a .mp3 message to that recipient?
I believe one solution would be creating a conference with a bot.
Your app makes an outbound call to you, to the bot and to the recipient and puts everyone into a conference room called "room-timestamp" where timestamp is the current time. The bot is a twilio number that listens for a Gather dtmf. If you press 1, it will play message 1 then hang up. But because this is a conference, you can hangup at anytime and move on to the next call.
The bot could loop a few times and if no dtmf is detected, it will hang itself up.
This is all made easier using the new Outbound conference API where you can pass it the conference name instead of conference SID :
https://www.twilio.com/docs/api/rest/participant#list-post
Edit:
Connect three numbers to a conference room :
$uniqueid = time();
$call = $client->account->calls->create($officeline,$twilionum,
array("url" => "http://yourdomain/conference.php?id=$uniqueid"));
$call = $client->account->calls->create($botline,$twilionum,
array("url" => "http://yourdomain/conference.php?id=$uniqueid"));
$call = $client->account->calls->create($customerline,$twilionum,
array("url" => "http://yourdomain/conference.php?id=$uniqueid"));
This will connect three numbers to a conference room:
$officeline (your number),
$botline (twilio phone # of a bot that responds to dtmf)
$customerline (the customer you're calling)
conference.php just returns a conferenceID for calls to connect to:
header('Content-Type: text/xml');
$confid = $_REQUEST['id'];
echo<<<XMLOUT
<?xml version="1.0" encoding="ISO-8859-1"?>
<Response>
<Dial>
<Conference statusCallbackEvent="leave" statusCallback="killconference.php">$confid</Conference>
</Dial>
</Response>
XMLOUT;
killconference.php is called so that the conference can be terminated when there's only one person left. Just make sure your bot hangs up after playing something.
killconference.php
$theconference = $_REQUEST['ConferenceSid'];
$participants = $client
->conferences($theconference)
->participants
->read();
if (count($participants) == 1) {
$conference = $client
->conferences($theconference)
->fetch();
$conference->update(array(
"Status" => "completed"
));
}
your botline twilio number will be pointing to bot.php that responds to dtmf:
bot.php
header('Content-Type: text/xml');
$dtmf = isset($_REQUEST["Digits"]) ? $_REQUEST["Digits"] : "";
$playmore = "";
if ($dtmf == "1") {
$playmore = "<Say>Hey I just wanted to leave you a message </Say><Hangup/>\n";
}
if ($dtmf == "2") {
$playmore = "<Play>http://www.soundboard.com/mediafiles/22/224470-33a9f640-d998-45a3-b0c1-31c1687c2ae4.mp3</Play><Hangup/>\n";
}
echo<<<XMLOUT
<?xml version="1.0" encoding="ISO-8859-1"?>
<Response>
$playmore
<Gather action="bot.php" numDigits="1" timeout="30">
</Gather>
<Hangup/>
</Response>
XMLOUT;
The bot will stay on the line for 30 seconds, if no dtmf is entered it hangs itself up. Press 1 to leave the customer a message, 2 for Leroy Jenkins
I am trying to setup a call between two people and I am able to make a call but the person who pick up the call can listen pre-recorded voice mail. I want to have live conversation between these two people. I am not getting what should be the URL and how can I set it up.
My Sample PHP Code is -
require_once "application/helpers/Services/twilio-php-master/Twilio/autoload.php";
use Twilio\Rest\Client;
// Step 2: Set our AccountSid and AuthToken from https://twilio.com/console
$AccountSid = "Axxxxxxxxxxxxxxxxxxxxxc0";
$AuthToken = "xxxxxxxxxxxxxxxxxxxxxxxxx";
// Step 3: Instantiate a new Twilio Rest Client
$client = new Client($AccountSid, $AuthToken);
try {
// Initiate a new outbound call
$call = $client->account->calls->create(
// Step 4: Change the 'To' number below to whatever number you'd like
// to call.
"+91my_number",
//$_POST['to'],
// Step 5: Change the 'From' number below to be a valid Twilio number
// that you've purchased or verified with Twilio.
"+1_twilioverified_number",
// Step 6: Set the URL Twilio will request when the call is answered.
array("url" => "http://demo.twilio.com/welcome/voice/")
);
echo "Started call: " . $call->sid;
} catch (Exception $e) {
echo "Error: " . $e->getMessage();
}
Is there anyone who can help me with this.
Thank you in advance. Awaiting for reply.
Twilio developer evangelist here.
Currently your code is working fine, the thing you need to change is the URL that is listed as "Step 6" in the comments. Currently that URL points to some TwiML that reads out a message.
Instead of reading that message, you will need to provide a URL that returns some TwiML that <Dial>s another <Number>. You see, when the first part of the call connects, Twilio makes an HTTP POST request to that URL to get the instructions for what to do next.
This URL needs to be available online for Twilio to make the HTTP request to. You can either deploy this TwiML to a server of yours, use a TwiML Bin from the Twilio console or test it out using ngrok on your local development machine.
The TwiML you want should look a bit like this:
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Dial>
<Number>YOUR_NUMBER_HERE</Number>
</Dial>
</Response>
Let me know if that helps at all.
We are trying to implement simple P2P VoIP connection between iOS devices. We picked Twilio to handle calls and using Parse to interact with Twilio.
We are successfully generating capability tokens per user and initiate a call. However call is hanging up instantly after successful connection.
Receiver is receiving the call successfully and hearing the trial message.
Initiator is hearing the trial message and also "Application error occurred.".
We are suspecting that there may be something wrong at our call method on Parse Cloud Code.
app.get('/call', function(request, response) {
var client = require('twilio')('ACC_ID', 'AUTH_ID');
// Create a TwiML response generator object
var fromName = 'client:' + request.query.from;
var toName = 'client:' + request.query.to;
client.makeCall({
to:toName, // Any number Twilio can call
from: fromName,
url: 'http://xxxyyzz.parseapp.com/consult' // A URL that produces an XML document (TwiML) which contains instructions for the call
}, function(err, responseData) {
//executed when the call has been initiated.
console.log(responseData.from); // outputs "+14506667788"
});
});
We are not sure about what should url parameter supposed to do.
app.post('/consult', function(request, response) {
response.send();
});
Thanks.
You are almost there, but there seems to be a problem in your /call service (you also don't need any other urls, /call' should be enough).
What Twilio expects as a response from /call is a TwiML message (https://www.twilio.com/docs/api/twiml). Your server here should respond proper TwiML so that Twilio will know what to do.
If you want to connect two clients then /call should return the Dial TwiML message. The documentation (https://www.twilio.com/docs/api/twiml/dial) can let you know about the details of the Dial message. There are some interesting options such as limiting the phone call to 40 seconds for example.
If you want to dial a client called 'Jenna', then the response from your /call service should be:
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Dial>
<Client>Jenna</Number>
</Dial>
</Response>
Good luck with your application, hope this helps!