Send POST request in Google Apps Script with Headers and Body - google-apps-script

I am trying to send a POST request in order to receive an Access Token in return.
The documentation is as follows:
Client Credentials
This is your first route to obtain an access_token to communicate with the API.
Route : POST https://api.helloasso.com/oauth2/token
Headers
Content-Type = application/x-www-form-urlencoded
Body
client_id = Your Client Id
client_secret = Your Client Secret
grant_type = client_credentials
Solution I tried
Based on this post, I tried the following code:
function qwe()
{
const url = 'https://api.helloasso.com/oauth2/token';
const headers = {
"client_id": "Your Client Id",
"client_secret": "Your Client Secret",
"grant_type": "client_credentials"
};
const options = {
'method' : 'post',
'contentType': 'application/x-www-form-urlencoded',
'headers': headers
};
const response = UrlFetchApp.fetch(url, options);
var data = JSON.parse(response);
Logger.log(data);
}
Upon running this, I get an error "Exception: Request failed for https://api.helloasso.com returned code 400. Truncated server response: {"error":"unauthorized_client","error_description":"client_id is not set"}".
I am a beginner, and would appreciate any help on this! Thank you in advance

Modification points:
In the case of UrlFetchApp, the default content type is application/x-www-form-urlencoded.
From your question and situation, I guessed that your Body might be required to be sent as form data.
If those points are reflected in your script, it becomes as follows.
Modified script:
function qwe() {
const url = 'https://api.helloasso.com/oauth2/token';
const data = {
"client_id": "Your Client Id",
"client_secret": "Your Client Secret",
"grant_type": "client_credentials"
};
const options = {
'method': 'post',
'payload': data
};
const response = UrlFetchApp.fetch(url, options);
console.log(response.getContentText())
}
Note:
If you tested this modified script, when an error occurs, please show the detailed error message and provide the official document. By this, I would like to confirm it.
Reference:
fetch(url, params)

Need to make it stringify first
'payload' : JSON.stringify(data)

Related

How can seen the untrucated server response? [duplicate]

This question already has answers here:
How can I see the full server response for this API error message in Google Scripts?
(2 answers)
Closed 6 months ago.
When using google Apps Script, sometimes I create errors on external API's I'm using.
The response is:
Exception: Request failed for https://dev1.example.com returned code 400. Truncated server response: {"code":"rest_invalid_param","message":"Invalid parameter(s): line_items","data":{"status":400,"params":{"line_items":"line_items[0][subtotal] is n... (use muteHttpExceptions option to examine full response)
I understand how to set the muteHttpExceptions :
var options = {
'method': 'post',
'contentType': 'application/json',
'headers': headers,
'muteHttpExceptions': true,
'payload': JSON.stringify(data)
};
apiurl = "https://" + apidomain + "/wp-json/wc/v3/customers/"
but I don't understand where I should then be looking for the untruncated server response.
The documentation: https://developers.google.com/apps-script/reference/url-fetch/url-fetch-app is not something I'm finding very helpful
Am I looking on the API server endpoint logs?
Or somewhere in Appscript?
Maybe here?
var response = UrlFetchApp.fetch(apiurl, options);
Logger.log(response);
Or in my local web browser?
Or am I totally confused?
I'm new to SO and Apps Script, so please be gentle.
As per this answer, the muteHttpExceptions option stops the script stopping on error, but instead puts the server error into the response of the call. This is the bit you'd usually look for your response from your API Call.
So this is how you'd get the full response, and it'd appear on the Apps Script debugging interface:
var headers = { "Authorization": "Basic " + encodedAuthInformation };
var options = {
'method': 'post',
'contentType': 'application/json',
'headers': headers, // Convert the JavaScript object to a JSON string.
'muteHttpExceptions': true,
'payload': JSON.stringify(data),
};
apiurl = "https://" + apidomain + "/wp-json/wc/v3/orders/"
var response = UrlFetchApp.fetch(apiurl, options);
Logger.log(response);

