Streaming is available in most browsers,
and in the WWDC app.
-
Accessing Health Records with HealthKit
HealthKit provides a consolidated repository for a variety of data including health records containing information such as lab results, immunizations, and medications downloaded directly from institutions. Discover new health records classes and types created to provide easy access to high-level record types without preventing access to the underlying raw data. Learn new authorization techniques that allows your app to access health record data for analysis and presentation in a manner that respects your customer's privacy.
Resources
- Accessing Health Records
- Argonaut Data Query Implementation Guide
- FHIR specification (DSTU2, 1.0.2)
- HL7 FHIR Foundation
- Presentation Slides (PDF)
Related Videos
WWDC 2020
WWDC 2019
WWDC 2018
-
Download
Good afternoon, I'm Jason Morley, a software engineer on the Health Team here at Apple. And along with my colleague Peyton I'd like to take some time to introduce you to an exciting new feature we have in iOS 12 this year, access to health records with HealthKit. Earlier this year in iOS 11.3 we introduced Health Records and Health. Users can connect to their healthcare institutions and securely download their health records for quick access and safekeeping. We aggregate data from multiple healthcare institutions and present it in a timeline allowing users to search and surfacing important details like lab values and reference ranges really helping users to better understand their health data.
As of today we have support for more than 500 US hospitals and clinics covering over 50 healthcare institutions and we are continuing to add more. Of course this wouldn't be possible without the fantastic standards work of the Health Level Seven organization with their fast healthcare interoperability resources or FHIR and the Smart health IT project.
For us it all starts with health, we establish a secure connection to healthcare institutions and download users' health records in FHIR direct to their iOS devices.
From here we it store securely in HealthKit and aggregate data across multiple institutions.
Starting today in iOS 12 we are providing APIs to allow you to access this data and work with it in your apps.
First, I'm going to introduce the new sample types that we've added to support this feature.
Then we can see how you authorize your application and query for data. After that, I'll take a brief dive into FHIR and show you what's possible here.
And finally, we can take some time to think about how you can help protect your users' privacy in this sensitive domain. So let's jump right in.
If you've used HealthKit before you may be familiar with HKSampleType and its subclasses. These group similar types of data, for example QuantityType groups data represented by a single numerical value, things like step count and heart rate. While CategoryType groups data characterized by enumeration, things like sleep analysis, am I in bed or asleep or menstrual flow, heavy or light. And to support Health Records we're introducing HKClinicalType which groups the categories of health records that you see in Health, things like conditions and medications.
Within each of these sample types the different data types are differentiated by a type identifier.
HKClinicalType identifier identifies the clinical types that correspond with the categories of Health Records and Health. We have allergies, conditions, these might be short-term conditions such as pregnancy or ongoing conditions like type II diabetes, immunizations, lab results, these might be my blood glucose measurement for my annual physical.
Medications, procedures, a diagnostic procedure or a surgery. And vital signs, things like blood pressure or weight. Alongside these sample types and sample type identifiers, we're also introducing a new HK sample subclass HKClinicalRecord.
If you're not familiar with working with samples in HealthKit we have a number of talks that cover this topic and I'll provide details of these at the end.
There are a few key properties you'll be working with on HKClinicalRecord. The clinical type, we looked at this earlier and this allows you to determine the type of a given record. I want to know that a health record is for example an immunization. We provide a display name which is a string that we use when showing that health record to users in Health. It's selected from the FHIR resource and it's your opportunity to tie back your app's experience to something users are familiar with.
You can see in this lab result that there are a number of alternative representations and names, including a coding in the LOINC coding system. This is an industry standard reference for medical information and it is required by FHIR for observations. You can see here that we've taken that LOINC coding and performed a lookup to provide a canonical name which we will surface to you as the display name.
And finally, we provide access to the full FHIR resource, but there's a lot you can benefit from looking at the HKClinicalRecord so I'm going to set this aside right now and we can come back to it later.
Like all of Health data, provenance, or the source of that data, is very important. You want to know where this health record comes from. And as with the rest of HealthKit we model this using HKSource which is available on the HKSample superclass.
We set the name to be the name of the healthcare institution that they have shared with us and we provide a bundle identifier which is a stable identifier for that healthcare institution across multiple user logins and devices.
So now we've seen the new sample types. Let's see how you authorize your application and query for data.
As you can see, there's a huge wealth of information in medical records and we really believe that that is a fantastic opportunity for you to provide your users with truly empowering experiences around their health data. But of course health records also contain incredibly sensitive information. A user's health records might contain details of medications that they are taking or conditions that they are living with on a daily basis.
This is information they may not be comfortable sharing with a close friend or family member. And it can change over time as a user interacts with their healthcare institution, they might receive a new diagnosis of a condition.
So to help our users better understand and manage access to that data we're introducing a new authorization flow specific to Health Records. When your app requests authorization we will present a new permission sheet specific to clinical types.
First, we inform users what it means to share that data with your app and just how sensitive it is. Since we will present this new authorization flow, whenever you request authorization you should ensure that you time your authorization requests to make sure your user has sufficient context with which to understand this new dialogue.
After this we allow users to select the types of data that they choose to share with your app from the categories that you have requested. We also present a new purpose string and your app's privacy policy in the app explanation section. This is really your opportunity to explain to users why you need access to that data, what you're going to do with it, and how you will protect that data. You should be sure to make sure that what you request is proportional to what you need. Users are really going to be surprised and concerned if they see types here that don't pertain to the primary function of your app. And finally because data can change over time as a user interacts with their healthcare institution, we're introducing a new way to control how new data is shared with your app. We default to asking before sharing new data each and every time.
This means we may need to present the new permission sheet whenever new data is available. So when you need to query for data you should always request authorization prior to doing so.
Okay, so how do I get started and request authorization? This flow is going to look very familiar to those of you who've worked with HealthKit before. First, I need to configure the project. After that request authorization. And finally query for data. To configure your project you need to add a new health records capability in Xcode after enabling HealthKit.
Then you add the new Health Records Usage Description purpose string to your Info.plist.
Again, this is your opportunity to explain to users why you need access to this data and what you will do with it.
Having done this, you can request authorization. Here I define the types I wish to access, conditions, immunizations, and medications.
And then you can call request authorization on the Health Store. Being sure to handle any errors and after that you're good to query. You should be aware that in order to maintain user privacy we don't reveal to you which categories a user has granted access or denied access to.
And now to querying. Because HKClinicalRecord is an HKSample you can take advantage of all of the existing sample query infrastructure in HealthKit. Things like SampleQuery, AnchoredObjectQuery and ObserverQuery will all work and if your user has granted continuous access background delivery will also work. Again, you define the type that you wish to query for. We're creating a sample query here and you can execute that on the Health Store.
So that's the basic authorization flow. But we've actually introduced some additional mechanisms specific to Health Records. We have a new API Get Request Status for Authorization, which allows you to determine if we would present a permission sheet to the user.
This gives you an opportunity to determine whether your user will need to see the authorization sheet and optionally present a UI to provide them with more context prior to authorization.
To do this you call Get Request Status for Authorization on the Health Store, handle any errors, and if the request status is should request you can optionally present that UI prior to requesting authorization.
Now there may also be some types of data that your app requires access to, to provide a safe experience or perhaps if you have a research app you need access to a comprehensive set of types to avoid skewed results.
We have a new required types key in the Info.plist, which allows you to specify these types. And if they're present we will return a new required types error if the user has not granted access to these types. And this allows you to determine how to behave, optionally explaining to the user that you cannot continue if you don't have this data.
You can implement this by adding the new required read authorization key to your Info.plist. Here I'm specifying that I require allergies, conditions and immunizations. And then you handle the new error in the authorization request.
You should be sure to use this judiciously and try not to limit your app's functionality based on the data that you have access to. You really want to make sure as many users as possible can benefit from your app irrespective of how much data they choose to share.
So that's the full authorization flow and there's just a couple of points I'd like to focus on. Firstly, you should be sure to request authorization each and every time that you need access to data, especially now because users may want to see that sheet every time when new data comes in we may need to present a sheet when you need to query.
You should also be sure to request only access to the data that you need. And finally, you should consider taking advantage of the new APIs to provide users with better context and allow you to time those authorization requests.
And with that I'd like to hand over to my colleague Peyton to see what he can do with this in his app. Thank you.
Thanks, Jason. So I'm working on an app for mountain climbers training for their next summit. I've got a HealthKit powered view of all my users walking, hiking and stairclimbing workouts. Now after extensive market research, I've determined that mountain climbers travel to mountains and travelers should know their vaccination status. So by the transitive property of future development mountain climbers should know their vaccination status. So I'm going to help out my users. I've started implementing a new tab, an immunization dashboard. So let me tap on what I have now. Here's my immunization dashboard and to start out with I'm going to display my users a list of their current vaccinations and I'm going to use the HKClinicalRecords display name property. I've already added the Health Records capability to my project and I've created a purpose string to tell my users how I plan to use their immunizations. Now it's time to implement my dashboard. So here I am at the ImmunizationsViewController powering that tab. In HealthKit it's good practice to request authorization every time your user enters the part of your application using HealthKit. So for this app viewWillAppear is a great place.
Here I need to first specify that I'm interested in immunization record samples. And next, call my Health Store's requestAuthorization method. In the callback I'm going to check for success and handle errors appropriately. Finally, once I'm unauthorized I'm going to call this query for immunizations method which I'll implement now. Here in query for immunizations I'm going to create a sample query, I'm going to iterate over all the return samples, and I'm going to pass each sample's display name to my data source. So let's do that.
Here I've got my sample query and I'm using the humanization record sample type. No predicate because I want all of the users' immunizations and similarly no limit because I want to get all of my users' immunizations. No sort descriptors, it doesn't matter to me in what order these samples are returned. And with that I'm going to check for results and if not handle errors appropriately.
Next, I'm going to iterate over the samples and I'll pass them to my data source by display name.
With the names in my data source it's time to head out to the main queue and call this reload UI method that I wrote earlier.
Finally, I'm going to execute my sample query on my Health Store and that's all it takes, so let's build and run.
So here I have my training log, I'm going to tap on my immunization dashboard tab. I see the new Health Records authorization sheet explaining to my users how my app could potentially use my users' health records. I'm going to tap continue and here my user has a chance to allow or deny categories as they see fit. There is my purpose string that I defined in my Info.plist earlier alongside a link to my app's privacy policy. Now users have to explicitly switch for every single category, there's no turn on all button. So for the purposes of the demo I'm going to enable immunizations and to have share current records. For future records I'll leave with the default Ask Before Sharing and I'll tap done. And just like that I have a list of all my users' immunizations. So that's just-- So that's just using display name, but there's a lot more information contained in the clinical records FHIR resources. So to tell you more about FHIR I'd like to hand it back to Jason. Thank you, Peyton. So Peyton just showed us how we can request authorization in our app, query for data, and take advantage of the new display name on HKClinicalRecord to present that information to users in a way they're familiar.
So now let's take a look at FHIR and see what you can do with this rich data format. Users interact with multiple healthcare institutions over the course of their lives and these are often running different electronic health record systems that don't always represent data in the same way. This makes interoperability incredibly difficult. So to address this the healthcare community came together in an effort called the Argonaut Project, this uses FHIR, a flexible JSON representation of health records and 2 as defined by the Smart Authorization Guide to allow connections, consistent connections to healthcare institutions and to allow data to be downloaded in a common format and related across those multiple institutions.
FHIR itself models a huge universe of health data from allergy intolerance to vision prescription and it organizes this data into different data types called resources. Each resource has a resource type and there is one for each and every kind of health data. Today we are selecting the eight most common resource types and these are defined within the Argonaut Project and we are grouping these into the seven different clinical types that we saw earlier. You'll note that we split observations into lab results and vital signs based on the categorization and we group multiple medication resource types into the medications category. So FHIR represents data as a JSON dictionary and there are some key properties that are present on all FHIR resources. Things like the resource type, here we're looking at an observation and this tells us that in the context of health this is a lab result or a vital sign.
We also have an ID present on all resource types. This is a unique identifier for that resource, but you should note that it is only unique within the domain of that resource type for that healthcare institution.
One of the most fundamental building blocks of FHIR is a coding.
This allows for a reference to a unique identifier or a code scoped within an external coding system. There are a number of coding systems specified within FHIR and you can use these to find out more about the items that are referenced in medical records or to relate specific things across multiple healthcare institutions. Here we're actually looking at a category coding which tells us that this is a lab result.
There's also a code in the case of an observation for what is being measured.
This is blood glucose as defined in the LOINC coding system and it could take that code and look it up in the LOINC database for alternative names and further information. And of course this is an observation so I have the value that is observed. This is 60 milligrams per deciliter and you'll note that even the units here are coded, so I have a really comprehensive understanding about what's going on.
FHIR resources have many additional data elements and I encourage you to go and look at the Argonaut Project documentation to find out more and I'll have details of these at the end. In HealthKit we model a FHIR resources as HKFHIRResource. We provide some key properties like the data, access to the full raw data.
We surface common elements like the resource type and identifier. You can access the data using Swift codable or JSON serialization. Here you can see that I've defined my own codable struct, my codable observation and I'm using that to pull out the value quantity that we saw earlier. You can have confidence that the data is structured correctly here as we only share valid FHIR resources through the API. We also introduce some predicates to make it easier for you to work with HKClinicalRecord. We have a predicate to allow you to query by resource type, here I'm looking for prescription or in FHIR a medication order.
We also have a predicate to allow you to uniquely identify records by their source, resource type and identifier. This can be incredibly useful as FHIR resources can reference other FHIR resources. For example, a medication might reference the condition that it treats.
Now there are some additional considerations you need to be aware of when working with FHIR.
Firstly, FHIR resources may contain their own dates. For example, prescriptions may contain the order data of that prescription while a condition may contain the onset date, abatement date and the date that that prescription is first observed. You should therefore use the FHIR resource directly to access these dates for each resource type. Start date and end date that are available on the HKSample superclass are set for the date that we first add that resource to Health.
You should use source, resource, type and identifier when uniquely identifying a health record. This will allow you to identify a health record across the course of its lifetime as it is updated by the healthcare institution. And finally, you should be aware that FHIR and JSON don't fully agree when it comes to numerical precision. FHIR ascribes significance to the number of digits following the decimal place and this can be lost when using Swift codable or JSON serialization. If it's really fundamental to your app that you have full access to this information Swift codable and JSON serialization may not be appropriate tools. And with that, I'd love to hand back to Peyton and see what wonderful things he can do with this new API. Thanks, Jason. So back to the immunization dashboard I've been working on. I'm using HealthKit to fetch my users' vaccinations, but right now it's tough for a user to tell what vaccinations they have and what they might need to get. So I'm going to solve that by implementing an immunization checklist. Users can see a summary of their immunizations in plain language.
To populate this list I need to know that this combination vaccine induces immunity against chickenpox and against MMR. Health institutions speak different languages so I can't rely on name alone, so that's where the interoperability of FHIR comes into play. FHIR gives a way to use predefined codes rather than natural language to specify what things are.
So after taking a look at the FHIR documentation here's the algorithm I've come up with to identify a chickenpox vaccine.
First, I'll take the immunization records JSON, I'm going to deserialize it and pull out the vaccination code in a system called CVX. CVX is a commonly used coding system for immunizations, but there are many other coding systems for different areas of medicine. Finally, I'm going compare the CVX code I found in my immunization record to a list of vaccines I know induce immunity against chickenpox. If there's a match I'll show a checkmark in my UI next to chickenpox. So let's talk about the immunization record JSON.
The structure starts with a resource type immunization. There's a vaccine code object and contained therein is an array of codings. There may be multiple codings, so I need to search by system to find CVX. In this example, the first system is NDC so I move until I see CVX. With that in hand I look at the code and I look it up and I see that I have MMRV. So that's the structure of these immunization records JSON. Now it's time to implement. So here we are back in my immunizations view controller. I've done some work ahead of time to implement the UI of the checklist and I instantiate it with a showChecklist property. Now it's time to populate my checklist with data.
Here I am in the query for immunizations method. When I iterate over my users' samples I'm going to add a call to a new method matchCodedVaccine and I'll pass it if the sample is FHIR resource, so let's implement that now.
Here I am in matchCodedVaccine from resource and what I need to do is deserialize the FHIR resources data, pull out the vaccination codes, search for CVX, and compare it against lists of CVX codes for different diseases. I have a lot of freedom in how I choose to deserialize the FHIR resource, so today I'm going to use Swift codables. I need to define a codable for exactly the keys that I'm interested in.
So I've done that now. An immunization resource has a vaccine code, a vaccine code has an array of codings and a vaccine coding has a system and a code. With that I instantiate a JSON decoder and I use it to decode the FHIR resources data as an immunization resource. All that's left is to iterate over each coding, check to see whether the system is CVX, and then pass the code to this method to mark it in the data source. All this method does is compares the code against lists of codes per disease and if there's a match marks in the UI that disease for the found disease. So with that I'm going to build and run and take a look at my immunization checklist. So here I am on my training log, I'm going to tap on the Immunizations tab and just like that with a few lines of code I have an immunization checklist. So that's an example of solving a problem using FHIR. Now for a word on granting consent for your users I'm going to hand it back to Jason. Jason. Thanks Peyton. So Peyton has shown us how we can take that rich FHIR data and take advantage of the coding that's provided to really provide our users with a very meaningful and comprehensive experience around their health records.
And now I'd like to think a little bit about how you can help protect your users' privacy in this domain. As you've seen this is incredibly sensitive data. We've built privacy in from the ground up, establishing secure connections direct to healthcare institutions. Downloading data straight to users' iOS devices. Storing it securely in HealthKit. And providing comprehensive management tools around access to that data. Your users will expect you to treat their data with that same level of care and attention.
Every choice that you make here can have a direct impact on individuals. This can be a truly positive impact and it's why we are choosing to provide this API today, but it can also be a negative one. If users feel that this data is out of their control or worse still, it is shared without their consent. You can show respect for your users and help establish a relationship of trust by providing them with clear policies around that data and informing them what you do with it. This starts with your application, your purpose string, and your privacy policy and it continues every step of the way as you work with that data and as you move it around.
For example, you should make sure you give users details about how you manage their data. You should publish clear retention policies and you should provide them tools to allow them to delete that data should they choose to stop sharing it with you. And finally, you should make sure that you always request data proportional to your use case. You should never be asking for more data than you need.
I encourage you all to go to the Privacy Talk, Better Apps Through Better Privacy on Thursday at 4 p.m. and this covers the whole ecosystem, so it's a great opportunity to find out more. So we've seen the new sample types that we're introducing to support Health Records. We understand how to configure entitlements and privacy strings in our app, to request authorization and to query for data.
Hopefully I have shown you just enough to whet your appetite to go and find out more about FHIR. And we've seen how you can do more to help protect your users' privacy.
We continue to be amazed by the fantastic apps that our developer community creates and how it really empowers users when accessing their health data.
This is a journey that we started with Health and HealthKit and it's one that we have continued with ResearchKit and CareKit. And now today with Health Records and HealthKit we are thrilled to be continuing on that journey with you. We can't wait to see what amazing things you do. You can find the documentation that I was talking about earlier at the URL behind me and we have some labs. We have a health and fitness lab immediately after this talk where we're very happy to get you started with this new API. Our colleagues Anherika and Kareem have a talk tomorrow morning introducing new ways to work with workouts. And we have a health fitness and research get together tomorrow night where it's an opportunity for you all to get to know each other and talk with us as well, so please do come along to that. And with that, thank you very much and have a fantastic conference. [ Applause ]
-
Looking for something specific? Enter a topic above and jump straight to the good stuff.
An error occurred when submitting your query. Please check your Internet connection and try again.