Health Connect Medical Records API: FHIR Data on Android
Last verified October 4, 2026 · 8 min read
Covered here:Health ConnectHealthKit
Health Connect started as a store for fitness and wellness data. Google's Medical Records overview describes the extension: it "extends this capability to include basic medical data in Fast Healthcare Interoperability Resources (FHIR) format." Apps write FHIR resources, the user browses them in Health Connect, and other apps read them under fine-grained permissions.
Status: experimental, and it says so#
Google is plain about the state of this API. "The Medical Records APIs are marked with an annotation of ExperimentalPersonalHealthRecordApi, which indicates that these APIs are still under development and subject to change." The overview lists two current limits:
- "The Play Policy for Medical Records access is still being developed, and apps may need to meet additional requirements before they can be released on the Play Store."
- "Some features, such as changelogs-based APIs, have not been developed for Medical Records APIs yet."
The APIs "are made available through Health Connect version 1.1.0-beta02 in Jetpack," and "Updating your Jetpack dependency to this version requires that apps be compiled against the Android 16 SDK." The MedicalResource and MedicalDataSource reference pages say "Added in 1.1.0". Google also recommends moving off the framework APIs that came first, because "All guides and sample code are written for Jetpack."
Every class, method and permission constant below carries the experimental annotation. Plan for source changes between releases.
The feature gate#
Check availability first. The read and write guides both use HealthConnectFeatures.FEATURE_PERSONAL_HEALTH_RECORD with getFeatureStatus, comparing against FEATURE_STATUS_AVAILABLE. The reference is specific about what happens otherwise. For the classes and client methods, "An UnsupportedOperationException would be thrown if the feature is not available." For the permission constants, "If not available, this permission will not be granted if requested." Our Health Connect not available page covers the wider availability checks.
Data model#
| Class | Fields | What Google says |
|---|---|---|
MedicalDataSource | id, packageName, fhirBaseUri, displayName, fhirVersion, lastDataUpdateTime | Represents "a user-facing source of data, such as a healthcare organization, a hospital, or an API." The id is "generated by HealthConnect at creation time." |
MedicalResource | type, id (MedicalResourceId), dataSourceId, fhirVersion, fhirResource | "a Health Connect specific concept" that contains more than a FhirResource, including its data source and type |
MedicalResourceId | dataSourceId, fhirResourceType, fhirResourceId (as Google's read and write guides construct it) | Used to read and delete specific resources |
Google sets a few rules on data sources. displayName "must be unique across all medical data sources created by an app, otherwise an IllegalArgumentException will be thrown." The FHIR base URI is the server's base URL, or an app-defined URI such as a deep link when there is no FHIR server, with a "maximum length for the URI" of "2000 characters." And "The data source can not be updated after creation."
The twelve medical resource types#
Health Connect assigns each resource a type at insertion. Google's reference adds that "this list is non exhaustive and may increase in future releases."
| Type constant | Value | FHIR resources (data format page) | Read permission |
|---|---|---|---|
MEDICAL_RESOURCE_TYPE_VACCINES | 1 | Immunization | READ_MEDICAL_DATA_VACCINES |
MEDICAL_RESOURCE_TYPE_ALLERGIES_INTOLERANCES | 2 | AllergyIntolerance | READ_MEDICAL_DATA_ALLERGIES_INTOLERANCES |
MEDICAL_RESOURCE_TYPE_PREGNANCY | 3 | Observation with pregnancy LOINC codes | READ_MEDICAL_DATA_PREGNANCY |
MEDICAL_RESOURCE_TYPE_SOCIAL_HISTORY | 4 | Observation with social history LOINC codes or the social-history category | READ_MEDICAL_DATA_SOCIAL_HISTORY |
MEDICAL_RESOURCE_TYPE_VITAL_SIGNS | 5 | Observation with vital signs LOINC codes or the vital-signs category | READ_MEDICAL_DATA_VITAL_SIGNS |
MEDICAL_RESOURCE_TYPE_LABORATORY_RESULTS | 6 | Observation with the laboratory category | READ_MEDICAL_DATA_LABORATORY_RESULTS |
MEDICAL_RESOURCE_TYPE_CONDITIONS | 7 | Condition | READ_MEDICAL_DATA_CONDITIONS |
MEDICAL_RESOURCE_TYPE_PROCEDURES | 8 | Procedure | READ_MEDICAL_DATA_PROCEDURES |
MEDICAL_RESOURCE_TYPE_MEDICATIONS | 9 | Medication, MedicationRequest, MedicationStatement | READ_MEDICAL_DATA_MEDICATIONS |
MEDICAL_RESOURCE_TYPE_PERSONAL_DETAILS | 10 | Patient | READ_MEDICAL_DATA_PERSONAL_DETAILS |
MEDICAL_RESOURCE_TYPE_PRACTITIONER_DETAILS | 11 | Practitioner, PractitionerRole | READ_MEDICAL_DATA_PRACTITIONER_DETAILS |
MEDICAL_RESOURCE_TYPE_VISITS | 12 | Encounter, Location, Organization | READ_MEDICAL_DATA_VISITS |
Every permission string is prefixed android.permission.health.. The full list, with the Jetpack constant names, is on our Health Connect permissions reference.
The client methods#
From the HealthConnectClient reference, fetched 2026-10-04:
| Method | Permission | Notes |
|---|---|---|
createMedicalDataSource(request) | WRITE_MEDICAL_DATA | Must run before any resource is upserted for that source |
upsertMedicalResources(requests) | WRITE_MEDICAL_DATA | Inserts or updates by data source, FHIR type and FHIR id; all-or-nothing |
readMedicalResources(request) | Medical read or write | Paged, with ReadMedicalResourcesInitialRequest then ReadMedicalResourcesPageRequest until nextPageToken is null |
readMedicalResources(ids) | Medical read or write | Order and count of results are "not guaranteed" |
getMedicalDataSources(ids) / (request) | Medical read or write | "There is no specific read permission for getting data sources." |
deleteMedicalResources(ids) / (request) | WRITE_MEDICAL_DATA | Your app "can only delete records that it has written" |
deleteMedicalDataSourceWithData(id) | WRITE_MEDICAL_DATA | Deletes the source "and all data contained within it" |
Google adds that with PERMISSION_WRITE_MEDICAL_DATA granted, "caller is permitted to call this API in either foreground or background."
Who can read what#
The read rules are spelled out in priority order on the client reference, and they surprise people:
- A caller with no medical read permission and no write permission "is not permitted to read any
MedicalResource, including ones that it created." - A caller with the write permission can read its own resources "of any type regardless whether it's in foreground or background."
- A caller with only a read permission, in the background, can read only its own resources of that type. In the foreground, or holding
PERMISSION_READ_HEALTH_DATA_IN_BACKGROUND, "it is permitted to read all vaccinesMedicalResources, including ones that were written by other apps" (Google's example uses vaccines).
Data sources follow the same pattern. A source is visible to a reader only if it contains at least one resource of a type that reader may see.
Writing: validation and transactions#
Health Connect "is intended to store medical records data for a single individual only at this time," so every resource you write should belong to the same person. Google prefers that apps "reconcile data and write a single Patient resource," though it does not enforce that.
Each upsert request must contain an id and a resourceType, must not have a contained field, and must use the FHIR version of its data source. Then the rule that matters most for imports: "If any request is failed to be processed for any reason, none of the requests will be inserted or updated in one transaction." One malformed resource rejects the batch.
The data format page lists the validation checks. Several are marked "Coming soon", meaning not yet enforced, and Google recommends "developing against all listed validation checks to maintain compatibility with future releases." The reference also warns readers that "Each returned MedicalResource is not guaranteed to meet all requirements of the Fast Healthcare Interoperability Resources (FHIR) spec," so validate on read too.
Traps#
- Observations can vanish. Observations are mapped by LOINC code and FHIR category, and "Observations not belonging to any of these categories are not written to Health Connect." Check what came back from an upsert.
- Merging sources hides provenance. If you merge several origins into one data source you "must also assign a new ID to each resource to avoid clashes, and update resource references." Google recommends filling
meta.sourcewith the original source, typically a FHIR base URL. - No change feed yet. Changelog-based APIs do not exist for Medical Records. Sync by paging reads and comparing.
- Deleting a source deletes its data. Google's caution: "deleting a
MedicalDataSourcealso deletes all medical resource records associated with that data source." - Separate permission screen. Google notes medical permission requests show "a separate health records screen." Tell users what they are about to see.
Other sources#
| Source | Medical records | Verified from |
|---|---|---|
| Android Health Connect | FHIR R4 and R4B as MedicalResource, experimental | Google's medical records overview, data format, read and write guides, and Kotlin reference, fetched 2026-10-04 |
| Apple HealthKit | Read-only FHIR DSTU2 and R4 as HKClinicalRecord | See HealthKit clinical records API |
| Wearable cloud APIs and aggregators | Not documented on our pages for Health Connect medical data, so verify with each vendor | None |
The platforms differ at the root. HealthKit apps only read records the system downloads. Health Connect apps write them too, which makes your app a data source for every other app the user authorizes.
Publishing and privacy#
Declare every medical permission in the manifest and the Play Console, and expect extra review: Google says the Play policy for this data is unfinished. Our Health Connect publishing requirements page covers the existing declaration process. Medical records may bring you into regulated territory depending on your role; see is fitness data PHI. This page describes APIs. It is not legal or medical advice.
Before you ship#
Gate every call on FEATURE_PERSONAL_HEALTH_RECORD. Request only the read types your feature uses. Validate FHIR before upserting and batch small. Re-read Google's medical records pages before each release, because the experimental annotation means the shapes above can change.
Frequently asked questions
- Which FHIR versions and resource types does Health Connect accept?
- Google's data format page lists R4 (v4.0.1) and R4B (v4.3.0). The validation table accepts fourteen resource types: AllergyIntolerance, Condition, Encounter, Immunization, Location, Medication, MedicationRequest, MedicationStatement, Observation, Organization, Patient, Practitioner, PractitionerRole and Procedure. Observations are kept only if they map to the laboratory, pregnancy, social history or vital signs categories by LOINC code or FHIR category; Google states other observations are not written.
- How do read and write permissions differ for Health Connect medical data?
- Writing is one permission for everything: Google describes PERMISSION_WRITE_MEDICAL_DATA as allowing the write of medical data of any type, and notes that read permissions are specified per type. Reading needs one of twelve android.permission.health.READ_MEDICAL_DATA_ strings, such as READ_MEDICAL_DATA_VACCINES. Each MedicalResource type is tied to its read permission. All of these must be declared in the manifest and in the Play Console.
- Can a background Health Connect app read medical records written by other apps?
- Only with an extra permission. Google's HealthConnectClient reference says a caller holding only a medical read permission can, in the background, read only its own resources of that type. In the foreground, or with android.permission.health.READ_HEALTH_DATA_IN_BACKGROUND, it can read every resource of that type, including other apps'. A caller with no medical permission at all cannot read anything, even resources it created.
- What happens if one resource in an upsertMedicalResources batch is invalid?
- The whole batch fails. Google documents that if any request fails to be processed for any reason, none of the requests are inserted or updated, as one transaction. Each request must contain a FHIR id and resourceType, must not include a contained field, and must use the same FHIR version as its MedicalDataSource. Validate resources before you send them, and split large imports so one bad record does not block the rest.
Keep reading
Elsewhere on the site
Pages that share this one’s concepts and sources, from other sections.
Next steps
Was this page useful?
Independent comparison, last reviewed October 4, 2026. Pricing, rate limits, and feature availability change often — confirm current details in each provider’s official documentation before you commit. Product and company names are trademarks of their respective owners; AIFitnessAPI is not affiliated with, endorsed by, or sponsored by any product listed here.
← All health data · by AIFitnessAPI