Withings: more than weight — body composition and vascular age
Photo: Ernest F · Wikimedia Commons (BY-SA 3.0), via Openverse
A bathroom scale measures weight. That's how we learned it, and that's how most people think about the device in their bathroom. You step on, a number appears, you're pleased or annoyed. But weight alone is a surprisingly poor metric. Two people with identical weight can have completely different bodies — one muscular, the other not. And what weight doesn't reveal at all is the condition of your blood vessels.
That's exactly where the Withings integration I worked on this week comes in. Modern Withings devices have long since stopped being scales in the classic sense and have become small measuring stations instead. Integrating them meant extending the data models in Xircuit so they live up to that claim — instead of condensing a rich measurement down to a single number.
What a Withings scale actually measures
Anyone who steps onto a current Withings scale gets far more than weight. Using bioelectrical impedance analysis, the device determines body composition: body fat percentage, muscle mass, and body water. That's the difference between "78 kilograms" and "78 kilograms, of which 22 percent is fat, with a solid muscle base." The first number fluctuates with fluid balance and says little. The second tells a story about training, nutrition, and progress.
For Xircuit, that's the real value. Our users don't just want to know whether the number is higher or lower today than yesterday — they want to know whether something has changed in substance. Muscle mass that climbs over weeks while weight stays stable is a success that a plain weight curve would never make visible. Body water, in turn, explains part of the daily fluctuations that would otherwise look like unexplainable jumps. So it was clear: if we connect Withings, we capture all of these values, not just the most obvious one. Every measurement the device delivers is a data point we can later put to meaningful use in a chart, a trend, or a comparison.
Pulse wave velocity and vascular age
The part that appealed to me most technically is a different one. Certain Withings devices measure pulse wave velocity, or PWV for short. That's the speed at which the pressure wave of a heartbeat propagates through the arteries. The stiffer the vessels, the faster this wave travels — and vascular stiffness is an established indicator of cardiovascular health. From the PWV, a so-called vascular age can be derived — a way of classifying how "old" the vessels appear compared to calendar age.
These values don't fit into any weight column. So I introduced a dedicated data structure, WithingsBodyComposition, which captures PWV and vascular age alongside body fat, muscle mass, and body water. This is deliberately designed as a standalone model, not as an appendage to a generic weight entry. Health data of this kind has its own semantics, its own provenance, and its own privacy implications, and it deserves a model that respects that. Anyone who doesn't have these values because their device doesn't measure them simply gets empty fields — the structure doesn't force a measurement on anyone that never existed.
Photo: Rawpixel (CC0 1.0), via Openverse
The same pattern every time: library, sync, worker
Anyone who's been following along the last few weeks already knows the architecture. Withings follows exactly the same pattern as the glucose integration and the other integrations: its own provider library, its own sync, and its own worker. This three-way split isn't a formality — it has proven itself sound because it cleanly isolates every integration.
The library encapsulates everything specific to Withings — the data model, the mapping of API responses to our internal types, the quirks of the provider. The sync takes care of pulling data from outside in and reconciling it with what we already have, without producing duplicates when a measurement gets fetched twice. The worker, finally, runs in the background and kicks off this synchronization on a regular basis. Every new integration gets its own version of these three building blocks, and none can accidentally drag another one down with it. If Withings changes its API format tomorrow, that stays a local problem of the Withings library — the rest of Xircuit doesn't notice. This repetition of the same shape across every provider makes new integrations predictable: I know in advance which three parts I'm going to write.
Server-side polling via OAuth
On the question of how the data comes in, Withings takes its cue from the Google Health cloud connection. It's not a model where a device talks directly to the phone and the app collects the values. Instead, we rely on a server-side OAuth poller: the user authorizes Xircuit once via OAuth against Withings, and after that our worker periodically queries the Withings cloud for new measurements.
This approach has tangible advantages. Synchronization still works even when the user's phone is off or the app hasn't been opened for days — the poller keeps running server-side. Authorization is tied to a token that gets renewed, rather than to a permanent device pairing. And because the same approach already works for Google Health, we could build on a proven structure instead of reinventing every detail. Cloud-to-cloud instead of device-to-device: for a provider like Withings, which already collects everything in its own cloud anyway, that's the natural path.
Built, but still behind a flag
At this point, the honest assessment that belongs in a dev log: the integration is built, but it's switched off behind a flag by default. It isn't live yet. Before we turn it on, several things need to be in place that have nothing to do with the code but are nonetheless essential.
We need a registered app with Withings, we need the associated credentials, and we need a working redirect URL for the OAuth callback. Without these three, the authorization flow leads nowhere. Just as important: we want to verify the integration on a real device before any user relies on it. Data structures and pollers are one thing — but whether the PWV values that actually come from a real scale arrive correctly on our end and get interpreted properly only shows up on the device. Until that's confirmed, the flag stays off. For us, that's not a sign of incompleteness — it's the deliberate order: build first, then verify, then enable.
What's next?
Next week: activity and body-measurement tracking — steps, calories, weight, and progress curves in one overview.
Comments
No comments yet. Be the first to share your thoughts!
Leave a Comment