Python - Foursquare API "Missing Auth Credentials'" userless search? - python

I am trying to use the foursquare API for the first time and have not been able to get a 200 status code no matter what I tried. Using directly the code foursquare provides in its docs, I attempt to do a userless request, replacing my client ID and secret where necessary.
def places_search(term,street, zipcode):
params = dict(
client_id='MY_CLIENT_ID',
client_secret='MY_CLIENT_SECRET',
v='20181122',
near=street + 'New York, NY ' + zipcode,
query=term,
limit=1
)
url = "https://api.foursquare.com/v2/venues/explore"
resp = requests.get(url=url, params=params)
#grabbing the JSON result
data = json.loads(resp.text)
return data
print(places_search("starbucks","3rd avenue","10009"))
I get the following error code:
{'meta': {'code': 400, 'errorType': 'invalid_auth', 'errorDetail': 'Missing access credentials. See https://developer.foursquare.com/docs/api/configuration/authentication for details.', 'requestId': '5bf6cbb26a607137bc33b7f2'}, 'response': {}}
I find it odd given my request is userless and matches exactly the way they outline it in the docs... Would you have an idea what I am doing wrong?
Thanks,

As per the documentation:
To make a userless request, specify your consumer key’s Client ID and
Secret instead of an auth token in the request URL.
Like this:
https://api.foursquare.com/v2/venues/search?ll=40.7,-74&client_id=CLIENT_ID&client_secret=CLIENT_SECRET&v=YYYYMMDD
Since you are passing the credentials as the request parameters, the server cannot authenticate you.

Related

Strava getting data from api

