Node.js Twilio make calls using REST API - node.js

I am trying to make call from the Twilio REST API but I am getting an error, looks like I missed something, any help will appreciate:
var options = { method: 'POST',
url: 'https://xxxxxxxxxxxx#api.twilio.com/2010-04-01/Accounts/xxxxxxxxxxx/Calls',
headers:
{
'Cache-Control': 'no-cache',
'content-type': 'multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW' },
formData:
{ To: '+919200070974',
From: '14245060471',
Url: '<?xml version="1.0" encoding="UTF-8"?>\n<Response>\n <Say voice="woman">This is me....</Say>\n</Response>'} };
request(options, function (error, response, body) {
if (error) throw new Error(error);
console.log(body);
});
Now I set url parameters but its showing invalid
<?xml version='1.0' encoding='UTF-8'?>
<TwilioResponse>
<RestException>
<Code>21205</Code>
<Message>Url is not a valid url: <?xml version="1.0" encoding="UTF-8"?>
<Response>
<Say voice="woman">This is me....</Say>
</Response></Message>
<MoreInfo>https://www.twilio.com/docs/errors/21205</MoreInfo>
<Status>400</Status>
</RestException>
</TwilioResponse>
I am not getting where I have to set URL parameter, I didn't find in the documentation clearly what I have to set.

Twilio developer evangelist here.
What you need to do in this case, is send to Twilio a URL. When the call connects, Twilio will then make a request to that URL to get the TwiML response.
From the documentation:
When you initiate a call through the REST API, Twilio makes a synchronous HTTP request to the URL found in the value of the 'Url' POST parameter, in order to retrieve TwiML for handling the call. This request is identical to the request Twilio sends when receiving a phone call to one of your Twilio numbers. URLs must contain a valid hostname (underscores are not permitted).
So, your formData here should be:
formData: {
To: '+919200070974',
From: '14245060471',
Url: 'https://example.com/twiml'
}
And the URL at https://example.com/twiml should respond with the TwiML you defined originally.

twilio has an npm library already.
you can follow their Node.js Guide
// Twilio Credentials
const accountSid = 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
const authToken = 'your_auth_token';
// require the Twilio module and create a REST client
const client = require('twilio')(accountSid, authToken);
client.messages
.create({
to: '+15558675310',
from: '+15017122661',
body: 'This is the ship that made the Kessel Run in fourteen parsecs?',
})
.then(message => console.log(message.sid));

Related

bearer token in Twilio webhook

Im setting up a Twilio Sandbox for WhatsApp
for when a message comes in I set a webhook to my application’s link.
But my application requires a bearer token.
How can I set up twilio to send our bearer token together with the request it makes to my URL?
thank you
i make all test without the bearer token and it works fine.
but to go live, we need this token autentication for security reasons.
The webhook just triggers a GET or POST request to the registered URL, as you rightfully said. To be able to add custom parameters, such as a bearer token, you need to add an intermediate step in between. This can be achieved, for example, with any Serverless function.
Naturally, using Twilio Serverless would be the easiest option to do this:
const axios = require('axios');
exports.handler = async (context, event, callback) => {
// Create a new voice response object
const twiml = new Twilio.twiml.VoiceResponse();
try {
// Open APIs From Space: http://open-notify.org
// Number of people in space
const response = await axios.request({
method: "POST",
url: `http://api.open-notify.org/astros.json`,
headers: {
"Authorization": `Bearer ${request.body.token}`,
"Content-Type": "application/json; charset=utf-8"
},
});
const { number, people } = response.data;
const names = people.map((astronaut) => astronaut.name).sort();
// Create a list formatter to join the names with commas and 'and'
// so that the played speech sounds more natural
const listFormatter = new Intl.ListFormat('en');
twiml.say(`There are ${number} people in space.`);
twiml.pause({ length: 1 });
twiml.say(`Their names are: ${listFormatter.format(names)}`);
// Return the final TwiML as the second argument to `callback`
// This will render the response as XML in reply to the webhook request
// and result in the message being played back to the user
return callback(null, twiml);
} catch (error) {
// In the event of an error, return a 500 error and the error message
console.error(error);
return callback(error);
}
};

how to send xml response to a given url from express route?

I need to send a XML response from express route to an url given as a POST Request?
const xml = `<sourcedGUID>
<sourcedId>ASSMT12345</sourcedId>
</sourcedGUID>
<contextID>
<textString>cls1234</textString>
</contextID>
<userID>
<textString>usr123</textString>
</userID>`
I am in express route of /status and I need to send the xml variable to the url: 'https://example.com/cli' using express.
How can I achieve this use case?
You need to use something like request or axios or http, I will use request here
var request = require('request');
request.post({
url: <the-url-where-to-send-xml>,
method: 'POST',
headers:{
'Content-Type': 'application/xml',
},
body: xml
},
function(error, response, body){
console.log(response.statusCode);
console.log(body);
console.log(error);
});

Node js: sendgrid 'acces forbidden'

