I'm trying to make a phone call using twilio programmable voice with TwiML. Not sure if I'm doing something completely wrong, but I created an express route to output TwiML
router.get('/data', function(req, res) {
var testXML = builder.create('Response')
.ele('Say')
.att('voice', 'alice')
.txt('You ordered a hamburger')
.ele('Say')
.txt('Now this order is complete')
res.type('text/xml');
res.set('Content-Type', 'text/xml');
res.send(testXML.toString());
});
This outputs XML as seen below:
My code to make the phone call is as follows:
client.calls
.create({
url: 'http://XXXXX.com/api/request',
to: '+1XXXXXXXXXX',
from: '+1XXXXXXXXXX',
})
.then(call => console.log(call.sid))
.done();
But twilio keeps outputting Error - 11200 HTTP retrieval failure. Any ideas?
I noticed in the REST API call, you are passing a URL with the path:
http://XXXXX.com/api/request
But your Express Route is /data. Also, Twilio uses POST by default, unless you indicate GET in the REST API call.
https://www.twilio.com/docs/voice/api/call (Method)
Related
We have a studio flow called "Google LA" that's triggered via Rest API. This flow has a Send and Wait for Reply so we hook this flow to "When a message comes in" so it will follow the rest of the flow when customer rates the service 1 to 5 stars. Now, within the Send and Wait for Reply, we want the customer's reply be forwarded to our main business phone number for tracking/recording purposes and so we can address their issues for rating us 1 to 3 stars. Here's our setup:
This is what we want:
Edited for philnash suggestion:
I created a function in Twilio with this code:
exports.handler = function(context, event, callback) {
const accountSid = context.ACCOUNT_SID;
const authToken = context.AUTH_TOKEN;
const client = require('twilio')(accountSid, authToken);
client.messages
.create({
body: widgets.negative1_3.inbound.Body,
from: '+12132779513',
to: '+12133885256'
})
.then(message => console.log(message.sid));
};
However, it did not send anything or the customer response. I renamed the negative1-3 widget to negative1_3 and published the studio flow.
I tried changing the body: 'Hello' to make sure that my function works, and yes. I received the 'Hello' sms to my verified caller ID phone number after it reaches the first_question -> check_response -> negative1_3.
Twilio developer evangelist here.
You don't necessarily need to forward the message here. You can make an API call to your own service with all the data you need from the message, so you can store and react to the information that way.
To do so you will want to add either an HTTP Request widget or a Run Function widget after the Send and Wait For Reply widget. Within those widgets, you can access the reply from the Send And Wait For Reply widget using liquid tags. You can see how to call on the variables in the docs for the Send and Wait For Reply widget. In the case of your widget, you should be able to get the body of the reply by referring to:
widgets.negative1-3.inbound.Body
(Although I am not sure how the name "negative1-3" will work, so you might try widgets["negative1-3"] instead, or rename the widget with underscores.)
Using the body of the inbound message, as well as the from number, you can send the data to your own application with the HTTP request widget or with a Run Function widget.
Edit
Your function can only access parameters that you set in the function widget config. You can then access those parameters in the event object. You also need to return once the message is sent successfully using the callback function. One other tip, you don't need to instantiate your own client, you can get it from the context. Like so:
exports.handler = function(context, event, callback) {
const client = context.getTwilioClient();
client.messages
.create({
body: event.Body,
from: '+12132779513',
to: '+12133885256'
})
.then(message => {
console.log(message.sid);
callback(null, "OK");
})
.catch(error => callback(error));
};
I'm trying to make an outgoing call to an automated phone system, but I'm running into a content-type error. I don't understand what a content-type error is, so if someone could help me understand that would be great. Here's the code I have right now.
exports.handler = function(context, event, callback) {
const accountSid = 'AC5ca0acd115283b6d7ed38279';
const authToken = 'not my real auth token';
const client = require('twilio')(accountSid, authToken);
client.calls
.create({
to: '+14805402416',
from: '+18448345500',
record: 'True',
transcribe: 'True',
sendDigits: 'wwww1wwww123#wwww1', // w's are .5 second delays to navigate pauses in the automated system
// '1' - English, '123#' - PIN #, '1' - Confirm PIN
});
callback(null, client);
};
You are missing either url or twiml in your construct.
https://www.twilio.com/docs/voice/api/call-resource
url
The absolute URL that returns the TwiML instructions for the call. We will call this URL using the method when the call connects. For more information, see the Url Parameter section in Making Calls.
TwiML instructions for the call Twilio will use without fetching Twiml
from url parameter. If both twiml and url are provided then twiml
parameter will be ignored.
My company uses Twilio Flex as our phone system and I was recently tasked with setting up a feature that will let us edit a TwiML voice message that plays before our normal voice message. This TwiML message will be changed through a Twilio bot that I've published in our Microsoft Teams.
The reason for this is so that our support desk can add a short message in the lines of "We're currently experiencing issues with X" before our normal "Welcome to [Company] support" message.
If TwiML's can be edited using HTTP POST/PUT or Twilio's API this should be a trivial matter, but so far I've not been able to figure out how.
I couldn't find any reference to this in the API doc, so I decided that HTTP POST would be the way to go. Using this as a start off point, I'm able to retrieve my TwiML using HTTP GET:
https://support.twilio.com/hc/en-us/articles/223132187--Not-Authorized-error-when-trying-to-view-TwiML-Bin-URL
const axios = require('axios');
const crypto = require('crypto');
const accountSidFlex = process.env.accountSidFlex;
const authTokenFlex = process.env.authTokenFlex;
var URL = 'https://handler.twilio.com/twiml/EHXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' + '?AccountSid=' + accountSidFlex
var twilioSig = crypto.createHmac('sha1', authTokenFlex).update(new Buffer(URL, 'utf-8')).digest('Base64')
var config = {
headers:{
'X-TWILIO-SIGNATURE': twilioSig
}
}
axios.get(
URL,config
).catch(error => console.log(error))
.then(response => {
console.log(response.data)
})
response.data shows the TwiML's current XML content.
My attempts at a POST only gives the same output as the GET, while PUT gives 405 Method Not Allowed.
var URL = 'https://handler.twilio.com/twiml/EHXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' + '?AccountSid=' + accountSidFlex
var twilioSig = crypto.createHmac('sha1', authTokenFlex).update(new Buffer(URL, 'utf-8')).digest('Base64')
var config = {
headers:{
'X-TWILIO-SIGNATURE': twilioSig,
'Content-Type': 'text/xml'
}
}
var xml =
'<?xml version="1.0" encoding="UTF-8"?>\
<Response><Play digits="www"/>\
<Say voice="alice">"We are currently experiencing X related issues". </Say>\
</Response>';
axios.post(
URL,xml,config
)
.catch(error => console.log(error))
.then(response => {
console.log(response.data)
})
Ideally I'd like to be able to change a specific TwiML using either HTTP methods or the Twilio-API, so that we can use it in out Studio Flow. We'd just keep it silent until we need to add something to it and revert back to silent once the issues have passed.
Any help would be appreciated!
You cannot currently change the contents of TwiML Bins, Studio Flows, or Twilio Functions programatically. I believe the key functionality you are looking for is a way to dynamically update the messaging (Say/Play Widget) in a Studio flow based on some condition.
One way is to use a Function Widget to retrieve a Twilio Sync document for the message, returning the message as JSON and have the Say/Play widget play that message. You can find the Twilio Sync REST API examples for Add, Modify, and Retrieve in the associated document.
You can retrieve the parsed response using variable syntax detailed here, https://www.twilio.com/docs/studio/widget-library#run-function.
we're using a nodejs on the serverside, and then ios sdk (Version 3 w/support for custom parameters)
we need a way to be able to send custom parameters from our nodejs server into the client. In PHP i was able to figure it out by just sending it with the dial verb by doing
$dial->parameter(['name'=>'param','value'=>'value']);
but for nodejs i am not able to find a solution that fits with:
call = await client.api.calls.create({
url: url,
to: 'client:' + defaultIdentity,
from: callerId,
});
Twilio developer evangelist here.
You can absolutely generate TwiML with the Twilio Node.js library. To generate a <Dial> you need code like:
const VoiceResponse = require('twilio').twiml.VoiceResponse;
const response = new VoiceResponse();
const dial = response.dial({
callerId: '+15551112222'
});
dial.number('+15558675310');
console.log(response.toString());
Let me know if that helps at all.
Okay so, apparantly its the same way you would do it in php, except a bit different
function incoming() {
const voiceResponse = new VoiceResponse();
const dial = voiceResponse.dial({action:'http://21402340.ngrok.io/endCall'});
let client = dial.client({
statusCallback: 'completed',
statusCallback: 'http://21402340.ngrok.io/endCall',
statusCallbackMethod: 'POST'
},'alice');
client.parameter({name:'subscriber_name',value:'Richard abear'});
return voiceResponse.toString();
}
here is a sample function that sends a custom parameter subscriber_name to the client's customCallParameters
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.