Mailchimp Restful API 3.0 in Node.js always Resource not Found - node.js

I'm trying to hit one of the mailchimp's api, but for somehow I always get
{
"type": "http://developer.mailchimp.com/documentation/mailchimp/guides/error-glossary/",
"title": "Resource Not Found",
"status": 404,
"detail": "The requested resource could not be found.",
"instance": ""
}
I'm using request library to make the request and see the code below
var uniqueListId = "XXXX";
var apiKey = "XXX";
.post(function(req, res) {
var email = req.body.email;
var status = "subscribed";
request({
url: 'https://usX.api.mailchimp.com/3.0/lists/' + uniqueListId + '/members',
headers: {
'Authorization': 'randomUser ' + apiKey,
'Content-Type': 'application/json',
},
method: 'POST',
json: {
email_address: email,
status: status
}
}, function(err, response, body) {
if (err) {
res.json(err);
} else {
res.json(response.statusCode, body);
}
});
});
For the sake of clarity, this is the documentation that I'm referring to http://developer.mailchimp.com/documentation/mailchimp/reference/lists/members/
Is it because of my req.body data?

I agree with #TooMuchPete, The same issue happened with me and scratched my head for a whole day to solve that issue, and finally, I've found that Audience Idlist_id is wrong.
we need to pick the one which is located under the AudienceTab > ViewContacts > Settings > Audience and Defaults > Audience ID, but unfortunately, I have picked the one which is showing in the URL.

If you're getting a 404 it's because the URL you're hitting doesn't refer to an actual resource. Probably uniqueListId is either empty or not the right ID.

I would suggest using the Postman chrome add-on app to play with the requests and posts - you could also use it to generate sample code, in most languages. It is great for debugging.
After using it, I found that your request options should look something like:
let requestOptions = {
hostname: 'us14.api.mailchimp.com',
method: 'GET',
path: '/3.0/lists' + listId,
headers: {
'Authorization': 'User ' + config.mailChimp.apiKey,
'Content-Type': 'application/json',
},
}

You're almost certainly confusing mailchimp's web_id with list_id. The list_id is the one you need for the API, the web_id is the one you see in the url when you open your list.
I have absolutely no idea why mailchimp uses 2 different ids, nor why they don't seem to put it forward in any of their developer documentation.
Below is an article which explains how to find it - basically you go to your list -> settings tab -> list name and defaults.
https://3by400.com/get-support/3by400-knowledgebase?view=kb&kbartid=6

Related

Trying to send a POST request using the body of a GET request

I am currently working on a project to create API routes for two third party applications to communicate with one another using NodeJS/express. The issue I am having is that I am trying to have third party application A (3PA) get a list of timeslots from a calendar in third party application B (3PB) and then send a message to a user in 3PB containing those timeslots.
The route looks like this:
router.post('/request_appointment_times', function(req, res){
**google sheets api logic**
async function gsrun(client){
**getting data from google sheet**
var request = require('request');
require('request-debug')(request);
var options = {
'method': 'GET',
'url': '3PB API URL',
'headers': {
'accept' : '*/*',
'Authorization': 'Bearer ' + apiKey,
'content-type' : 'application/json'
},
};
request(options, function (error, response) {
if (error) throw new Error(error);
//console.log(response.body);
else
res.json({"message": "It Works!",});
slotsList = new String(response.body.slots);
slotsListArr = slotsList.split(',');
var rnd = Math.random(0, slotsListArr.length);
ssn.providedSlots = slotsListArr[rnd];
ssn.providedSlots2 = slotsListArr[rnd];
if (ssn.providedSlots == ssn.providedSlots2) {
ssn.providedSlots2 = ssn.slotsListArr[rnd]
}
if (ssn.providedSlots == ssn.providedSlots2) {
ssn.providedSlots2 = ssn.slotsListArr[rnd]
}
console.log(providedSlots);
console.log(providedSlots2);
});
}
});
Currently, I can't even get the providedSlots to print as the request function won't communicate with the console. My question is, is it possible/how can I do a POST to 3PB using the response body from my GET request within this same route. I apologize if I worded this poorly or didn't provide enough information. Any help is much appreciated and if I need to provide additional information let me know!
By the looks of this you are defining gsrun in your route handler but aren't actually invoking it. Should be more like this:
function gsrun() { /* logic */ }
router.post('/request_appointment_times', function(req, res){
gsrun();
});

Facebook Messenger Bot - How to use NodeJS to get User Information?

