---
title: "Body Temperature API: Core, Skin and Wrist Temperature Data"
canonical: "https://aifitnessapi.com/data/body-temperature-api"
cluster: "Health Data"
primary_query: "body temperature api"
last_reviewed: "2026-10-18"
description: "Body, basal and skin temperature on each platform: absolute readings, deltas against a baseline, nightly means, and the Celsius flag on Bluetooth."
publisher: "AIFitnessAPI — independent, not sponsored"
cite_as: "\"Body Temperature API: Core, Skin and Wrist Temperature Data\", AIFitnessAPI, https://aifitnessapi.com/data/body-temperature-api"
---

# Body Temperature API: Core, Skin and Wrist Temperature Data

> The platforms split temperature into three kinds that are not interchangeable: a body or core reading (HealthKit bodyTemperature, Health Connect BodyTemperatureRecord, the Google Health API's core-body-temperature, the Bluetooth Temperature Measurement characteristic), a basal reading filed under cycle tracking, and a skin value taken during sleep. That sleep-time skin value has a different shape on every platform: Health Connect's SkinTemperatureRecord stores deltas against a baseline that may be unstated, the Google Health API gives a nightly mean beside a 30-day median baseline, and Apple's appleSleepingWristTemperature is a read-only temperature sample. Wear OS Health Services defines no temperature data type at all. Record which kind a value is, and its unit, before you put two of them on one chart.

- Canonical: https://aifitnessapi.com/data/body-temperature-api
- Last reviewed: 2026-10-18
- Publisher: AIFitnessAPI (https://aifitnessapi.com) — independent, not sponsored
- Cite as: "Body Temperature API: Core, Skin and Wrist Temperature Data", AIFitnessAPI, https://aifitnessapi.com/data/body-temperature-api

---

Temperature looks like the simplest vital a health store holds: one number, one unit. In the platform data it is three different measurements that happen to share a word. One is a reading of the body, taken with a thermometer. One is the same kind of reading taken at rest, which both mobile stores file under cycle tracking rather than vitals. The third is skin temperature measured overnight by a wearable, and that one is often not an absolute temperature at all. Mixing them is the main way a temperature feature goes wrong.

## Three temperatures, not one

| Kind | Google Health API | Apple HealthKit | Android Health Connect | Bluetooth GATT |
|---|---|---|---|---|
| Body or core reading | [`core-body-temperature`](/google-health-api/core-body-temperature): a Sample in Celsius | [`bodyTemperature`](/healthkit-identifiers/body-temperature): discrete, temperature units, group Vital signs | [`BodyTemperatureRecord`](/health-connect/body-temperature-record): instantaneous, Vitals | [Temperature Measurement 0x2A1C](/bluetooth-fitness/temperature-measurement) |
| Basal, at rest | none | [`basalBodyTemperature`](/healthkit-identifiers/basal-body-temperature): group Reproductive health | [`BasalBodyTemperatureRecord`](/health-connect/basal-body-temperature-record): Cycle Tracking | none |
| Skin, during sleep | [`daily-sleep-temperature-derivations`](/google-health-api/daily-sleep-temperature-derivations): one Daily record a night; [`skin-temperature-sensors`](/google-health-api/skin-temperature-sensors): v4beta samples | [`appleSleepingWristTemperature`](/healthkit-identifiers/apple-sleeping-wrist-temperature): read-only, group Body measurements | [`SkinTemperatureRecord`](/health-connect/skin-temperature-record): a Series of deltas, Vitals | none |

Every cell comes from this site's generated references: Google Health API types read from Google's documentation on 2026-10-17, HealthKit identifiers from Apple's on 2026-10-02, Health Connect records from Google's on 2026-10-03, and the Bluetooth SIG's GATT files read on 2026-10-17. Wear OS Health Services has no row because none of the 65 `DataType` constants in Google's reference, read 2026-10-04, is a temperature.

The descriptions say plainly that these are different measurements. Google describes `core-body-temperature` as a "Core body temperature measurement, distinct from peripheral body temperature," that "reflects the temperature of the body's internal organs." Health Connect's basal record "Captures the body temperature of a user when at rest (for example, immediately after waking up). Can be used for checking the fertility window." On both mobile stores the basal type sits with reproductive data and has its own permission, `android.permission.health.READ_BASAL_BODY_TEMPERATURE` on Android, separate from `READ_BODY_TEMPERATURE`. The [menstrual cycle API](/data/menstrual-cycle-api) guide covers basal temperature as a cycle input.

## Absolute readings and deltas

The skin-temperature types are where the shapes split.

Health Connect's `SkinTemperatureRecord` is a Series record that "can represent a series of measurements of temperature differences." Its `deltas` field is "a list of skin temperature Delta. If baseline is set, these values are expected to be relative to it. Otherwise, they are deltas against an unspecified starting baseline." The `baseline` itself is optional and null by default. Its aggregates are `TEMPERATURE_DELTA_AVG`, `TEMPERATURE_DELTA_MAX` and `TEMPERATURE_DELTA_MIN`, typed `TemperatureDelta`, and the record sits behind a feature check: Google's reference says to call `getFeatureStatus` with `FEATURE_SKIN_TEMPERATURE` before reading or writing it.

The Google Health API reports the same idea as a daily summary. Its `daily-sleep-temperature-derivations` type "Provides derived sleep temperature values, calculated from skin or internal device temperature readings during sleep." The required `nightlyTemperatureCelsius` is "the mean of skin temperature samples taken from the user’s sleep"; the optional `baselineTemperatureCelsius` is "the median of the user's nightly skin temperature over the past 30 days"; and `relativeNightlyStddev30dCelsius` gives the spread of nightly minus baseline over 30 days. Google's migration table maps the Fitbit Web API's skin temperature data to it, and the type supports webhooks.

Apple's `appleSleepingWristTemperature` is a discrete sample in temperature units, available from iOS 16.0 and watchOS 9.0, and Apple states "These samples are read-only." Apple's longer discussion of how Apple Watch builds the nightly value is quoted on our [menstrual cycle API](/data/menstrual-cycle-api) page.

So a Health Connect value may be relative to nothing you can see, a Google value is an absolute nightly mean with its baseline beside it, and an Apple value is a sample whose shape Apple sets. If you want one series across platforms, our recommendation is to store Google's nightly mean and baseline separately and compute any difference yourself, and to keep Health Connect deltas in a column of their own until a record tells you its baseline.

Among the wearable vendors, our [Oura vs WHOOP comparison](/compare/oura-vs-whoop) describes Oura's temperature as a nightly deviation from the user's own baseline rather than an absolute reading, and WHOOP's skin temperature as available to 4.0 members. Verify both in each vendor's current documentation.

## Units, ranges and the Fahrenheit flag

- **Google Health API:** Celsius in the field name. `core-body-temperature` takes `temperatureCelsius` in the range `[0, 100]`; the nightly and sensor types report Celsius too.
- **Health Connect:** a `Temperature` unit object. Body, basal and skin baseline values share the documented valid range of 0 to 100 Celsius degrees.
- **HealthKit:** temperature units chosen by you on read and write, as for every quantity type; store the `HKUnit` you used beside the value.
- **Bluetooth:** bit 0 of the Temperature Measurement Flags field decides the unit. At 0 the value field is Celsius; at 1 it is Fahrenheit. The value is a `medfloat32` either way, so a parser that ignores the flag reads a plausible number in the wrong scale.

## Where the reading was taken

Each platform records the body site differently, and only some make it a field:

- **Google:** `core-body-temperature` has an optional `measurementLocation` enum of 18 values, from `ARMPIT`, `EAR`, `MOUTH` and `FOREHEAD` to `TEMPORAL_ARTERY`, `WRIST` and `GASTRO_INTESTINAL`, plus `OTHER` and `MEASUREMENT_LOCATION_UNSPECIFIED`.
- **Health Connect:** `BodyTemperatureRecord` has `measurementLocation`, which Google's data-types table lists among the mandatory fields while the Kotlin reference calls it optional; check both against your SDK version. `SkinTemperatureRecord` takes `MEASUREMENT_LOCATION_FINGER`, `MEASUREMENT_LOCATION_TOE`, `MEASUREMENT_LOCATION_WRIST` or `MEASUREMENT_LOCATION_UNKNOWN`, the default.
- **HealthKit:** no field; Apple keeps the site in [`HKMetadataKeyBodyTemperatureSensorLocation`](/healthkit-metadata-keys#key-hkmetadatakeybodytemperaturesensorlocation), "The location where a specific body temperature reading was taken."
- **Bluetooth:** an optional Temperature Type field, present when bit 2 of Flags is set, in the format of the [Temperature Type characteristic](/bluetooth-fitness#char-temperature-type), which the SIG ties to IEEE 11073-10408-2008.

## How each one is read

- **Google Health API:** `core-body-temperature` lists `list`, `get`, `reconcile`, `rollup` and `dailyRollup`, and its rollup returns an average, maximum and minimum in Celsius; Google's table marks it with no webhook support and names no compatible device. `daily-sleep-temperature-derivations` lists `list` and `reconcile` only. `skin-temperature-sensors` is on the v4beta preview channel, lists only `list`, and Google's table names two compatible devices, Pixel Watch 4 and Pixel Watch 5.
- **HealthKit:** all three temperature identifiers are discrete, so a statistics query averages or takes the minimum or maximum; summing them is meaningless.
- **Health Connect:** `BodyTemperatureRecord` and the basal record have no aggregate metrics; read the records. The skin record aggregates deltas only.
- **Bluetooth:** a thermometer can also send [Intermediate Temperature 0x2A1E](/bluetooth-fitness/intermediate-temperature), which the SIG describes as values sent "for display purposes while a measurement is in progress." It has the same layout as the final measurement, so subscribe to both only if you show progress, and store the final one.

## Traps

- **A delta is not a temperature.** Plotting Health Connect skin deltas on the same axis as a Google nightly mean draws a line that means nothing.
- **Basal is its own permission.** An app granted body temperature on Android has not been granted basal temperature, and the two live in different categories on both stores.
- **The feature check is not optional.** On a device without the skin temperature feature, `SkinTemperatureRecord` cannot be read or written at all; design the empty state.
- **Preview channel.** `skin-temperature-sensors` is v4beta; build against it knowing Google can change it before it reaches v4.
- **Unit flags on the wire.** Read the Bluetooth Flags byte before the value, every notification.

## Keep the claims small

Body temperature is a vital sign, and an app that flags a fever, predicts illness or reads meaning into a skin-temperature change is making a different product from one that shows a trend. Our [FDA fitness app regulation](/compliance/fda-fitness-app-regulation) page sets out how the general-wellness line is usually drawn. Nothing on this page is medical advice, and none of the platforms above documents a threshold your UI should apply.

## Before you ship

Re-read each type's reference page here before release; they regenerate from Google's, Apple's and the SIG's sources. Store the kind of temperature, the unit, the site and whether the value is a delta. On Android, gate skin temperature behind the feature check and request basal temperature separately. On Bluetooth, read the unit flag first.

## FAQ

### Is Health Connect skin temperature an absolute reading or a change?

A change. Google documents SkinTemperatureRecord as a Series record that can represent a series of measurements of temperature differences. Its deltas are relative to the record's baseline when one is set, and otherwise to an unspecified starting baseline, and the baseline field is optional and null by default. The aggregates it offers, TEMPERATURE_DELTA_AVG, MAX and MIN, are temperature deltas too. Check FEATURE_SKIN_TEMPERATURE before reading it.

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

### Does Wear OS Health Services have a temperature data type?

No. None of the 65 DataType constants in Google's Health Services reference, read on 2026-10-04, is a temperature, so a Wear OS app cannot ask Health Services for one. The temperature types this site documents for Android are Health Connect's BodyTemperatureRecord, BasalBodyTemperatureRecord and SkinTemperatureRecord, read through the Health Connect client, and the Google Health API's cloud types for Fitbit and Pixel devices.

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

### How does a Bluetooth thermometer say whether a reading is Celsius or Fahrenheit?

With bit 0 of the Flags field that opens the Temperature Measurement characteristic, 0x2A1C. When the bit is 0 the measurement value is in degrees Celsius, and when it is 1 the value is in degrees Fahrenheit, a medfloat32 in both cases. Bit 1 adds a time stamp and bit 2 a temperature type giving the body site. Intermediate Temperature, 0x2A1E, uses the same layout for values shown while a measurement is still in progress.

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

### What does the Google Health API report for nightly skin temperature?

One Daily record per night from daily-sleep-temperature-derivations. Google describes nightlyTemperatureCelsius as the mean of skin temperature samples taken during sleep, an optional baselineTemperatureCelsius as the median of the nightly value over the past 30 days, and an optional standard deviation of nightly minus baseline over 30 days. The type supports list and reconcile with webhooks, and Google maps the Fitbit Web API's skin temperature data to it.

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