Big_Ozzy
Big_Ozzy

Reputation: 275

POST request using HTTR

I am trying to request data using the httr package. Following this format:

args <- list(metrics = c(list(name = "Jobs.2018",as = "Jobs 2018")),
             constraints = list(dimensionName ="Area",
                                map = list("Latah County ID" = c(16057))))

test <- POST(url =
"https://agnitio.emsicloud.com/emsi.us.demographics/2018.3",
     add_headers(`authorization` = paste("bearer",token)),
    add_headers(`content-type` ="application/json"),
    body = toJSON(args,auto_unbox = TRUE),
    verbose())

I keep getting a 400 Bad Request error with everything I have looked up and tried. Do I need to add something to the arguments that I am just not finding?

P.S. I am sorry that this isn't a repeatable example

Upvotes: 1

Views: 2857

Answers (1)

hrbrmstr
hrbrmstr

Reputation: 78832

We'll assume (a bad thing but necessary for an answer) that you obtained token by issuing a prior POST request as indicated on the linked API page and then properly decoded the JSON web token into token.

If you did that properly, then one next likely possibility is malformed body data in POST request.

When I look at a sample API call:

curl --request POST \
  --url https://agnitio.emsicloud.com/emsi.us.industry/2018.3 \
  --header 'authorization: bearer <access_token>' \
  --header 'content-type: application/json' \
  --data '{ "metrics": [ { "name": "Jobs.2017", "as":"2017 Jobs" }, { "name": "Establishments.2017" } ], "constraints": [ { "dimensionName": "Area", "map": { "Latah County, ID": ["16057"] } }, { "dimensionName": "Industry", "map": { "Full Service Restaurant s": ["722511"] } } ] }'

that sample JSON looks like this pretty-printed:

{
  "metrics": [
    {
      "name": "Jobs.2017",
      "as": "2017 Jobs"
    },
    {
      "name": "Establishments.2017"
    }
  ],
  "constraints": [
    {
      "dimensionName": "Area",
      "map": {
        "Latah County, ID": [
          "16057"
        ]
      }
    },
    {
      "dimensionName": "Industry",
      "map": {
        "Full Service Restaurants": [
          "722511"
        ]
      }
    }
  ]
}

Yours looks like:

{
  "metrics": {
    "name": "Jobs.2018",
    "as": "Jobs 2018"
  },
  "constraints": {
    "dimensionName": "Area",
    "map": {
      "Latah County ID": 16057
    }
  }
}

when it needs to look more like this:

{
  "metrics": [
    {
      "name": "Jobs.2018",
      "as": "Jobs 2018"
    }
  ],
  "constraints": [
    {
      "dimensionName": "Area",
      "map": {
        "Latah County ID": [
          "16057"
        ]
      }
    }
  ]
}

To do that, we need to use this list structure:

list(
  metrics = list(
    list(
      name = jsonlite::unbox("Jobs.2018"),
      as = jsonlite::unbox("Jobs 2018")
    )),
  constraints = list(list(
    dimensionName = jsonlite::unbox("Area"),
    map = list("Latah County ID" = c("16057"))
  ))
) -> args

Note especially that the API expects that map ID JSON data element to be character and not integer/numeric.

Now, we can make the POST request like this (spaced out for answer readability as it has embedded comments):

httr::POST(

  url = "https://agnitio.emsicloud.com/emsi.us.demographics/2018.3",

  httr::add_headers(
    `authorization` = sprintf("bearer %s", token)
  ),

  encode = "json", # this lets' httr do the work for you

  httr::content_type_json(), # easier than making a header yourself

  body = args,

  httr::verbose()

) -> res

That should work but b/c it's a closed API without free registration I cannot test it.

Upvotes: 5

Related Questions