Python API with Response - Authentication - python

Working with the Streak CRM API by using Python and Request. I am getting 4XX errors depending on how I phrase the request. (Examples below)
response = requests.get('https://www.streak.com/api/v1/pipelines?api-key=xxxxxxxx')
response.headers['Content-Type'] = 'application/json'
print(response.status_code)
print(response.content)
Result: 401 "Authentication Required for Streak API: try HTTP Basic Auth or cookie auth"
If I add ".json" after the file path:
requests.get('https://www.streak.com/api/v1/pipelines.json?api-key=xxxxxxxx')
Result: 400 "Invalid API path specified" So I am assuming that I was authenticated but just have a poorly defined file path.
But if I use the same file path and credentials entered in the terminal:
curl https://www.streak.com/api/v1/pipeline -u xxxxxxxx:
Works like a charm.
Why would the file path work in the terminal but not in python? Why do I need to add .json to my file path? New to using APIs so any help is appreciated. Thanks.

I don't know why, but rephrasing it like below worked. I received status code 200:
response = requests.get('https://www.streak.com/api/v1/pipelines', auth=('xxxxxx',''))
The API key goes in the username parameter, and the password parameter is left blank.

The error message tells you all you need to know. For Basic Auth you put the authorization info in the request headers, not in the url. When you add .json to a endpoint, that usually means that you want a JSON response. The reason why it worked with curl is because curl's -u flag is setting the Auth header.

Related

Thoughtspot: API calls to fetch metadata via Python

I'm trying to fetch metadata from thoughtspot. I am able to call the url using browser and fetch the data. But here I'm trying to achieve it via python program. According to thougthspot documentation. I have to enable trusted authentication and pass my secret key & username to obtain a token which I can use in my program.
https://developers.thoughtspot.com/docs/?pageid=api-auth-session
my username : username#username.com
secret key : secret-key
Below is my code:(generated by postman)
import requests
url = "https://<ThoughtSpot-host>/callosum/v1/tspublic/v1/session/auth/token?auth_token=secret-key&access_level=FULL&username=username#username.com"
payload={}
headers = {}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
I'm getting Bad request error. Anyone here using thoughtspot over this issue. Appreciate your support very much.
Error I'm getting:
{"type":"Bad Request","description":"The server could not understand the request due to invalid syntax."}
I can fetch data by calling the api using a web-browser. Below url returns list of all meta-data objects. I want to achieve this using a python program (I have to authenticate first & call the below URL - Authentication step is not working for me when I tried to follow the documentation)
https://<ThoughtSpot-host>/callosum/v1/tspublic/v1/metadata/list
Did you try changing the url so that it includes the domain name?
Also post the error you are getting. And a screenshot of a working request would be great!

HTTP 401 error when accessing WebDAV with Python client

I've built a Python application that generates a inventory CSV file, and I want to upload that file to my store through BigCommerce's WebDAV application. I'm using the following Python client to access the WebDAV.
https://pypi.org/project/webdavclient3/
I can access my store and add files to the content folder with CyberDuck, but I get a HTTP 401 error when I try to access it from my Python script. Here is what I'm using to connect with WebDAV.
# webDAV upload to BigCommerce
options = {
'webdav_hostname': "https://mystore.com",
'webdav_login': "email#email.com",
'webdav_password': "password",
'webdav_root': "/dav/",
}
client = Client(options)
print("Exist:", client.check("/content/mytest")) # returns "Exist: False"
print(client.list())
print(client.free())
print("HERE")
I get an error at client.list() that reads
Request to https://mystore.com/dav/ failed with code 401 and message:
<?xml version="1.0" encoding="utf-8"?>
<d:error xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns"><s:exception>Sabre\\DAV\\Exception\\NotAuthenticated</s:exception><s:message>No 'Authorization: Digest' header found. Either the client didn't send one, or the server is misconfigured</s:message>
</d:error>
I guess it's saying my login and/or password is incorrect or there is no authentication? But how come I could log in through CyberDuck with the same credentials?
I saw someone asking about a similar problem in the following link, and I've tried the suggestions from Karen. None of them worked.
https://support.bigcommerce.com/s/question/0D51B00004G4XfYSAV/unable-to-access-upload-files-or-create-directory-through-webdav-api
I know this is 6 months old, but I figured I'd still post the solution for visibility when others try to do this.
The webdavclient library does not support HTTP Digest Authentication which is required to upload to the WebDAV. You can achieve this using the basic Python Requests library combined with the HTTPDigestAuth library.
Sample code:
import requests
from requests.auth import HTTPDigestAuth
# Below, put the URL of your BigCommerce WebDAV, including the file name you want to create/upload
# If you're uploading a CSV that you want to use as a product import, you will put it in the /dav/import_files/ directory.
url='https://store-abcdefg123.mybigcommerce.com/dav/import_files/products_upload_filename.csv' # example
# Local filename relative to this python script to upload
files = open('products_upload_filename.csv', 'rb')
# BigCommerce WebDAV login credentials.
# Found under Server Settings > File Access (WebDAV)
usern = 'youremail#email.com' # username
passw = 'password123' # password
# Make the file upload request
r = requests.request('PUT', url=url, data=files, auth=HTTPDigestAuth(usern, passw))
r.status_code
print(r.headers)
print(r.status_code)
I had the same issue and it was from the AuthType in the VirtualHost (/etc/httpd/conf.d/webdav.conf). I switched from Digest to Basic to fix it.

curl to python requests error: "no api key supplied"

