Writing data to google sheets using Google Sheets API with R - r

I try to write a data frame to google sheets using R. I've successfully added data frame example from google for developers API reference method selector but got Error 404 when tried to do so from my R script.
I've successfully got API credentials by token <- gargle::token_fetch() with spreadsheet and drive scopes. I've inserted some blank lines in the beginning of my table:
sheet_ins_range <- jsonlite::fromJSON('{
"requests": [
{
"insertRange": {
"range": {
"startRowIndex": 2,
"endRowIndex": 2,
"sheetId": XXXXX
},
"shiftDimension": "ROWS"
}
}
]
}')
sheet_ins_range$requests$insertRange$range$endRowIndex <- 10
body <- jsonlite::toJSON(sheet_ins_range)
response <- POST("https://sheets.googleapis.com/v4/spreadsheets/{spreadsheetId}:batchUpdate",
body = body, encode = "json", config(token = token))
# response: Status: 200
But when I try to write some data into this region I get Error Status: 404.
google_BU <- jsonlite::fromJSON('{
"data": [
{
"range": "Sheet1!A1:D4",
"values": [
["Item", "Cost", "Stocked", "Ship Date"],
["Wheel", "$20.50", "4", "3/1/2016"],
["Door", "$15", "2", "3/15/2016"],
["Engine", "$100", "1", "3/20/2016"]],
"majorDimension": "ROWS"
}
],
"valueInputOption": "USER_ENTERED"
}')
body <- jsonlite::toJSON(google_BU)
response <- POST("https://docs.google.com/spreadsheets/d/{spreadsheetId}/values:batchUpdate",
body = body, encode = "json", config(token = token))
# response: Status: 404
I suppose I do something wrong with HTTP request, because there is nothing wrong with this request body when I use googles "Try this method" page.

Related

How to pass parameter to REST API?

I am using R and have one question on how to pass parameter to the REST API REQUEST.
I already got the token and I am using R, and need to retrieve data from REST API service, by passing some parameters. Here is my code:
library(httr)
r <- POST("https://XXXXXXXX/api/locationhazardInfo",
add_headers("Content-Type"="text/plain; charset=UTF-8",
Accept="text/plain",
"Authorization"=paste("Bearer", tok)),
body = list(
"Latitude":40.738269,
"Longitude":-74.02826,
"CountryCode":"USA",
"HazardLayers":[
{
"LayerId":"18",
"Description":""
},
{
"LayerId":"6",
"Description":""
}
],
"Distances":[
{
"Value":1,
"Unit":"miles"
}
]
)
)
The tok is the token I got from previous step. And I got the systax errors (seem all syntax errors) as shown below,
Any input is greatly appreciated.
here is the screenshot of the error
Your body isn't a list. (I don't think!). I also think you have a rogue ) at the end (second last) which should be a }
A list would look like:
body = list(x = "A simple text string", y="Another String")
Your body is JSON encoded text.
body = '{"a":1,"b":{}}', encode = "raw")
So your code might look like this:
library(httr)
r <- POST(
"https://XXXXXXXX/api/locationhazardInfo",
add_headers(
"Content-Type"="text/plain; charset=UTF-8",
Accept="text/plain",
"Authorization"=paste("Bearer", tok)
),
body = '{
"Latitude":40.738269,
"Longitude":-74.02826,
"CountryCode":"USA",
"HazardLayers":[
{
"LayerId":"18",
"Description":""
},
{
"LayerId":"6",
"Description":""
}
],
"Distances":[
{
"Value":1,
"Unit":"miles"
}
]
}',
encode = "raw" )
An update, here is the solution at least it fixed my problem:
rg <- POST(url,
# add_headers("Content-Type"="text/plain; charset=UTF-8",
add_headers("Content-Type"="application/json",
Accept="text/plain",
"Authorization"=paste("Bearer", tok)),
body = '{
"Latitude":40.738269,
"Longitude":-74.02826,
"CountryCode":"USA",
"HazardLayers":[
{
"LayerId":"18",
"Description":""
},
{
"LayerId":"6",
"Description":""
}
],
"Distances":[
{
"Value":1,
"Unit":"miles"
}
]
}' ,
encode = "raw" #### , verbose()
)

