Apple Health into Home Assistant — Healthcove Guide

Guide

Apple Health into Home Assistant

Turn heart rate, sleep, HRV, steps, workouts and any of 182 Apple Health data types into Home Assistant sensors, an MQTT stream, or a webhook payload, straight from your iPhone. No cloud in between.

Do you need this? The companion app's own sensors

Since version 2026.8 (August 2026) the official Home Assistant iOS app can expose Apple Health metrics as sensors, as a Labs feature. If those cover what you want, use them: they're free and native. Healthcove earns its place when you need more than they carry.

Home Assistant app (Labs)Healthcove
Data typesAbout 29: steps, distance, energy, flights, exercise time, VO2 max, weight, body fat, height, heart rate, resting and walking heart rate, HRV, blood pressure, water, respiratory rate, blood oxygen, body temperature, blood glucose, sleep stages182, including workouts, ECG classifications, State of Mind, medication doses, menstrual tracking, mindful minutes, time in daylight, environmental sound, cycling power and the full nutrition set
What a value isThe current reading, or today's running totalLatest reading per run for sensors; the actual samples with timestamps, or hourly / daily / weekly aggregates, for MQTT and REST
HistoryStarts the day you enable the sensorCan send everything Health holds on the first run, then only new data
SleepLast night's minutes per stageEvery sleep segment with its stage, start and end time
TargetsHome Assistant onlyHome Assistant, any MQTT broker, any REST endpoint or webhook, Calendar, files in a folder
CostFreePro: 7-day free trial, then a one-time purchase

Rule of thumb: everyday dashboard numbers, use the companion app. Workouts, history, unusual types, or a broker or database on the receiving end, use Healthcove. Running both is fine; the entity names don't collide.

Before you start

  • Healthcove Pro on your iPhone (the 7-day trial counts). Automations live under Settings → Automations.
  • A Home Assistant URL your phone can reach, such as http://homeassistant.local:8123 on your Wi-Fi, or your remote URL if you use one. Plain http:// is accepted for local instances.
  • A long-lived access token (for Option A). In Home Assistant open your profile, switch to the Security tab, and under Long-lived access tokens choose Create token. Copy it once; Home Assistant won't show it again.
  • Background App Refresh turned on for Healthcove in iOS Settings, so scheduled and on-change runs can happen while the app is closed.

Option A: Home Assistant sensors (recommended)

This target posts each metric straight to your instance's REST API as a sensor entity. It's the simplest path and the one to use when the goal is entities on a dashboard or in automations.

  1. In Healthcove open Settings → Automations, tap + and choose Home Assistant.
  2. Give it a Name, enter your Home Assistant URL and paste the Long-Lived Access Token.
  3. Under Health Data Types pick what to send. Start small; you can add types later.
  4. Choose a Trigger: when new data arrives, every 15 minutes, hourly, every 6 hours, or once a day.
  5. Leave Send only new data on. Each run then covers samples since the previous run.
  6. Tap Test Connection. It checks that the instance answers and the token is accepted. Then save.

What appears in Home Assistant

One entity per type, named sensor.health_<type>: for example sensor.health_step_count, sensor.health_heart_rate, sensor.health_resting_heart_rate, sensor.health_oxygen_saturation, sensor.health_body_mass. The state is the latest value in that run. Each entity carries friendly_name, unit_of_measurement in your display units, a device_class where Home Assistant has a matching one (temperature, weight, distance, duration, power, speed) and a state_class (measurement, or total_increasing for cumulative types like steps and energy), so history graphs and long-term statistics work without extra YAML.

Because these are pushed states rather than an integration, Home Assistant doesn't restore them across a restart. They reappear on the next run. If you want a value per day instead of the latest sample, set Aggregation to daily and Home Assistant will receive one number per type per day.

Use them like any other sensor

automation:
  - alias: "Resting heart rate is up"
    trigger:
      - platform: numeric_state
        entity_id: sensor.health_resting_heart_rate
        above: 70
    action:
      - service: notify.mobile_app_iphone
        data:
          message: "Resting HR is {{ states('sensor.health_resting_heart_rate') }} bpm"

Option B: MQTT

