NAV
hidden ruby

HealtheIntent API Workshop

Course Objective

This course will teach you how to consume Population Health concepts using the Cerner HealtheIntent APIs. First, you will learn to authenticate your API calls using OAuth1 and to use HealtheRecord person search and patient data retrieval services. Next, you will retrieve registry and measure outcomes with the HealtheRegistries API, and learn how to filter the outcomes in the response.

Click here to take you to the HealtheIntent slide deck.

Prerequisites

Introduction to HealtheIntent APIs

URI Structure

HealtheIntent is a multi-tenant platform and it follows an URI pattern.

https://{client}.{solution}.healtheintent.com

For this workshop we will be using the cernerdemo client. So the URI structure will look like:

https://cernerdemo.{solution}.healtheintent.com

To make calls to your production client, you would replace cernerdemo with your client mnemonic.

Authentication and Authorization

HealtheIntent‘s APIs use the two-legged (or B2B) OAuth 1.0a based authentication workflow. For detailed documentation on how to authenticate against Cerner services, please see the documentation we have for Authentication.

Authentication using the cerner-oauth1a Gem

For the purpose of this workshop, we will be using the cerner-oauth1a gem to request an OAuth token. cerner-oauth1a supports functionality to return an Authorization header, which we will use in our REST calls.

Creating Authorization header using cerner-oauth1a gem

require 'cerner/oauth1a'

auth_header = Cerner::OAuth1a::AccessToken.request(consumer_key: 'consumer_key', consumer_secret: 'consumer_secret', oauth_url: 'URL for OAuth provider').get_authorization_header

Exercise 1

Create an OAuth Authorization header using the given credentials.

Note The Authorization header created as part of this exercise will be used in the later exercises.

Authorization

The system account we will be using has already been created. It has permissions to access HealtheRecord, HealtheRegistries, and Data Syndication services. You used the credentials (the consumer_key and consumer_secret) for that account to create the OAuth token.

Note We will be disabling this account at the end of this workshop. To request a new system account to pursue further development against our platform, follow the instructions here.

Request Headers

The following headers must be set before you can call the HealtheIntent APIs:

HealtheRecord

The Cerner longitudinal record, HealtheRecord, is designed to provide an organized, coherent representation of the aggregated clinical data for a member. We will use HealtheRecord to demonstrate how to authenticate your REST calls and how to use the APIs.

Detailed API documentation for HealtheRecord can be found here

We will be using the httparty gem as our HTTP client for the purpose of this workshop.

This API is used for searching among the people in a population. You can also refine your search using query parameters.

Person search API: GET /api/populations/{population_id}/people

We will be using the following population id for all our exercises: 1424e81d-8cea-4d6b-b140-d6630b684a58

Exercise 2

require 'httparty'

# psssst... remember to substitute the population id in the URL

response = HTTParty.get('https://cernerdemo.record.healtheintent.com/api/populations/{population_id}/people', headers: {'Accept' => 'application/json', 'Authorization' => <auth_header>})

Retrieve a list of people from the given population. You will need to use the Authorization header created in the previous exercise.

How many people do you have in your population?

The unformatted response object is hard to read, so let’s make it look pretty by using pretty_generate!

require 'json'

puts JSON.pretty_generate(response)

Click here for the answer The answer is 111971 (total_results attribute gives your the result).

Exercise 3

query_parameters = {
  'date_of_birth' => '1972-01-22',
  'q' => 'butler'
}

response = HTTParty.get('https://cernerdemo.record.healtheintent.com/api/populations/1424e81d-8cea-4d6b-b140-d6630b684a58/people', headers: {'Accept' => 'application/json', 'Authorization' => <auth_header>}, query: query_parameters)

puts JSON.pretty_generate(response)

We need to find the person ID for Tammy Butler, whose birthdate is 1972-01-22.

Click here for the answer Person ID for Tammy Butler is 6faf92f6-f3d3-4e0e-b633-48a45df383db

Person Demographics

We just found the person_id for Tammy Butler. Now let’s learn a little more about her using the Person Demographics API.

Person demographic API: GET /api/populations/{population_id}/people/{person_id}

Exercise 4