I'm trying to do a curl command with python requests. As far as I can tell I'm doing everything correctly but the website won't recognize the api key no matter how I try to include it. Basically, the site I'm trying to reach wants the api key put in the beginning of the url. When I do this with curl, it works perfectly. When I try it via python requests, however, it doesn't work. It also doesn't work to send it in as a key-value pairing in dictionary.
This works
curl -H "Content-Type:application/json" -d '{"ndbno":["11124"],"type":"f"}' [API KEY]#api.nal.usda.gov/ndb/V2/reports
and here's the requests code:
import requests
headers = {'Content-Type': 'application/json',}
data = '{"ndbno":["11124"],"type":"f"}'
response = requests.post('http://[API KEY]#api.nal.usda.gov/ndb/V2/reports', headers=headers, data=data)
The result from this is a json response containing the message: "{'error': {'code': 'API_KEY_MISSING', 'message': 'No api_key was supplied. Get one at http://api.nal.usda.gov:80'}}
"
It also doesn't work if I remove the [API KEY] from the url and add it to the data dictionary as "api_key":"[API KEY]"
BTW I'm not passing the key in as a list or anything, I just didn't want to post the physical key in my question.
I'm a total newb to python and stackoverflow, but I've done my due diligence and have been searching out answers and testing different ways to format the request for a few hours now. Any help is greatly appreciated!
Looking at the PubAG API, it appears that you can simply pass the api_key in the URL query string. I'd assume it's the same for the API you're using, but a cursory search yielded no documentation.
Try:
https://api.nal.usda.gov/ndb/V2/reports?api_key=[API_KEY]
response = requests.post('https://api.nal.usda.gov/ndb/V2/reports?api_key=[API_KEY]', headers=headers, data=data)
I don't have an API key to try this out with, but navigating to https://api.nal.usda.gov/ndb/V2/reports?api_key=asdfds in my browser gives me an invalid API key error, which suggests that the endpoint recognizes that I've given an API key.
It's probably because requests does not parse the API KEY from the URL, try this:
response = requests.post('http://api.nal.usda.gov/ndb/V2/reports', headers=headers, data=data, auth=(API_KEY, ''))
This passes it using Basic Authentication (Authorization header) which is the same behavior that curl does when parsing the URL.
Normally in Basic Auth you would have the username and the password. E.g:
auth=('<username>', '<password>')
Since this API only seems to care about the username, I have left the password as blank.

403 (Forbidden) error when using Fortnite Tracker api with urllib.request

I am attempting to get user statistics from the Fortnite tracker api.
I have an api key and am using the correct url as indicated in the documentation
Template url:
https://api.fortnitetracker.com/v1/profile/{platform}/{epic-nickname}
Desired url:
https://api.fortnitetracker.com/v1/profile/pc/xantium0
If I use this link in browser I get {"message":"No API key found in request"} (as I have not passed the API key) so the link should be correct. Also if I do not pass the api key with urllib then I still get a 403 error.
I have checked out how to pass a header in a request: How do I set headers using python's urllib?
and so far have this code:
import urllib.request as ur
request = ur.Request('https://api.fortnitetracker.com/v1/profile/pc/xantium0', headers={'TRN-Api-Key' : 'xxx'})
response = ur.urlopen(request)
print(response.read())
When run I get this error:
urllib.error.HTTPError: HTTP Error 403: Forbidden
403 checks out as:
HTTP 403 is a standard HTTP status code communicated to clients by an HTTP server to indicate that the server understood the request, but will not fulfill it. There are a number of sub-status error codes that provide a more specific reason for responding with the 403 status code.
https://en.wikipedia.org/wiki/HTTP_403
The response is the same if I don't pass the api key in the header.
I can only think of three reasons this code is not working:
I have passed the wrong header name (i.e. it's not TRN-Api-Key)
My code is incorrect and I am not actually passing a header to the server
I have been banned
My problem is that I think my code is correct:
From the documentation:
urllib.request.Request(url, data=None, headers={}, origin_req_host=None, unverifiable=False, method=None)
I have passed the url and I have passed the headers (wihout confusing with the data arguement). The api documentation also mentions it should be passed in the headers.
I am also quite sure I need to use the TRN-Api-Key as it is shown in the api documentation:
TRN-Api-Key: xxx
Also in this question (using Ruby):
header = {
key: "TRN-Api-Key: Somelong-api-key-here"
}
Or I have been banned (this is possible although I got the key 15 minutes ago) is there a way to check? Would this error be returned?
What is preventing me from getting the user statistics?
Try using requests, a pythonic, fast and widely used module.
import requests
url = 'https://api.fortnitetracker.com/v1/profile/pc/xantium0'
headers = {
'TRN-Api-Key' : 'xxx'
}
response = requests(url, headers=headers)
print('Requests was successful:', response.ok)
print(response.text)
If it doesn't work you can visit the url with your browser, then check the requests:
in Firefox press Cntrl+Shift+E, in Chrome Cntrl+E (or Inspect with Cntrl+Shift+I and then go to Network). Press on "https://api.fortnitetracker.com/v1/profile/pc/xantium0" and change the headers. On Firefox there's the button Modify and resend. Check the response and eventually, try to change the header api key name.
Hope this helps, let me know.

Using Python request post method but getting 401 response code

I am using Python request module post method to process json data, like so.
r = requests.post(url,data=json.dumps(payload),headers=headers)
However I am getting response[401]. Does it mean I need to first authorize it
by adding login first?
A 401 response, as you noticed, means that you need to authenticate in order to make the request. How you do this depends on the auth system in place, but your comment "I use HTTPBasicAuth(user, password) that give me response code of 200" suggests that it's just Basic Auth - which is easy to deal with in requests.
Anywhere you do a requests call, add the kwarg auth=(USERNAME, PASSWORD) - so for your example above, you'd do r = requests.post(url,data=json.dumps(payload),headers=headers, auth=(USERNAME, PASSWORD)) (replacing USERNAME and PASSWORD with the right values, as shown here.

Categories

Resources