Retrieving the profile image from LinkedIn API response

I've gone through the authentication and am receiving the correct data from LinkedIn and receiving a response as shown in this link:
https://developer.linkedin.com/docs/ref/v2/profile/profile-picture
However, I'm unsure how to extract the image from this:
"displayImage": "urn:li:digitalmediaAsset:C4D03AQGsitRwG8U8ZQ",
Do I need to make another request for the image url next?
For anyone else looking, I overlooked there is an identifier field like so with a url:
"identifiers": [
{
"identifier": "https://media.licdn.com/dms/image/C4D03AQGsitRwG8U8ZQ/profile-displayphoto-shrink_100_100/0?e=1526940000&v=alpha&t=12345",
"file": "urn:li:digitalmediaFile: (urn:li:digitalmediaAsset:C4D03AQGsitRwG8U8ZQ,urn:li:digitalmediaMediaArtifactClass:profile-displayphoto-shrink_100_100,0)",
"index": 0,
"mediaType": "image/jpeg",
"identifierExpiresInSeconds": 1526940000
}
To get the above response in ruby I'm doing the following:
url = 'https://api.linkedin.com/v2/me?projection=(id,firstName,lastName,profilePicture(displayImage~:playableStreams))'
res = RestClient.get(url, Authorization: "Bearer #{access_token}")
Use this:
url = 'https://api.linkedin.com/v2/me?projection=(id,firstName,lastName,emailAddress,profilePicture(displayImage~:playableStreams))&oauth2_access_token=' + access_token

Httpt batch call for multiple POST operations

I am trying to do multiple $http post call and my code looks something like this:
var data = [{"id": 1, "Name": A}, {"id": 2, "Name": B},...];
var requests = [];
angular.forEach(data, function(value) {
requests.push($http(
url:'/example.com',
method: "POST",
dataType: 'json',
contentType:'application/json',
data:value ))
});
$q.all(requests).then(function(results){
results.forEach(function(data,status,headers,config){
console.log('success');
})
})
This works fine, but when the length of data array is more the number of service calls from client side is high. So I would like to make it as a batch request. Am not able to find any proper documentation for batch request for POST operation. Kindly help me on this.

Unable to POST to Grafana using Python3 module requests

I'm trying to create a dashboard on Grafana using their backend API. I first test that my API token is set up by using GET and successfully get a return code of 200(shown below). I then try to use POST to create a simple dashboard but I keep getting a return code of 400. I'm pretty sure it has something to do with the payload I'm trying to send, but I have been unable to figure it out. Here is the link to the example page I'm using for their JSON format. http://docs.grafana.org/reference/http_api/
import requests
headers = {"Accept": "application/json","Content-Type": "application/json" ,"Authorization": "Bearer xxx"}
r = requests.get("http://www.localhost",headers=headers)
print(r.text)
print(r.status_code)
dashboard = {"id": None,
"title": "API_dashboard_test",
"tags": "[CL-5]",
"timezone": "browser",
"rows":"[{}]",
"schemaVersion": 6,
"version": 0
}
payload = {"dashboard": "%s" % dashboard}
url = "http://www.localhost/api/dashboards/db"
p = requests.post(url,headers=headers, data=payload)
print(p)
print(p.status_code)
print(p.text)
OUTPUT:
200
<Response [400]>
400
[{"classification":"DeserializationError","message":"invalid character 'd' looking for beginning of value"},{"fieldNames":["Dashboard"],"classification":"RequiredError","message":"Required"}]
The problem is that your object is not an actual json object.
You can use post method with json=YOUR_PYTHON_OBJECT
So to fix your code, change your dictionary to use just a regular python dictionary, use json=payload, rather than data=payload.
So refactoring your code, you will have:
import requests
headers = {"Accept": "application/json",
"Content-Type": "application/json",
"Authorization": "Bearer xxx"
}
r = requests.get("http://www.localhost", headers=headers)
print(r.text)
print(r.status_code)
dashboard = {"id": None,
"title": "API_dashboard_test",
"tags": ["CL-5"],
"timezone": "browser",
"rows": [{}],
"schemaVersion": 6,
"version": 0
}
payload = {"dashboard": dashboard}
url = "http://www.localhost/api/dashboards/db"
p = requests.post(url, headers=headers, json=payload)
print(p)
print(p.status_code)
print(p.text)
Note the differences in dashboard, for example, "rows" was changed from "[{}]" to just [{}] so that it is a python object (list with empty dictionary), rather than a string.
The output is
200
<Response [200]>
200
{"slug":"api_dashboard_test","status":"success","version":0}

Connecting to BI tool's REST API using rcurl

I am trying to connect directly to a BI tool's API from within R. The API Documentation lists the curl command below to obtain an authentication token:
curl -X POST -H "Content-Type: application/json" -d
'{
"email": "your#email.com",
"password": "your_password"
}'
https://app.datorama.com/services/auth/authenticate
Further, below is an example of a JSON query that can be used to query data:
{
"brandId": "9999",
"dateRange": "CUSTOM",
"startDate": "2016-01-01",
"endDate": "2016-12-31",
"measurements": [
{
"name": "Impressions"
}
],
"dimensions": [
"Month"
],
"groupDimensionFilters": [],
"stringDimensionFilters": [],
"stringDimensionFiltersOperator": "AND",
"numberDimensionFiltersOperator": "AND",
"numberMeasurementFilter": [],
"sortBy": "Month",
"sortOrder": "DESC",
"topResults": "50",
"groupOthers": true,
"topPerDimension": true,
"totalDimensions": []
}
I'm trying to 1) translate the curl command above into R so as to obtain the authentication token required, and 2) query the data through the JSON script above.
So far i've attempted using the httr library as follows:
library(httr)
r <- POST('https://app.datorama.com/services/auth/authenticate',
body = list(
brandId = "9999",
dateRange = "CUSTOM",
measurements = list(name="Impressions"),
dimensions = list(name="Month"),
startDate = "2016-01-01",
endDate = "2016-12-31"
),
encode = "json",
authenticate("username", "password"))
to no avail.
The API documentation is behind a password protected page and as such i'm unable to link it. Let me know if additional information is required.
hrbrmstr is totally right! you should generate two api calls, the first one is to authenticate the user and the second one is to query the data.
Below is a fully working example of using the Datorama query API from R. feel free to contact the Datorama support for any additional questions.
library(httr)
res <- POST("https://app.datorama.com/services/auth/authenticate",
body=list(email="your#email.com",
password="your_password"),
encode="json")
token <- content(res)$token
res_query <- POST(paste("https://app.datorama.com/services/query/execQuery?token=",token, sep=""),
body = list(
brandId = "9999",
dateRange = "CUSTOM",
measurements = list(list(name = "Impressions")),
dimensions = list("Month"),
startDate = "2016-01-01",
endDate = "2016-12-31"
),
encode = "json")
cat(content(res_query, "text"), "\n")
I don't have access to their API and would have prbly written a small wrapper pkg to this service if they had a free tier. Having said that,
curl -X POST \
-H "Content-Type: application/json" \
-d '{ "email": "your#email.com",
"password": "your_password" }'
translates to:
library(httr)
res <- POST("https://app.datorama.com/services/auth/authenticate",
body=list(email="your#email.com",
password="your_password"),
encode="json")
They don't have their app API documentation online for free either but I'm going to assume it sends back a JSON response with some type of authorization_token and encoded string.
You then—most likely—need to pass that result with every subsequent API call (and there is probably a timeout where the initial auth will need to be re-upped).
authenticate() is used for HTTP basic auth, not for this type of in-API JSON/REST auth.
Your actual API call looks fine apart from using the token auth.

Resources