Using the vendor's supplied Python code, I've hacked a working version that runs in the Alteryx Python tool (see below). It's slow and I'm curious -- how could I convert this code into a call from the Download tool to get my token? For example, I'm not finding online documentation about how the requests library handles the auth piece.
from ayx import Alteryx
import requests
import json
import pandas as pd
#client (subscriber application) id and secret
client_id = 'xxx'
client_secret= 'xxx'
data = {'grant_type': 'client_credentials'}
access_token_response = requests.post('https://oauth.machineq.net/oauth2/token',
data=data,
allow_redirects=False,
auth=(client_id, client_secret))
tokens = json.loads(access_token_response.text)
access_token = tokens['access_token']
token = "Bearer " + access_token
data = [token]
df = pd.DataFrame(data)
Solved! Go to Solution.
The download tool can have headers and payload values either hard coded into it or fed into it from upstream. Here is a helpful article that walks you through API calls with the download tool: https://community.alteryx.com/t5/Alteryx-Designer-Knowledge-Base/APIs-in-Alteryx-cURL-and-Download-T...
Thanks Brandon! I have been successfully using the Download tool (thanks to your referenced article as well as other very useful Community posts) to scrape data from a few different sites. There is still a lot of trial and error, but I'm getting decent at figuring out what belongs in the Header section and what belongs in Payload.
Authentication is still really tricky. For example, my vendor's documentation for authentication is limited to some messy Python, which I got to work in the Python tool even though I don't understand exactly why it works. That is the code I have shared.
Given that the Python requests library is pretty much the de facto standard for http requests in Python, I thought the mapping and manipulation of some of these parameter might be something someone in the Alteryx community had already worked out. In particular, I'm puzzled by how the requests library is manipulating the client_id and client_secret inputs via "auth=" to generate the token. For example, I've tried the concatenation of the two with a Base64 conversion, but it has not taken.
I've noted that other Community members just rely on the Python tool to handle API calls. My first choice is Download.
So your URL will be https://oauth.machineq.net/oauth2/token
This will be fed in via a Text Input tool to the Download tool. Then the auth=(client_id, client_secret)) takes a client ID and secret and creates a base64 encoded string which is passed in as an authentication header. The data = {'grant_type': 'client_credentials'} refers to a payload name/value pair where it is specifying the grant type.
Once this call is passed to the URL, it will return back a JSON response with the bearer token in the Download Data column.
I believe that to create your clientID/clientSecret base64 encoded string for your auth header you will need to do the following:
Create a new string that is your client ID and client Secret separated by a colon like so: ClientID:ClientSecret. Then you will want to pass this through a base64 encoding tool. Then you want to take the encoded string and create a new string with the word Basic then a space then the encoded string from the previous step. So something like Basic asd384ASDGH
Can you give this a try and let me know if it works for you?
Thanks for the response Brandon. Here is my implementation of your suggestions:
My workflow (which I also attached):
My Text Input:
My response message:
I also added "allow_redirects" as a parameter (since it is in the Python call) which I included in both the Headers and Payload sections. I also tried permutations using "auth" vs "Authorization" in addition to "allow_redirects".
I got same response message for all.
BTW -- I just got an iterative macro working today for an API download requiring pagination. It worked thanks to a lot of your posts and comments as well as some others.
A bit tricky, but you need to pass in a field called Authorization, not auth and that should do the trick
I am using dummy credentials so getting an invalid credentials error now, but I take that as a good sign. I believe that this should work once you load yours in. I have attached a new version of the workflow
As a followup... some APIs can be VERY picky about extra headers or payload values (even being case sensitive) passed in so you were likely very close in one of your attempts. Fingers crossed that this gets you the rest of the way there!
Worked!!! Yeah, this syntax is the pickiest I've seen since JCL....does that date me?
Thanks a ton Brendon!
Happy to help!