API request Google Apps Scripts

I need to request information from api.I tried to make a request with UrlFetchApp.fetch and fetchAll.In both cases i got nothing.Here s my code:
var request1 = {
url: "https://seo-fast-audit.p.rapidapi.com/?url=" + url,
method : 'GET',
params: {url: 'https://docteurseo.fr/'},
headers: {
"x-rapidapi-host": "seo-fast-audit.p.rapidapi.com",
"x-rapidapi-key": "KEY"
}
};
let response = UrlFetchApp.fetchAll([request1])
(here i replaced key)
So what is my problem?Is that problem in async functions or am i requesting not correctly?
Here s API i am using
https://rapidapi.com/DocteurSEO/api/seo-fast-audit
If you want to convert the following javascript to Google Apps Script, Ref
var axios = require("axios").default;
var options = {
method: 'GET',
url: 'https://seo-fast-audit.p.rapidapi.com/',
params: {url: 'https://docteurseo.fr/'},
headers: {
'x-rapidapi-host': 'seo-fast-audit.p.rapidapi.com',
'x-rapidapi-key': 'SIGN-UP-FOR-KEY'
}
};
axios.request(options).then(function (response) {
console.log(response.data);
}).catch(function (error) {
console.error(error);
});
how about the following modification?
function myFunction() {
var url = "https://seo-fast-audit.p.rapidapi.com?url=" + encodeURIComponent('https://docteurseo.fr/');
var option = {
headers: {
"x-rapidapi-host": "seo-fast-audit.p.rapidapi.com",
"x-rapidapi-key": "KEY"
}
};
let response = UrlFetchApp.fetch(url, option);
console.log(response.getContentText())
}
In your script, params is not included in the object for fetch and fetchAll. And, I thought that in your situation, url is required to do the URL encode, and com/?url= is com?url=.
Note:
I think that the request of the above Google Apps Script is the same as the top of Javascript. But if an error occurs, please check your KEY again.
If an error of 403 forbidden occurs, the site might not be accessed from the Google side. I'm worried about this.
Reference:
fetch(url, params)

Requesting access token to Zoom API via Oauth - error 'missing grant type'

I'm trying to receive an access token from the Zoom api via Oauth. No matter what form I try and send the body as, 'Content-Type': 'application/json' or Content-Type:application/x-www-form-urlencoded, it always errors to { reason: 'Missing grant type', error: 'invalid_request' }.
var options = {
method: "POST",
url: "https://zoom.us/oauth/token",
body: JSON.stringify({
grant_type: "authorization_code",
code: process.env.AUTH_CODE,
}),
redirect_uri: "https://zoom.us",
};
var header = {
headers: {
Authorization:
"Basic " +
Buffer.from(process.env.ID + ":" + process.env.SECRET).toString("base64"),
},
"Content-Type": "application/json",
};
var tokCall = () =>
axios
.post("https://zoom.us/oauth/token", options, header)
.then((response) => {
console.log(response);
})
.catch((error) => {
console.log(error.response);
});
tokCall();
I'm fairly certain the answer lies in either the data type in which Oauth is receiving the data, or where/if it's receiving the body at all. Any suggestions would be gratefully received.
The error is being thrown because you're sending the data as the body of the post request when the Request Access Token Zoom API is expecting to find them as query parameters which you might know as query strings.
Reference
https://marketplace.zoom.us/docs/guides/auth/oauth#local-test
Image of page from link to highlight the use of query parameters and content-type requirement for API call
Change
var options = {
method: "POST",
url: "https://zoom.us/oauth/token",
body: JSON.stringify({
grant_type: "authorization_code",
code: process.env.AUTH_CODE,
}),
redirect_uri: "https://zoom.us",
};
to
var options = {
method: "POST",
url: "https://zoom.us/oauth/token",
params: {
grant_type: "authorization_code",
code: process.env.AUTH_CODE,
redirect_uri: "<must match redirect uri used during the app setup on zoom>"
},
};
The Content-Type header should be set to application/x-www-form-urlencoded as this is a requirement of the zoom API itself.
BTW, axios requires you to name the body field/object of your request as data and also there's no need for JSON.stringify() method since axios does that for you under-the-hood
Though it's a late answer, I'd like to share it since it took me some time to complete this using Axios.
So to make Zoom authorization, you need to do:
Base64 encode the secret and client id
const base64EncodedBody =
Buffer.from(`${ZOOM_CLIENT_ID}:${ZOOM_CLIENT_SECRET}`).toString('base64');
URI encode the grant_type, code and redirect_uri
const data =
encodeURI(`grant_type=authorization_code&code=${code}&redirect_uri=${redirectUri}`);
Send the request
const response = await axios.post('https://zoom.us/oauth/token', data, {
headers: {
Authorization: `Basic ${base64EncodedBody}`,
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength(data),
},
});

