tiny
Health platform·
The tiny health platform the ring feeds: sample contract, devices, day summaries, the /health page and the inline chat card.
In 10 seconds
A generic health store in the tiny worker (D1 rows, R2 media) — the ring is its first real device. Gateways post
samples {ts, metric, value, unit, raw} to /api/health/ingest with a device token; you read day summaries at
tiny.technology/health, in chat as a health card, and in the morning brief. Charger readings are excluded.
Ingest — the sample contract·
POST /api/health/ingest — no session; the body carries the fleet device credentials and a batch:
{"deviceId": "…", "token": "…",
"device": {"name": "JY-Y3-011A", "ble_address": "…", "firmware": 152, "label": "black"},
"samples": [
{"ts": "2026-09-19T15:51:40Z", "metric": "heart_rate", "value": 85, "unit": "bpm", "raw": "0b …"},
{"ts": "2026-09-19T15:51:40Z", "metric": "charging", "value": false},
{"ts": "2026-09-19T15:50:00Z", "metric": "sleep_stage", "value": 2, "session": "sl_<mac>_<night>"}
]}
| metric | unit | source cmd |
|---|---|---|
heart_rate |
bpm | 11 live, 36 records |
spo2 |
% | 24 live, 36 records |
temperature |
°C | 36 records (tenths → °C) |
steps · calories · distance |
count · kcal · m | 29 snapshot, 33 buckets |
sleep_stage |
code, with session |
34 buckets (300 s) |
battery · charging |
% · bool | 6 |
button |
event | 40 |
Rules: raw is printable ASCII ≤ 128 chars · source ∈ ring | app | manual | demo | import · a charging sample marks
the device row · send a real User-Agent (the edge rejects bare python-urllib) · the reply carries device_id and
labels, and a button sample may trigger the hotkey.
Read it back — devices, summary, samples, rules, staleness cron
GET /api/health/devices |
one row per ring: name, label, firmware, battery, charging, last sync, synced_by |
GET /api/health/summary?day= |
resting/min/max/latest HR, SpO₂, temperature, steps, sleep total + stages, battery; cradle_excluded = readings taken on that ring's charger, left out. Sleep sessions < 10 min ignored; longest session ending that day wins |
GET /api/health/samples?metric=&from=&to= |
the series behind any chart (cradle rows included, tagged) |
/api/health/notes · /api/health/rules |
notes; the owner's switches (memo_agent, button_prompt, auto_hr_min, alert rules) |
| staleness cron | a ring silent > 3 h → one push + health_stale event per outage, cleared by the next ingest |
Where you see it·
tiny.technology/health — day view (sparkline, sleep bar, battery), a card per ring with Find · Battery · HR now ·
Record · Memos buttons (they enqueue ring commands and show "waiting for your phone…"), memo list. In chat —
health_summary / health_query render an inline health card on web, iOS and Android. Morning brief — a
healthBrief line when data exists. Accounts without a ring get a seeded demo day (/api/health/demo), deleted
the moment real samples arrive.