Skip to content

Instantly share code, notes, and snippets.

@katemonkeys
Last active February 20, 2024 15:36
Show Gist options
  • Star 59 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save katemonkeys/e17580777b57915f5068 to your computer and use it in GitHub Desktop.
Save katemonkeys/e17580777b57915f5068 to your computer and use it in GitHub Desktop.
Everything Wrong With The Withings API

Top Six Things You Need To Know About The Withings API*

*where “you” is probably a developer, or at least a strange user

I should preface this by saying that I got a Withings Smart Body Analyzer for Christmas last year and I’ve been generally happy with it. It purports to be able to take my heart rate through my bare feet and that seems not to work for my physiology, but overall I’m a fan. If if their Wikipedia page is to be believed they are having a pretty rad impact on making the Quantified Self movement more for normal people and they only have 20 full time employees. Also they try hard to use SI units, which I can get behind. Anyway, on to the rant.

I originally called this post “Everything wrong with the Withings API” and I meant it. For every useful field I can extract from their “award winning” app, I have spent an hour screaming at the inconsistencies in their implementation or inexplicable holes in their data coverage. This is as much a post for developers looking for reasons why they are tearing their hair out trying to access an unruly metric as it is for anyone who provides a third party API that is intended to be consumed by anyone not themselves, and what us poor data consumers have to deal with.

It’s inconsistent about formatting

Sometimes we assemble a query for startdate (which needs to be formatted as a time in epoch seconds, for sleep detail measures) and sometimes for startdateymd (which returns a starttime in epoch milliseconds for sleep summary measures). Some measures return device identifiers: a model 16, for example, is their Pulse watch, and a model 32 is their Aura bedmat. What then am I to make of a sleep data object reporting a model 61??

Model 61, you say?

They don’t understand OAuth.

“The Withings OAuth implementation is not perfect” says the gentle author in the README for the withings-request node module. That author has helpfully rendered transparent a lot of the failings (encrypting the wrong url parameters, returning unparseable nonsense) to consumers of the data, and for that I am grateful. I’m not sure if this is a problem of multiple authors on the part of Withings or what. Hey, try a code review.

Cat quota: complete

It is incomplete

Their API lacks access to certain measures, like the Smart Body Analyzer is supposed to track air quality and it doesn’t show up even in v2. It’s their prerogative, I suppose, and might plausibly have the benefit of forcing people to come back to the mothership app? Anyway, even with an enabled subscription it will arbitrarily and for no reason not deliver days worth of data of one measure or another. When it does deliver the data it disagrees with the primary presentation in the master: see below to contrast (1) a week of data as presented in the app (2) a week of data as returned by a sleep detail query and (3) the same week as queried for at the sleep summary endpoint.

Data they are willing to present

Caption3b: This is the JSON output of the sleep detail for this past week. Notice not a single “state:3”, which would represent REM sleep

{
model: 16,
series: [
{
startdate: 1421586709,
state: 2,
enddate: 1421587669
},
{
startdate: 1421587669,
state: 1,
enddate: 1421589589
},
{
startdate: 1421589589,
state: 2,
enddate: 1421593849
},
{
startdate: 1421593849,
state: 1,
enddate: 1421595229
},
{
startdate: 1421595229,
state: 2,
enddate: 1421596429
},
{
startdate: 1421596429,
state: 1,
enddate: 1421599309
},
{
startdate: 1421599309,
state: 2,
enddate: 1421601769
},
{
startdate: 1421601769,
state: 1,
enddate: 1421602189
},
{
startdate: 1421602189,
state: 0,
enddate: 1421603089
},
{
startdate: 1421603089,
state: 1,
enddate: 1421603569
},
{
startdate: 1421603569,
state: 0,
enddate: 1421603629
}
]
}

Caption 3c: The JSON output of the sleep summary data for this past week, indicating upwards of single-digit minutes of REM sleep on a given night instead of multiple hours as in the app screenshot. A somewhat abbreviated snapshot of reality

It disagrees with itself

Conversely but just as irritatingly, for some days a user on a single account will get several sets of sleep summary data, with several mutually incompatible descriptions of the same night. Look at how many times I must have traveled back and forth in time last Thursday, for example.

