How to Post API in R having header & json body - r

How to call API Post in R
Request URL
https://westus.api.cognitive.microsoft.com/text/analytics/v2.0/sentiment
Request headers
Ocp-Apim-Subscription-Key = some value &
Content-Type = application/json
Body application/json
{
"documents": [
{
"language": "string",
"id": "string",
"text": "string"
}
]
}
Please help!!!

Here is the example -
request_body <- data.frame(
language = c("en","en"),
id = c("1","2"),
text = c("This is wasted! I'm angry","This is awesome! Good Job Team! appreciated")
)
Converting the Request body(Dataframe) to Request body(JSON)
require(jsonlite)
request_body_json <- toJSON(list(documents = request_body), auto_unbox = TRUE)
Below we are calling API (Adding Request headers using add_headers)
require(httr)
result <- POST("https://westus.api.cognitive.microsoft.com/text/analytics/v2.0/sentiment",
body = request_body_json,
add_headers(.headers = c("Content-Type"="application/json","Ocp-Apim-Subscription-Key"="my_subscrition_key")))
Output <- content(result)
Show Output
Output

Related

Build JSON content in R according Google Cloud Pub Sub message format

In R, I want to build json content according this Google Cloud Pub Sub message format: https://cloud.google.com/pubsub/docs/reference/rest/v1/PubsubMessage
It have to respect :
{
"data": string,
"attributes": {
string: string,
...
},
"messageId": string,
"publishTime": string,
"orderingKey": string
}
The message built will be readed from this Python code:
def pubsub_read(data, context):
'''This function is executed from a Cloud Pub/Sub'''
message = base64.b64decode(data['data']).decode('utf-8')
file_name = data['attributes']['file_name']
This following R code builds a R dataframe and converts it to json content:
library(jsonlite)
data="Hello World!"
df <- data.frame(data)
attributes <- data.frame(file_name=c('gfs_data_temp_FULL.csv'))
df$attributes <- attributes
msg <- df %>%
toJSON(auto_unbox = TRUE, dataframe = 'columns', pretty = T) %>%
# Pub/Sub expects a base64 encoded string
googlePubsubR::msg_encode() %>%
googlePubsubR::PubsubMessage()
It seems good but when I visualise it with a json editor :
indexes are added.
Additionally there is the message content:
I dont'sure it respects Google Cloud Pub Sub message format...
Not sure why, but replacing the dataframe by a list seems to work:
library(jsonlite)
df = list(data = "Hello World")
attributes <- list(file_name=c('toto.csv'))
df$attributes <- attributes
df %>%
toJSON(auto_unbox = TRUE, simplifyVector=TRUE, dataframe = 'columns', pretty = T)
Output:
{
"data": "Hello World",
"attributes": {
"file_name": "toto.csv"
}
}

Creating a function/loop