I have a bare bones chatbot in messenger set up and would like to expand on its potential functionality. The first thing I want to be able to do is access user info, mostly the users first name. I know this is possible, but as I am new to NodeJS I am not sure how to achieve this. I have not been able to find very many tutorials on chatbots past the intro stage. Any help is greatly appreciated!
Below is a link to an abbreviated version of my chatbot
This is the main bit of code that I think needs refining (see it below in the context of the rest of the bot)
function getName(event){
request({
url: "https://graph.facebook.com/v2.6/" + sender,
qs: {
access_token : token,
fields: "first_name"
},
method: "GET",
}, function(error, response, body) {
if(error){
console.log("error getting username")
} else{
var bodyObj = JSON.parse(body)
name = bodyObj.first_name
sendText(sender, "Hi, ")
sendText(sender, name)
sendText(sender, " whatsup?")
}
})
}
Chatbot Code
You can get the facebook user info by below code:
request({
url: "https://graph.facebook.com/v2.6/" + senderId + "?",
qs: {
access_token: config.FB_PAGE_ACCESS_TOKEN
},
headers: {
'Accept': 'application/json',
'Accept-Charset': 'utf-8',
'User-Agent': 'test-bot'
},
method: "GET",
json: true,
time: true
},
function(error, res, faceUserInfo) {
console.log("faceUserInfo", faceUserInfo)
}
);
Double check your access token is correct.
I also suggest you check the what the error message is
console.log("error getting username", error);
Sender is not defined in your function.
It is being passed into your other functions, or delcared in the scope of your post request handler.
Make sure sender is defined, and your code should work fine.
Add the below line to your getName function:
var sender = event.sender.id
Your variable name is not defined, should add let name=... and it works fine

Mailchimp API v3.0 add email to list via NodeJS http

I'm using NodeJS to call the new MailChimp 3.0 API in order to add an email to a list. While I can get it working via POSTman, I'm having a hard time with Node's http:
var http = require('http');
var subscriber = JSON.stringify({
"email_address": "test#test.com",
"status": "subscribed",
"merge_fields": {
"FNAME": "Tester",
"LNAME": "Testerson"
}
});
var options = {
host: 'https://us11.api.mailchimp.com',
path: '/3.0/lists/<myListID>/members',
method: 'POST',
headers: {
'Authorization': 'randomUser myApiKey',
'Content-Type': 'application/json',
'Content-Length': subscriber.length
}
}
var hreq = http.request(options, function (hres) {
console.log('STATUS CODE: ' + hres.statusCode);
console.log('HEADERS: ' + JSON.stringify(hres.headers));
hres.setEncoding('utf8');
hres.on('data', function (chunk) {
console.log('\n\n===========CHUNK===============')
console.log(chunk);
res.send(chunk);
});
hres.on('end', function(res) {
console.log('\n\n=========RESPONSE END===============');
});
hres.on('error', function (e) {
console.log('ERROR: ' + e.message);
});
});
hreq.write(subscriber);
hreq.end();
Rather than getting even some sort of JSON error from Mailchimp, however, I'm getting HTML:
400 Bad Request
400 Bad Request
nginx
Is it clear at all what I"m doing wrong here? It seems pretty simple, yet nothing I've tried seems to work.
A few additional thoughts:
While http's options have an "auth" property, I'm using the headers instead to ensure the authorization is sent without the encoding (as mentioned here). Still, I've also tried with the "auth" property, and I get the same result.
I'm actually making this call from inside an ExpressJS API (my client calls the Express API, that calls the above code - I've edited all that out of this example for simplicity). That's why my variables are "hres" and "hreq", to distinguish them from the "res" and "req" in Express. Is there any reason that could be the issue?
As mentioned above, I am able to get successful results when using POSTman, so I at least know my host, path, list ID, and API key are correct.
It turns out this had a very simple solution: the "host" property of the options object needed to have only the domain name. IE, remove the "https://" protocol:
var options = {
host: 'us11.api.mailchimp.com',
path: '/3.0/lists/<myListID>/members',
method: 'POST',
headers: {
'Authorization': 'randomUser myApiKey',
'Content-Type': 'application/json',
'Content-Length': subscriber.length
}
}
Try this , its working fine for Me.
var request = require('request');
function mailchimpAddListCall(email, cb){
var subscriber = JSON.stringify({
"email_address": email,
"status": "subscribed"
});
request({
method: 'POST',
url: 'https://us13.api.mailchimp.com/3.0/lists/<Your list id>/members',
body: subscriber,
headers:
{
Authorization: 'apikey <your Mailchimp API key>',
'Content-Type': 'application/json'
}
},
function(error, response, body){
if(error) {
cb(err, null)
} else {
var bodyObj = JSON.parse(body);
console.log(bodyObj.status);
if(bodyObj.status === 400){
cb(bodyObj.detail, null);
}
var bodyObj = JSON.parse(body);
cb(null, bodyObj.email_address +" added to list.");
}
});
}
request is a node module, that you'll need to install into your package.json. npm install --save request
You can use the auth properties just fine with API v3, but if you're getting a 400, that's not the problem. The body of the 400 Error should provide more detailed information, but one thing that jumps out immediately: MailChimp doesn't allow fake or fake-looking emails to be added to lists (like test#test.com), so I'd try a real address and see if that works for you.

