---
title: "Health Connect Medical Records API: FHIR Data on Android"
canonical: "https://aifitnessapi.com/data/health-connect-medical-records-api"
cluster: "Health Data"
primary_query: "health connect medical records api"
last_reviewed: "2026-10-04"
description: "Write and read FHIR R4 and R4B records in Health Connect: MedicalResource, MedicalDataSource, the 12 medical permissions, and the experimental API status."
publisher: "AIFitnessAPI — independent, not sponsored"
cite_as: "\"Health Connect Medical Records API: FHIR Data on Android\", AIFitnessAPI, https://aifitnessapi.com/data/health-connect-medical-records-api"
---

# Health Connect Medical Records API: FHIR Data on Android

> Health Connect's Medical Records feature lets Android apps write and read medical data as FHIR resources in versions R4 (4.0.1) and R4B (4.3.0), organized into MedicalDataSource containers and returned as MedicalResource objects across twelve medical resource types such as vaccines, medications and laboratory results. Writing needs one permission, android.permission.health.WRITE_MEDICAL_DATA, while reading needs a separate READ_MEDICAL_DATA permission per type. Google marks the APIs @ExperimentalPersonalHealthRecordApi, ships them in Jetpack Health Connect 1.1.0-beta02, which requires compiling against the Android 16 SDK, and says the Play policy for medical records access is still being developed. Check FEATURE_PERSONAL_HEALTH_RECORD before every call, because unsupported devices throw UnsupportedOperationException.

- Canonical: https://aifitnessapi.com/data/health-connect-medical-records-api
- Last reviewed: 2026-10-04
- Publisher: AIFitnessAPI (https://aifitnessapi.com) — independent, not sponsored
- Cite as: "Health Connect Medical Records API: FHIR Data on Android", AIFitnessAPI, https://aifitnessapi.com/data/health-connect-medical-records-api

---

Health Connect started as a store for fitness and wellness data. Google's [Medical Records overview](https://developer.android.com/health-and-fitness/health-connect/medical-records) 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](/fix/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](/health-connect/permissions).

## 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 vaccines `MedicalResource`s, 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.source` with 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 `MedicalDataSource` also 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](/data/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](/compliance/google-play-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](/compliance/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.

## FAQ

### 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.

[Permalink](https://aifitnessapi.com/data/health-connect-medical-records-api#faq-1)

### 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.

[Permalink](https://aifitnessapi.com/data/health-connect-medical-records-api#faq-2)

### 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.

[Permalink](https://aifitnessapi.com/data/health-connect-medical-records-api#faq-3)

### 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.

[Permalink](https://aifitnessapi.com/data/health-connect-medical-records-api#faq-4)