Extra data that disagrees with itself!

Account linking and device sharing is terrible.

My partner and I share a scale and prior to its purchase we had separate accounts, but couldn’t figure out how to get it to recognize a measurement as his without making him a new account which was subordinate to mine, which screwed up activity tracking through his own phone. Now he basically doesn’t use the step counter, so, fail.

This is also a very special advanced use case but my boss, another colleague, and I are all 'friends' or 'connections' or whatever on Withings and weigh within rounding error of each other (I gather that the delta must be like 10 pounds). This means that about one time in three, I'll get one of their weights as the data point in my graph, and vice versa, and the jump is still five pounds or more. With only two people of approximately the same weight sharing a scale, you take a measurement then lean to the left foot or right foot to indicate which account you want the measurement to go to. But with three people in range, it's arbitrary, and sucks.

They don't listen

I wrote to them complaining about this and got a rapid, unhelpful response, where the link to the referenced press release returns a 404. Customer service is hard.

This is the assistance you get.

In conclusion, Withings, you’ve got good products and I wish you the best as a company, but I quietly curse you about 30 times a day. Please don’t take it personally.

@cloom
Copy link

cloom commented Nov 5, 2016

I have the smart body analyzer that also takes temperature humidity and I was so happy and excited to use the API to get my bedroom's temperature (yes I jump on it in the morning and before going to bed sometimes).
I was so disappointed when I realized it was not possible. I really don't understand how you can provide API for one type of data and not another, this should be pretty much the same code. So at the end, I never use the temperature data this device is getting :(

@toomaskordemets
Copy link

Have You tested, how fast data appears on their server. I.e. is it possible to detect that user has entered into light sleep phase within couple of minutes, or it takes much more time until the data appears?

@jlwin
Copy link

jlwin commented Jan 23, 2017

Has anyone been able to get the activity score that is displayed e.g. on the Withings Steel HR/pop/activé in the second dial? I would like to manipulate the shown score with any other score on a 0-100 scale that I provide to an api. For example: I would like to show my rescuetime.com productivity score on my watch.
Any Idea how to make this happen? If there is a possibility to change the goal, I could set the step goal to a value that is calculated based on the current amount of steps and the productivity score value (step goal = current amount of steps / own score).

@antarr
Copy link

antarr commented Apr 2, 2017

Has anyone seen the x-recruitment headers?

@kempyk
Copy link

kempyk commented May 14, 2017

Great article highlighting the problems out there! Does anyone have an examples that export the intraday heart rate readings out to say a csv? Seems like a such as basic ask that's missing from their product i can't believe someone hasn't coded something like this already since the steel HR is out.

@caedn
Copy link

caedn commented May 29, 2017

Thank you for the article. I was pulling my hair out trying to get some more data from the API. Withings really need to fix this.

@MarvinT
Copy link

MarvinT commented Jan 20, 2018

Has this improved at all?

@raipat
Copy link

raipat commented Jan 23, 2018

It got actually even worse. Tomorrow they will remote-f*ckup the Body Cardio scales.

@mcgarrah
Copy link

Awesome. Thanks for writing this. I'm on the journey to learning about the API and this was a useful starting point.

@nathyvir
Copy link

nathyvir commented May 2, 2018

How do you find token for API ? I don't find this in my account.

@tanyagupta
Copy link

Thanks for writing this article. Very helpful

@Espoir777
Copy link

I'm novice on this Withings APi technology , i need some tutos to start to use this API, i'm developing an mobile android app and (Symfony/angular ) web site, is there someone can help me to get information about how i can create a withings api ?

@jhmleung
Copy link

katemonkeys is my hero

@RKopczynski
Copy link

Does it changed in any way in past few years?
We are checking similar products for our use case and we need to find hardware with decent API and support.

@KevinMayfield
Copy link

Also noticed some measurements values change. Since 2017 my BP has been whole numbers e.g. 120/80 before this 0.120/0.070.
CORS support seems a bit off, I've used a proxy to get around OAuth2 token issues (not fully investigated - quicker to add a proxy)

@fabianmossberg
Copy link

Would be interesting to get a follow-up on this post @katemonkeys

What has changed in 6 years?

@aharwood2
Copy link

