Connecting to BI tool's REST API using rcurl - r

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.

Related

Writing data to google sheets using Google Sheets API with 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.

Translate curl call using httr in R, with multiple calls

I am trying to "translate" the curl call below, so that I can make an API call with R (using httr), with no luck. I have tried curlconverter and using the suggestion here. However, the API I want to access has multiple layers, and parenthesis are all over the place, which complicate conversion. Any suggestions for a function that will translate this recurring logic dynamically?
curl call:
curl -X POST 'https://api.notion.com/v1/databases/897e5a76ae524b489fdfe71f5945d1af' \
-H 'Authorization: Bearer '"$NOTION_API_KEY"'' \
-H 'Notion-Version: 2021-05-13' \
-H "Content-Type: application/json" \
--data '{
"filter": {
"or": [
{
"property": "In stock",
"checkbox": {
"equals": true
}
},
{
"property": "Cost of next trip",
"number": {
"greater_than_or_equal_to": 2
}
}
]
},
"sorts": [
{
"property": "Last ordered",
"direction": "ascending"
}
]
}'
Desired outcome (function)
api_call(page, token, filters)
This question is a bit difficult to answer, since you have the access key and therefore nobody can test code to make sure it works. However, in terms of simply translating the curl call to httr code, I think the following code will do so.
library(httr)
library(jsonlite)
# Create the body of the POST request
json_body <- list(
"filter" = list(
"or" = list(
list(
"property" = "In stock",
"checkbox" = list(
"equals" = "true"
)
),
list(
"property" = "Cost of next trip",
"number" = list(
"greater_than_or_equal_to" = 2
)
)
)
),
"sorts" = list(
list(
"property" = "Last ordered",
"direction" = "ascending"
)
)
)
# Make post request
request <- POST(
url = "https://api.notion.com/v1/databases/897e5a76ae524b489fdfe71f5945d1af",
add_headers("Authorization" = paste("Bearer", notion_api_key),
"Notion-Version" = "2021-05-13"),
body = json_body,
encode = "json"
)
In terms of defining a function that creates the body dynamically, that's simply a question of formatting the filters similarly to the above example.

Writing a proper API request in R for curl -X POST

I am new to this topic and reviewed several SO answers before, but still cannot figure it out.
Trying to access API, using R:
curl -X POST "http://api.spending.gov.ua/api/rest/1.0/transactions" -H "accept: application/json" -H
"Content-Type: application/json" -d "{ \"payers_edrpous\": [ \"string\" ], \"recipt_edrpous\": [
\"string\" ], \"startdate\": \"string\", \"enddate\": \"string\", \"regions\": [ 0 ]}"
My current stage
library(httr)
r <- GET("http://api.spending.gov.ua/api/rest/1.0/transactions")
status_code(r)
This works, I have 200 response.
But how to write a query to get data in json format? Appreciate any tips.
The link from #dcruvolo was helpful.
In order get to this to work, you need to start with some valid values. From the API link in the question, there is a test page to order to test the submittal:
One can substitute in test values and then press the "Execute" button submit values. Attempted values from the comments above, valid enough not to cause an error but also did not return any valid results.
To perform the POST in R here is an example:
posting<-'{
"payers_edrpous": [
"00013534"
],
"recipt_edrpous": [
""
],
"startdate": "2020-03-01",
"enddate": "2020-03-28",
"regions": [
0
]
}'
library(httr)
r <- POST("http://api.spending.gov.ua/api/rest/1.0/transactions", body=posting,
httr::add_headers(`accept` = 'application/json'),
httr::content_type('application/json')) #encode="json"
content(r)
Posting is the JSON body to pass, edit this as necessary. All variables are strings except "regions" where it is an integer, not sure what the valid range is.
Sorry this is the best I can do. Good luck.

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}

Array in body for httr POST request

This curl call works to create a new droplet on Digital Ocean
curl -X POST "https://api.digitalocean.com/v2/droplets" \
-d '{"name":"test3","region":"nyc2","size":"512mb","image":5562742,"ssh_keys":[89103]}' \
-H "Authorization: Bearer $TOKEN"
-H "Content-Type: application/json"
However, I'm having trouble getting an httr::POST() request to work only when the parameter ssh_keys is given. In the above method the ssh_keys parameter, if given, has to be an array.
I assumed the list of parameters could be passed to the body as, e.g., where the ssh_keys parameter is inside a list
args <- list(name="test3", region="nyc2", size="512mb", image="5562742", ssh_keys=list(891111))
POST(url, config=auth, body=args)
I assume this is what's happening on the inside:
jsonlite::toJSON(args)
[1] "{ \"name\" : [ \"test3\" ], \"region\" : [ \"nyc2\" ], \"size\" : [ \"512mb\" ], \"image\" : [ \"5562742\" ], \"ssh_keys\" : [ [ 89103 ] ] }"
Which I imagine would work, but perhaps that's not what's happening? Fiddling with the encode parameter in POST doesn't seem to help.
The curl call works from terminal, but using httr::POST() I keep getting the error message
You specified invalid ssh key ids for Droplet creation.
In this specific case,
x <- jsonlite::toJSON(args, auto_unbox=TRUE)
cat(x)
seems to return the correct format (assuming the problem is not with the headers) so them
POST(url, config=auth, body=x)
should send the correct request.
Maybe something like:
req <- POST(
url = "https://api.digitalocean.com/v2/droplets",
body = toJSON(args, auto_unbox=TRUE),
add_headers (
"Content-Type" = "application/json",
"Authorization" = paste("Bearker", TOKEN)
)
)

Resources