I have data being pulled from an API, but for the purposes of this, I will use dummy data:
test <- structure(list(Id = 201:203, firstname = c("Jackie", "Liz", "Jack"),
lastname = c("Jormpjomp", "Lemon", "Donaghy"),
address = c("4 Main St.", "5 Main St.", "6 Main St."),
zip = c(89044L, 60301L, 85281L),
dob = c(NA, "7/1/88", "2/13/90"),
phone = c("333-333-3333","4444", "555-555-5555"),
statecode = c("NV", "WI", "AZ")),
class = "data.frame",
row.names = c(1, 2, 3))
First I isolate all the needed variables as their own values:
Ids <- test$Id
firstnames <- test$firstname
lastnames <- test$lastname
addresses <- test$address
zips <- test$zip
dobs <- test$dob
phones <- test$phone
Then I create a character vector to add on to the final API call:
data_upsert = paste0(
'{ "Id": ', Ids, ',
"firstName": "', firstnames, '",
"lastname": "', lastnames, '",
"dateOfBirth": "', dobs, '",
"phones": [
{ "phoneNumber": "', phones, '" } ],
"addresses": [
{ "addressLine1": "', addresses, '",
"zipOrPostalCode": "', zips, '",
} ] }
')
Then I make a variable for my header - this will stay the same throughout
headers_upsert = c(
`Accept` = 'application/json',
`Authorization` = 'Basic JFOJDIFvdhSOFOHAD83820348voqpTOESV==',
`Content-Type` = 'application/json'
)
Finally, I complete the API call, as such:
upsert <- httr::POST(url = 'https://api.secure.com/v1/people/Create', httr::add_headers(.headers=headers_upsert), body = data_upsert)
Running that creates a response that looks like this:
Response [https://api.secure.com/v1/people/Create]
Date: 2021-08-31 20:28
Status: 201
Content-Type: application/json; charset=utf-8
Size: 58 B
{
"Id": 222323178,
"status": "UnmatchedStored"
I then want to store this response in table form:
resContent <- content(res, as="text")
resJSON <- jsonlite::fromJSON(resContent)
resTable <- as.data.frame(resJSON)
If you run everything above, it obviously only works with the first row in test, but I'm looking for a sleek way to write a function and loop which:
A) Runs the API call for all three rows
B) Creates a table with all three responses
EDIT: Based on Bing's response:
After running Bing's response, it accomplishes the first part, but the issue comes in making the table at the end.
The results for response looks like this:
[[1]]
Response [https://api.secure.com/v1/people/111322450]
Date: 2021-09-01 15:02
Status: 200
Content-Type: application/json; charset=utf-8
Size: 1.56 kB
{
"Id": 111322450,
"firstName": "Jackie",
"lastName": "Jormpjomp",
"middleName": null,
"suffix": null,
"title": "Mr.",
"contactMode": "Person",
"organizationContactCommonName": null,
"organizationContactOfficialName": null,
...
[[2]]
Response [https://api.secure.com/v1/people/findOrCreate/]
Date: 2021-09-01 15:02
Status: 201
Content-Type: application/json; charset=utf-8
Size: 58 B
{
"Id": 111323215,
"status": "UnmatchedStored"
[[3]]
Response [https://api.secure.com/v1/people/findOrCreate/]
Date: 2021-09-01 15:02
Status: 201
Content-Type: application/json; charset=utf-8
Size: 58 B
{
"Id": 111323216,
"status": "UnmatchedStored"
When I run:
resContent=map(response , httr::content, as="text")
resJSON <- map(resContent, jsonlite::fromJSON)
resTable <- map(resJSON, as.data.frame)
resTable is still stored as a List that looks like this EDIT:
$data
$data[[1]]
Response [https://api.secure.com/v1/people/111322450]
Date: 2021-09-01 18:24
Status: 200
Content-Type: application/json; charset=utf-8
Size: 1.58 kB
{
"Id": 111322450,
"firstName": "Jackie",
"lastName": "Jormpjomp",
"middleName": null,
"suffix": null,
"title": null,
"contactMode": "Person",
"organizationContactCommonName": null,
"organizationContactOfficialName": null,
...
$data[[2]]
Response [https://api.secure.com/v1/people/findOrCreate/]
Date: 2021-09-01 18:24
Status: 201
Content-Type: application/json; charset=utf-8
Size: 58 B
{
"Id": 111323215,
"status": "UnmatchedStored"
$data[[3]]
Response [https://api.secure.com/v1/people/findOrCreate/]
Date: 2021-09-01 18:24
Status: 201
Content-Type: application/json; charset=utf-8
Size: 58 B
{
"Id": 111323216,
"status": "UnmatchedStored"
$args
$args[[1]]
[1] "map(jsonlite::fromJSON)"
attr(,"type")
[1] "map"
$args[[2]]
[1] "map(as.data.frame)"
attr(,"type")
[1] "map"
attr(,"class")
[1] "jqr"
The only data I need from each response is Id
EDIT #2
Running the following:
resContent=map(response , httr::content)
resTable <- map(resContent, ~.x$Id) %>% as.data.frame()
returns the following error:
Error in as.data.frame.default(.) :
cannot coerce class ‘"jqr"’ to a data.frame
httr::POST is not vectorized. You will need to loop through each one. You can use lapply or a tidy version like:
library(purrr)
response = map(data_upsert,
~httr::POST(url = 'https://www.google.com/',
httr::add_headers(.headers=headers_upsert),
body = .x))
See if these works. Edits:
resContent=map(response , httr::content)
resTable <- map(resContent, ~.x$Id) #%>% as.data.frame()

Converting a cURL command to HTTR in R

I have a cURL command that I would like to convert to R using the httr package. The cURL command looks something like this (I obviously can't post the full scope of it, given certain confidentiality restrictions):
curl --request POST \
--url https://api.cfb.com/v1/players/110960703/stats \
--header 'Accept: application/json' \
--header 'Authorization: Basic ThisIsWhereTheAPIKeyGoes==' \
--header 'Content-Type: application/json' \
--data '
{
"statsContext": {
"statsId": "1"
},
"responses": [
{
"type": "ReceiverStats",
"QuestionId": "466069",
"ResponseId": "1898226"
}
]
}
'
I would like to convert it to an HTTR script that looks like this:
ExportIdAPI <- POST(
'https://api.cfb.com/v1/players/110960703/stats',
accept_json(),
content_type_json(),
add_headers(Authorization = Basic ThisIsWhereTheAPIKeyGoes==),
encode = "json",
body=list(statsId = 1,
QuestionId = 466069,
ResponseId = 1898226))
The problem is, this script does not work. What does work is this script:
ExportIdAPI <- POST(
'https://api.cfb.com/v1/players/110960703/stats',
accept_json(),
content_type_json(),
add_headers(Authorization = Basic ThisIsWhereTheAPIKeyGoes==),
encode = "json",
body=list(statsId = 1))
Based on how the original curl request is structured, am I just not storing it right in the body=list statement?
EDIT: I should note that this script runs perfectly fine. I just don't want it to be structured that way and I would like it to better reflect the format I'm trying to achieve from above.
headers = c(
`Accept` = 'application/json',
`Authorization` = 'Basic ThisIsWhereTheAPIKeyGoes==',
`Content-Type` = 'application/json'
)
data = ' { "statsContext": { "statsId": "1" }, "responses": [ { "type": "SurveyResponse", "QuestionId": "466069", "ResponseId": "1898226" } ] } '
res <- httr::POST(url = 'https://api.cfb.com/v1/players/110960703/stats', httr::add_headers(.headers=headers), body = data)
EDIT 2: Based on MrFlick's response, I tried running:
ExportIdAPI <- POST(
'https://api.cfb.com/v1/players/110960703/stats',
accept_json(),
content_type_json(),
add_headers(Authorization = Basic ThisIsWhereTheAPIKeyGoes==),
encode = "json",
data = list(statsContext = list(statsId = 1), responses= list(list(type="SurveyResponse", QuestionId="466069", ResponseId="1898226")))
)
But I'm met with the following error:
Response [https://api.cfb.com/v1/players/110960703/stats]
Date: 2021-08-26 20:58
Status: 400
Content-Type: application/json; charset=utf-8
Size: 144 B
{
"errors": [
{
"code": "INVALID_PARAMETER",
"text": "The body of the request is null or cannot be parsed."
}
]
The httr documentation for the POST function provides an example for how to post a json.
In your case, you could really just copy the json of the cURL command to the body parameter of the POST function:
ExportIdAPI <- POST(
'https://api.cfb.com/v1/players/110960703/stats',
accept_json(),
content_type_json(),
add_headers(Authorization = 'Basic ThisIsWhereTheAPIKeyGoes=='),
body = '
{
"statsContext": {
"statsId": "1"
},
"responses": [
{
"type": "ReceiverStats",
"QuestionId": "466069",
"ResponseId": "1898226"
}
]
}', encode = "raw")
You can have the ROST() request format the JSON for you. As a general rule named lists are turned into JSON objects {} and unnamed list become arrays []. You can do
POST(
'https://api.cfb.com/v1/players/110960703/stats',
accept_json(),
content_type_json(),
add_headers(Authorization = "Basic ThisIsWhereTheAPIKeyGoes=="),
encode = "json",
body = list(
statsContext = list(
statsId = 1
),
responses= list(
list(
type="SurveyResponse",
QuestionId="466069",
ResponseId="1898226"
)
)
)
)

AWS API in R - Added Authorization Header but getting InvalidSignatureException

I am trying to use AWS API in R. I am using R so that i can add it to an exisiting ShinyApp (which is a web application build in R).
This API: https://docs.aws.amazon.com/connect/latest/APIReference/API_GetCurrentMetricData.html
Using signature version 4:
https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html
I have added the 'Authorization' details to the header as per AMZ documentation, and the exact header works perfectly in python, but strangely not in R and returns an error saying 'InvalidSignatureException'.
My guess is that i have got something wrong with the variables in the POST function. I've quite a few different arrangements of the POST variables to try and get it to work but nothing seems to help.
This is the python code which works:
import requests
url = "https://connect.eu-central-1.amazonaws.com/metrics/current/XXXXXXX"
payload = "{\r\n \"InstanceId\" : \"XXXXXXX\",\r\n \"Filters\" : {\r\n \"Queues\" : [\r\n \"XXXXXXX\",\r\n \"arn:aws:connect:eu-central-1:XXXXXXX:instance/XXXXXXX/queue/XXXXXXX\"\r\n ]\r\n },\r\n \"CurrentMetrics\" : [\r\n {\r\n \"Name\" : \"AGENTS_ONLINE\",\r\n \"Unit\" : \"COUNT\"\r\n },\r\n {\r\n \"Name\" : \"AGENTS_AVAILABLE\",\r\n \"Unit\" : \"COUNT\"\r\n },\r\n {\r\n \"Name\" : \"OLDEST_CONTACT_AGE\",\r\n \"Unit\" : \"SECONDS\"\r\n },\r\n {\r\n \"Name\": \"AGENTS_ERROR\",\r\n \"Unit\": \"COUNT\"\r\n }\r\n ]\r\n}\r\n "
headers = {
'Content-Type': "application/json",
'X-Amz-Content-Sha256': "XXXXXXX",
'Host': "connect.eu-central-1.amazonaws.com",
'X-Amz-Date': "20190724T162517Z",
'Authorization': "AWS4-HMAC-SHA256 Credential=XXXXXXX/20190724/eu-central-1/connect/aws4_request, SignedHeaders=content-type;host;x-amz-content-sha256;x-amz-date, Signature=XXXXXXX",
}
response = requests.request("POST", url, data=payload, headers=headers)
print(response.text)
My attempt to write in R. (returns x-amzn-ErrorType: InvalidSignatureException)
library(httr)
library(jsonlite)
request_body_json <-
'{
"InstanceId" : "xxxxxxxxxx",
"Filters" : {
"Queues" : [
"xxxxxxxxxx",
"arn:aws:connect:eu-central-1:xxxxxxxxxx:instance/xxxxxxxxxx/queue/xxxxxxxxxx"
]
},
"CurrentMetrics" : [
{
"Name" : "AGENTS_ONLINE",
"Unit" : "COUNT"
},
{
"Name" : "AGENTS_AVAILABLE",
"Unit" : "COUNT"
},
{
"Name" : "OLDEST_CONTACT_AGE",
"Unit" : "SECONDS"
},
{
"Name": "AGENTS_ERROR",
"Unit": "COUNT"
}
]
}'
hdrs <- list(
'Content-Type'= "application/json",
'X-Amz-Content-Sha256'= "XXXXXXX",
'Host'= "connect.eu-central-1.amazonaws.com",
'X-Amz-Date'= "20190724T162517Z",
'Authorization'= "AWS4-HMAC-SHA256 Credential=XXXXXXX/20190724/eu-central-1/connect/aws4_request, SignedHeaders=content-type;host;x-amz-content-sha256;x-amz-date, Signature=XXXXXXX"
)
a <- POST(
url = "https://connect.eu-central-1.amazonaws.com/metrics/current/xxxxxxxxxx"
,do.call(add_headers,hdrs)
,verbose(info = TRUE)
,body = request_body_json
,encode = "json"
)
Fixed and added the authorisations steps in too.
# Librarys used
library(httr)
library(jsonlite)
library(aws.signature)
#gather variables
host <- "connect.eu-central-1.amazonaws.com"
sha <- "xxxx"
amzdate <- format(Sys.time(), "%Y%m%dT%H%M%SZ",tz = "UTC")
payload <-
'{
"InstanceId" : "xxxx-xxxx-xxxx-xxxx-xxxx",
"Filters" : {
"Queues" : [
"xxxx-xxxx-xxxx-xxxx"
]
},
"CurrentMetrics" : [
{
"Name" : "OLDEST_CONTACT_AGE",
"Unit" : "SECONDS"
},
{
"Name": "CONTACTS_IN_QUEUE",
"Unit": "COUNT"
}
]
}'
content_type <-"application/json"
url_api <-"https://connect.eu-central-1.amazonaws.com/metrics/current/xxxx-xxxx-xxxx-xxxx"
region <- "eu-central-1"
service <- "connect"
verb <- "POST"
action <- "/metrics/current/xxxx-xxxx-xxxx-xxx-xxxx"
key <- "xxxx"
secret <- "xxxx"
#headers so far (can't add signature yet)
hdrs <- list('Content-Type' = content_type,
Host = host,
'x-amz-content-sha256' = sha,
'x-amz-date' = amzdate)
#get v4 signature
sig <- signature_v4_auth(datetime = amzdate,
region = region,
service = service,
verb = verb,
action = action,
query_args = list(),
canonical_headers = hdrs,
request_body = payload,
key = key,
secret = secret,
session_token = NULL,
query = FALSE,
algorithm = "AWS4-HMAC-SHA256")
#add signature header to header
auth <- sig$SignatureHeader
a <- httr::VERB(verb = "POST"
,url = url_api
,encode = 'json'
,content_type_json()
,body = payload
,httr::add_headers(
'Content-Type' = content_type,
Authorization = auth,
Host = host,
`X-Amz-Content-Sha256` = sha,
`X-Amz-Date` = amzdate)
)
results <- content(a,"parsed")

R interface to imgflip API (https://api.imgflip.com/). Always ends in with the failure "No texts supplied"

A simple post using the httr package always ends with an error?
# Post a random meme and print its url
res <- httr::POST(
url = "https://api.imgflip.com/caption_image",
body = list(
template_id = "61579",
username = "<my-username>",
password = "<my-password>",
text0 = "abc",
text1 = "def",
font = "impact",
max_font_size = "50"
),
httr::verbose(),
encode = "json"
)
httr::content(res, "text")
Im not sure how to do it in R, but I tried using postman and sending the request as JSON do not work you have to send it as a form-data:

Resources