response = HTTParty.get('https://cernerdemo.record.healtheintent.com/api/populations/1424e81d-8cea-4d6b-b140-d6630b684a58/people/{person_id}', headers: {'Accept' => 'application/json', 'Authorization' => <auth_header>})

puts JSON.pretty_generate(response)

Find out Tammy Butler’s insurance plan name and how long has she been in the same plan.

Click here for the answer Her plan name is Healthe and she has been on the same plan since 2015-09-06.

Medications

Time to check out the Medications currently prescribed to Tammy.

Medication groups API: GET /api/populations/{population_id}/people/{person_id}/medication_groups

Exercise 5

response = HTTParty.get('https://cernerdemo.record.healtheintent.com/api/populations/1424e81d-8cea-4d6b-b140-d6630b684a58/people/{person_id}/medication_groups', headers: {'Accept' => 'application/json', 'Authorization' => <auth_header>})

puts JSON.pretty_generate(response)

Find out all the medications that Tammy has been prescribed. How many medications has she been prescribed?

Click here for the answer 12

Allergies

Before we prescribe any new medications to Tammy, let’s check out what she is allergic to.

Allergen groups API: GET /api/populations/{population_id}/people/{person_id}/allergen_groups

Exercise 6

response = HTTParty.get('https://cernerdemo.record.healtheintent.com/api/populations/1424e81d-8cea-4d6b-b140-d6630b684a58/people/{person_id}/allergen_groups', headers: {'Accept' => 'application/json', 'Authorization' => <auth_header>})

puts JSON.pretty_generate(response)

Find out if Tammy is allergic to anything.

Click here for the answer Tammy is allergic to penicillin.

Conditions

Now it’s time to see all the conditions Tammy has. We can use the conditions_groups resource to find them.

Conditions groups API: GET /api/populations/{population_id}/people/{person_id}/condition_groups

Exercise 7

response = HTTParty.get('https://cernerdemo.record.healtheintent.com/api/populations/1424e81d-8cea-4d6b-b140-d6630b684a58/people/{person_id}/condition_groups', headers: {'Accept' => 'application/json', 'Authorization' => <auth_header>})

puts JSON.pretty_generate(response)

Take a look at all the conditions Tammy has. How many conditions does she have?

Click here for the answer She has 12 conditions.

Procedures

Let’s check out all the procedures we know about for Tammy. The Procedure_groups API consolidates procedures for easier viewing.

Procedure groups API: GET /api/populations/{population_id}/people/{person_id}/procedure_groups

Exercise 8

response = HTTParty.get('https://cernerdemo.record.healtheintent.com/api/populations/1424e81d-8cea-4d6b-b140-d6630b684a58/people/{person_id}/procedure_groups', headers: {'Accept' => 'application/json', 'Authorization' => <auth_header>})

puts JSON.pretty_generate(response)

Find out all the procedures Tammy has undergone.

Click here for the answer Tammy has undergone ‘Abdomen Ultrasound’, ‘Foot Exam’, and ‘Laparoscopy’.

Bonus Questions

Exercise 9

response = HTTParty.get('https://cernerdemo.record.healtheintent.com/api/populations/1424e81d-8cea-4d6b-b140-d6630b684a58/people/6faf92f6-f3d3-4e0e-b633-48a45df383db/vaccine_groups', headers: {'Accept' => 'application/json', 'Authorization' => <auth_header>})

response = HTTParty.get('https://cernerdemo.record.healtheintent.com/api/populations/1424e81d-8cea-4d6b-b140-d6630b684a58/people/6faf92f6-f3d3-4e0e-b633-48a45df383db/vaccine_groups/F8BD9284FBC0082BE043902F47AAB2CA/immunizations', headers: {'Accept' => 'application/json', 'Authorization' => <auth_header>})

puts JSON.pretty_generate(response)

Find out when Tammy was vaccinated against polio.

Hint You will need to call “/api/populations/{population_id}/people/{person_id}/vaccine_groups” first to figure out the “vaccine_group_id” for polio.

Click here for the answer The answer is ‘2009-01-05’ and ‘2010-04-12’.

Exercise 10

response = HTTParty.get('https://cernerdemo.record.healtheintent.com/api/populations/1424e81d-8cea-4d6b-b140-d6630b684a58/people/6faf92f6-f3d3-4e0e-b633-48a45df383db/provider_relationships', headers: {'Accept' => 'application/json', 'Authorization' => <auth_header>})