aharwood2 commented Feb 16, 2021

Excellent! I've been struggling with Withings for the last year e.g. not supporting custom redirect URL schemes, dodgy formatting in JSON, incomplete data. Hilariously, their own web dashboard doesn't even make sense -- the number of total daily steps does not add up to the amount the graph next to it says, and the web API agrees with the graph! So I had a customer telling me that our app gave "wrong" values for daily steps compared with Healthmate but our app just reported what the API gave us! So by the sounds of it, the issues are all still there! I even offered them my .NET client library which I wrote to encapsulate the API calls if they would just fix stuff. No dice...

@aharwood2
Copy link

Oh and don't even get me started on their 120 requests / min / app limit. Try syncing intraday day activity for the last year when your user first installs your app. Geez, get a server that can handle some real world traffic!

@confucius78
Copy link

As far as I can tell, and I am indeed a mere weird user, still as valid as it has ever been. Great piece, kudos!

@Venryx
Copy link

Venryx commented Jan 4, 2022

I have the same question as @toomaskordemets above:

Have You tested, how fast data appears on their server. I.e. is it possible to detect that user has entered into light sleep phase within couple of minutes, or it takes much more time until the data appears?

  1. Has anyone been able to retrieve sleep-stage data "during the night"? (Or is it only possible to get any data from the device after the user has gotten out of bed?)

  2. If not: perhaps there is a way to programmatically trigger the Withings app to "sync" with the pad during the night, to force the sleep-stage data to get calculated earlier? (I have done something like this for the ResMed S+ Sleep Tracker, so I know it's possible for some of them)

  3. If even that is not possible (for example, if the sync can only be initiated from the device's side, when it detects out-of-bed motion), then an idea I have is to set up a bed-shaker device next to the Withings Sleep Analyzer device, and trigger it occasionally, making the device think the user woke up and thus syncing even during the night. There would likely need to be workarounds done to not disrupt the data (eg. intercepting the call to the machine-learning model [whether local or remote], and filtering out the data recorded during the synthetic vibrations), but it's a possible workaround.

@GHRoss
Copy link

GHRoss commented Jan 5, 2022

@Venryx I don't suppose you could help me out with an example URI?

I keep getting Invalid params when making a call and Withings examples are awful.

@Venryx
Copy link

Venryx commented Jan 5, 2022

@GHRoss Unfortunately no; I do not have a Withings device. My question above is part of my evaluation to see whether getting a Withings device is worthwhile.

@GHRoss
Copy link

GHRoss commented Jan 5, 2022

Fair enough.

@aharwood2 Could you help me out with an example URI? Looking for heart rate specifically.

@aharwood2
Copy link

@GHRoss what precisely do you mean? When I was referring to a URI I meant the return URL for OAuth that you have to register along with your app on the Withings developer portal. If you want to get heart rate information then you are first going to need to complete the OAuth flow to get an access token and then use that token to make REST API calls to the Heart endpoint to the get the data back you need: https://developer.withings.com/api-reference/#tag/heart

@GHRoss
Copy link

GHRoss commented Jan 5, 2022

I've got all the secrets and stuff that I need, but I'm struggling to work out what a real world example of the body of the call for heart rate would look like. For example, this body gives me an 'invalid params' error.

"action=getmeas&meastype=11&category=hr&startdate=1641168000&enddate=1641254399"

@aharwood2
Copy link

aharwood2 commented Jan 5, 2022

@GHRoss According to the docs (https://developer.withings.com/api-reference/#operation/measure-getmeas) the "category" parameter should be an integer.

@GHRoss
Copy link

GHRoss commented Jan 5, 2022

Yeah, I've tried that, but no luck.

@aharwood2
Copy link

To save crowding this thread with a back and forth about this why don't you post the question on SO and I can pick it up on there and help you solve the issue?

@conan747
Copy link

conan747 commented Aug 7, 2022

No surprise I found this thread...

I've been trying to extract some simple metrics from the API. Namely sleep duration, sleep score and the time when I went to sleep. The results I get from Sleep v2 - Getsummary are very strange. They differ a lot compared to what the app shows. The score and duration are way off (the values are always lower compared to that of the app)` . I want to get the same data that the app does...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment