The Google Health API allows your application to receive notifications when a
user's health data changes. Instead of polling for changes, your server
receives an HTTPS POST request
[webhook](https://en.wikipedia.org/wiki/Webhook)
as soon as data is available in the Google Health API.

## Supported data types

Webhook notifications are supported for the following data types:

<br />

| Data type | Available operations | Scope |
|---|---|---|
| **[Active Minutes](https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints.md.txt#activeminutes)** **dataType:** `active-minutes` **filter parameter:** `active_minutes` **Record type:** [Interval](https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints.md.txt#ObservationTimeInterval) **Storage resolution:**1 minute [Webhook support](https://developers.google.com/health/webhooks.md.txt) #### Compatible devices - [Fitbit Air](https://store.google.com/product/google_fitbit_air) - Fitbit Alta - Fitbit Alta HR - Fitbit Blaze - Fitbit Charge 2 - Fitbit Charge 3 - [Fitbit Edge](https://store.google.com/product/google_fitbit_edge) - Fitbit Flex 2 - Fitbit Inspire - Fitbit Inspire HR - [Pixel Watch 4](https://store.google.com/product/pixel_watch_4) | list, reconcile, rollup, dailyRollup | `.activity_and_fitness.readonly` `.activity_and_fitness.writeonly` |
| **[Active Zone Minutes](https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints.md.txt#activezoneminutes)** **dataType:** `active-zone-minutes` **filter parameter:** `active_zone_minutes` **Record type:** [Interval](https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints.md.txt#ObservationTimeInterval) **Storage resolution:**1 minute [Webhook support](https://developers.google.com/health/webhooks.md.txt) #### Compatible devices - [Fitbit Air](https://store.google.com/product/google_fitbit_air) - Fitbit Charge 4 - Fitbit Charge 5 - [Fitbit Charge 6](https://store.google.com/product/fitbit_charge_6) - [Fitbit Edge](https://store.google.com/product/google_fitbit_edge) - Fitbit Inspire 2 - [Fitbit Inspire 3](https://store.google.com/product/fitbit_inspire_3) - Fitbit Ionic - Fitbit Luxe - Pixel Watch - Pixel Watch 2 - [Pixel Watch 3](https://store.google.com/product/pixel_watch_3) - [Pixel Watch 4](https://store.google.com/product/pixel_watch_4) - Fitbit Sense - [Fitbit Sense 2](https://store.google.com/product/fitbit_sense_2) - Fitbit Versa - Fitbit Versa 2 - Fitbit Versa 3 - [Fitbit Versa 4](https://store.google.com/product/fitbit_versa_4) - Fitbit Versa Lite | list, reconcile, rollup, dailyRollup | `.activity_and_fitness.readonly` `.activity_and_fitness.writeonly` |
| **[Activity Level](https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints.md.txt#activitylevel)** **dataType:** `activity-level` **filter parameter:** `activity_level` **Record type:** [Interval](https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints.md.txt#ObservationTimeInterval) [Webhook support](https://developers.google.com/health/webhooks.md.txt) | list, reconcile | `.activity_and_fitness.readonly` `.activity_and_fitness.writeonly` |
| **[Altitude](https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints.md.txt#altitude)** **dataType:** `altitude` **filter parameter:** `altitude` **Record type:** [Interval](https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints.md.txt#ObservationTimeInterval) **Storage resolution:**1 minute [Webhook support](https://developers.google.com/health/webhooks.md.txt) [True zeros support](https://developers.google.com/health/data-presence-and-true-zeros) | list, reconcile, rollup, dailyRollup | `.activity_and_fitness.readonly` `.activity_and_fitness.writeonly` |
| **[Blood Glucose](https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints.md.txt#bloodglucose)** **dataType:** `blood-glucose` **filter parameter:** `blood_glucose` **Record type:** [Sample](https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints.md.txt#ObservationSampleTime) [Webhook support](https://developers.google.com/health/webhooks.md.txt) [Vitals guide](https://developers.google.com/health/data-types/vitals.md.txt) | list, get, reconcile, rollup, dailyRollup | `.health_metrics_and_measurements.readonly` `.health_metrics_and_measurements.writeonly` |
| **[Body Fat](https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints.md.txt#bodyfat)** **dataType:** `body-fat` **filter parameter:** `body_fat` **Record type:** [Sample](https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints.md.txt#ObservationSampleTime) [Webhook support](https://developers.google.com/health/webhooks.md.txt) #### Compatible devices - Fitbit Aria - Fitbit Aria 2 - [Fitbit Aria Air](https://store.google.com/product/fitbit_aria_air) | list, get, reconcile, rollup, dailyRollup, create, update, batchDelete | `.health_metrics_and_measurements.readonly` `.health_metrics_and_measurements.writeonly` |
| **[Calories In Heart Rate Zone](https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints/rollUp.md.txt#RollupDataPoint.FIELDS.calories_in_heart_rate_zone)** **dataType:** `calories-in-heart-rate-zone` **filter parameter:** `calories_in_heart_rate_zone` **Record type:** [Interval](https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints.md.txt#ObservationTimeInterval) **Storage resolution:**1 minute [Webhook support](https://developers.google.com/health/webhooks.md.txt) | rollup, dailyRollup | `.activity_and_fitness.readonly` `.activity_and_fitness.writeonly` |
| **[Daily Heart Rate Variability](https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints.md.txt#dailyheartratevariability)** **dataType:** `daily-heart-rate-variability` **filter parameter:** `daily_heart_rate_variability` **Record type:**Daily [Webhook support](https://developers.google.com/health/webhooks.md.txt) [Vitals guide](https://developers.google.com/health/data-types/vitals.md.txt) [Sleep guide](https://developers.google.com/health/data-types/sleep.md.txt) #### Compatible devices - [Fitbit Air](https://store.google.com/product/google_fitbit_air) - Fitbit Alta HR - Fitbit Blaze - Fitbit Charge 2 - Fitbit Charge 3 - Fitbit Charge 4 - Fitbit Charge 5 - [Fitbit Charge 6](https://store.google.com/product/fitbit_charge_6) - [Fitbit Edge](https://store.google.com/product/google_fitbit_edge) - Fitbit Inspire 2 - [Fitbit Inspire 3](https://store.google.com/product/fitbit_inspire_3) - Fitbit Inspire HR - Fitbit Ionic - Fitbit Luxe - Pixel Watch - Pixel Watch 2 - [Pixel Watch 3](https://store.google.com/product/pixel_watch_3) - [Pixel Watch 4](https://store.google.com/product/pixel_watch_4) - Fitbit Sense - [Fitbit Sense 2](https://store.google.com/product/fitbit_sense_2) - Fitbit Versa - Fitbit Versa 2 - Fitbit Versa 3 - [Fitbit Versa 4](https://store.google.com/product/fitbit_versa_4) | list, reconcile | `.health_metrics_and_measurements.readonly` `.health_metrics_and_measurements.writeonly` |
| **[Daily Heart Rate Zones](https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints.md.txt#dailyheartratezones)** **dataType:** `daily-heart-rate-zones` **filter parameter:** `daily_heart_rate_zones` **Record type:**Daily [Webhook support](https://developers.google.com/health/webhooks.md.txt) [Vitals guide](https://developers.google.com/health/data-types/vitals.md.txt) | list, reconcile | `.health_metrics_and_measurements.readonly` `.health_metrics_and_measurements.writeonly` |
| **[Daily Oxygen Saturation](https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints.md.txt#dailyoxygensaturation)** **dataType:** `daily-oxygen-saturation` **filter parameter:** `daily_oxygen_saturation` **Record type:**Daily [Webhook support](https://developers.google.com/health/webhooks.md.txt) [Vitals guide](https://developers.google.com/health/data-types/vitals.md.txt) [Sleep guide](https://developers.google.com/health/data-types/sleep.md.txt) #### Compatible devices - [Fitbit Air](https://store.google.com/product/google_fitbit_air) - Fitbit Charge 4 - Fitbit Charge 5 - [Fitbit Charge 6](https://store.google.com/product/fitbit_charge_6) - [Fitbit Edge](https://store.google.com/product/google_fitbit_edge) - [Fitbit Inspire 3](https://store.google.com/product/fitbit_inspire_3) - Fitbit Ionic - Fitbit Luxe - Pixel Watch 2 - [Pixel Watch 3](https://store.google.com/product/pixel_watch_3) - [Pixel Watch 4](https://store.google.com/product/pixel_watch_4) - Fitbit Sense - [Fitbit Sense 2](https://store.google.com/product/fitbit_sense_2) - Fitbit Versa - Fitbit Versa 2 - Fitbit Versa 3 - [Fitbit Versa 4](https://store.google.com/product/fitbit_versa_4) | list, reconcile | `.health_metrics_and_measurements.readonly` `.health_metrics_and_measurements.writeonly` |
| **[Daily Respiratory Rate](https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints.md.txt#dailyrespiratoryrate)** **dataType:** `daily-respiratory-rate` **filter parameter:** `daily_respiratory_rate` **Record type:**Daily [Webhook support](https://developers.google.com/health/webhooks.md.txt) [Vitals guide](https://developers.google.com/health/data-types/vitals.md.txt) [Sleep guide](https://developers.google.com/health/data-types/sleep.md.txt) #### Compatible devices - [Fitbit Air](https://store.google.com/product/google_fitbit_air) - Fitbit Alta HR - Fitbit Blaze - Fitbit Charge 2 - Fitbit Charge 3 - Fitbit Charge 4 - Fitbit Charge 5 - [Fitbit Charge 6](https://store.google.com/product/fitbit_charge_6) - [Fitbit Edge](https://store.google.com/product/google_fitbit_edge) - Fitbit Inspire 2 - [Fitbit Inspire 3](https://store.google.com/product/fitbit_inspire_3) - Fitbit Inspire HR - Fitbit Ionic - Fitbit Luxe - Pixel Watch - Pixel Watch 2 - [Pixel Watch 3](https://store.google.com/product/pixel_watch_3) - [Pixel Watch 4](https://store.google.com/product/pixel_watch_4) - Fitbit Sense - [Fitbit Sense 2](https://store.google.com/product/fitbit_sense_2) - Fitbit Versa - Fitbit Versa 2 - Fitbit Versa 3 - [Fitbit Versa 4](https://store.google.com/product/fitbit_versa_4) | list, reconcile | `.health_metrics_and_measurements.readonly` `.health_metrics_and_measurements.writeonly` |
| **[Daily Resting Heart Rate](https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints.md.txt#dailyrestingheartrate)** **dataType:** `daily-resting-heart-rate` **filter parameter:** `daily_resting_heart_rate` **Record type:**Daily [Webhook support](https://developers.google.com/health/webhooks.md.txt) [Vitals guide](https://developers.google.com/health/data-types/vitals.md.txt) #### Compatible devices - [Fitbit Air](https://store.google.com/product/google_fitbit_air) - Fitbit Alta HR - Fitbit Blaze - Fitbit Charge 2 - Fitbit Charge 3 - Fitbit Charge 4 - Fitbit Charge 5 - [Fitbit Charge 6](https://store.google.com/product/fitbit_charge_6) - [Fitbit Edge](https://store.google.com/product/google_fitbit_edge) - Fitbit Inspire 2 - [Fitbit Inspire 3](https://store.google.com/product/fitbit_inspire_3) - Fitbit Inspire HR - Fitbit Ionic - Fitbit Luxe - Pixel Watch - Pixel Watch 2 - [Pixel Watch 3](https://store.google.com/product/pixel_watch_3) - [Pixel Watch 4](https://store.google.com/product/pixel_watch_4) - Fitbit Sense - [Fitbit Sense 2](https://store.google.com/product/fitbit_sense_2) - Fitbit Versa - Fitbit Versa 2 - Fitbit Versa 3 - [Fitbit Versa 4](https://store.google.com/product/fitbit_versa_4) - Fitbit Versa Lite | list, reconcile | `.health_metrics_and_measurements.readonly` `.health_metrics_and_measurements.writeonly` |
| **[Daily Sleep Temperature Derivations](https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints.md.txt#dailysleeptemperaturederivations)** **dataType:** `daily-sleep-temperature-derivations` **filter parameter:** `daily_sleep_temperature_derivations` **Record type:**Daily [Webhook support](https://developers.google.com/health/webhooks.md.txt) [Vitals guide](https://developers.google.com/health/data-types/vitals.md.txt) [Sleep guide](https://developers.google.com/health/data-types/sleep.md.txt) [Skin Temperature guide](https://developers.google.com/health/data-types/skin-temperature.md.txt) #### Compatible devices - [Fitbit Air](https://store.google.com/product/google_fitbit_air) - Fitbit Charge 4 - Fitbit Charge 5 - [Fitbit Charge 6](https://store.google.com/product/fitbit_charge_6) - [Fitbit Edge](https://store.google.com/product/google_fitbit_edge) - Fitbit Inspire 2 - [Fitbit Inspire 3](https://store.google.com/product/fitbit_inspire_3) - Fitbit Inspire HR - Fitbit Ionic - Fitbit Luxe - Pixel Watch 2 - [Pixel Watch 3](https://store.google.com/product/pixel_watch_3) - [Pixel Watch 4](https://store.google.com/product/pixel_watch_4) - Fitbit Sense - [Fitbit Sense 2](https://store.google.com/product/fitbit_sense_2) - Fitbit Versa - Fitbit Versa 2 - Fitbit Versa 3 - [Fitbit Versa 4](https://store.google.com/product/fitbit_versa_4) | list, reconcile | `.health_metrics_and_measurements.readonly` `.health_metrics_and_measurements.writeonly` |
| **[Distance](https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints.md.txt#distance)** **dataType:** `distance` **filter parameter:** `distance` **Record type:** [Interval](https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints.md.txt#ObservationTimeInterval) **Storage resolution:**1 minute [Webhook support](https://developers.google.com/health/webhooks.md.txt) [True zeros support](https://developers.google.com/health/data-presence-and-true-zeros) #### Compatible devices - [Fitbit Air](https://store.google.com/product/google_fitbit_air) - Fitbit Alta - Fitbit Alta HR - Fitbit Blaze - Fitbit Charge 2 - Fitbit Charge 3 - Fitbit Charge 4 - Fitbit Charge 5 - [Fitbit Charge 6](https://store.google.com/product/fitbit_charge_6) - [Fitbit Edge](https://store.google.com/product/google_fitbit_edge) - Fitbit Flex 2 - Fitbit Inspire - Fitbit Inspire 2 - [Fitbit Inspire 3](https://store.google.com/product/fitbit_inspire_3) - Fitbit Inspire HR - Fitbit Ionic - Fitbit Luxe - Fitbit MobileTrack - Pixel Watch - Pixel Watch 2 - [Pixel Watch 3](https://store.google.com/product/pixel_watch_3) - [Pixel Watch 4](https://store.google.com/product/pixel_watch_4) - Fitbit Sense - [Fitbit Sense 2](https://store.google.com/product/fitbit_sense_2) - Fitbit Versa - Fitbit Versa 2 - Fitbit Versa 3 - [Fitbit Versa 4](https://store.google.com/product/fitbit_versa_4) - Fitbit Versa Lite | list, reconcile, rollup, dailyRollup | `.activity_and_fitness.readonly` `.activity_and_fitness.writeonly` |
| **[Exercise](https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints.md.txt#exercise)** **dataType:** `exercise` **filter parameter:** `exercise` **Record type:**Session [Webhook support](https://developers.google.com/health/webhooks.md.txt) [Workouts guide](https://developers.google.com/health/data-types/workouts.md.txt) #### Compatible devices - [Fitbit Air](https://store.google.com/product/google_fitbit_air) - Fitbit Alta - Fitbit Alta HR - Fitbit Blaze - Fitbit Charge 2 - Fitbit Charge 3 - Fitbit Charge 4 - Fitbit Charge 5 - [Fitbit Charge 6](https://store.google.com/product/fitbit_charge_6) - [Fitbit Edge](https://store.google.com/product/google_fitbit_edge) - Fitbit Flex 2 - Fitbit Inspire - Fitbit Inspire 2 - [Fitbit Inspire 3](https://store.google.com/product/fitbit_inspire_3) - Fitbit Inspire HR - Fitbit Ionic - Fitbit Luxe - Fitbit MobileTrack - Pixel Watch - Pixel Watch 2 - [Pixel Watch 3](https://store.google.com/product/pixel_watch_3) - [Pixel Watch 4](https://store.google.com/product/pixel_watch_4) - Fitbit Sense - [Fitbit Sense 2](https://store.google.com/product/fitbit_sense_2) - Fitbit Versa - Fitbit Versa 2 - Fitbit Versa 3 - [Fitbit Versa 4](https://store.google.com/product/fitbit_versa_4) - Fitbit Versa Lite | list, get, reconcile, create, update, batchDelete | `.activity_and_fitness.readonly` `.activity_and_fitness.writeonly` |
| **[Floors](https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints/rollUp.md.txt#RollupDataPoint.FIELDS.floors)** **dataType:** `floors` **filter parameter:** `floors` **Record type:** [Interval](https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints.md.txt#ObservationTimeInterval) **Storage resolution:**1 minute [Webhook support](https://developers.google.com/health/webhooks.md.txt) [True zeros support](https://developers.google.com/health/data-presence-and-true-zeros) #### Compatible devices - [Fitbit Air](https://store.google.com/product/google_fitbit_air) - Fitbit Blaze - Fitbit Charge 2 - Fitbit Charge 3 - Fitbit Charge 4 - [Fitbit Edge](https://store.google.com/product/google_fitbit_edge) - Fitbit Ionic - Pixel Watch - Pixel Watch 2 - [Pixel Watch 3](https://store.google.com/product/pixel_watch_3) - [Pixel Watch 4](https://store.google.com/product/pixel_watch_4) - Fitbit Sense - [Fitbit Sense 2](https://store.google.com/product/fitbit_sense_2) - Fitbit Versa - Fitbit Versa 2 - Fitbit Versa 3 - [Fitbit Versa 4](https://store.google.com/product/fitbit_versa_4) | reconcile, rollup, dailyRollup | `.activity_and_fitness.readonly` `.activity_and_fitness.writeonly` |
| **[Heart Rate](https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints.md.txt#heartrate)** **dataType:** `heart-rate` **filter parameter:** `heart_rate` **Record type:** [Sample](https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints.md.txt#ObservationSampleTime) **Storage resolution:**1 second [Webhook support](https://developers.google.com/health/webhooks.md.txt) [Vitals guide](https://developers.google.com/health/data-types/vitals.md.txt) #### Compatible devices - [Fitbit Air](https://store.google.com/product/google_fitbit_air) - Fitbit Alta HR - Fitbit Blaze - Fitbit Charge 2 - Fitbit Charge 3 - Fitbit Charge 4 - Fitbit Charge 5 - [Fitbit Charge 6](https://store.google.com/product/fitbit_charge_6) - [Fitbit Edge](https://store.google.com/product/google_fitbit_edge) - Fitbit Inspire 2 - [Fitbit Inspire 3](https://store.google.com/product/fitbit_inspire_3) - Fitbit Inspire HR - Fitbit Ionic - Fitbit Luxe - Pixel Watch - Pixel Watch 2 - [Pixel Watch 3](https://store.google.com/product/pixel_watch_3) - [Pixel Watch 4](https://store.google.com/product/pixel_watch_4) - Fitbit Sense - [Fitbit Sense 2](https://store.google.com/product/fitbit_sense_2) - Fitbit Versa - Fitbit Versa 2 - Fitbit Versa 3 - [Fitbit Versa 4](https://store.google.com/product/fitbit_versa_4) - Fitbit Versa Lite | list, reconcile, rollup, dailyRollup | `.health_metrics_and_measurements.readonly` `.health_metrics_and_measurements.writeonly` |
| **[Heart Rate Variability](https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints.md.txt#heartratevariability)** **dataType:** `heart-rate-variability` **filter parameter:** `heart_rate_variability` **Record type:** [Sample](https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints.md.txt#ObservationSampleTime) [Webhook support](https://developers.google.com/health/webhooks.md.txt) [Vitals guide](https://developers.google.com/health/data-types/vitals.md.txt) [Sleep guide](https://developers.google.com/health/data-types/sleep.md.txt) #### Compatible devices - [Fitbit Air](https://store.google.com/product/google_fitbit_air) - Fitbit Alta - Fitbit Alta HR - Fitbit Blaze - Fitbit Charge 2 - Fitbit Charge 3 - Fitbit Charge 4 - Fitbit Charge 5 - [Fitbit Charge 6](https://store.google.com/product/fitbit_charge_6) - [Fitbit Edge](https://store.google.com/product/google_fitbit_edge) - Fitbit Flex 2 - Fitbit Inspire - Fitbit Inspire 2 - [Fitbit Inspire 3](https://store.google.com/product/fitbit_inspire_3) - Fitbit Inspire HR - Fitbit Ionic - Fitbit Luxe - Fitbit MobileTrack - Pixel Watch - Pixel Watch 2 - [Pixel Watch 3](https://store.google.com/product/pixel_watch_3) - [Pixel Watch 4](https://store.google.com/product/pixel_watch_4) - Fitbit Sense - [Fitbit Sense 2](https://store.google.com/product/fitbit_sense_2) - Fitbit Versa - Fitbit Versa 2 - Fitbit Versa 3 - [Fitbit Versa 4](https://store.google.com/product/fitbit_versa_4) - Fitbit Versa Lite | list, reconcile | `.health_metrics_and_measurements.readonly` `.health_metrics_and_measurements.writeonly` |
| **[Height](https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints.md.txt#height)** **dataType:** `height` **filter parameter:** `height` **Record type:** [Sample](https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints.md.txt#ObservationSampleTime) [Webhook support](https://developers.google.com/health/webhooks.md.txt) | list, get, reconcile, create, update, batchDelete | `.health_metrics_and_measurements.readonly` `.health_metrics_and_measurements.writeonly` |
| **[Hydration Log](https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints.md.txt#hydrationlog)** **dataType:** `hydration-log` **filter parameter:** `hydration_log` **Record type:**Session [Webhook support](https://developers.google.com/health/webhooks.md.txt) | list, get, reconcile, rollup, dailyRollup, create, update, batchDelete | `.nutrition.readonly` `.nutrition.writeonly` |
| **[Nutrition Log](https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints.md.txt#nutritionlog)** **dataType:** `nutrition-log` **filter parameter:** `nutrition_log` **Record type:**Session [Webhook support](https://developers.google.com/health/webhooks.md.txt) [Nutrition guide](https://developers.google.com/health/data-types/nutrition.md.txt) | list, get, reconcile, rollup, dailyRollup, create, update, batchDelete | `.nutrition.readonly` `.nutrition.writeonly` |
| **[Respiratory Rate Sleep Summary](https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints.md.txt#respiratoryratesleepsummary)** **dataType:** `respiratory-rate-sleep-summary` **filter parameter:** `respiratory_rate_sleep_summary` **Record type:** [Sample](https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints.md.txt#ObservationSampleTime) [Webhook support](https://developers.google.com/health/webhooks.md.txt) [Vitals guide](https://developers.google.com/health/data-types/vitals.md.txt) [Sleep guide](https://developers.google.com/health/data-types/sleep.md.txt) #### Compatible devices - [Fitbit Air](https://store.google.com/product/google_fitbit_air) - Fitbit Alta HR - Fitbit Blaze - Fitbit Charge 2 - Fitbit Charge 3 - Fitbit Charge 4 - Fitbit Charge 5 - [Fitbit Charge 6](https://store.google.com/product/fitbit_charge_6) - [Fitbit Edge](https://store.google.com/product/google_fitbit_edge) - Fitbit Inspire 2 - [Fitbit Inspire 3](https://store.google.com/product/fitbit_inspire_3) - Fitbit Inspire HR - Fitbit Ionic - Fitbit Luxe - Pixel Watch - Pixel Watch 2 - [Pixel Watch 3](https://store.google.com/product/pixel_watch_3) - [Pixel Watch 4](https://store.google.com/product/pixel_watch_4) - Fitbit Sense - [Fitbit Sense 2](https://store.google.com/product/fitbit_sense_2) - Fitbit Versa - Fitbit Versa 2 - Fitbit Versa 3 - [Fitbit Versa 4](https://store.google.com/product/fitbit_versa_4) | list, reconcile | `.health_metrics_and_measurements.readonly` `.health_metrics_and_measurements.writeonly` |
| **[Run VO2 Max](https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints.md.txt#runvo2max)** **dataType:** `run-vo2-max` **filter parameter:** `run_vo2_max` **Record type:** [Sample](https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints.md.txt#ObservationSampleTime) [Webhook support](https://developers.google.com/health/webhooks.md.txt) #### Compatible devices - [Fitbit Air](https://store.google.com/product/google_fitbit_air) - Fitbit Alta HR - Fitbit Blaze - Fitbit Charge 2 - Fitbit Charge 3 - Fitbit Charge 4 - Fitbit Charge 5 - [Fitbit Charge 6](https://store.google.com/product/fitbit_charge_6) - [Fitbit Edge](https://store.google.com/product/google_fitbit_edge) - Fitbit Inspire 2 - [Fitbit Inspire 3](https://store.google.com/product/fitbit_inspire_3) - Fitbit Ionic - Fitbit Luxe - Pixel Watch - Pixel Watch 2 - [Pixel Watch 3](https://store.google.com/product/pixel_watch_3) - [Pixel Watch 4](https://store.google.com/product/pixel_watch_4) - Fitbit Sense - [Fitbit Sense 2](https://store.google.com/product/fitbit_sense_2) - Fitbit Versa - Fitbit Versa 2 - Fitbit Versa 3 - [Fitbit Versa 4](https://store.google.com/product/fitbit_versa_4) - Fitbit Versa Lite | list, reconcile, rollup, dailyRollup | `.activity_and_fitness.readonly` `.activity_and_fitness.writeonly` |
| **[Sedentary Period](https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints.md.txt#sedentaryperiod)** **dataType:** `sedentary-period` **filter parameter:** `sedentary_period` **Record type:** [Interval](https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints.md.txt#ObservationTimeInterval) [Webhook support](https://developers.google.com/health/webhooks.md.txt) #### Compatible devices - [Fitbit Air](https://store.google.com/product/google_fitbit_air) - Fitbit Alta - Fitbit Alta HR - Fitbit Blaze - Fitbit Charge 2 - Fitbit Charge 3 - Fitbit Charge 4 - Fitbit Charge 5 - [Fitbit Charge 6](https://store.google.com/product/fitbit_charge_6) - [Fitbit Edge](https://store.google.com/product/google_fitbit_edge) - Fitbit Flex 2 - Fitbit Inspire - Fitbit Inspire 2 - [Fitbit Inspire 3](https://store.google.com/product/fitbit_inspire_3) - Fitbit Inspire HR - Fitbit Ionic - Fitbit Luxe - Fitbit MobileTrack - Pixel Watch - Pixel Watch 2 - [Pixel Watch 3](https://store.google.com/product/pixel_watch_3) - [Pixel Watch 4](https://store.google.com/product/pixel_watch_4) - Fitbit Sense - [Fitbit Sense 2](https://store.google.com/product/fitbit_sense_2) - Fitbit Versa - Fitbit Versa 2 - Fitbit Versa 3 - [Fitbit Versa 4](https://store.google.com/product/fitbit_versa_4) - Fitbit Versa Lite | list, reconcile, rollup, dailyRollup | `.activity_and_fitness.readonly` `.activity_and_fitness.writeonly` |
| **[Sleep](https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints.md.txt#sleep)** **dataType:** `sleep` **filter parameter:** `sleep` **Record type:**Session [Webhook support](https://developers.google.com/health/webhooks.md.txt) [Sleep guide](https://developers.google.com/health/data-types/sleep.md.txt) #### Compatible devices - [Fitbit Air](https://store.google.com/product/google_fitbit_air) - Fitbit Alta - Fitbit Alta HR - Fitbit Blaze - Fitbit Charge 2 - Fitbit Charge 3 - Fitbit Charge 4 - Fitbit Charge 5 - [Fitbit Charge 6](https://store.google.com/product/fitbit_charge_6) - [Fitbit Edge](https://store.google.com/product/google_fitbit_edge) - Fitbit Flex 2 - Fitbit Inspire - Fitbit Inspire 2 - [Fitbit Inspire 3](https://store.google.com/product/fitbit_inspire_3) - Fitbit Inspire HR - Fitbit Ionic - Fitbit Luxe - Pixel Watch - Pixel Watch 2 - [Pixel Watch 3](https://store.google.com/product/pixel_watch_3) - [Pixel Watch 4](https://store.google.com/product/pixel_watch_4) - Fitbit Sense - [Fitbit Sense 2](https://store.google.com/product/fitbit_sense_2) - Fitbit Versa - Fitbit Versa 2 - Fitbit Versa 3 - [Fitbit Versa 4](https://store.google.com/product/fitbit_versa_4) - Fitbit Versa Lite | list, get, reconcile, create, update, batchDelete | `.sleep.readonly` `.sleep.writeonly` |
| **[Steps](https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints.md.txt#steps)** **dataType:** `steps` **filter parameter:** `steps` **Record type:** [Interval](https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints.md.txt#ObservationTimeInterval) **Storage resolution:**1 minute [Webhook support](https://developers.google.com/health/webhooks.md.txt) [True zeros support](https://developers.google.com/health/data-presence-and-true-zeros) [Steps guide](https://developers.google.com/health/data-types/steps.md.txt) #### Compatible devices - [Fitbit Air](https://store.google.com/product/google_fitbit_air) - Fitbit Alta - Fitbit Alta HR - Fitbit Blaze - Fitbit Charge 2 - Fitbit Charge 3 - Fitbit Charge 4 - Fitbit Charge 5 - [Fitbit Charge 6](https://store.google.com/product/fitbit_charge_6) - [Fitbit Edge](https://store.google.com/product/google_fitbit_edge) - Fitbit Flex 2 - Fitbit Inspire - Fitbit Inspire 2 - [Fitbit Inspire 3](https://store.google.com/product/fitbit_inspire_3) - Fitbit Inspire HR - Fitbit Ionic - Fitbit Luxe - Fitbit MobileTrack - Pixel Watch - Pixel Watch 2 - [Pixel Watch 3](https://store.google.com/product/pixel_watch_3) - [Pixel Watch 4](https://store.google.com/product/pixel_watch_4) - Fitbit Sense - [Fitbit Sense 2](https://store.google.com/product/fitbit_sense_2) - Fitbit Versa - Fitbit Versa 2 - Fitbit Versa 3 - [Fitbit Versa 4](https://store.google.com/product/fitbit_versa_4) - Fitbit Versa Lite | list, reconcile, rollup, dailyRollup | `.activity_and_fitness.readonly` `.activity_and_fitness.writeonly` |
| **[Time in Heart Rate Zone](https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints.md.txt#timeinheartratezone)** **dataType:** `time-in-heart-rate-zone` **filter parameter:** `time_in_heart_rate_zone` **Record type:** [Interval](https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints.md.txt#ObservationTimeInterval) **Storage resolution:**1 minute [Webhook support](https://developers.google.com/health/webhooks.md.txt) | list, reconcile, rollup, dailyRollup | `.activity_and_fitness.readonly` `.activity_and_fitness.writeonly` |
| **[Weight](https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints.md.txt#weight)** **dataType:** `weight` **filter parameter:** `weight` **Record type:** [Sample](https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints.md.txt#ObservationSampleTime) [Webhook support](https://developers.google.com/health/webhooks.md.txt) #### Compatible devices - Fitbit Aria - Fitbit Aria 2 - [Fitbit Aria Air](https://store.google.com/product/fitbit_aria_air) | list, get, reconcile, rollup, dailyRollup, create, update, batchDelete | `.health_metrics_and_measurements.readonly` `.health_metrics_and_measurements.writeonly` |
[*Table: Google Health API data types with webhook support*]

<br />

### Notifications scopes

Notifications are sent for these data types only when a user has granted consent
for one of the corresponding scopes:

- **Activity** , which covers active minutes, steps, altitude, distance, and floors data types:
  - `https://www.googleapis.com/auth/googlehealth.activity_and_fitness.readonly`
  - `https://www.googleapis.com/auth/googlehealth.activity_and_fitness.writeonly`
- **Health Metrics** , which covers the weight data type:
  - `https://www.googleapis.com/auth/googlehealth.health_metrics_and_measurements.readonly`
  - `https://www.googleapis.com/auth/googlehealth.health_metrics_and_measurements.writeonly`
- **Sleep** , which covers the sleep data type:
  - `https://www.googleapis.com/auth/googlehealth.sleep.readonly`
  - `https://www.googleapis.com/auth/googlehealth.sleep.writeonly`

## IAM service accounts

While not required, we recommend using an
[IAM Service Account](https://cloud.google.com/iam/docs/service-account-overview)
when configuring subscribers for the Google Health API. Service accounts provide
better security for application workloads compared to standard user accounts
through the following features:

- **Automated short-lived credentials:** When attached to a Google Cloud execution environment (such as Compute Engine, Cloud Run, or Google Kubernetes Engine), service accounts automatically obtain and rotate secure, short-lived credentials. This removes the risks of managing and storing persistent static keys.
- **Principle of least privilege:** Service accounts provide dedicated identities for workloads. You can grant them only the specific permissions needed to manage subscriber endpoints, avoiding broader access to your Google Cloud resources.
- **Lifecycle independence:** Service accounts operate independently of any individual user's account, ensuring that personnel changes don't impact long-term authentication stability.

### Set up a service account

To configure your subscriber application to authenticate using a service
account:

1. **Create a service account:** In the Google Cloud console, navigate to your project's IAM \& Admin page to [create a new user-managed service account](https://cloud.google.com/iam/docs/service-accounts-create).
2. **Grant necessary IAM roles:** [Assign the service account the appropriate roles](https://cloud.google.com/iam/docs/granting-changing-revoking-access) required to manage subscribers on your Google Cloud project.
3. **Attach the service account to your workload:** [Configure the environment hosting your subscriber logic to run as the new service account](https://cloud.google.com/iam/docs/attach-service-accounts). This allows your application code (such as Google API client libraries) to automatically detect and use the service account's short-lived credentials when calling the `projects.subscribers` REST API.

## CPE roles

To manage Google Health API Subscribers or Subscriptions, you must grant the
appropriate role to the impersonated Service Account making the API calls.
Depending on the level of access needed, assign one of the following roles:

- Google Health API Read
- Google Health API Editor
- Google Health API Admin

[Learn more about Google Health API IAM roles and permissions](https://docs.cloud.google.com/iam/docs/roles-permissions/health).

## Manage subscribers

Before you can receive notifications, you must register a Subscriber, which
represents your application's notification endpoint. You can manage subscribers
using the REST API available at
[`projects.subscribers`](https://developers.google.com/health/reference/rest/v4/projects.subscribers.md.txt).

Your subscriber endpoint must use HTTPS (TLSv1.2+) and be publicly accessible.
During subscriber creation and updates, the Google Health API performs a
verification challenge to ensure you own the endpoint URI. If verification
fails, subscriber creation and update operations fail with a
`FailedPreconditionException`.

### Create a subscriber

To register a new subscriber for your project, use the
[`create`](https://developers.google.com/health/reference/rest/v4/projects.subscribers/create.md.txt)
endpoint. You need to provide:

- `project-id`: The project number where the webhook service account was created.
- `subscriberId`: A unique identifier that you provide for the subscriber. This ID must be between 4 and 36 characters, and match the regular expression (`[a-z]([a-z0-9-]{2,34}[a-z0-9])`).
- `endpointUri`: The destination URL for webhook notifications.
- `subscriberConfigs`: The data types you want to receive notifications for, and the subscription policy for each.
- `endpointAuthorization`: The authorization mechanism for your endpoint. This must contain a `secret` that you provide. The value of `secret` is sent in the `Authorization` header with each notification message. You can use this token to verify that incoming requests are from the Google Health API. For example, you can set `secret` to `Bearer R4nd0m5tr1ng123` for Bearer authentication, or `Basic dXNlcjpwYXNzd29yZA==` for Basic authentication.

In `subscriberConfigs` you must set `subscriptionCreatePolicy` for each data
type. Set it to `AUTOMATIC` to use automatic subscriptions, or `MANUAL` if you
intend to manage user subscriptions yourself. See
[automatic subscriptions](https://developers.google.com/health/webhooks.md.txt#automatic_subscriptions) and
[manual subscriptions](https://developers.google.com/health/webhooks.md.txt#manual_subscriptions) for more details on each option.

### Request

```
POST https://health.googleapis.com/v4/projects/project-id/subscribers?subscriberId=subscriber-id
{
  "endpointUri": "https://myapp.com/webhooks/health",
  "subscriberConfigs": [
    {
      "dataTypes": ["steps", "altitude", "distance", "floors", "weight"],
      "subscriptionCreatePolicy": "AUTOMATIC"
    },
    {
      "dataTypes": ["sleep"],
      "subscriptionCreatePolicy": "MANUAL"
    }
  ],
  "endpointAuthorization": {
    "secret": "Bearer example-secret-token"
  }
}
```

### Response

```
{
  "name": "projects/project-id/subscribers/subscriber-id",
  "endpointUri": "https://myapp.com/webhooks/health",
  "subscriberConfigs": [
    {
      "dataTypes": ["steps", "altitude", "distance", "floors", "weight"],
      "subscriptionCreatePolicy": "AUTOMATIC"
    },
    {
      "dataTypes": ["sleep"],
      "subscriptionCreatePolicy": "MANUAL"
    }
  ]
}
```

### List subscribers

Use the [`list`](https://developers.google.com/health/reference/rest/v4/projects.subscribers/list) endpoint
to retrieve all subscribers registered for your project.

### Request

```
GET https://health.googleapis.com/v4/projects/project-id/subscribers
```

### Response

```
{
  "subscribers": [
    {
      "name": "projects/project-id/subscribers/subscriber-id",
      "endpointUri": "https://myapp.com/webhooks/health",
      "subscriberConfigs": [
        {
          "dataTypes": ["steps", "altitude", "distance", "floors", "weight"],
          "subscriptionCreatePolicy": "AUTOMATIC"
        },
        {
          "dataTypes": ["sleep"],
          "subscriptionCreatePolicy": "MANUAL"
        }
      ],
      "endpointAuthorization": {
        "authorizationTokenSet": true
      }
    }
  ],
  "totalSize": 1
}
```

### Update a subscriber

Use the [`patch`](https://developers.google.com/health/reference/rest/v4/projects.subscribers/patch.md.txt) endpoint
to update a subscriber in your project. The fields that can be updated are
`endpointUri`, `subscriberConfigs`, and `endpointAuthorization`.

You update fields by providing an `updateMask` query parameter and a request
body. The `updateMask` must contain a comma-separated list of field names that
you want to update, using camel case for field names
(for example, `endpointUri`). The request body must contain a partial Subscriber
object with the new values for fields you want to update. Only fields specified
in `updateMask` are updated. If you provide fields in the request body that are
not in `updateMask`, they are ignored.

If you update `endpointUri` or `endpointAuthorization`, endpoint verification is
performed. See [Endpoint verification](https://developers.google.com/health/webhooks.md.txt#endpoint_verification) for details.

When updating `subscriberConfigs`, note that it's a **full replacement** , not a
merge. If `subscriberConfigs` is included in `updateMask`, all stored
configurations for that subscriber are overwritten with list provided in request
body. To add or remove a configuration, you must provide the complete set of
configurations. If you are updating other fields and want to keep your current
configurations, omit `subscriberConfigs` from `updateMask`.

### Request

```
PATCH https://health.googleapis.com/v4/projects/project-id/subscribers/subscriber-id?updateMask=endpointUri
{
  "endpointUri": "https://myapp.com/new-webhooks/health"
}
```

### Response

```
{
  "name": "projects/project-id/subscribers/subscriber-id",
  "endpointUri": "https://myapp.com/new-webhooks/health",
  "subscriberConfigs": [
    {
      "dataTypes": ["steps", "altitude", "distance", "floors", "weight"],
      "subscriptionCreatePolicy": "AUTOMATIC"
    },
    {
      "dataTypes": ["sleep"],
      "subscriptionCreatePolicy": "MANUAL"
    }
  ]
}
```

### Delete a subscriber

Use the [`delete`](https://developers.google.com/health/reference/rest/v4/projects.subscribers/delete.md.txt)
endpoint to remove a subscriber from your project. Once deleted, the subscriber
will no longer receive notifications.

### Request

```
DELETE https://health.googleapis.com/v4/projects/project-id/subscribers/subscriber-id
```

### Response

An empty response body with HTTP status \`200 OK\` is returned if deletion is successful.

```
{}
```

## Endpoint verification

To ensure the security and reliability of your notification delivery, the Google
Health API performs a mandatory two-step verification handshake whenever you
create a subscriber or update its endpoint configuration (`endpointUri` or
`endpointAuthorization`). This process is performed synchronously during the
API call. The service sends two automated POST requests to your endpoint URI,
using the User-Agent `Google-Health-API-Webhooks`, with the JSON body
`{"type": "verification"}`.

- **Authorized Handshake** : The first request is sent with your configured `Authorization` header. Your server must respond with a `200 OK` or `201 Created` status.
- **Unauthorized Challenge** : The second request is sent without credentials. Your server must respond with a `401 Unauthorized` or `403 Forbidden` status.

This handshake confirms that your endpoint is active and correctly enforcing
security. If either step fails, the API request fails with a
`FAILED_PRECONDITION` error. Only after this handshake succeeds is your
subscriber saved and activated to receive health data notifications.

### Key rotation

If you need to rotate keys for `endpointAuthorization`, follow these steps:

1. Configure your endpoint to accept both old and new `endpointAuthorization` values.
2. Update the subscriber configuration with new `endpointAuthorization` value using a `patch` request with `?updateMask=endpointAuthorization`.
3. Configure your endpoint to accept only new `endpointAuthorization` value after confirming step 2 was successful.

## User subscriptions

The Google Health API helps you manage user subscriptions efficiently, reducing
the need for manual registration during user onboarding.

### Automatic subscriptions

We recommend using automatic subscriptions. To enable this feature, set
`subscriptionCreatePolicy` to `AUTOMATIC` in your `subscriberConfigs` for the
specific data types. The `dataTypes` you specify with an `AUTOMATIC` policy are
the same data types for which the Google Health API sends notifications,
provided user consent is also granted for those data types.

When a user grants application consent for scopes that correspond to data
types with an `AUTOMATIC` policy, the Google Health API automatically tracks and
sends out notifications for the data types resulting from the intersection
between user consented data types and the automatic subscriber config data types
for that user. Notifications are then sent to your endpoint
whenever that user generates new data for those types. This works for users who
grant consent either before or after you create the subscriber. Notifications
are not backfilled for data generated before the subscriber was created.

If a user revokes consent, notifications for the corresponding data types will
stop. Automatic subscriptions are managed by Google and cannot be listed or
deleted individually; they are removed only when the parent subscriber is
deleted.

### Manual subscriptions

If your subscriber is configured with a MANUAL `subscription_create_policy`
for specific data types, you must explicitly create and manage subscriptions
for each user. A Subscription links a specific user to your subscriber
endpoint for a defined set of data types. Developers can use specific APIs to:

- Create (manual) subscriptions per `healthUserId` - Creates a new subscription for a specific user. This method requires the subscriber to have a `SubscriptionCreatePolicy` set to `MANUAL` for the requested data types.
- Update (manual) subscription - Updates the data types for an existing user subscription.
- Delete (manual) subscription - Deletes a specific user subscription. Once deleted, your subscriber endpoint will no longer receive notifications for this user for the associated data types.
- List (manual) subscriptions - Lists all active subscriptions for a given subscriber. You can filter the results by user or data type.

## Notifications

When a user's data changes for a subscribed data type, the Google Health API
sends an HTTPS POST request to the subscriber endpoint URL.

### Notification format

The notification payload contains details about the data change, including the
user ID, data type, and time intervals, which you can use to query the updated
data. When multiple updates occur or updates are aggregated, notifications are
batched together and delivered as a JSON array of notification objects.

When a webhook notification is triggered, the Google Health API sends an HTTPS
POST request to your subscriber endpoint with the following format:

### Upsert (time-series data)

```
POST https://your-endpoint-uri
Authorization: Bearer example-secret-token
GOOGLE-HEALTH-API-SIGNATURE: signature-value
Content-Type: application/json

{
  "data": {
    "version": "1",
    "clientProvidedSubscriptionName": "subscription-name",
    "healthUserId": "health-user-id",
    "operation": "UPSERT",
    "dataType": "steps",
    "intervals": [
      {
        "physicalTimeInterval": {
          "startTime": "2026-03-08T01:29:00Z",
          "endTime": "2026-03-08T01:34:00Z"
        },
        "civilDateTimeInterval": {
          "startDateTime": {
            "date": {
              "year": 2026,
              "month": 3,
              "day": 7
            },
            "time": {
              "hours": 17,
              "minutes": 29
            }
          },
          "endDateTime": {
            "date": {
              "year": 2026,
              "month": 3,
              "day": 7
            },
            "time": {
              "hours": 17,
              "minutes": 34
            }
          }
        },
        "civilIso8601TimeInterval": {
          "startTime": "2026-03-07T17:29:00",
          "endTime": "2026-03-07T17:34:00"
        }
      }
    ]
  }
}
```

### Delete (time-series data)

```
POST https://your-endpoint-uri
Authorization: Bearer example-secret-token
GOOGLE-HEALTH-API-SIGNATURE: signature-value
Content-Type: application/json

[
  {
    "data": {
      "version": "1",
      "clientProvidedSubscriptionName": "subscription-name",
      "healthUserId": "health-user-id",
      "operation": "DELETE",
      "dataType": "steps",
      "intervals": [
        {
          "physicalTimeInterval": {
            "startTime": "2026-08-12T12:00:00Z",
            "endTime": "2026-08-12T12:30:00Z"
          },
          "civilIso8601TimeInterval": {
            "startTime": "2026-08-12T12:00:00",
            "endTime": "2026-08-12T12:30:00"
          }
        }
      ]
    }
  }
]
```

### Delete (identifiable data)

```
POST https://your-endpoint-uri
Authorization: Bearer example-secret-token
GOOGLE-HEALTH-API-SIGNATURE: signature-value
Content-Type: application/json

{
  "data": {
    "version": "1",
    "clientProvidedSubscriptionName": "subscription-name",
    "healthUserId": "health-user-id",
    "operation": "DELETE",
    "dataType": "sleep",
    "intervals": [
      {
        "physicalTimeInterval": {
          "startTime": "2026-08-12T22:00:00Z",
          "endTime": "2026-08-13T06:00:00Z"
        },
        "civilIso8601TimeInterval": {
          "startTime": "2026-08-12T22:00:00",
          "endTime": "2026-08-13T06:00:00"
        }
      }
    ],
    "recordId": "9875412"
  }
}
```

### Batch (multiple users and data types)

```
POST https://your-endpoint-uri
Authorization: Bearer example-secret-token
GOOGLE-HEALTH-API-SIGNATURE: signature-value
Content-Type: application/json

[
  {
    "data": {
      "version": "1",
      "clientProvidedSubscriptionName": "auto-project-number-subscriber-id-WEBHOOK_DATA_TYPE_STEPS",
      "healthUserId": "health-user-id-1",
      "operation": "UPSERT",
      "dataType": "steps",
      "intervals": [
        {
          "physicalTimeInterval": {
            "startTime": "2026-03-08T01:29:00Z",
            "endTime": "2026-03-08T01:34:00Z"
          },
          "civilDateTimeInterval": {
            "startDateTime": {
              "date": {
                "year": 2026,
                "month": 3,
                "day": 7
              },
              "time": {
                "hours": 17,
                "minutes": 29
              }
            },
            "endDateTime": {
              "date": {
                "year": 2026,
                "month": 3,
                "day": 7
              },
              "time": {
                "hours": 17,
                "minutes": 34
              }
            }
          },
          "civilIso8601TimeInterval": {
            "startTime": "2026-03-07T17:29:00",
            "endTime": "2026-03-07T17:34:00"
          }
        }
      ]
    }
  },
  {
    "data": {
      "version": "1",
      "clientProvidedSubscriptionName": "auto-project-number-subscriber-id-WEBHOOK_DATA_TYPE_WEIGHT",
      "healthUserId": "health-user-id-1",
      "operation": "UPSERT",
      "dataType": "weight",
      "intervals": [
        {
          "physicalTimeInterval": {
            "startTime": "2026-03-07T15:14:00Z",
            "endTime": "2026-03-07T15:16:00Z"
          },
          "civilDateTimeInterval": {
            "startDateTime": {
              "date": {
                "year": 2026,
                "month": 3,
                "day": 7
              },
              "time": {
                "hours": 7,
                "minutes": 14
              }
            },
            "endDateTime": {
              "date": {
                "year": 2026,
                "month": 3,
                "day": 7
              },
              "time": {
                "hours": 7,
                "minutes": 16
              }
            }
          },
          "civilIso8601TimeInterval": {
            "startTime": "2026-03-07T07:14:00",
            "endTime": "2026-03-07T07:16:00"
          }
        }
      ]
    }
  },
  {
    "data": {
      "version": "1",
      "clientProvidedSubscriptionName": "auto-project-number-subscriber-id-WEBHOOK_DATA_TYPE_STEPS",
      "healthUserId": "health-user-id-2",
      "operation": "UPSERT",
      "dataType": "steps",
      "intervals": [
        {
          "civilDateTimeInterval": {
            "startDateTime": {
              "date": {
                "year": 2026,
                "month": 8,
                "day": 20
              },
              "time": {
                "hours": 0,
                "minutes": 0
              }
            },
            "endDateTime": {
              "date": {
                "year": 2026,
                "month": 8,
                "day": 21
              },
              "time": {
                "hours": 0,
                "minutes": 0
              }
            }
          },
          "civilIso8601TimeInterval": {
            "startTime": "2026-08-20T00:00:00",
            "endTime": "2026-08-21T00:00:00"
          }
        }
      ]
    }
  },
  {
    "data": {
      "version": "1",
      "clientProvidedSubscriptionName": "subscription-name",
      "healthUserId": "health-user-id-2",
      "operation": "UPSERT",
      "dataType": "sleep",
      "intervals": [
        {
          "physicalTimeInterval": {
            "startTime": "2026-08-12T22:00:00Z",
            "endTime": "2026-08-13T06:00:00Z"
          },
          "civilDateTimeInterval": {
            "startDateTime": {
              "date": {
                "year": 2026,
                "month": 8,
                "day": 12
              },
              "time": {
                "hours": 22,
                "minutes": 0
              }
            },
            "endDateTime": {
              "date": {
                "year": 2026,
                "month": 8,
                "day": 13
              },
              "time": {
                "hours": 6,
                "minutes": 0
              }
            }
          },
          "civilIso8601TimeInterval": {
            "startTime": "2026-08-12T22:00:00",
            "endTime": "2026-08-13T06:00:00"
          }
        }
      ],
      "recordId": "9875412"
    }
  }
]
```

The `operation` field indicates the type of change that triggered the
notification:

- **`UPSERT`**: Sent for any data addition or modification.
- **`DELETE`** : Sent when a user explicitly deletes data (such as deleting `dataPoints` using the Fitbit app or performing a batch delete using the API). Webhook notifications are **not** sent for system-level deletion events, such as a user revoking application permissions or deleting their Fitbit account.

We recommend making your notification handling logic idempotent, especially for
`UPSERT` operations, as retries can cause duplicate notifications to be sent.

The `clientProvidedSubscriptionName` field is a unique identifier:

- For subscriptions with a `MANUAL` policy, this field contains the persistent, developer-provided subscription name specified when the subscription is created. This provides a stable ID for managing manual subscriptions.
- For subscriptions created with an `AUTOMATIC` policy, the Google Health API automatically generates and assigns an identifier in the format: `auto-<project-number>-<subscriber-id>-<WEBHOOK_DATA_TYPE_TOKEN>`, where:
  - `<project-number>` is the developer's Google Cloud project number (for example, `362978535920`).
  - `<subscriber-id>` is the subscriber's registration ID / subscriber name (for example, `google-health-sync`).
  - `<WEBHOOK_DATA_TYPE_TOKEN>` is the token representing the specific data type. See [Vocabulary of webhook data type tokens](https://developers.google.com/health/webhooks.md.txt#dataTypeTokens) for all possible tokens.

Including `clientProvidedSubscriptionName` for both manual and
automatic policies ensures a consistent notification payload format across all
subscription types.

### User ID mapping

The `healthUserId` is a Google Health API identifier for the user whose
data has changed. If your application supports multiple users, you can receive
notifications for any user who has granted your application consent. When
you receive a notification, use `healthUserId` to identify which user's
data has changed, so you can use their OAuth credentials to query their data.

To map a user's OAuth credentials to their `healthUserId`, use the
[`getIdentity`](https://developers.google.com/health/reference/rest/v4/users/getIdentity.md.txt) endpoint. Call
this endpoint with a user's credentials during user onboarding to retrieve
their `healthUserId`, and store this mapping. This mapping doesn't change over
time, so it can be cached indefinitely. For an example, see
[Get user ID](https://developers.google.com/health/endpoints.md.txt#get-user-id). This lets you select the correct
user credentials when querying data based on the `healthUserId` in a
notification.

### Time intervals

The `intervals` array contains one or more objects representing the time
intervals for the modified data:

| Field | Type | Required | Description |
|---|---|---|---|
| `physicalTimeInterval` | `object` | No | The UTC physical time interval of the modified data (`YYYY-MM-DDTHH:MM:SSZ` format). Populated for intraday metrics; omitted for daily rollups and full-day activities. |
| `civilDateTimeInterval` | `object` | Yes | The civil (local) calendar date and time interval of the modified data, without UTC or timezone offsets. |
| `civilIso8601TimeInterval` | `object` | Yes | The civil (local) time interval represented as an ISO 8601 string (`YYYY-MM-DDTHH:MM:SS` format) without UTC or timezone offsets. |

For full-day activities and daily aggregates, the `physicalTimeInterval`
field is intentionally omitted from the notification payload. This is because
full-day events are bucketed by their nominal civil date, and physical time
durations can be inaccurate when crossing timezones. When processing full-day
events, you should rely on the `civilDateTimeInterval` or
`civilIso8601TimeInterval` fields as a best practice. For details on how to
query these data points using civil time filters, see
[Filter data by an interval civil start time](https://developers.google.com/health/endpoints.md.txt#filter-by-civil-time).

The following is an example notification payload for a full-day activity where
the `physicalTimeInterval` field is omitted:

```
{
  "data": {
    "version": "1",
    "clientProvidedSubscriptionName": "auto-503461148219-lindasubscriber-WEBHOOK_DATA_TYPE_STEPS",
    "healthUserId": "343864966078399341",
    "operation": "UPSERT",
    "dataType": "steps",
    "intervals": [
      {
        "civilDateTimeInterval": {
          "startDateTime": {
            "date": {
              "year": 2026,
              "month": 7,
              "day": 14
            },
            "time": {}
          },
          "endDateTime": {
            "date": {
              "year": 2026,
              "month": 7,
              "day": 15
            },
            "time": {}
          }
        },
        "civilIso8601TimeInterval": {
          "startTime": "2026-07-14T00:00:00",
          "endTime": "2026-07-15T00:00:00"
        }
      }
    ]
  }
}
```

### Vocabulary of webhook data type tokens

When using an `AUTOMATIC` policy, the generated `clientProvidedSubscriptionName`
contains one of the following capitalized `WEBHOOK_DATA_TYPE_*` suffix tokens
depending on the data type:

<br />

| Webhook Data Type Token | Corresponding Data Type |
|---|---|
| `WEBHOOK_DATA_TYPE_ACTIVE_MINUTES` | `active-minutes` |
| `WEBHOOK_DATA_TYPE_ACTIVE_ZONE_MINUTES` | `active-zone-minutes` |
| `WEBHOOK_DATA_TYPE_ACTIVITY_LEVEL` | `activity-level` |
| `WEBHOOK_DATA_TYPE_ALTITUDE` | `altitude` |
| `WEBHOOK_DATA_TYPE_BLOOD_GLUCOSE` | `blood-glucose` |
| `WEBHOOK_DATA_TYPE_BODY_FAT` | `body-fat` |
| `WEBHOOK_DATA_TYPE_CALORIES_IN_HEART_RATE_ZONE` | `calories-in-heart-rate-zone` |
| `WEBHOOK_DATA_TYPE_DAILY_HEART_RATE_VARIABILITY` | `daily-heart-rate-variability` |
| `WEBHOOK_DATA_TYPE_DAILY_HEART_RATE_ZONES` | `daily-heart-rate-zones` |
| `WEBHOOK_DATA_TYPE_DAILY_OXYGEN_SATURATION` | `daily-oxygen-saturation` |
| `WEBHOOK_DATA_TYPE_DAILY_RESPIRATORY_RATE` | `daily-respiratory-rate` |
| `WEBHOOK_DATA_TYPE_DAILY_RESTING_HEART_RATE` | `daily-resting-heart-rate` |
| `WEBHOOK_DATA_TYPE_DAILY_SLEEP_TEMPERATURE_DERIVATIONS` | `daily-sleep-temperature-derivations` |
| `WEBHOOK_DATA_TYPE_DISTANCE` | `distance` |
| `WEBHOOK_DATA_TYPE_EXERCISE` | `exercise` |
| `WEBHOOK_DATA_TYPE_FLOORS` | `floors` |
| `WEBHOOK_DATA_TYPE_HEART_RATE` | `heart-rate` |
| `WEBHOOK_DATA_TYPE_HEART_RATE_VARIABILITY` | `heart-rate-variability` |
| `WEBHOOK_DATA_TYPE_HEIGHT` | `height` |
| `WEBHOOK_DATA_TYPE_HYDRATION_LOG` | `hydration-log` |
| `WEBHOOK_DATA_TYPE_NUTRITION_LOG` | `nutrition-log` |
| `WEBHOOK_DATA_TYPE_RESPIRATORY_RATE_SLEEP_SUMMARY` | `respiratory-rate-sleep-summary` |
| `WEBHOOK_DATA_TYPE_RUN_VO2_MAX` | `run-vo2-max` |
| `WEBHOOK_DATA_TYPE_SEDENTARY_PERIOD` | `sedentary-period` |
| `WEBHOOK_DATA_TYPE_SLEEP` | `sleep` |
| `WEBHOOK_DATA_TYPE_STEPS` | `steps` |
| `WEBHOOK_DATA_TYPE_TIME_IN_HEART_RATE_ZONE` | `time-in-heart-rate-zone` |
| `WEBHOOK_DATA_TYPE_WEIGHT` | `weight` |
| `WEBHOOK_DATA_TYPE_USER_DELETED` | `user-deleted` *(system event)* |
| `WEBHOOK_DATA_TYPE_USER_REVOKED_ACCESS` | `user-revoked-access` *(system event)* |

<br />

### Aggregation of updates

To minimize network traffic, the Google Health API batches messages together.
The system is configured to send out a maximum of 99 messages per batch, which
are automatically pushed as they become available.

When messages are batched, the payload is delivered as a JSON array containing
multiple notification objects. A single batch can include updates for multiple
users across multiple subscribed data types. For an example payload, see the
[Batch (multiple users and data types)](https://developers.google.com/health/webhooks.md.txt#batch-multiple-users-and-data-types)
example in the Notification format section.

### Respond to a notification

Your server must validate the `Authorization` header, handle the synchronous
[endpoint verification](https://developers.google.com/health/webhooks.md.txt#endpoint_verification) handshake, and respond to data
change notifications with an HTTP `204 No Content` status code immediately. To
avoid timeouts, process the notification payload asynchronously after sending
the response. If the Google Health API receives any other status code or the
request times out, it retries sending the notification later.

Node.js (Express) Example:

```javascript
app.post('/webhook-receiver', (req, res) => {
    if (req.headers.authorization !== EXPECTED_SECRET) {
        return res.status(401).send();
    }
    if (req.body && !Array.isArray(req.body) && req.body.type === 'verification') {
        return res.status(200).send();
    }

    // 1. Immediately acknowledge the notification batch
    res.status(204).send();

    // 2. Normalize single-object or batched array notifications and reconcile asynchronously
    const notifications = Array.isArray(req.body) ? req.body : [req.body];
    setImmediate(async () => {
        for (const notification of notifications) {
            const { healthUserId, dataType, intervals = [] } = notification.data || {};
            console.log(`Update for user ${healthUserId} of type ${dataType}`);
            // Query /v4/users/${healthUserId}/dataTypes/${dataType}/dataPoints:reconcile?filter=...
            // for each interval in `intervals` (using >= and < comparators; for sleep, filter on
            // sleep.interval.end_time or sleep.interval.civil_end_time).
        }
    });
});
```

To fetch the updated data for each notified interval, call the
[`reconcile`](https://developers.google.com/health/reference/rest/v4/users.dataTypes.dataPoints/reconcile.md.txt)
endpoint with a [filter](https://developers.google.com/health/filters.md.txt) for the interval's time range. This
automatically deduplicates overlapping intervals from connected devices. For
details and examples, see
[Get a reconciled view of interval data](https://developers.google.com/health/endpoints.md.txt#get-reconciled-view).

There are three common strategies for updating your database after receiving a
data change notification:

- **Queuing (recommended)**: Place the incoming notifications into a message queue and process them off the queue based on system resources.
- **Immediate retrieval**: Direct your backend to immediately call the Google Health API to fetch the updated data and commit it to your database.
- **Lazy updates**: Mark the user's local database records as dirty and only fetch the updated data from the Google Health API when the user next visits your application.

The queueing strategy lets you process data promptly while remaining resilient
to a flood of notifications (for example, if a service outage causes a backlog
of notifications to be delivered all at once). While you can choose to process
these queues on a long-interval batch schedule (for example, every 3 hours) to
save resources, the drawback is that users typically expect to see their data
updated promptly.

### Best practices

Follow these best practices to ensure reliable and efficient handling of data
updates:

- **Use the Subscription API**: Use the Subscription API to be notified when a user has new data to download rather than polling endpoints.
- **Queue and process notifications separately**: When receiving subscription notifications, place them into a queue and process them separately based on your system's resources. Keep the webhook endpoint lightweight by acknowledging the request immediately.

### Signature verification

To ensure the authenticity of Webhooks notifications, the raw JSON payload of
every outgoing webhook notification is signed with a private key using [Tink's
PublicKeySign](https://developers.google.com/tink/digitally-sign-data),
providing the Base64-encoded signature in the `GOOGLE-HEALTH-API-SIGNATURE` HTTP
header in the request. These signing keys are automatically rotated every 30
days, and the corresponding official public keyset is distributed as a JSON
file at the permanent URL
https://www.gstatic.com/googlehealthapi/webhooks/webhooks_public_keyset.json.

#### How to verify the signature

**Using Tink (Recommended)** : Developers can verify the signature using Tink's
[PublicKeyVerify](https://developers.google.com/tink/digitally-sign-data.md.txt)
primitive. Fetch the public keyset from the permanent URL, instantiate the
PublicKeyVerify primitive with the keyset, and verify the decoded
`GOOGLE-HEALTH-API-SIGNATURE` header against the raw webhook JSON payload.

**Manual Verification (Without Tink)**: If developers choose not to use Tink,
they can manually verify the signature by following these steps:

1. Base64-decodes the `GOOGLE-HEALTH-API-SIGNATURE` header to separate the 5-byte Tink prefix (which contains a 1-byte version prefix and a 4-byte keyId) from the actual DER-encoded signature.
2. Fetch the JSON keyset from https://www.gstatic.com/googlehealthapi/webhooks/webhooks_public_keyset.json.
3. Locate the key matching the parsed keyId and Base64-decode its value field, which contains a serialized EcdsaPublicKey Protocol Buffer.
4. Extract the big-endian x and y coordinates (Protobuf tags 3 and 4) from this binary payload.
5. Instantiate a standard ECDSA P-256 public key in a built-in cryptography library using the extracted x and y coordinates.
6. Verify the raw webhook JSON payload against the extracted DER signature using the SHA-256 algorithm.

## Subscriber status and recovery

If your subscriber endpoint becomes unavailable or returns an error status code
(anything other than `204`), the Google Health API stores pending
notifications for up to 7 days and retries delivery with exponential backoff.

Once your endpoint is back online and responds with `204`, the API
automatically delivers the backlog of stored messages. Notifications older than
7 days are discarded and cannot be recovered.

> [!TIP]
> **Tip:** Have questions about the content on this page? Use the AI assistance and developer tools to get explanations and clarify your understanding. See [AI assistance and developer tools](https://developers.google.com/health/ai-assistance-and-developer-tools.md.txt) to learn more.

## Common errors


| Error code | Message | Description | Recommendation |
|:---|:---|:---|:---|
| 400 Bad Request | Invalid project number in resource name | When deleting or updating a subscriber using your Google Cloud project ID in the request URL instead of project number. This applies to webhook subscriptions using the `projects.subscribers` endpoint. | Use your Google Cloud project number in the request URL, not the project ID. |
| 403 Forbidden | The caller does not have permission | When creating or listing subscribers using your Google Cloud project ID in the request URL instead of project number. This applies to webhook subscriptions using the `projects.subscribers` endpoint. | Use your Google Cloud project number in the request URL, not the project ID. |

<br />