Find out the total number of healthcare providers for Tammy.

Hint You will have to use the provider_relationships API. The answer is 17.

HealtheRegistries

A registry is an aggregation of an organization’s patients who share a particular clinical characteristics.

Detailed API documentation for HealtheRegistries can be found here

Person Registries Summaries

Person Registries summary lets you fetch a person’s registry data using the HealtheIntent person id.

Person Registries summary API: GET api/populations/{population_id}/people/{person_id}/registries

Exercise 11

require 'httparty'

# psssst... remember to create the authorization header

response = HTTParty.get('https://cernerdemo.registries.healtheintent.com/api/populations/1424e81d-8cea-4d6b-b140-d6630b684a58/people/6faf92f6-f3d3-4e0e-b633-48a45df383db/registries',headers: {'Accept' => 'application/json', 'Authorization' => <auth_header>})

puts JSON.pretty_generate(response)

MARA risk score is a metric that is used to gauge a patient’s cost of care to the hospital. Average risk score for a person is 1. The cost of care will be more expensive for a patient with a higher risk score.

Using Tammy Butler’s person_id from the previous exercise fetch her registry. What is the MARA score for Tammy?

Click here for the answer The MARA score is 0.05

Exercise 12

query_parameters = {fields: 'mara_total_risk_score'}

response = HTTParty.get('https://cernerdemo.registries.healtheintent.com/api/populations/1424e81d-8cea-4d6b-b140-d6630b684a58/people/6faf92f6-f3d3-4e0e-b633-48a45df383db/registries',headers: {'Accept' => 'application/json', 'Authorization' => <auth_header>}, query: query_parameters)

puts JSON.pretty_generate(response)

Now using the query parameters filter the response so that you only get the mara score

Hint Use the “fields” query parameter to filter the mara_total_risk_score field.

Exercise 13

query_parameters = { measures_status_filter: 'due' }

response = HTTParty.get('https://cernerdemo.registries.healtheintent.com/api/populations/1424e81d-8cea-4d6b-b140-d6630b684a58/people/6faf92f6-f3d3-4e0e-b633-48a45df383db/registries',headers: {'Accept' => 'application/json', 'Authorization' => <auth_header>}, query: query_parameters)

puts JSON.pretty_generate(response)

As Tammy’s primary care provider you want to know all the measures that are due.

Fetch her registry and find out all the measures that are due under Adult Wellness program.

Hint Use the “measures_status_filter” query parameter to filter only those measures that are due.

Click here for the answer These are the measures that are due are “Alcohol Use Screening”, “Blood Pressure Measurement”, “Body Mass Index Follow-Up Plan”, “Cervical Cancer Screening” “Influenza Vaccination - Full Season”, and “Influenza Vaccination - Partial Season”.

Person Measure Component Group

Supporting facts for a measure can be fetched using the component group API.

Person Measure Component Group API: GET api/populations/{population_id}/people/{person_id}/registries/{program_id}/measures/{fqn}/componentGroup

fqn is the fully qualified name of the measure (its identifier), example is cernerstandard.adultwellness.org2014.clinical/body-mass-index. And program_id is the HealtheIntent program id to which the corresponding measure belongs to, example is cernerdemo.adultwellness.org.clinical.cernerdemo-adult-wellness.

Exercise 14

response = HTTParty.get(  'http://cernerdemo.registries.healtheintent.com/api/populations/1424e81d-8cea-4d6b-b140-d6630b684a58/people/6faf92f6-f3d3-4e0e-b633-48a45df383db/registries/cernerdemo.diabetes.org.clinical.cernerdemo-diabetes/measures/cernerstandard.diabetesmellitus.org2014.clinical%2Fbp-measurement/componentGroup' ,headers: {'Accept' => 'application/json', 'Authorization' => <auth_header>})

puts JSON.pretty_generate(response)

Let’s take a look at what Tammy’s last measured blood pressure is. Fetch supporting facts for cernerstandard.diabetesmellitus.org2014.clinical/bp-measurement measure from cernerdemo.diabetes.org.clinical.cernerdemo-diabetes program.

