uniquehuman
Engineering

Making wearable data comparable across every device

UniqueHuman Engineering · Jul 3, 2026 · 5 min read

Not everyone living with chronic pain tracks it the same way, and UniqueHuman builds for all of them. One wears an Apple Watch. Another has an Oura ring. A third has a Garmin, or a band from a company you have never heard of, or nothing at all on the mornings the charger was in the other room. Every one of those devices is quietly recording its wearer, each in a slightly different dialect. Our job is to take whatever someone brings us and turn it into one picture they and their doctor can actually trust.

Reading a device is easy, agreeing with it is not

The raw numbers are the simple part. On an iPhone, whatever you wear writes what it measures into Apple HealthKit, the shared place iOS keeps health data, and reading from there is straightforward: heart rate, heart rate variability, sleep, steps, blood oxygen, workouts, all sitting in one spot.

The trouble starts the instant you try to compare across them. Two devices measuring the "same" thing rarely measure it the same way. One person's watch samples continuously, thousands of tiny readings a day. Another person's ring reports a single summary once a night. And any single device has holes: a watch on the wrist at 2 a.m. is recording, but the same watch left charging on the nightstand has nothing at all to say about those hours. Treat that silence as a zero and you have just invented a resting heart rate that never happened, and every trend built on top of it inherits the fiction. The unnerving part is that nothing breaks when this goes wrong. No error, no crash. The chart just quietly misleads, which is worse than failing outright.

We translate every device into one language

So before any of it leaves the phone, we do the unglamorous work of translation. Each HealthKit type is mapped to a single signal we have agreed on, with one fixed unit, so it reads the same no matter which device it came from.

Raw HealthKit typeSignal we storeUnit
HeartRateVariabilitySDNNhrv_sdnnmilliseconds
OxygenSaturationblood_oxygenpercent
HeartRateheart_ratebpm
StepCountstepscount

Continuous streams like heart rate and steps get grouped into fixed ten-minute windows, the same interval the app syncs on, so a flood of tiny readings becomes one steady number you can compare hour to hour. Sleep and workouts are left whole, as sessions, because slicing them into windows would destroy the very thing they are. By the time our servers see anything, it already speaks one language, no matter which device it came from. Adding a new kind of device is then just a new mapping to an existing signal, not a new pipeline, which is what lets us say yes to whatever someone shows up wearing.

For the data your wearables produce, HealthKit is the single door in. An Oura, a Whoop, a Garmin, an Apple Watch all write into it, so we read every one of them through that one interface rather than integrating each device separately. The tradeoff is that we only see what a device chooses to share with HealthKit, in the shape HealthKit gives it. Doing the translation on the phone, at the source, instead of re-deriving it every time someone opens a report, is what keeps every later comparison honest.

A reading only means something once you know its day

Even in one language, a number is not much use until you know when it happened, and "when" is slipperier than it looks. We file each reading under the person's own local calendar day, using the timezone their phone reports when it syncs, so a late-night workout counts toward the day they actually lived it, not the day it happens to land in a server's clock. Sleep needs even more care, because a night refuses to sit inside a single date. So we file a sleep session under the day it ends on, as long as it ends before 2 p.m. local time, which lets a 1 a.m. bedtime count as one night's sleep on the morning you wake rather than being sliced across two days. None of this is glamorous, and every bit of it will quietly corrupt everything downstream if you get it wrong.

When the data isn't there, we would rather say nothing

The most important choice we made is also the most restrained. We do not fill in gaps. If a reading is missing, we never guess a value to smooth it over; a hole stays a hole. Before we will compare anything against your personal baseline, your own normal, we want at least five real data points, and each pattern we look for carries its own minimum before it is allowed to speak. When there simply is not enough to say something true, the app says so plainly instead of dressing a guess up as insight. The safety checks fail open, which is just a way of saying that missing data raises no alarm rather than a false one. We would far rather miss a day than frighten someone over noise.

A signal starts a conversation, it does not end one

Which brings us to the honest edge of all this. What we show you today is closer to "this is unusual for you" than "this is why you hurt." It is your body measured against its own history, explained in plain language, not a proven cause pulled from a tidy statistical model. One person's data is a small and noisy thing, and a lot of what looks like a trigger is really an early symptom of an attack already on its way. So we treat every pattern as the opening of a conversation with your clinician, never the final word. Making all of this comparable only matters if what we hand back is something you can trust, and trust is earned by being careful about what we claim.

More resources