Get Inspire insights from former attendees in our AMA discussion thread on Inspire Buzz. ACEs and other community members are on call all week to answer!

Alteryx Server Discussions

Find answers, ask questions, and share expertise about Alteryx Server.

How to Run a Job Using Alteryx Server API and Python

Jake_Jake_Jake
7 - Meteor

I'm really struggling to figure out how to make this work.  I can successfully get my job to fire off using the interactive API documentation, but when it comes to putting it in a python script I can't get it to work.  I keep getting 400 errors.  Below is my code:  

 

 

import requests
import json

#URL provided by interactive API documentation with id and key removed for online question
URL = 'http://dminform:80/gallery/api/v1/workflows/<id>/jobs/?oauth_timestamp=1539784724&oauth_signature_method=HMAC-SHA1&oauth_consumer_key=<Key>&oauth_version=1.0&oauth_nonce=7Ck8g&oauth_signature=TC1bpIecwPsMPO2Ui1l5O%2FwEhzU%3D'

#Response body provided by interactive API documentation
responseBody = {
"id": "<id>",
"appId": None,
"createDate": "2018-10-17T13:58:43.9759132Z",
"status": "Queued",
"disposition": "None",
"outputs": [],
"messages": [],
"priority": 0,
"workerTag": None
}

#Response header provided by interactive API documentation
responseHeaders = {
"Access-Control-Allow-Origin": "*",
"Date": "Wed, 17 Oct 2018 13:58:43 GMT",
"Access-Control-Max-Age": "1728000",
"Access-Control-Allow-Headers": "Content-Type, Accept, Authorization",
"Transfer-Encoding": "chunked",
"Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS",
"Content-Type": "application/json"
}

r = requests.post(url = URL)
# r = requests.post(url = URL, headers = responseHeaders, data = json.dumps(responseBody))
# r = requests.post(url = URL, headers = responseHeaders, params = responseBody)


print(r)
3 REPLIES 3
patrick_digan
17 - Castor
17 - Castor

@Jake_Jake_Jake  The URL from the interactive documentation can't be copied over to python. They're just trying to show you an example so you can build your own. Here are my comments on specific pieces of your URL that you would have to create yourself:

1) oauth_timestamp: You will need to calculate the elapsed time. More details here.

2) oauth_nonce: You will need to create a random string. More details here.

3) oauth_signature: You will need to build your oauth_signature in python. That's the hardest part of the api, and it's a bummer the interactive documentation doesn't spell this out as well; however, they provide a link to the signing process. The signing process has a link to an appendix item which spells out an example of the data that is used to create the signature (along with the key). Notice that the signature includes a timestamp and nonce, which prohibits it from being re-used (and hence you'll need to build it like I mention above). 

 

As for things I've stubbed my toe on,

1) the order can matter (ie to create the signature you have to properly order the several oauth_elements alphabetically).

2) Case matters (Get  does not work but GET does)

3) Some things are url encoded and some things are not. (& in some spots and %26 in other spots)

4) Time zones and daylight savings can affect your timestamp. Luckily the api will respond that you have a bad timestamp if that's the issue.

 

For what it's worth, here is my functioning VBA code to do the signature generation process which may help point you in the right direction.

strBaseString = WorksheetFunction.EncodeURL(strUrl) & _
"&oauth_consumer_key%3D" & strKey & _
"%26oauth_nonce%3D" & Nonce & _
"%26oauth_signature_method%3DHMAC-SHA1" & _
"%26oauth_timestamp%3D" & Time & _
"%26oauth_version%3D1.0"

CreateNewSignature = Base64_HMACSHA1(UCase(getpost) & "&" & strBaseString, strSecret & "&") 
Jake_Jake_Jake
7 - Meteor

@patrick_digan  Thanks for the help!  You are right about the oauth_signature being the hard part.

 

I understand that how to generate the signature base string, but I'm not sure what to do with it next.  Just putting it in the browser results in a google search instead of calling the website.  How does one call send the request?  Does the signature base string go directly in the URL for the post request?

 

This is the sanitized version of my signature base string. 

 

GET&http%3%2%2gallery.<MySite>.com%2gallery%2api%2&oauth_consumer_key=<consumerKey>&oauth_nonce=<my generated uuid>&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1539870497&oauth_token=<secret>&oauth_version=1.0&size=original

patrick_digan
17 - Castor
17 - Castor

@Jake_Jake_Jake 

 

1) I think all of your oauth_xxxxx stuff needs encoded. The & after the GET can stay as well as the & before oauth_consumer_key, but the rest of the & and = need to be encoded ( %26 and %3D i believe)

2) I don't think the size=original at the end should be there.

 

3) I don't think oauth_token=<secret> part should be in there. Here is an example of a key I generate using alteryx tools:

GET&<encoded URL>&oauth_consumer_key%3D<key>%26oauth_nonce%3D818945583%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1539871608%26oauth_version%3D1.0

 

4) With your signature base string, you would need to then need to hash it using the specified hmac-sha1 algorithm. Your 2 inputs would be the signature base string and your secret. Your secret will need to have an & at the end.

 

5) You would need to base64 encode your output from step 4. this is the signature you pass in the next step

 

6) You can now make a GET request to this URL:

<normal URL>?oauth_consumer_key=<key>&oauth_nonce=373116378&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1539872288&oauth_version=1.0&oauth_signature=<base 64 encoded signature>

I'm attaching a macro that I got from another post on the community and slightly modified. If you're not in the Eastern US time zone, you'll need to adjust the timestamp calculation in the macro. Formula (66) is currently adding 4 hours to my computer's time since I'm 4 hours behind GMT.