POST json file using request module

I am planning to translate the curl API call below to node.js though I am still getting an error when doing a POST.
curl -X POST --user user1#customer1:secret http://demo.test.com/controller/actions/38 -F file=#ExportActions.json
Below is initial code using the request - npm module, but the API call still fails.
var requestdata = fs.readFileSync('./ExportActions.json').toString();
var request = require('request');
request.post({
url: 'https://demo.test.com/controller/actions/38',
auth: {
'user': 'user1#customer1',
'pass': 'secret'
},
body: requestdata
}, function(error, response, body){
console.log(body);
});
I am getting the error below every time I run the script:
Could not import Actions: org.apache.commons.fileupload.FileUploadException: the request was rejected because no multipart boundary was found
Are there any workarounds when posting a JSON file using the npm request module?
Thanks!
You are trying to upload to file by posting it to the body. It looks like the server wants a multi-part upload instead. This might work better
var req = require('request');
request.post({
url: 'https://demo.test.com/controller/actions/38',
auth: {
'user': 'user1#customer1',
'pass': 'secret'
},
}, function(error, response, body){
console.log(body);
});
var form = req.form()
form.append('file', fs.readFileSync('./ExportActions.json'));
You can use Postman client to check this api instead of curl.

google apps script post basecamp

I'm trying to make calls to Basecamp's new API through Google Apps Script. GET, I can do. POST, not so much.
Starting with the path
https://basecamp.com/xxxxxxx/api/v1/projects/xxxxxxx/todolists.json
My code:
var headers = {
'User-Agent' : BCuseragent,
'Authorization' : 'Basic ' + Utilities.base64Encode(BCuser + ':' + BCpass),
'Content-Type' : 'application/json',
'Accept' : 'application/json',
'validateHttpsCertificates' : false
}
function getBC(path) {
var url = BCurl + path;
var opt = {
'headers' : headers,
'method' : "GET"
};
var response = UrlFetchApp.fetch(url, opt);
return response;
}
function postBC(path, payload) {
var url = BCurl + path;
var opt = {
'headers' : headers,
'method' : "POST",
'payload' : JSON.stringify(payload)
};
var response = UrlFetchApp.fetch(url, opt);
return response;
}
The payload I'm passing as a parameter:
{name: "foo", description: "bar"}
The getBC function works (200 OK), the postBC function returns a 403 error. Yet I am the owner of the project, and I've used curl and a Chrome REST client to confirm I can in fact POST new todolists to this project with the same authorization.
Obviously, my headers are malformed somewhere, but I can't see how.
This is a quirk of UrlFetchApp. You can't set the Content-Type using the general "headers" parameter, instead you must use the "contentType" parameter.
See the "Advanced Parameters" table here:
https://developers.google.com/apps-script/reference/url-fetch/url-fetch-app#fetch(String,Object)