Call method for Twilio on Parse Cloud Code - ios

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!

Related

Gathering speech during outbound twilio voice call

I am trying to create a voice call from twilio to a number using programmable voice.
I also intend to gather recipient's speech transcribed. However, the documentation contains examples and tutorials only for inbound voice calls.
This is what I have tried-
Initiating voice call:
client.calls
.create({
twiml: `<Response><Gather input="speech" action="https://ngrok-url-for-my-local-server/voice" method="POST" speechTimeout="5"><Say>Hey there, How are you?</Say><Pause length="4" /></Gather></Response>`,
to: toPhoneNumber,
from: myPhoneNumber,
})
.then((call) => {
console.log(call.sid)
console.log(call)
})
.catch((e) => {
console.log(e)
})
Code in handler for gathering speech-
const VoiceResponse = twiml.VoiceResponse
const res = new VoiceResponse()
res.gather()
console.log(res.toString())
However I am not getting anything useful in the console.
Can anybody point me to a useful tutorial or example or tell me what I should do ?
You need to first make the call and then modify the call to gather.
When you make the call using the new VoiceResponse() call you will be returned a SID for the call. Next, use that SID to modify a call that is in progress by redirecting to the Twiml to gather the digits.
You will have three legs:
Make the outbound call (you provided this code in your questions).
Modify the active outbound call by using the call's SID to redirect to a Gather twiml.
After the gather has finished tell the call what do to using the action parameter of the gather. Here is an example.
If you are trying to go for a conference bridge type feature where you press * to move into an admin type menu, you will need a more complex solution involving a conference call.

Twilio function to call external API - invalid Content-Type error code 12300

I have a twilio phone # that receives an SMS, which calls a Twilio protected function, which calls an external (Hologram.io) API. The call to the Twilio function succeeds, the call to Hologram.io succeeds, everything is working, but I always get this error and it's just really annoying. I do not get what is wrong.
Part of the body of the Twilio function:
Twilio developer evangelist here.
Your Function is called by Twilio when you receive an SMS, so the response of the Function is going back to Twilio to tell it what to do. You do so by returning TwiML. This means that if you return TwiML like this, you will get a message sent back from the Twilio number:
const twiml = new Twilio.twiml.MessagingResponse();
twiml.message("Hello from your function");
callback(null, twiml);
In your code, you are returning the result of your API call to Hologram straight to Twilio. Since that result is JSON instead of TwiML, Twilio doesn't know what to do with it and you get an error.
If you don't want to respond to the incoming text message, you can return empty TwiML, like this:
instance.post('/api/1/sms/incoming', {
// hologram data
})
.then((response) => {
const twiml = new Twilio.twiml.MessagingResponse();
callback(null, twiml);
});
Let me know if this helps.
You need to return TwiML to Twilio rather then JSON, reference:
TwiML™ for Programmable SMS

How do you forward Twilio calls to different URLs in the middle of a call? (Using Node)

I'd like the following functionality with Twilio/Node: either
my server receives incoming call and the call rings on our custom client; at some point during the call (ideally can work before answering or after answering) or if no one answers on the client, the call is transferred to a webhook on a different server (my CRM provider) so the CRM can deal with it. OR
same as above, but the incoming call posts the incoming call request to both my server & my CRM webhook for the incoming call; I think this might not be possible though, not sure
I'm able to receive a Twilio call on my server without problem, and able to receive Twilio calls in my CRM without problem. However, when I tried to forward a call to the CRM after first receiving it on my custom server/client, it seems to always disconnect abrubtly. Pls help!
The code I'm using to update the call is below. The url works normally if sending the call directly to the CRM webhook. The CallSid is from my custom client from the incoming call
client.calls(req.body.CallSid)
.update({method: 'POST', url: 'https://crm.crmprovider.com/ctiapi/xml/cticall/twilio?authtoken=abc'})
Appreciate any help!
Think I figured out the proper way to do this. Should be using an "action" with "dial" and then checking "DialCallStatus" in the action endpoint and dealing with various statuses as appropriate. Sample code:
// On server, receive call. This is the url Twilio is
// set to post webhook to when call comes in
app.post('/incomingCall', (req, res) => {
const twiml = new VoiceResponse();
// Dial client first; after, call /callAction
// I believe this will call /callAction if call is unanswered for 10 seconds or after a completed call or if there's no client open
const dial = twiml.dial({timeout:10, action: '/callAction'});
const client = 'whateverClientName'
dial.client(client)
res.type('text/xml')
res.send(twiml.toString())
})
app.post('/callAction',(req,res)=>{
const twiml = new VoiceResponse();
// Can set below if for other things like if call not completed, answered, or cancelled
// In this example we say if call's not completed, route call to 3rd party site's webhook to further deal with the ongoing call
if(req.body.DialCallStatus!=='completed'){
twiml.redirect({method: 'POST'},'https://thirdpartywebhook.com/abc')}
else {twiml.hangup()}
res.type('text/xml')
res.send(twiml.toString())
})
I didn't find Twilio docs super straightforward on this so hopefully this helps someone in the future!

Twilio Programmable Fax TwiML bin receive handler error 11200

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
}

How to make call through Twilio where two people will have live conversation?

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.

Resources