Hint The “/” in the measure needs to be changed to “%2F”.

Click here for the answer Blood Pressure 112/60 mmHg.

Bonus questions

Exercise 15

response = HTTParty.get( 'http://cernerdemo.registries.healtheintent.com/api/populations/1424e81d-8cea-4d6b-b140-d6630b684a58/programs' ,headers: {'Accept' => 'application/json', 'Authorization' => <auth_header>})

puts JSON.pretty_generate(response)

Retrieve all the programs for the population.

Hint Need to use the Programs API: “GET api/populations/{population_id}/programs”.

Exercise 16

response = HTTParty.get('https://cernerdemo.registries.healtheintent.com/api/populations/1424e81d-8cea-4d6b-b140-d6630b684a58/programs/cernerdemo.asthma.org.clinical.cernerdemo-asthma-care',headers: {'Accept' => 'application/json', 'Authorization' => <auth_header>})

puts JSON.pretty_generate(response)

How many measures does the cernerdemo.asthma.org.clinical.cernerdemo-asthma-care program have?

Hint Need to use the Programs API: “GET /populations/{population_id}/programs/{program_id}” to retrieve a single program.

Click here for the answer cernerdemo.asthma.org.clinical.cernerdemo-asthma-care program has 6 measures.

Exercise 17

request_body = { person_ids: ['ae3a2060-1261-43a3-a42b-013b0d700fca', 'a6facde2-b5b3-41e0-b939-3d9c87b258c9', '6faf92f6-f3d3-4e0e-b633-48a45df383db'],
  program_ids: [ 'cernerdemo.adultwellness.org.clinical.cernerdemo-adult-wellness']
}

query_parameters = { measures_status_filter: 'due' }

response = HTTParty.post('https://cernerdemo.registries.healtheintent.com/api/populations/1424e81d-8cea-4d6b-b140-d6630b684a58/people/registries', headers: {'Authorization' => <auth_header>}, body: request_body, query: query_parameters)

Stephanie (ae3a2060-1261-43a3-a42b-013b0d700fca), Jason (a6facde2-b5b3-41e0-b939-3d9c87b258c9) and Tammy (6faf92f6-f3d3-4e0e-b633-48a45df383db) are coming in today for a checkup. Fetch their registries and find out what measures are due for their Cerner adult wellness program. The program id for “Cerner adult wellness” is cernerdemo.adultwellness.org.clinical.cernerdemo-adult-wellness.

Hint Need to use the Multiple People registries API: “POST /populations/{population_id}/people/registries” to retrieve multiple registries. You will also have to use the “measures_status_filter” query parameter.

Click here for the answer The measures due for Stephanie, Jason, and Tammy are 11, 9, and 6 respectively.

Readmission Risk

The Readmission Risk API can be used to determine how likely a patient is of being readmitted based on the Cerner Readmission algorithm.

Detailed API documentation for Readmission Risk can be found here

Person Lookup

This endpoint is used to lookup a HealtheIntent person ID from a particular data partition and person ID from the data partition source.

Person lookup API: POST /api/populations/{population_id}/data_partitions/{data_partition_id}/persons

Prerequisites

In order to look up a HealtheIntent person ID, you must first have the id of the source data partition and the person id from that source data partition.

Cerner Millennium Demo partition id: 8dee150d-505f-4635-b009-1bef63d7cf5a

The readmissions API also uses a different population than the other APIs we have worked with.

Readmissions population id: 0a9cc467-094c-403a-84d0-35604e1e418c

Person IDs from the Cerner Millennium Demo partition:

Exercise 18

response = HTTParty.post('https://cernerdemo.programs.healtheintent.com/api/populations/0a9cc467-094c-403a-84d0-35604e1e418c/data_partitions/8dee150d-505f-4635-b009-1bef63d7cf5a/persons',
headers: {'Accept' => 'application/json', 'Authorization' => <auth_header>, 'Content-Type' => 'application/json'},
body: {values: ['3614281', '1427933', '2235926']}.to_json)

puts JSON.pretty_generate(response)

Lookup the HealtheIntent person IDs for the people in the Cerner Millennium data partition.

