Access Patterns¶
Due to Jobalyzer's async access, some patterns may be useful as a reference.
Authentication¶
Authentication is handled by the service at the URL https://accounts.payscale.com/connect/token
, as shown in the code below.
The response from this system is a json object containing the following keys:
access_token: This is your access token, good for 10 minutes.
expires_in: This is how long your token is good for, in seconds. Generally 3600.
token_type: This is how you will use your token. Generally, this is "Bearer" type.
scope: This is the service your token is good for. Generally, this is just Jobalyzer.
import requests
import time
auth_url = 'https://accounts.payscale.com'
get_token_url = f'{auth_url}/connect/token'
client_id = '<your-client-id>'
client_secret = '<your-client-secret>'
# get oauth token using given clientId and clientSecret
payload = {
'grant_type': 'client_credentials',
'scope': 'jobalyzer',
'client_id': client_id,
'client_secret': client_secret
}
token_response = requests.post(get_token_url, data=payload)
if token_response.status_code == 200:
token = token_response.json()['access_token']
else:
print(f'failed to get token: {token_response.text}')
Async Access¶
Jobalyzer is a completely asynchronous service, meaning that the requests for generating a report and the requests for pulling down a report will complete whether the report is ready or not. In order to successfully retrieve a completed report, you must wait until the returned status code is 200.
First, we will take a look at submitting the Report Generation Request:
import requests
import time
jobalyzer_url = 'https://jobalyzer.payscale.com'
generate_reports_url = f'{jobalyzer_url}/jobalyzer/v1/reports'
client_id = '<your-client-id>'
client_secret = '<your-client-secret>'
# make a request for reports using the new token
# make a request for reports using the new token
data = {
"customerId": client_id,
"user": client_id,
"AutoResolveJobTitle": True, # optional, tries to automatch submitted job title
"requestedReports": ["yoe", "pay"],
"answers": {
"JobTitle": "Software Developer",
"City": "Seattle", # optional
"State": "Washington", # optional
"Country": "United States",
"YearsExperience": 5, # optional, effects Pay report
"HighestDegreeEarned": "Bachelors" # optional
}
}
headers = {'Authorization': f'Bearer {token}'}
request_response = requests.post(generate_reports_url, json=data, headers=headers)
The response will look like the following:
{
"Links": {
"Self": "https://jobalyzer.payscale.com/jobalyzer/v2/reports/<unique-ID>",
"PayReport": "https://jobalyzer.payscale.com/jobalyzer/v1/reports/<unique-ID>/pay",
"YearsExperienceReport": "https://jobalyzer.payscale.com/jobalyzer/v2/reports/<unique-ID>/yoe",
},
"Warnings": null,
"Errors": null
}
Any errors will be present in "Errors". Common errors include:
Submitting an Unconfirmed Answer. This means that the answer does not appear in our database, and cannot be used to describe our data.
Expired token: This will result in a 401 Unauthorized error. Please refresh your token and try again.
Retrying¶
When the report links are generated, the reports are not done. Occasionally, depending upon load, there can be a minor delay between the link being generated and the report being ready. In these instances, it's fine to keep hitting the same link until the report is returned.
# parse the returned links to receive the reports
yoe_report_url = request_response.json()['Links']['YearsExperienceReport']
pay_report_url = request_response.json()['Links']['PayReport']
# request the completed reports until a 200 is returned
report_urls = {'Years of Experience': yoe_report_url,
'Pay': pay_report_url}
reports = {}
for key in report_urls.keys():
while reports.get(key) is None:
response = requests.get(f'{report_urls[key]}?customerId={client_id}&user={client_id}', headers=headers)
if response.status_code == 200:
print(f'{key} report returned.')
reports[key] = response.json()
elif response.status_code == 202:
print(f'{key} not ready, sleeping')
time.sleep(response.json()['RetryAfterMilliseconds']/1000)
else:
print(f'failed for some other reason: {response.text}')
break
print(reports)
Note
In both instances, a json object will be returned, and the status code should be used to differentiate between these events.
Once a report is collected, it can be collected again for a period of time, so expecting an error after a successful return is also not a viable strategy.
Sync Access¶
Some endpoints are synchronous, like the /jobalyzer/v1/impact/skills and /jobalyzer/v1/impact/certs endpoints. These still require the authentication token, but do not require polling for the result.