Unexpected grunt-http error when posting to Atlassian Confluence api

Attempting to create a wiki page on an Atlassian wiki. I previously was using a python script and this code worked no problem:
data = json.dumps({"type":"page", "data":"testData", "title":postTitle,"space":{"key":"EB"}, "body":{"storage":{"value": content,"representation":"storage"}}})
r = requests.post("https://estech.atlassian.net/wiki/rest/api/content/", data=data, headers=headers, auth=(confluenceLogin['username'], confluenceLogin['password']))
Now I'm trying to use the following grunt task configuration:
http: {
atlassianwiki: {
options: {
uri: atlassianURL + "/wiki/rest/api/content/",
headers: {"Content-Type": "application/json"},
auth: {
"user": confluencelogin,
"pass": confluencepass
},
method:"POST",
body: JSON.stringify(wikijson)
}
}
}
with wikijson looking like:
wikijson = {
"type": "page",
"data": "testData",
"title": "testtitle",
"space": {key:"EB"},
"body": {
"storage": {
"value": "<p>testing posting</p>",
"representation": "storage"
}
}
}
And I get the following error when this task runs:
Fatal error: 500 {"statusCode":500, "message":"java.io.EOFException: No content to map to Object due to end of input"}
Upon a bit of google-fu, I found that some people claim they fixed this by adding "--post302" to their curl command line. But I don't really know or understand how that applies here.
i was fighting with confluence REST API and in my case the problem was in content-type header, but you seem to have it already.
I didn't try to create new page but to update existing one
Confluence API seemed a little bit magic to me, so i just leave here all steps i had to make before it started working, maybe one of them will help you.
function composeRequest(method) {
var auth = new Buffer(user + ':' + pass).toString('base64');
var request = {
host: 'confluence.myserver.com',
port: 443,
contentType: "application/json; charset=utf-8",
'path': path,
method: method || "GET",
headers: {
'Authorization': 'Basic ' + auth,
'Content-Type': 'application/json'
},
rejectUnauthorized: false,
requestCert: true,
agent: false
};
return request;
}
And it appeared that page update request JSON MUST contain
pageId (even it is inside path, you need to repeat it)
type
title
version (it's weird, but you should set it. 0 or 1, i don't remember)
And when your data if filled, you should convert it to string and fill content-type field in your request!
data = JSON.stringify(data);
request.headers['Content-Length'] = data.length;
https.request(request, respondHandler)

POSTing to a basic access authorization protected resource

I am experiencing a problem while POSTing to a resource which is protected by basic access authentication.
Here is the code, I am using #mikeal's request:
request.post({
uri: "http://user:password#mysite.com/resource",
json: {
"id": "1",
"par1": "a",
"par2": "b"
}
}, function (error, response, body) {
console.log(error);
console.log(response);
console.log(body);
});
I have { [Error: Parse Error] bytesParsed: 0 } in error and undefined in both response and body. If I remove the "user:password" part I correctly get a 401 HTTP Basic: Access denied.
Do you know if there's a way to POST JSON to a protected resource like in my case? If not, I believe I'll have to go the http module way, but I'm leaving that as a final resource since it's a lot more verbose.
UPDATE: To have this as simple as possible I've moved this file in a new directory and did a npm install request. The problem went away, I checked from where the byteParsed come from and found it's in "formidable" which is required by express, which I had in the directory where I was running this test. A bit confused right now.
I did it like this:
var options = {
method: 'POST',
uri: 'http://your.url.com/',
form: {
field1: 'somevalue',
field2: 666.66
},
headers: {
'Authorization': 'Basic ' + new Buffer("username:password").toString('base64')
}
};
request(options, function(error, response, body) {
// do stuff
});
You must add an header to your request with this rules:
http://en.wikipedia.org/wiki/Basic_access_authentication
Basically you must encode the string: username:password in base64 and add encoded string in an http header:
Authorization: Basic "Base64(username:password)"
I don't know if is possible add header with jquery or javascript. Sorry.
Look here: http://api.jquery.com/extending-ajax/#Transports

Resources