I was following tutorial https://towardsdatascience.com/using-the-strava-api-and-pandas-to-explore-your-activity-data-d94901d9bfde and this github https://github.com/franchyze923/Code_From_Tutorials/blob/master/Strava_Api/strava_api.py (proposed in tutorial).
And cannot find solution to problem below, I found something about scope but do not know how to use it, thus I am here seeking help
{'message': 'Authorization Error',
'errors': [{'resource': 'AccessToken',
'field': 'activity:read_permission',
'code': 'missing'}]}
import requests
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
auth_url = "https://www.strava.com/oauth/token"
activites_url = "https://www.strava.com/api/v3/athlete/activities"
payload = {
'client_id': "XXXXXX",
'client_secret': 'XXXXXX',
'refresh_token': 'XXXXXXXXX',
'grant_type': "refresh_token",
'f': 'json'
}
print("Requesting Token...\n")
res = requests.post(auth_url, data=payload, verify=False)
access_token = res.json()['access_token']
print("Access Token = {}\n".format(access_token))
activities_url = f"https://www.strava.com/api/v3/athlete/activities?" \
f"access_token={access_token}"
print('RESTful API:', activities_url)
# Get the response in json format
response = requests.get(activities_url)
activity = response.json()
I tried to change payload and find another solution but results were always as above. I receive my access token though
Access Token = 61766e12XXXX062XXX2a2eXXXXXXXXXX
first of all, scope in strava api is something that represents what types of access are being granted to the app from a strava user account. it can be read user's public activity, read private activity, write etc.
in case of getting authenticated: strava uses oAuth2 and has a very detailed guideline to get started for the first time. You may check their official doc page: (https://developers.strava.com/docs/authentication/#oauthoverview).
the process is explained in very detailed and should be enough for your problem.

Zoho CRM API: Python request-based POST or GET authentication + insertion of contacts

The Task##
A django application that allows users to sign up and once the user clicks on the account activation link, Zoho CRM is receiving the data and a contact is created in the CRM section.
The Problem
I am currently working on an absolute masterpiece - the ZOHO API.
I am struggling to set up the native Python code that uses POST/GET requests.
Regarding the zcrmsdk 3.0.0, I have completely given up on this solution unless somebody can provide a fully functional example. The support simply blames my code.
The documentation I consulted:
https://www.zoho.com/crm/developer/docs/api/v2/access-refresh.html,
https://www.zoho.com/crm/developer/docs/api/v2/insert-records.html
Since the post request in postman API works fine I do not understand why it does not work in python code
My approach
Generate an self-client API code on: https://api-console.zoho.com/
Insert that code on Postman and retrieve the access or refresh token
Use this access token in an add_user_contact function that is defined in the documentation
It works! Response is success and it is in Zoho CRM
The permsissions scope I am using is: ZohoCRM.modules.contacts.ALL, ZohoCRM.users.ALL, ZohoCRM.modules.deals.ALL, ZohoCRM.modules.attachments.ALL, ZohoCRM.settings.ALL, AAAserver.profile.ALL
Picture of Post Man POST REQUEST
My own Code
def authenticate_crm():
"""
access to response object id:
response_object.get('data')[0].get('details').get('id')
"""
url = 'https://accounts.zoho.com/oauth/v2/token'
headers = {
'Content-Type': 'application/x-www-form-urlencoded'
}
# one time self-client token here -
request_body = {
"code": "1000.aa8abec144835ab79b8f9141fa1fb170.8ab194e4e668b8452847c7080c2dd479",
"redirect_uri": "http://example.com/yourcallback",
"client_id": "1000.H95VDM1H9KCXIADGF05E0E1XSVZKFQ",
"client_secret": "290e505ec52685fa62a640d874e6560f2fc8632e97",
" grant_type": "authorization_code"
}
response = requests.post(url=url, headers=headers, data=json.dumps(request_body).encode('utf-8'))
if response is not None:
print("HTTP Status Code : " + str(response.status_code))
print(response.json())
I am essentially struggling to convert the Postman API request to a Python request to get the token as part of the workflow. What am I doing wrong here?
The documentation states: Note: For security reasons, pass the below parameters in the body of your request as form-data. (access-refresh link) but passing it in postman as form-data breaks the call completely.
According to their own documentation (which is convoluted, contradictory and full of outdated screenshots) the authentication key is needed only once.
Once the request from above runs, I would take the response in the third image and use the refresh key to add the contact.
I am also open to a solution with the SDK 3.0.0, if anybody can help.
I solved it!
I have changed this line:
response = requests.post(url=url, headers=headers, data=json.dumps(request_body).encode('utf-8'))
to this and added some return statement:
payload = '1000.6d9411488dcac999f02304d1f7843ab2.e14190ee4bae175debf00d2f87143b19&' \
'redirect_uri=http%3A%2F%2Fexample.com%2Fyourcallback&' \
'client_id=1000.H95VDM1H9KCXIADGF05E0E1XSVZKFQ&' \
'client_secret=290e505ec52685fa62a640d874e6560f2fc8632e97&'\
'grant_type=authorization_code'
response = requests.request(method="POST", url=url, headers=headers, data=payload)
if response is not None:
print("HTTP Status Code : " + str(response.status_code))
# print(response.text)
print(response.json())
# catch access and refresh token
at = response.json().get('access_token')
rt = response.json().get('refresh_token')
return at, rt
I do not understand why that is different but that fixed it and I could retrieve keys from ZOHO.

Python HTTP Requests

The following figure shows the TMDb endpoint documentation by which a client can request a movie or TV show be added to a user's watchlist, where the user has previously established a session_id.
Based on the developer documentation, and using the (fictional) values of the various pieces that need to be part of the request and that are presented in the following table:
Question !!
Can you please provide the HTTP for this request? You can present the request in a line-oriented fashion, and without needing to note linefeeds or carriage returns.
If you are asking about writing code, the following lines could be useful for you:
import requests
account_id = 12345
url = 'https://YOUR_URL.com/accout/' + account_id + '/watchlist'
payload = {'media_type': 'movie', 'media_id': 777, 'watchlist': 'true'}
x = requests.post(url, data = payload)
print(x.text)
Where is:
requests.post(url, data={key: value}, json={key: value} -> string, args)

gae appengine + auth0 localhost

Goodmorning,
i have some trouble in wrinting a callback method that it's used to login to my web app (hosted in gae)
#app.route('/callback')
def callback_handling():
env = os.environ
code = request.args.get('code')
json_header={'Content-Type': 'application/x-www-form-urlencoded'}
token_url = "https://{domain}/oauth/token".format(domain='mydomain')
token_payload = {
'client_id': 'myid',
'client_secret': 'mysecret',
'redirect_uri': 'http://localhost:8080/callback',
'code': code,
'grant_type': 'authorization_code'
}
encoded = urllib.urlencode(token_payload)
user_url = "https://{domain}/userinfo?access_token={access_token}"\
.format(access_token=token_info['access_token'])
user_info = urlfetch.Fetch(user_url, method=urlfetch.GET, headers=json_header)
session['profile'] = user_info
return redirect('/dashboard')
i costantly get error 401 unathorized..from debug console any ideas to fix?..reading over the internet i understand that i must use urlfetch from gae because is the only lib allowed in gae (requests does not in localhost)..
In your code, is this : "https://{domain}/userinfo" your own endpoint or is this some third-party that you are trying to auth with?
Either way the 401 unauthorised seems legit, and being thrown by the endpoint, If "https://{domain}/userinfo" is pointing to your own endpoint then being able to see that logic would help, alternatively if it is a third-party I would recommend testing your request with something like postman, to see what your request looks like, headers etc. and make sure that it matches what the endpoint is expecting.
Hope this helps.

How do I insert a row in my google fusion table using Python

I am working on a project and part of it involves inserting rows in to a Google Fusion Table for the Project from a python script. I have spent the last couple days trying to figure out just how to do that and I am officially confused.
My research seems to indicate that I need to use Oauth 2.0 to access the API. In doing so I can successfully get an access token but I can't seem to successfully get a refresh token. I'm not sure if this is going to hamper my ability to successfully integrate access to my Fusion Table with my Python code.
The second problem I am having is that I don't really understand how exactly to code inserting a row in my table. Most of the material I have found on it is from the deprecated Fusion Tables SQL API and I don't fully understand the new way of doing it.
I'm a beginner at this sort of thing and any direction to help me is very much appreciated!
Edit:
So the code I have working so far looks like this:
client_id = "<client_i>"
client_secret = "<client_secret>"
table_id = "<table_id>"
access_token = ""
refresh_token = "<refresh_token>"
# the refresh token is used to request a new access token
data = urllib.urlencode({
'client_id': client_id,
'client_secret': client_secret,
'refresh_token': refresh_token,
'grant_type': 'refresh_token'})
request = urllib2.Request(
url='https://accounts.google.com/o/oauth2/token',
data=data)
request_open = urllib2.urlopen(request)
response = request_open.read()
request_open.close()
tokens = json.loads(response)
access_token = tokens['access_token']
# Read the table
request_read = urllib2.Request(
url='https://www.google.com/fusiontables/api/query?%s' % \
(urllib.urlencode({'access_token': access_token,
'sql': 'SELECT * FROM table_id'})))
request_open = urllib2.urlopen(request_read)
response = request_open.read()
request_open.close()
print response
And my code for trying to insert a new row into my table:
date = str(datetime.now().date())
time = str(datetime.now().time())
query = 'INSERT INTO table_id (Date,Time,Saskatoon,Regina,MeadowLake)VALUES(date,time,60.01,60.02,59.99)'
data = urllib2.Request(
url='https://www.google.com/fusiontables/api/query?%s' % \
(urllib.urlencode({'access_token': access_token,
'sql': query})))
request_open = urllib2.urlopen(data)
When I run this i get
HTTP Error 400: HTTP GET can only be used for select queries.
I am know I'm supposed to be making a POST not a GET for the INSERT, I'm just not sure what needs to change in my code for that to happen.
Sorry for being a noob.
2ND EDIT:
Sorry for making this longer but I feel it is pertinent to show where I've gotten so far. I switched to the library requests and things have gotten somewhat easier however I still haven't successfully made a POST. My new code for importing rows is as follows:
def importRows(self):
print 'IMPORT ROWS'
date = str(datetime.now().date())
time = str(datetime.now().time())
data = {'Date': date,
'Time': time,
'Saskatoon': '60.01',
'Regina': '59.95'}
url = 'https://www.googleapis.com/upload/fusiontables/v1/tables/%s/import/%s' % \
(tableid, self.params) # self.params is access token
importRow = requests.post(url, params=data)
print importRow.status_code
print importRow.text
Which gives me
400
{
"error": {
"errors": [
{
"domain": "fusiontables",
"reason": "badImportInputEmpty",
"message": "Content is empty."
}
],
"code": 400,
"message": "Content is empty."
}
}
If your application needs offline access to a Google API, then the request for an authorization code should include the access_type parameter, where the value of that parameter is offline.
https://developers.google.com/accounts/docs/OAuth2WebServer#offline
Then, to obtain an access token using the refresh token you send a POST request including grant_type with value refresh_token.
Basically, the way SQL works is you send POST requests using a subset of SQL statements https://www.googleapis.com/fusiontables/v1/query?sql=STATEMENT_HERE
Refer to
https://developers.google.com/fusiontables/docs/v1/reference/query
https://developers.google.com/fusiontables/docs/v1/sql-reference
Edit:
Since you are using urllib2 without a data parameter, it defaults to GET. To fix this you should either use another HTTP library that allows for explicitly specifying method (like requests or httplib) or do something like this:
query = "INSERT INTO %s(EXAMPLE_COL1,EXAMPLE_COL2) VALUES"\
"('EXAMPLE_INFO1','EXAMPLE_INFO2')" % table_id # Single quotes
opener = urllib2.build_opener(urllib2.HTTPHandler)
request = urllib2.Request('https://www.google.com/fusiontables/api/query?%s' % \
(urllib.urlencode({'access_token': access_token,
'sql': query})),
headers={'Content-Length':0}) # Manually set length to avoid 411 error
request.get_method = lambda: 'POST' # Change HTTP request method
response = opener.open(request).read()
print response
Important to notice:
Monkey patch the method to do what we want (POST with an empty body) otherwise we would receive HTTP Error 400: HTTP GET can only be used for SELECT queries.
Manually specify that we do not have a body (Content-Length is 0) otherwise we would receive HTTP Error 411: Length Required.
Must use double quotes with single quotes inside or escape the inner quotes to submit strings via the query. In other words, "INSERT INTO %s(EXAMPLE_COL1,EXAMPLE_COL2) VALUES(EXAMPLE_INFO1,EXAMPLE_INFO2)" % table_id does not work.
If we tried to use the previous line we would get something like HTTP Error 400: Parse error near 'SOME_STRING' (line X, position Y)
See for info on changing method with urllib2:
Is there any way to do HTTP PUT in python

Categories