Quick start
API credentials
First choose a data collection
Example
import base64
import json
import hmac
import hashlib
from requests import Request, Session
from datetime import date
from urllib import parse
ACCESS_KEY = '<put your access key here>'
SECRET_KEY = '<put your secret key here>'
BASE_URL = 'https://portal-api.ihme.services'
class IhmePortalApi:
def __init__(self, base_url, access_key, secret_key):
self.session = Session()
self.base_url = base_url
self.access_key = access_key
self.secret_key = secret_key
def calculate_request_signature(self, request):
todays_date = date.today() \
.strftime('%Y-%m-%d')
string_to_sign = ' ' \
.join([
request.method,
request.path_url,
todays_date
]) \
.encode('utf-8')
secret_key_bytes = base64.b64decode(self.secret_key)
signature_bytes = hmac \
.new(secret_key_bytes, string_to_sign, hashlib.sha256) \
.digest()
return base64 \
.b64encode(signature_bytes) \
.decode('utf-8')
def request(self, method, endpoint, params={}, headers={}):
request = Request(method, self.base_url + endpoint, params=params, headers=headers) \
.prepare()
signature = self.calculate_request_signature(request)
request.headers['Authorization'] = 'IHME ' + self.access_key + ':' + signature
return self.session.send(request)
def get(self, endpoint, params={}):
response = self.request('GET', endpoint, params)
decoded = json.loads(response.content)
if response:
return decoded['data']
else:
raise Exception(decoded['error']['message'])
api = IhmePortalApi(BASE_URL, ACCESS_KEY, SECRET_KEY)
# Get a list of data collections shared with my organization
data_collections = api.get('/my-organization/group-content-data-collection-resources')['results']
# Pick which one we want to query
data_collection = data_collections[0]
# Data collection is a collection of several datasets, select which dataset we want to query
dataset = next((d for d in data_collection['datasets'] if d['data_type'] == 'cause_outcome'))
# Get the id of the round we are interested in
rounds = api.get('/rounds')
gbd2023_round_id = next((r['id'] for r in rounds if r['name'] == 'GBD 1990-2024')) # 9
# Get the ids of the causes we are interested in
causes = api.get('/causes')
malaria_cause_id = next((c['id'] for c in causes if c['name'] == 'Malaria')) # 345
tuberculosis_cause_id = next((c['id'] for c in causes if c['name'] == 'Tuberculosis')) # 297
# You can also use constants for the ids as they never change
usa_location_id = 102
all_ages_age_group_id = 22
female_gender_id = 2
male_gender_id = 1
daly_measure_id = 2
rate_metric_id = 3
reference_forecast_scenario_id = 1
# Dataset has data only for values that are present in the granularity. The filter values should be picked based on it
assert gbd2023_round_id in dataset['granularity']['round_id']
assert malaria_cause_id in dataset['granularity']['cause_id']
assert tuberculosis_cause_id in dataset['granularity']['cause_id']
# For the rest of the filters it's possible to refine available granularity based on the selected cause and round
# to minimize the chance of choosing a combination of filters that do not return data
refined_granularity = api.get(
'/my-organization/data-collection-resources/{:d}/datasets/cause_outcome/granularity'.format(data_collection['id']),
{
'primary_entity_id': ','.join(map(str, [malaria_cause_id, tuberculosis_cause_id])),
'round_id': gbd2023_round_id
}
)
assert usa_location_id in refined_granularity['location_id']
# Query the data we are interested in
data = api.get(
'/my-organization/data-collection-resources/{:d}/datasets/cause_outcome/data'.format(data_collection['id']),
{
'round_id': gbd2023_round_id,
'location_id': usa_location_id,
'age_group_id': all_ages_age_group_id,
'gender_id': ','.join(map(str, [female_gender_id, male_gender_id])),
'measure_id': daly_measure_id,
'metric_id': rate_metric_id,
'cause_id': ','.join(map(str, [malaria_cause_id, tuberculosis_cause_id])),
'forecast_scenario_id': reference_forecast_scenario_id
}
)Last updated