WWDC Quick Look đź’“ By SwiftGGTeam
Meet the HealthKit Medications API

Meet the HealthKit Medications API

Watch original video

Highlight

The Health app has supported medication tracking since iOS 15, but third-party apps could not read this data. Now the Medications API opens that door.


Core Content

Users have been recording medications in the Health app for four years. Scheduled doses, missed doses, backlogged entries, archived meds—all this data stayed locked inside Health. Third-party health apps that wanted to build experiences like “medication-symptom correlation,” “long-term adherence charts,” or “side effect reminders” had to ask users to re-enter everything, creating a fragmented experience.

iOS 26 opens that door. HealthKit adds a new set of Medications APIs across iOS, iPadOS, and visionOS (00:17). Third-party apps can now read the medication list users added in Health and every dose record, and connect them to symptoms, side effects, and medical concepts using clinical coding systems like RxNorm. Authorization is smoother too: when users add a new medication in Health, the system directly shows a toggle to “share with authorized apps”—no need for the app to request permission again (22:46).


Details

Two Core Data Objects

The new API revolves around two objects (02:16):

  • HKUserAnnotatedMedication: A specific medication the user added to Health, containing isArchived (whether archived/no longer taken), hasSchedule (whether a reminder schedule is set), nickname (user’s nickname, e.g., calling Amoxicillin “Antibiotics”), and a reference to an HKMedicationConcept (02:59).
  • HKMedicationDoseEvent: A new type of HKSample representing “one dose that should have or actually did occur”. Contains log status (taken / skipped / snoozed / no interaction), scheduled date and scheduled quantity, actual dose quantity, and a medication concept identifier that links it to a specific medication (04:32).

HKMedicationConcept itself is not a prescription record—it is the “conceptual meaning of a medication”—a cross-device stable identifier, a display text (e.g., “Amoxicillin Trihydrate 500mg Oral Tablet”), a general form (capsule / tablet / liquid), and a set of related codings (e.g., RxNorm code 308192) (03:38).

Requesting Authorization: Per-Object for Medications, Doses Follow Automatically

Medications are objects, not samples, so authorization uses the per-object path, with object type set to the new HKUserAnnotatedMedicationType (10:18):

HealthDataAccessRequest(
    store: healthStore,
    objectType: HKUserAnnotatedMedicationType(),
    trigger: $triggerAuthorization
) { result in
    // Handle authorization result
}

Key points:

  • objectType uses HKUserAnnotatedMedicationType(), telling the system to authorize at the object level. This presents a per-medication selection interface where users can decide individually whether to share each medication with the current app.
  • trigger is a SwiftUI state binding; setting it to true brings up the authorization sheet.
  • Once the user authorizes a medication, you do not need to separately request read permission for that medication’s dose events—dose events are automatically authorized (11:10).

If you also need to read sample types like “symptoms” (headache, nausea), use a separate request passing a list of sample types (11:23).

Querying Medication List: New Query Descriptor

let descriptor = HKUserAnnotatedMedicationQueryDescriptor()
let medications = try await descriptor.result(for: healthStore)

Key points:

  • HKUserAnnotatedMedicationQueryDescriptor is a newly introduced descriptor specifically for fetching medication lists (02:39).
  • Without a predicate or limit, it returns both active and archived medications (12:32).
  • Supported predicates include two new predicates: isArchived and hasSchedule (08:07).
  • The app only sees medications the user has authorized; unauthorized ones won’t appear in results.

Querying Dose Events: Reuse HKSample Query System

Dose events are a new subtype of HKSample, so you can query them directly using the three existing query types: sample query, anchored object query, and observer query (08:29). In the demo, when querying “the most recent dose taken today,” a sample query descriptor was used with a compound predicate (filtering by medication concept, today’s date, and log status = taken), configured with sort + limit = 1 (13:22).

Chart Scenarios: Use Anchored Object Query for Real-Time Updates

For continuously refreshing views like “medication trend charts,” use anchored object query. Eric pointed out a few gotchas (18:21):

  • Dose events can be backlogged to a past date;
  • Editing once deletes the old sample before writing the new one;
  • Reminders with no user interaction still leave a record.

When processing results, you must consume deleted objects first, then handle added samples—otherwise your data model will show phantom points. The anchored query’s Swift async interface continuously yields new batches, making it ideal for real-time charts (19:57).

Connecting Medications to Symptoms with RxNorm

HKMedicationConcept.relatedCodings contains a set of clinical codings (system + code), where the RxNorm system URL is http://www.nlm.nih.gov/research/umls/rxnorm (15:55). In the demo, Srishti prepared a static dictionary mapping “RxNorm code → side effect symptom list,” used the medication’s RxNorm code to look up which symptom options to display, let users record symptom intensity with emoji, and finally saved it as a HealthKit category sample (16:18).

”Zero-Friction Authorization” for New Medications

After an app has requested medication authorization, when the user adds another new medication in Health, the Health app directly shows a “share with XX app” toggle before saving—developers don’t need to request authorization again (22:46). The app will naturally see the new medication on its next query.


Key Takeaways

1. Treat Health App as the Medication Data Source, Stop Re-entering Data

Why it’s worth doing: Many health apps previously required users to re-enter medications, creating a fragmented experience with low adherence. Now you can read directly from Health—users add meds where they add meds, third-party apps focus on value-added experiences.

How to start: Add an “Import medications from Health” entry point in onboarding, call HealthDataAccessRequest + HKUserAnnotatedMedicationType() to let users select which medications to share.

2. Use RxNorm to Link Medications to Side Effect Knowledge Bases

Why it’s worth doing: Medication names may drift across devices and languages, but RxNorm codes are stable global identifiers. Once your side effects, drug interactions, and educational content are indexed on RxNorm, they can be reused across users and regions.

How to start: Filter HKMedicationConcept.relatedCodings for codes where the system is the RxNorm URL (http://www.nlm.nih.gov/research/umls/rxnorm), build a lookup table of “RxNorm code → side effect list,” and map against existing HealthKit category types (headache, nausea, etc.) to let users log intensity.

3. Use Anchored Object Query for “Adherence” Charts

Why it’s worth doing: Dose events update as a stream—old data gets modified, past dates get backfilled. Anchored query provides dual-track updates with “increments + deletion list,” making it the best match for chart scenarios—more efficient than observer + sample query (19:50).

How to start: In your chart view, start a Swift async anchored query. Pass nil for the first anchor, then for each yielded batch of results, apply deletes first then additions, updating the chart data source.

4. Design Separate Views for Skipped / Snoozed

Why it’s worth doing: Log status isn’t just “taken.” Treat skipped as “reminder didn’t work” and snoozed as a signal to “redesign reminder frequency,” and you can surface insights deeper than Health’s built-in UI.

How to start: Pull the past 30 days of non-taken records using the dose event’s log status predicate, aggregate by medication, and show users “missed dose hot spots.”

5. Turn “Auto-Authorize New Medications” into a Product Promise

Why it’s worth doing: Users hate repeatedly authorizing across apps. Health has built new medication sharing into a toggle after the first authorization—write this mechanism into your onboarding promise with “Remember to check share with me when adding new meds in Health”—and retention becomes steadier.

How to start: Add explanation copy on the success screen after first authorization, and ensure your main app query path guarantees “new meds appear automatically,” avoiding local cache that blocks new data.


Comments

GitHub Issues · utterances