HealthPit is an open-source, local-first health data platform for iPhone and Home Assistant.
The iPhone app reads Apple Health locally and pushes what you select straight into Home Assistant. A custom integration stores it and creates native entities. There is no bridge, no container and no add-on in between.
iPhone (HealthKit) ──push──▶ Home Assistant ──▶ sensors, map, statistics
long-lived
access token
One config entry covers the whole household. Everyone creates their own
long-lived access token in their own Home Assistant profile, and Home Assistant
tells the tokens apart: each person gets their own device with their own
entities, so sensor.peter_schritte and sensor.anna_schritte never collide.
The app never claims an identity — the token decides.
| Path | Purpose | Installation |
|---|---|---|
custom_components/healthpit |
Home Assistant integration | HACS |
ios_app |
HealthPit iPhone app | Xcode |
- Add
https://github.com/doctorspreter/HealthPitto HACS as a custom Integration repository, install HealthPit, and restart Home Assistant. Alternatively copycustom_components/healthpitinto your configuration folder. - Settings > Devices & Services > Add Integration > HealthPit, then confirm. There is nothing to enter.
- In your Home Assistant profile, scroll to Long-lived access tokens and create one.
- In the app under Settings > Verbindung, enter your Home Assistant address and paste the token.
The local address is preferred and the external one is only used when the local one does not answer, so the app works at home and away without switching anything. The external address must be HTTPS.
Verify a setup from the command line:
curl -H "Authorization: Bearer YOUR_TOKEN" https://ha.example.com/api/healthpit/v1/statusA track is one thing, so it is one entity. Each user gets:
- an image entity that draws the newest track as a line, generated as SVG — no image library, no map tiles, no request leaving the machine. Drop it on a dashboard with a picture-entity card.
- a sensor whose state is the distance of that track, with the workout it belongs to, its bounding box and download links in the attributes.
Any stored track can be fetched whole:
GET /api/healthpit/v1/workouts/{workout_id}/route.gpx
GET /api/healthpit/v1/workouts/{workout_id}/route.geojson
GET /api/healthpit/v1/workouts/{workout_id}/route.svg
GPX goes into any other tool, GeoJSON into a map card. Both need the same long-lived access token as everything else.
Incoming tracks are thinned to 500 points, which keeps the shape and keeps the
store quick to load; the original sample count stays visible as
route_points_total.
Home Assistant cannot backdate its state history — there is no API for that.
Its long-term statistics can be backdated, and for sensors carrying a
state_class that is what long-range graphs are drawn from. The
healthpit.import_history service walks the stored workouts and writes the
cumulative sport values (count, total duration, total distance) into the
statistics. The iPhone app's Send all historical data to Home Assistant
action additionally reads the complete permitted HealthKit history, aggregates
quantity, sleep and numeric cycle metrics by hour, uploads all workouts and
backfills their existing Home Assistant sensor statistics. Repeating either
import updates the same hourly rows rather than creating duplicates.
- Home Assistant's own authentication guards the push API. Revoke a token in the profile and that phone is locked out immediately.
- The stored data lives in Home Assistant's own storage, marked private.
- Use HTTPS for the external address. Behind Cloudflare or another reverse
proxy, remember that TLS terminates there and set
use_x_forwarded_forplustrusted_proxiesin yourhttp:configuration.
Do not commit .env files, databases, backups, tokens or Xcode user data. See
SECURITY.md for reporting security issues.
The integration is plain Python and needs no build step. Copy
custom_components/healthpit into your Home Assistant configuration, or point
HACS at this repository.
The iPhone app builds with Xcode from ios_app.
Apache License 2.0. See LICENSE.