---
title: "Blood Pressure API: How to Read BP Data In Your App"
canonical: "https://aifitnessapi.com/data/blood-pressure-api"
cluster: "Health Data"
primary_query: "blood pressure api"
last_reviewed: "2026-08-12"
description: "How blood pressure works in HealthKit and Health Connect: systolic and diastolic as a pair, mandatory cuff-site fields, and why no wearable supplies it."
publisher: "AIFitnessAPI — independent, not sponsored"
cite_as: "\"Blood Pressure API: How to Read BP Data In Your App\", AIFitnessAPI, https://aifitnessapi.com/data/blood-pressure-api"
---

# Blood Pressure API: How to Read BP Data In Your App

> Blood pressure reaches an app through the two on-device stores, not through a wearable feed. Apple HealthKit splits it into the quantity types bloodPressureSystolic and bloodPressureDiastolic and asks you to combine them into a single correlation, HKCorrelationTypeIdentifier.bloodPressure. Android Health Connect uses one BloodPressureRecord in the Vitals category, where systolic, diastolic, bodyPosition, and measurementLocation are all mandatory fields. It is a real measurement, but the instrument is a cuff outside your app: both platforms also expose a write permission, so a stored value may have come from a monitor's companion app or from a person typing. Our pages document no consumer wearable that measures blood pressure, so verify any device claim against that vendor's own documentation and regulatory record.

