Building a Personal Health Dashboard from Samsung Health
I've had my reliable Samsung Galaxy Watch 4 now for almost 5 years and have been wearing it daily, even when I am asleep. As a result, it has collected a lot of health data.
My parents (who live 10 time zones away) keep asking about my vitals, as tracked by the watch, almost every time I call them. Mostly because I don't reveal much about myself or how I am doing. They ask how many steps I've taken that day to see if I have been on the couch all day, how much sleep I got to see if something kept me up, and what my heart rate has been like to check on my stress. I wanted a live dashboard I could send them a link to, but getting data from Samsung Health turned out to be way harder than it should have been.
Samsung Health doesn't have a public REST API. There's a Samsung Developer SDK, but you need a partner account and have to jump through enterprise hoops. Even if I got in, I'd be building against a vendor SDK with no guarantee it sticks around.
Google Fit had a REST API. It's being killed off by the end of 2026. Google Health Connect has its own thing, but it's local-only. Runs on the phone, no cloud endpoint. And honestly, I didn't want to tie myself to any Google API anyway.
So I had data sitting on my phone, no clean way to get it out, and a goal: a shareable URL my parents could bookmark.
Health Connect was already doing the hard part
Here's something I didn't realize until I dug into it. Samsung Health has been quietly syncing everything into Android's Health Connect platform. Steps, sleep stages, heart rate, SpO₂, workouts, BMR, floors climbed, and distance. It's all there, aggregated on-device, whether you know it or not.
Health Connect gives Android apps a local API to read (and write) health records. It's an on-device SDK, not something you can hit from a server. That's the catch. But it's also the key: if you can get the data off the device, you can do anything with it.
I built a small Android app to do exactly that. Called it Health Bridge.
Health Bridge
The app is built with Kotlin and Jetpack Compose. Single screen. Permissions, a sync button, a status line. All in a 3 MB APK.
WorkManager kicks off a periodic job that pulls recent data from Health Connect and POSTs it to my server. It tracks the last sync timestamp, so each upload is incremental. No re-sending years of data every time.
It reads these record types:
| Data | Health Connect Record |
|---|---|
| Steps & distance | StepsRecord, DistanceRecord |
| Sleep (with stages) | SleepSessionRecord |
| Heart rate | HeartRateRecord |
| Workouts | ExerciseSessionRecord |
| Body metrics | SpO₂, BMR, body fat, weight |
The JSON payload gets serialized with kotlinx.serialization and sent over HTTPS with an API key header. That's it. No background service is eating the battery. WorkManager handles the scheduling and the phone's Doze mode.
The server: Flask and SQLite
The sync endpoint is a Flask app. Receives JSON, validates it, and upserts into SQLite. That's the whole thing.
Schema:
steps (date, count, distance_meters)
sleep (date, start_time, end_time, duration_min, awake_min, light_min, deep_min, rem_min)
heart_rate (date, avg_bpm, min_bpm, max_bpm)
workouts (date, start_time, end_time, type, duration_min, calories, distance_km, avg_hr, max_hr)
readings (metric, time, values_json)
sync_log (received_at, last_sync, counts)
The sync endpoint validates the payload, upserts each record type, logs the sync, and returns counts. There are read endpoints too (/api/steps, /api/sleep, etc.), mostly for debugging or building other tools on top of them.
I run Flask in Docker behind nginx. The phone hits the sync endpoint every 12 hours.
Why SQLite? Because it works. Zero configuration, zero maintenance, handles everything I throw at it. For a single-user dataset this size, Postgres would be absurd.
The dashboard: we need more static sites.
I initially used the read APIs to fetch my health data from the SQLite database with a React frontend. But I didn't need the dashboard to be live, and I didn't want to hog any more memory on my Dell Optiplex 7050 homelab. So I avoided running a process, auth, session management, all the things that break at 3 AM.
Instead, a Python script (build.py) reads SQLite, aggregates the data, and spits out a single index.html with everything inlined. Plotly.js handles the charts. nginx serves the static file. No moving parts at render time.
The dashboard shows:
Four KPI cards at the top: avg daily steps, avg sleep, avg resting HR, total workouts
Steps with a 7-day rolling average overlayed
Sleep breakdown: stacked bars for awake, light, deep, REM
Heart rate: daily min/max band with the average line through it
Recent workouts: a table with type, duration, calories, and distance
Body metrics: whatever readings are available (SpO₂, BMR, weight) as time series
A cron job rebuilds the dashboard three times a day (8 AM, 2 PM, 8 PM), which lines up with the phone's 12-hour sync cycle.
How it all fits together

Things I'd change (and things I wouldn't)
The system's been running for months without any issues. A few things stand out.
SQLite continues to be the right call. I haven't touched the database once since setting it up. No migrations, no connection pooling, no nothing.
The static site + cron approach is perfect for this use case. I did not need real-time step counts. Three rebuilds a day are plenty, and there's no server to keep alive for serving pages. If nginx is up, the dashboard is up.
Android Health Connect's SDK is solid. Good documentation, clean API design. And Samsung's automatic sync into Health Connect means I never touch the Samsung SDK at all. That's the part that surprised me most. I came in expecting to fight Samsung's ecosystem and ended up bypassing it entirely.
The one thing I'd do differently: I initially tried pulling raw per-sample heart rate data instead of daily aggregates. The payloads got huge, and the sync took forever. Switching to daily min/avg/max was the simple fix.
Next step I've been thinking about: wrapping the read API as an MCP server. Then I could ask my Hermes agent, "How did I sleep last night?" or "What's my step average this week?" straight from chat. The API endpoints are already there; it's just a matter of wiring them up.
Stack
| Layer | What I used |
|---|---|
| Data source | Samsung Health → Android Health Connect |
| Phone app | Kotlin, Jetpack Compose, Health Connect SDK, WorkManager |
| Sync server | Python, Flask, SQLite |
| Dashboard | Python build script, Plotly.js, static HTML |
| Serving | nginx, Docker |
| Scheduling | Linux cron |
| Auth | API key |
The dashboard is at health.shambu.party. My parents have the link and access (protected by Cloudflare - Google OAuth). They don't ask about my vitals anymore. They look at the chart.