Use MQTT when the consumer is a broker pipeline: Node-RED, Telegraf into InfluxDB, a Grafana stack, or several subscribers at once. Each run publishes one JSON document with the samples themselves.

  1. Settings → Automations → +, choose MQTT.
  2. Enter the Broker Host and Port (8883 with Use TLS on, or 1883 without). Add a Username and Password if the broker needs them.
  3. Set the Topic. The default is healthkit/data. Pick a QoS Level; 1 is a sensible default.
  4. Under Payload choose Raw samples or an aggregation interval, then the Health Data Types and a Trigger.
  5. Test Connection, then save.

The payload is the same JSON document as the app's grouped export: a metadata block, then data keyed by type, each an array of samples with startDate, endDate, value and unit (sleep segments carry a stage value instead). Point Node-RED or Telegraf at data.<type>.

Auto-Discovery

Turn on Auto-Discovery under Home Assistant and each run also publishes, per type, a retained discovery config on homeassistant/sensor/healthcove_<automation id>/<type>/config and a retained value on <topic>/state/<type>, for example 72 on healthkit/data/state/heartRate. Home Assistant's MQTT integration creates one sensor per type under a device named after the automation, so two automations or two phones on one broker stay separate. Because every message is retained, a run that carries no new sample for a type leaves that type's last value in place, and the sensors keep their values across a Home Assistant restart.

The value is the latest sample in that run: the number for quantity types, the stage of the most recent segment for sleep as its Health category number (0 in bed, 1 asleep, 2 awake, 3 core, 4 deep, 5 REM), and the duration in seconds for workouts. With Aggregation on it is the latest bucket's total or average instead. Blood pressure and other correlation types get no sensor; use their systolic and diastolic quantity types. The full document on the main topic is unchanged, so a Node-RED flow and the discovered sensors can share one automation.

To remove the sensors, delete the device under Settings → Devices & services → MQTT in Home Assistant, which clears the retained configs. The retained values stay on the broker until overwritten, so clear <topic>/state/# there too if the broker is shared.

Requires Healthcove 1.2.3 or later. Earlier versions registered the entities but never published the state they read, so the sensors showed unknown. On 1.2.2 or earlier, leave the toggle off and use Option A for sensors.

Option C: REST, including Home Assistant webhooks

The REST target posts the payload to any URL with the headers you choose. Two useful cases:

  • A Home Assistant webhook. Create an automation with a Webhook trigger, then use its URL (http://homeassistant.local:8123/api/webhook/<your-id>) as the Endpoint URL. The whole payload arrives as trigger.json, so one automation can react to a workout or a new weight sample the moment it lands.
  • Your own receiver for InfluxDB, a database, n8n or a script. Add an Authorization: Bearer … header under HTTP Headers.

Payload Format offers JSON v2 (grouped by type), JSON v1 (a flat array, compatible with tools that read the Health Auto Export schema), and CSV. Aggregation and Send only new data work the same as above.

Triggers, background and history

  • When new data arrives uses Apple's background delivery, the same mechanism the companion app relies on. Samples usually land within minutes, but iOS decides when background work runs. It is not a second-by-second stream.
  • Scheduled triggers run while the app is open or during background refresh, as the app itself tells you. Keep Background App Refresh on, and don't force-quit the app.
  • Send only new data on: each run sends samples since the previous run. Off: each run sends everything Health has for the selected types. Turn it off for one run to backfill years of history into a database, then turn it back on.
  • Aggregation (hourly, daily, weekly, monthly, yearly) sends totals or averages per bucket instead of raw samples. It only applies to numeric types.

Troubleshooting

Test Connection fails

Check the URL includes the scheme and port (http://homeassistant.local:8123), the token was pasted whole, and the phone is on the same network as the instance or your remote URL is reachable. A VPN on the phone can route local names elsewhere.

Nothing arrives

With Send only new data on, a run with no new samples sends nothing; that's normal overnight for daytime metrics. Open Healthcove once to run due automations immediately. Confirm Background App Refresh is on for Healthcove and that iOS Low Power Mode isn't suspending background work.

Sensors vanished after a Home Assistant restart

Expected for states pushed over the REST API. They come back on the next run. If you need them to survive restarts, feed a webhook (Option C) into an input_number or template sensor instead.

Values look stale or jumpy

A sensor holds the latest sample from the last run. For a steadier number, use daily aggregation, or the on-change trigger with raw samples for the freshest one.

Which units?

Your display units in Healthcove. Change them in the app's settings and new pushes follow.

Ready? Healthcove is free to browse and export; automations are part of Pro, with a 7-day free trial.