Click here for the answer You should get back the following IDs: 0230b3ec-a541-3da1-bb60-4710f0446237, 06c3415b-deb5-3bbd-a6f4-f2293894758d, and 0655eafe-a71e-3b55-8258-2a51f43b14fc

Readmission Risk Score

Now that you have the HealtheIntent person IDs for the people from exercise 1 you can look up their actual risk scores. This endpoint actually allows looking up a history of risk scores for a person, but by default returns the most recent risk score. We will return to the historical risk scores later.

The risk score for a person is shown under the stratification of the response. The possible values are LOW, MODERATE, and HIGH.

Readmission Risk Score API: GET /api/populations/{population_id}/readmission_risk/{person_id}

Exercise 19

response = HTTParty.get('https://cernerdemo.programs.healtheintent.com/api/populations/0a9cc467-094c-403a-84d0-35604e1e418c/readmission_risk/0655eafe-a71e-3b55-8258-2a51f43b14fc',
headers: {'Accept' => 'application/json', 'Authorization' => <auth_header>})

puts JSON.pretty_generate(response)

What is the age of the person with a HIGH risk score?

Hint The age can be found in the risk_factors array under the field named age_in_years

Click here for the answer The person with a HIGH risk score is age 85

Exercise 20

response = HTTParty.get('https://cernerdemo.programs.healtheintent.com/api/populations/0a9cc467-094c-403a-84d0-35604e1e418c/readmission_risk/06c3415b-deb5-3bbd-a6f4-f2293894758d',
headers: {'Accept' => 'application/json', 'Authorization' => <auth_header>})

puts JSON.pretty_generate(response)

What is the age of the person with a MODERATE risk score?

Hint The age can be found in the risk_factors array under the field named age_in_years

Click here for the answer The person with a MODERATE risk score is age 40

Exercise 21

response = HTTParty.get('https://cernerdemo.programs.healtheintent.com/api/populations/0a9cc467-094c-403a-84d0-35604e1e418c/readmission_risk/0230b3ec-a541-3da1-bb60-4710f0446237',
headers: {'Accept' => 'application/json', 'Authorization' => <auth_header>})

puts JSON.pretty_generate(response)

What is the age of the person with a LOW risk score?

Hint The age can be found in the risk_factors array under the field named age_in_years

Click here for the answer The person with a LOW risk score is age 73

Exercise 22

query_parameters = {
  'start_version' => '0',
  'end_version' => '20161117'
}

response = HTTParty.get('https://cernerdemo.programs.healtheintent.com/api/populations/0a9cc467-094c-403a-84d0-35604e1e418c/readmission_risk/0655eafe-a71e-3b55-8258-2a51f43b14fc',
headers: {'Accept' => 'application/json', 'Authorization' => <auth_header>}, query: query_parameters)

puts JSON.pretty_generate(response)

As mentioned previously, the readmission risk endpoint returns only the latest risk score by default. Now we will use it to look up historical risk scores for a person. In order to do this the start_version and end_version query parameters can be used to provide a range. Despite the name these query parameters actually take in dates in the format YYYYMMDDhhmm in UTC.

What is the comorbidity_index for very first risk score of the person with a HIGH risk score?

Hint 0 can be used for the start_version query param and today’s date can be used for the end_version query param

Click here for the answer The comorbidity_index on the very first risk score is 2

Readmission Risk Score List

The readmission risk score list endpoint can be used to get the risk score for multiple people in a single call. Unlike the singular risk score endpoint, this endpoint uses a POST with the person IDs included in the post body.

Readmission Risk Score List API: POST /api/populations/{population_id}/readmission_risk

Exercise 23

response = HTTParty.post('https://cernerdemo.programs.healtheintent.com/api/populations/0a9cc467-094c-403a-84d0-35604e1e418c/readmission_risk',
headers: {'Accept' => 'application/json',  'Content-Type' => 'application/json', 'Authorization' => <auth_header>},
body: {empi_ids: ['0655eafe-a71e-3b55-8258-2a51f43b14fc', '06c3415b-deb5-3bbd-a6f4-f2293894758d', '0230b3ec-a541-3da1-bb60-4710f0446237']}.to_json)

puts JSON.pretty_generate(response)

Get the readmission risk score for all 3 persons at once.

Hint The POST body is an array of strings keyed by the field empi_ids