Unable to POST to Grafana using Python3 module requests - python-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}

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.

What is response headers format to output OpenAPI docs on FastAPI

Let me know someone way to output header name
I wrote response the following code,
responses={
st.HTTP_200_OK: {
"model": main_response_data,
"description": "main response data",
"headers": [{"header_name":"response_key", "description": "Response key", "type": "string"}]
},
But after run, OpenAPI document output "0" at header name
headers
Name Description Type
------------------------------------------
0 Response key string
headers should be a dictionary with the HTTP-header as a key:
"headers": {"response_key": {"description": "Response key", "type": "string"}}
When you define it as a list instead, the index will be used as the key - i.e. why you're getting 0.

Find and delete Discord webhook message

I'm using a Discord webhook to send information which may later be invalidated, so I want to be able to delete it. To do this i use these endpoints:
First i make a post request to send a message:
POST /webhooks/{webhook.id}/{webhook.token}
And then i want to do a delete request to remove the message again:
DELETE /webhooks/{webhook.id}/{webhook.token}/messages/{message.id}
However I don't have the ID of the message i want to delete, since no response is given to the first POST request which is always an empty 204 response. Is it possible to get the message id?
Any help would be appreciated.
Per this reddit post:
If you need to reference a message ID of a webhook message you sent, you can add ?wait=true to the end of the URL which will give you the message data (including the ID) instead of a 204 (No Content) when you don't include the query parameter.
So if you send your normal POST request to your url like this: POST /webhooks/{webhook.id}/{webhook.token}, add ?wait=true to the end of that. Then you will get back data like this:
{
"id": "MESSAGEID",
"type": 0,
"content": "This is a test",
"channel_id": "CHANNELID",
"author": {
"bot": true,
"id": "AUTHORID",
"username": "USERNAME",
"avatar": "AVATARID",
"discriminator": "0000"
},
"attachments": [],
"embeds": [],
"mentions": [],
"mention_roles": [],
"pinned": false,
"mention_everyone": false,
"tts": false,
"timestamp": "2021-11-13T18:10:24.412000+00:00",
"edited_timestamp": null,
"flags": 0,
"components": [],
"webhook_id": "WEBHOOKID"
}

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

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