- Canonical: https://aifitnessapi.com/data/blood-pressure-api
- Last reviewed: 2026-08-12
- Publisher: AIFitnessAPI (https://aifitnessapi.com) — independent, not sponsored
- Cite as: "Blood Pressure API: How to Read BP Data In Your App", AIFitnessAPI, https://aifitnessapi.com/data/blood-pressure-api

---

Blood pressure is the metric where the API question and the hardware question stop being separable. Steps, heart rate, and sleep land in a health store because a device the user already wears produced them in the background. A blood pressure pair lands because somebody wrapped a cuff around an arm and inflated it — or because an app wrote down a number a user read off a screen. Both mobile platform stores are built around that fact, and it drives every decision downstream.

## Both platforms model BP as a pair, not a number

On iOS the reading is split across two quantity sample types. Apple documents `HKQuantityTypeIdentifier.bloodPressureSystolic` as "A quantity sample type that measures the user's systolic blood pressure" and `HKQuantityTypeIdentifier.bloodPressureDiastolic` as the diastolic equivalent. Both are listed from iOS 8.0 and watchOS 2.0, both use pressure units, and both measure discrete values rather than cumulative ones.

Apple's own discussion note is the part teams miss: when recording blood pressure, combine the systolic and diastolic samples into a single correlation object, `HKCorrelationTypeIdentifier.bloodPressure`, documented as "A correlation sample that combines a systolic sample and a diastolic sample into a single blood pressure reading."

That has two practical consequences. When writing, you create two quantity samples and save them inside one correlation, not as two independent samples that happen to share a timestamp. When reading, if you query only the systolic type you get a column of numbers with no guaranteed partner — pairing them yourself by timestamp is a heuristic, not a contract.

Health Connect takes the opposite approach and puts the pair inside one record. `BloodPressureRecord` sits in the Vitals category, is an instantaneous record type, and uses the `Pressure` unit. Its mandatory fields are `systolic`, `diastolic`, `bodyPosition`, `measurementLocation`, `metadata`, and `time`. The Kotlin reference describes the class as capturing "the blood pressure of a user," where "Each record represents a single instantaneous blood pressure reading," and says it throws `IllegalArgumentException` if one of the values is outside the valid range.

## Where you can get it

| Source | What it gives you | How you access it | Verified from |
|---|---|---|---|
| Apple HealthKit | `bloodPressureSystolic` and `bloodPressureDiastolic` quantity types, plus the `bloodPressure` correlation | On-device read/write with per-type authorization; no cloud pull | Apple HealthKit developer documentation for each identifier, fetched 2026-08-12 |
| Android Health Connect | `BloodPressureRecord` — one record carrying both values plus position and cuff site | On-device read/write via the Health Connect client, gated on `android.permission.health.READ_BLOOD_PRESSURE` and `WRITE_BLOOD_PRESSURE` | Health Connect data types page and the `BloodPressureRecord` Kotlin reference, fetched 2026-08-12 |
| Health Connect aggregates | `SYSTOLIC_AVG`, `SYSTOLIC_MAX`, `SYSTOLIC_MIN`, `DIASTOLIC_AVG`, `DIASTOLIC_MAX`, `DIASTOLIC_MIN` | Aggregate query against the same record type | Health Connect data types page, fetched 2026-08-12 |
| Wearable cloud APIs (Fitbit, Garmin, Oura, WHOOP, Strava) | No blood pressure field is documented on our pages for any of them | Cloud OAuth where a field exists at all | Not documented on our pages — verify in each vendor's live data dictionary |
| Cuff and monitor vendors | Vendor SDK, or the vendor's companion app writing into HealthKit or Health Connect | Varies by product | Not documented on our pages — verify |
| Aggregators (Terra, Junction, Rook) | Whatever the underlying source supplies, under one normalized schema | One cloud API plus webhooks | Not documented on our pages — verify |

The honest summary of that table: the two on-device stores have a well-specified place to put a blood pressure reading, and nothing on our pages documents a consumer wearable that produces one. Treat a populated BP type as evidence that *some* app wrote a value, not as evidence that a watch measured it.

## The context fields are the honest part

Health Connect does not let you write a bare pair. `bodyPosition` and `measurementLocation` are mandatory, and the constants are explicit: `BODY_POSITION_UNKNOWN`, `BODY_POSITION_STANDING_UP`, `BODY_POSITION_SITTING_DOWN`, `BODY_POSITION_LYING_DOWN`, and `BODY_POSITION_RECLINING`; `MEASUREMENT_LOCATION_UNKNOWN`, `MEASUREMENT_LOCATION_LEFT_WRIST`, `MEASUREMENT_LOCATION_RIGHT_WRIST`, `MEASUREMENT_LOCATION_LEFT_UPPER_ARM`, and `MEASUREMENT_LOCATION_RIGHT_UPPER_ARM`.

Read that as design intent. The schema treats "sitting, left upper arm" and "standing, right wrist" as different readings, not the same reading with different notes attached. If your normalization layer flattens BP into two integers and a timestamp, you have thrown away the fields the platform considered mandatory — and you cannot get them back from an average.

## Measured, but by equipment you did not build

Blood pressure is a measurement, unlike a modeled value such as VO2 max. The catch is that the measuring instrument is outside your app and outside the platform's guarantees. Both platforms expose a *write* permission alongside the read permission, so any value you read could have come from a cuff's companion app, a general health-notes app, or a person typing what they saw. `metadata` is where provenance lives, and it is the first thing to inspect before you plot anything.

Wrist devices are the specific place to slow down. Our pages do not document any consumer wrist wearable that measures blood pressure, so this page will not claim one exists. What is verifiable is that Health Connect encodes wrist and upper-arm as distinct measurement locations, which is a strong hint that the two are not interchangeable inputs. Anything beyond that — whether a particular device is validated, against which protocol, and in which markets it is cleared to make the claim — has to come from that vendor's own documentation and regulatory record.

Useful questions to put to a device vendor before you integrate:

- Is the reading taken at the upper arm or the wrist, and does the API tell you which?
- Does the product carry a regulatory clearance for blood pressure measurement in the markets you ship to, and can they point you at the record?
- Was it validated against a published protocol, and is that validation public?
- Does the API return the reading the device computed, or a value smoothed or re-derived on their servers?
- Does it expose body position, or do you have to prompt the user for it yourself?

## Ranges, units, and the rest of the traps

- **Valid-range rejection.** Health Connect documents systolic as valid from 20-200 mmHg, and 20-300 mmHg for SDK extension 17 or higher; diastolic is 10-180 mmHg, and 10-300 mmHg for SDK extension 17 or higher. Out-of-range writes throw rather than silently clamping, and the bounds differ by SDK extension — so the same payload can be accepted on one device and rejected on another.
- **Aggregates break the pair.** `SYSTOLIC_AVG` and `DIASTOLIC_AVG` are computed independently. Average them over a week and you get a number pair that no single reading ever produced. For anything a user will read as "my blood pressure," aggregate whole readings, not columns.
- **There is no daily blood pressure.** The record is instantaneous on Android and discrete on iOS. Any notion of a daily or weekly value is yours to define, and you should say in the UI which readings went into it.
- **Units.** Apple's types use pressure units, so you pick the `HKUnit` on read and write; store the unit alongside the number instead of assuming millimetres of mercury everywhere in your pipeline.
- **Time zones.** Health Connect records carry `time` and a nullable `zoneOffset`, described as the user's experienced offset — absent, queries fall back to the current system offset. A morning reading taken while travelling can land on the wrong local day if you ignore it. See [heart rate API](/data/heart-rate-api) for how the same problem shows up in a higher-frequency metric.
- **Background and history are separate permissions.** Reading in the background needs `android.permission.health.READ_HEALTH_DATA_IN_BACKGROUND`, and reading data older than 30 days needs `android.permission.health.READ_HEALTH_DATA_HISTORY`, both declared separately from the data-type permission.

## Where the wellness framing runs out

Steps and sleep sit comfortably in general-wellness territory. Blood pressure is closer to the line, and the line is drawn by what your app *claims*, not by which API you called. Displaying a value a user's own cleared cuff wrote, with no interpretation, is a different product from flagging readings, suggesting thresholds, or telling someone their number looks high. Our [FDA fitness app regulation](/compliance/fda-fitness-app-regulation) page covers how the general-wellness versus medical-device distinction is framed; treat it as the vocabulary for a conversation with counsel, not as a substitute for one. This page gives no medical advice and no legal advice, and neither should your UI copy.

## Before you ship

Re-check both platform references against the live docs — identifiers, mandatory fields, permission strings, and the SDK-extension-dependent ranges all change. On iOS, write through the correlation and read through it too. On Android, carry `bodyPosition` and `measurementLocation` end to end. For any device vendor, get the measurement site and the regulatory position in writing before you display their numbers. If you also need the on-device versus cloud tradeoff spelled out, see [on-device vs cloud health data](/learn/on-device-vs-cloud-health-data), and the platform-by-platform integration details in [integrate Health Connect](/integrate/google-health-connect) and [integrate Apple HealthKit](/integrate/healthkit).

## FAQ

### Which platform data types store a blood pressure reading?

Apple HealthKit uses two quantity sample types, HKQuantityTypeIdentifier.bloodPressureSystolic and HKQuantityTypeIdentifier.bloodPressureDiastolic, both documented from iOS 8.0 and watchOS 2.0, both using pressure units and measuring discrete values. Android Health Connect uses a single BloodPressureRecord in the Vitals category, an instantaneous record in the Pressure unit, gated on android.permission.health.READ_BLOOD_PRESSURE. Re-check both references in the live docs before you build, since identifiers and permission strings change.

[Permalink](https://aifitnessapi.com/data/blood-pressure-api#faq-1)

### Why does HealthKit want systolic and diastolic combined into a correlation?

Because on iOS the two halves are separate sample types, and only the correlation ties them together as one reading. Apple documents HKCorrelationTypeIdentifier.bloodPressure as a correlation sample that combines a systolic sample and a diastolic sample into a single blood pressure reading, and its discussion notes say to combine them when recording. If you save them as two unrelated samples, anything reading them back has to guess at pairing by timestamp, which is a heuristic rather than a guarantee.

[Permalink](https://aifitnessapi.com/data/blood-pressure-api#faq-2)

### Does Health Connect require body position and cuff site for BP?

Yes. BloodPressureRecord lists systolic, diastolic, bodyPosition, measurementLocation, metadata, and time as mandatory fields. The constants are explicit, covering standing, sitting, lying down, reclining, and unknown positions, and left or right wrist versus left or right upper arm for location. Treat those as part of the reading rather than optional notes: a normalization layer that flattens BP to two integers and a timestamp discards fields the platform itself considers required.

[Permalink](https://aifitnessapi.com/data/blood-pressure-api#faq-3)

### Can a smartwatch send blood pressure into my app without a cuff?

Our pages document no consumer wrist wearable that measures blood pressure, so this is a claim to verify with the vendor rather than assume. What the platforms guarantee is only that some app wrote a value: both HealthKit and Health Connect expose a write permission alongside the read permission, so a stored reading may have come from a monitor's companion app or from a person typing a number in. Inspect the record metadata for provenance before you plot anything.

[Permalink](https://aifitnessapi.com/data/blood-pressure-api#faq-4)

### Why do Health Connect blood pressure writes throw an exception?

The record validates ranges and throws IllegalArgumentException when a value falls outside them. Health Connect documents systolic as valid from 20-200 mmHg, or 20-300 mmHg for SDK extension 17 or higher, and diastolic as 10-180 mmHg, or 10-300 mmHg for SDK extension 17 or higher. Because the bounds depend on the SDK extension level, the same payload can be accepted on one device and rejected on another, so handle the failure rather than assuming clamping.

[Permalink](https://aifitnessapi.com/data/blood-pressure-api#faq-5)