I'm using sendgrid (javascript) to add a new contact to my list.
Within marketing.
var request = require("request");
var options = { method: 'PUT',
url: 'https://api.sendgrid.com/v3/contactdb/lists/193029b7-0b8b-4c0c-948d-47d09a157542/recipients',
headers: { authorization: 'Bearer myapi' },
body: '{"contacts":[{"email": "myemail#gmail.com","unique_name":"hello"}]}' };
request(options, function (error, response, body) {
if (error) throw new Error(error);
console.log(body);
});
But then I get the message 'acces forbidden'.
Am I using the wrong url?
(The API token is set to administrator all access.)
Thanks!
It looks like there's a few things going on here.
According to the docs, there are not endpoints in the Contact API that accept the method PUT.
After checking our own implementation, it also looks like there's an issue with what you're intending to do.
See the docs for adding multiple recipients to a list:
POST https://api.sendgrid.com/v3/contactdb/lists/{list_id}/recipients HTTP/1.1
Request body:
[
"recipient_id1",
"recipient_id2"
]
In order to use that method, you need to first create the users and retrieve their recipient ID's.
POST https://api.sendgrid.com/v3/contactdb/recipients HTTP/1.1
[
{
"email": "myemail#gmail.com",
"unique_name":"hello"
}
]
Check out the links posted for more information on their usage and response.

angular $resource delete won't send body to express.js server

hye,
i am building an app with angular.js and node.js (Express.js) on the server side.
for some reason i am having a problem handling a delete request. no body is getting to the server side.
this is my angular.js resource code:
$scope.deleteProject = function(projectName){
var postData = {username: 'name', projectName: projectName};
Project.deleteProject.delete({}, postData,
function(res){
alert('Project Deleted');
},
function(err){
alert(err.data);
});
}
on the server side i have this:
var deleteProject = function(req, res){
console.log(req.body);
console.log(req.params);
if (req.body.projectName){
//do something
return res.send(200);
}
else
return res.send(400, 'no project name was specified');
}
now for some reason there is no body at all!! it is empty.
i have defined the route as app.delete.
if i change the route in node.js to post and in angular.js to save it works fine.
what am i missing here (banging my head).
thanks.
As per this stack overflow question and the $http service source code, a DELETE request using $http does not allow for data to be sent in the body of the request. The spec for a DELETE request is somewhat vague on whether or not a request body should be allowed, but Angular does not support it.
The only methods that allow for request bodies are POST, PUT, and PATCH. So the problem is not anywhere in your code, its in Angular's $http service.
My suggestion would be to use the generic $http(...) function and pass in the proper method:
$http({
method: 'DELETE',
url: '/some/url',
data: {...},
headers: {'Content-Type': 'application/json;charset=utf-8'}
})
Angular by default sends the Content-Type as text/plain for DELETE requests. Just add this to the headers:
var config = {
method: "DELETE"
url: yourUrl
data: yourData
headers: {"Content-Type": "application/json;charset=utf-8"}
};
$http(config);
If you want to add them to every single DELETE request add this to the app.config method in your main controller:
$httpProvider.defaults.headers.delete = { "Content-Type": "application/json;charset=utf-8" };
If you want to use the $resource object instead of $http you need to add hasBody and headers as follow:
delete: {
method: 'DELETE',
hasBody: true,
headers: {"Content-Type": "application/json;charset=UTF-8"}
}
Worked for me
Just ran into this problem. You'll have to use url params to send an id with delete.
in express:
app.delete('/api/user/:userId', user.remove);
and add to the url in angular:
$http({url: 'whatever/api/'+obj.id, method: 'DELETE'}) ...
The following works for me:
$httpProvider.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
$httpProvider.defaults.headers.common['Content-Type'] = 'application/json;charset=utf-8';
XMLHttpRequest is optional but useful if you are sending ajax.
https://docs.angularjs.org/api/ng/provider/$httpProvider for more information.
This worked for me.
$httpProvider.defaults.headers.delete = { "Content-Type": "application/json;charset=utf-8" };
And then
$http.delete(url, { data: data })

Box API Irregular Headers

I am trying to upload an image with the box API and the request module. I tried the provided curl example without any problems.
I have a request all setup like this
var request = require("request");
var fs = require("fs");
var path = require("path");
request({
url: "https://api.box.com/2.0/files/content",
method: "POST",
form: {
filename: fs.createReadStream(path.join(__dirname, "midguts.jpg")),
folder_id: "0"
},
headers: {
api_key: "<API_KEY>",
auth_token: "<AUTH_TOKEN>"
}
}, function (error, response, body) {
console.log(error);
console.log(body);
});
The problem arises when I get to the headers part. The box API call for a headers string of
"Authorization: BoxAuth api_key=API_KEY&auth_token=AUTH_TOKEN"
but I with the request module I can only send an object of key, value pairs. I also looked at the docs for nodes http.request and found it has the same issue.
So the question is, why does the API not follow the standard key pair format and how can I send a POST request that will work?
Authorization is the name of the HTTP Header (see also). This might work better:
headers: {
Authorization: "BoxAuth api_key=API_KEY&auth_token=AUTH_TOKEN"
}

Resources