I'm trying to get a Google script (on a Google Sheet) to retrieve data from Float API. The endpoint and key are fine (tested and all works as expected on Postman) but it keeps returning 401.
Below is my code:
var API_KEY = "{ENTER YOUR KEY HERE}";
var ENDPOINT_PROJECTS = "https://api.float.com/api/v1/projects";
function getProjects() {
var headers = {
"Authorization" : "Bearer " + API_KEY,
};
var requestData = {
"method" : "GET",
"headers": headers,
"muteHttpExceptions": false
};
// Get the data
var fetchResponse = UrlFetchApp.fetch(ENDPOINT_PROJECTS);
var responseCode = fetchResponse.getResponseCode();
if (responseCode == "200") {
var result = JSON.parse(fetchResponse.getContentText());
} else {
ui.alert("Error when attempting to fetch the list of spaces.");
}
}
Okay looked like I completely missed a small yet very important part...even though I created an object to hold the method and headers I was not passing this into the actual fetch!!! (This is what happens when you attempt to do a quick script at the end of the day)
So instead of this
var fetchResponse = UrlFetchApp.fetch(ENDPOINT_PROJECTS);
we have this:
var fetchResponse = UrlFetchApp.fetch(ENDPOINT_PROJECTS, requestData);
Related
I am trying to call the Asana Events API - https://developers.asana.com/reference/getevents
This endpoint uses a 'Sync' token to track when you last called it, each call returns a new sync token which can then be stored and used for the next call to only retrieve events since the last call.
If you do not provide a sync token the API will return an 'invalid token' response and give you a new token to get started with.
However, I cannot seem to get it beyond the initial 'invalid token' call, when I used the token in the following call it still returns 'invalid token'
This is using Google's Apps Script, which is basically just JavaScript with some built-in Google functions
Here is my code:
This function makes a call without the ‘sync’ parameter, uses muteHttpExceptions to get the full response text, and sets the sync token as a property in Apps Script (just a key/value pair)
var asanaBaseUrl = 'https://app.asana.com/api/1.0'
function getSyncToken() {
var url = asanaBaseUrl + '/projects/' + asanaProject + '/events'
var headers = {
'Authorization': 'Bearer ' + asanaPAT
}
var options = {
'method': 'GET',
'headers': headers,
'muteHttpExceptions': true
}
var r = UrlFetchApp.fetch(url, options)
var data = JSON.parse(r.getContentText())
var newSyncToken = data.sync
userProps.setProperty('syncToken', newSyncToken)
}
This function uses the properties service to pull the sync token set in the previous call and makes a new call with the sync parameter
function asanaEventCall() {
var url = asanaBaseUrl + '/projects/' + asanaProject + '/events'
var syncToken = userProps.getProperty('syncToken')
var headers = {
'Authorization': 'Bearer ' + asanaPAT
}
var options = {
'method': 'GET',
'headers': headers,
'sync': syncToken,
'muteHttpExceptions': true
}
var r = UrlFetchApp.fetch(url, options)
var data = JSON.parse(r.getContentText())
return data
}
The second function always returns the following
{sync=[SYNC TOKEN HERE], errors=[{message=Sync token invalid or too old. If you are attempting to keep resources in sync, you must fetch the full dataset for this query now and use the new sync token for the next sync.}]}
I’ve confirmed that the token is being set, retrieved, and sent correctly using the logs.
I’ve confirmed the flow above works by manually using the URL, like this:
Go to https://app.asana.com/api/1.0/projects/[PROJECT GID]/events
Copy sync token
Go to https://app.asana.com/api/1.0/projects/[PROJECT GID]/events?sync=[SYNC TOKEN]
Events show properly
I've looked for other answers but haven't found anything specific that helped, and I asked on the Asana forum but haven't got an answer in a few days.
I'm sure I'm missing something painfully obvious here but just can't see it!
From Go to https://app.asana.com/api/1.0/projects/[PROJECT GID]/events?sync=[SYNC TOKEN] of I’ve confirmed the flow above works by manually using the URL, like this:, in your script, it seems that it is required to add 'sync': syncToken, as the query parameter. So, how about modifying your asanaEventCall() as follows?
Modified script:
function asanaEventCall() {
var syncToken = userProps.getProperty('syncToken')
var url = asanaBaseUrl + '/projects/' + asanaProject + '/events' + '?sync=' + syncToken;
var headers = {
'Authorization': 'Bearer ' + asanaPAT
}
var options = {
'method': 'GET',
'headers': headers,
'muteHttpExceptions': true
}
var r = UrlFetchApp.fetch(url, options)
var data = JSON.parse(r.getContentText())
return data
}
Note:
In this modification, it supposes that your values of asanaProject, asanaPAT and syncToken are valid values. Please be careful about this.
I am trying to setup a small application based on Google App Script and Google sheets
So far I am able to get the facebook page feed and able to connect to facebook app through Oauth2 library and got the tokens
So I am struggling to write the code for posting to facebook ,
Currently I got the facebook page feeds but the post format documentation from facebook is referring to javascript SDK , and here I am not using SDK and graph API refers with POST and GET requests I think that also didn't work here .
So this is my Codes for getting facebook token and page feed .
Some one referred this as a duplicate but those question and answer doesn't fit in my question , I want facebook post format if it is with payload kindly include those payload options or someone can edit below code for POST
I am able to post to pages with the page access token not user access token
and pasting that page access token also throws the same error .
Updated Code But error appears as follows
Request failed for https://graph.facebook.com/v3.2/PAGE/feed?message=hello?access_token=TOKEN returned code 403. Truncated server response: {"error":{"message":"(#200) If posting to a group, requires app being installed in the group, and \\n either publish_to_groups permission... (use muteHttpExceptions option to examine full response) (line 53, file "FB postinf")
code updated
function example() {
var service = getService();
if (service.hasAccess())
var data = {
"message" : "Me Testing",
//"slug" : "me-testing",
// "text_to_subscribe" : "true"
};
var payload = JSON.stringify(data);
var options = {
"method" : "POST",
"contentType" : "application/json",
"payload" : payload
};
var url = "https://graph.facebook.com/v3.2/PAGENAME/feed?message=hello?access_token=ManuallyPastedTOKEN";
// + '?access_token=' + encodeURIComponent(service.getAccessToken());
var response = UrlFetchApp.fetch(url, options);
}
This is using OAuth2 GET FEED
function sasublish(){
var service= getService()
if (service.hasAccess()) {
var url = 'https://graph.facebook.com'
+ '/pagename/feed'
+'?fields='+ encodeURIComponent("name,full_picture,message,attachments{subattachments,url}")
+'&access_token='+ service.getAccessToken();
var response = UrlFetchApp.fetch(url, {'muteHttpExceptions': true});
var json = response.getContentText();
var jsondata = JSON.parse(json);
}
Need oAuth2 And Facebook.gs snippet you can use
.setScope('publish_pages,manage_pages,pages_show_list')
should be added to facebook.gs link to facebook.gs snippet
function example() {
var service = getService();
if (service.hasAccess())
var urls ='https://graph.facebook.com/v2.6/PAGEID?fields=access_token'; //specified page token
// var url = 'https://graph.facebook.com/v2.6/me/accounts?'; //tokens along with pages
var response = UrlFetchApp.fetch(urls, { //make url and urls changes
headers: {
'Authorization': 'Bearer ' + service.getAccessToken()
}
});
var result = JSON.parse(response.getContentText());
Logger.log(JSON.stringify(result , null, 2));
//Logger.log(JSON.stringify(result.data[0].access_token))
var datas = {
"message" : "Me Testing",
//"slug" : "me-testing",
// "text_to_subscribe" : "true"
};
var payload = JSON.stringify(datas);
var options = {
"method" : "POST",
"contentType" : "application/json",
"payload" : payload
};
var url = "https://graph.facebook.com/v3.2/PAGEID/feed"
+ '?access_token=' + encodeURIComponent(result.data[0].access_token);
// + '?access_token=' + encodeURIComponent(result.access_token);//direct pagetoken
var response = UrlFetchApp.fetch(url, options);
Logger.log('successfully posted to facebook page ',response)
}
I am trying to do a query on Jira and put these results on my google spreadsheet. Initially, I've tried to get the json file, but I've always have a DNS error on my response. When I get the link and insert it on the browser I am able to see the content on the screen.
I am supposed that it may be related to the authentication (Utilities.base64Encode(...)), but I don't know because the Google sheet only shows me:
DNS error: https://host.com.br/rest/api/2/search?jql=assignee%20=%20currentUser()%20AND%20resolution%20=%20Unresolved%20order%20by%20updated%20DESC
Does anyone know how to help me, please?
Thank you
function testJiraConnection()
{
var baseURL = "https://host.com.br/rest/api/2/search";
var username = "user";
var password = "password";
var encCred = Utilities.base64Encode(username+":"+password);
var headers = {
"Accept":"application/json",
"Content-Type":"application/json",
"Authorization":"Basic "+ encCred
};
var options = {
"method":"POST",
"contentType" : "application/json",
"headers": headers,
};
var jql = "?jql=assignee = currentUser() AND resolution = Unresolved order by updated DESC";
Logger.log(baseURL + jql);
var response = UrlFetchApp.fetch(baseURL + jql, options);
Logger.log(response);
}
I'm trying to connect my google sheet to Bitfinex through the 'authenticated' section of the API so I can access my account information. Here is the API link.
I haven't been able to get the 'request' or 'crypto' libraries to work so I've been trying to use other available functions in google sheets, but am having trouble.
Following is the code snippet I'm using:
var completeURL = "https://api.bitfinex.com/v1/account_infos";
var nonce = Math.floor(new Date().getTime()/1000);
var body = {
'request' : completeURL,
'nonce' : nonce
};
var payload = JSON.stringify(body).toString('base64');
var signature = Utilities.computeHmacSignature(Utilities.MacAlgorithm.HMAC_SHA_384,
payload,
secret);
signature = signature.map(function(byte) {
return ('0' + (byte & 0xFF).toString(16)).slice(-2);
}).join('');
var params = {
headers: {
'X-BFX-APIKEY': key,
'X-BFX-PAYLOAD': payload,
'X-BFX-SIGNATURE': signature
},
}
Logger.log(completeURL);
Logger.log(params);
var response = UrlFetchApp.fetch(completeURL, params);
var json = JSON.parse(response.getContentText());
I get the following error from the API:
Request failed for https://api.bitfinex.com/v1/account_infos returned code 400. Truncated server response: {"message":"Invalid json."} (use muteHttpExceptions option to examine full response). (line 209, file "Code")
And the following are the values from the Logger.log calls:
[17-09-24 16:22:28:170 AEST] https://api.bitfinex.com/v1/account_infos
[17-09-24 16:22:28:171 AEST] {headers={X-BFX-PAYLOAD={"request":"https://api.bitfinex.com/v1/account_infos","nonce":1506234148}, X-BFX-SIGNATURE=06d88a85098aefbf2b56af53721506863978f9350b1b18386c23f446254789dbbfc1eeb520bdfc7761b30f98ea0c21a2, X-BFX-APIKEY=ak6UoPiwaLjwt2UqDzZzZGjpb9P2opvdPCAIqLy0eVq}}
I'm stuck and not sure what else to try?
Can anyone spot what I'm doing wrong?
How about this modification? Since I have no secret, I couldn't debug this sample. So I don't know whether this modified sample works. I'm sorry.
Modification points :
secret is not defined.
When POST method is used, it requires to include method: "post" to UrlFetchApp.fetch().
When it reads Javascript sample of the document, signature has to be modified.
When it reads Javascript sample of the document, body: JSON.stringify(body) is included in the request parameters.
There is an error message of {"message":"Invalid json."}.
The script which was reflected above modifications is as follows.
Modified script :
var secret = "#####"; // Please input this.
var completeURL = "https://api.bitfinex.com/v1/account_infos";
var nonce = Math.floor(new Date().getTime()/1000);
var body = {
'request' : completeURL, // I don't know whether this is the correct value.
'nonce' : nonce
};
var payload = Utilities.base64Encode(Utilities.newBlob(JSON.stringify(body)).getDataAsString());
var signature = Utilities.computeHmacSignature(Utilities.MacAlgorithm.HMAC_SHA_384, payload, secret);
signature = signature.map(function(byte) {
return ('0' + (byte & 0xFF).toString(16)).slice(-2);
}).join('');
var params = {
method: "post",
headers: {
'X-BFX-APIKEY': key,
'X-BFX-PAYLOAD': payload,
'X-BFX-SIGNATURE': signature
},
payload: JSON.stringify(body),
contentType: "application/json",
muteHttpExceptions: true
}
var response = UrlFetchApp.fetch(completeURL, params);
var json = JSON.parse(response.getContentText());
If this was not useful for you, I'm sorry.
I am not sure if I am understanding your code, but if I do, there is at least one oddity at first sight:
In computeHmacSignature(...), you are using the variable secret which has not been initialized or even declared anywhere.
That's how it works
var body = {
'request' : "/v1/balances",
'nonce' : nonce,
'options':{}
};
I'm attempting to query items out of the Todoist API from Google Apps Script, mimicking a curl POST.
I originally tried to make OAuth2 work, but tokens were not persistent, and I instead opted for the API's method of using individual API tokens to exchange for a valid token.
Using App Script's UrlFetchApp class, I'm attempting to construct at POST request for Todoist's API to retrieve task items, and my getTodoistToken() function is indeed retrieving a valid token response, but the POST command is issuing the following 403:
"error_tag":"AUTH_CSRF_ERROR","error_code":0,"http_code":403,"error_extra":{"access_type":"web_session"},"error":"AUTH_CSRF_ERROR"}
Can anyone recommend a solution? Thanks so much, code below:
function getTodoistToken() {
var url = "https://todoist.com/api/access_tokens/migrate_personal_token";
var data = {
"client_id": "[my unique client_id]",
"client_secret": "[my unique client_secret]",
"personal_token":"[my API token from Todoist dashboard]",
"scope": "data:read"
};
var payload = JSON.stringify(data);
var headers = {
"Content-Type":"application/json",
};
var options = {
"method":"POST",
"contentType" : "application/json",
"headers": headers,
"payload" : payload
};
var response = UrlFetchApp.fetch(url, options);
var json = response.getContentText();
var data = JSON.parse(json);
return(data.access_token);
}
function getTodoistTasks(){
var apiURL = "https://todoist.com/API/v7/sync";
var data = {
"token" : getTodoistToken(),
"sync_token" : '*',
"resource_types" : '["items"]'
};
var payload = JSON.stringify(data);
Logger.log(payload);
var headers = {
"Content-Type":"application/json",
};
var options = {
"method":"POST",
"contentType" : "application/json",
"headers": headers,
"payload" : payload,
"muteHttpExceptions" : true
};
var response = UrlFetchApp.fetch(apiURL, options);
Logger.log(response.getContentText());
}
I have figured out the answer. The Todoist API documentation is bit ambiguous, seeming written around POST requests, but to download (sync) a full list of tasks, a simple URL-encoded GET request, as constructed below, did the trick:
function getTodoistTasks(){
var apiURL = "https://todoist.com/API/v7/sync";
var queryString = "?token=" + getTodoistTokenRev() + "&sync_token=%27*%27&resource_types=[%22items%22]";
//Get params
var fetchParameters = {};
fetchParameters.method = 'get';
fetchParameters.contentType = 'x-www-form-urlencoded';
fetchParameters.muteHttpExceptions = true;
//make request and return
var response = UrlFetchApp.fetch(apiURL + queryString, fetchParameters);
var syncData = JSON.parse(response.getContentText());
return(syncData);
}
And if anyone is looking for an example of creating an item (a task in this case), as I was, here's the code for that (note you need to specify a date_string and due_date for it to appear in the web UI):
var API_URL = "https://todoist.com/API/v7/sync"
var BASE_QUERY = "?token=" + TOKEN
function addTask() {
// var taskName = SpreadsheetApp.getUi().prompt('What the task\'s name?')
var taskName = 'Test 1652'
var commands = encodeURI(JSON.stringify([{
"type": "item_add",
"temp_id": uuidv4(),
"uuid": uuidv4(),
"args": {
"content": taskName,
"date_string": "today",
"due_date_utc": "2017-12-2T18:00",
}
}]))
var queryString = BASE_QUERY + '&commands=' + commands
var options = {
method: 'post',
contentType: 'x-www-form-urlencoded',
muteHttpExceptions: true}
var response = UrlFetchApp.fetch(API_URL + queryString, options)
if (response.getResponseCode() !== 200) {
var content = response.getContentText()
throw new Error('URL fetch failed: ' + content)
}
var syncData = JSON.parse(response.getContentText())
return syncData
// Private Functions
// -----------------
function uuidv4() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
} // addTask()