Apparently a lot has happened since Eric Blue reverse engineered the Jawbone UP API in the end of 2011 (documentation ).
I recently purchased my own Jawbone UP and I feel a bit limited by their app. After fiddling with raw HTTP requests using cURL with the instructions Eric provided, as well as libraries such as a Jawbone UP API gem by Andy Brett I noticed a few things:
Some of the previously documented end-points had moved The API is picky about the User-Agent string (the documented one is too old, apparently) The old documentation is still valid here, although I noticed that the token will not work if sent in the query string any more. Make sure to always use the x-nudge-token header for authentication.
Also note that the API is now picky about valid User-Agent strings. Logging in works, but additional requests after that with the User-Agent Nudge/1.3.1 CFNetwork/548.0.4 Darwin/11.0.0 as previously suggested yields this response:
{
"meta" : {
"error_type" : "endpoint_error" ,
"message" : "Not Found" ,
"code" : 404 ,
"error_detail" : "Unsupported UP Client: Nudge/1.3.1 CFNetwork/548.0.4 Darwin/11.0.0" ,
"time" : 1373664204
},
"data" : {}
}
The current Android app on my Nexus 4 has the User-Agent string NudgeAndroid/1.3.0 Dalvik/1.6.0 (Linux; U; Android 4.2.2; Nexus 4 Build/JDQ39)
Authentication Resource URL https://jawbone.com/user/signin/login
Method POST
Parameters
Response {
"newly" : false ,
"user" : {
"last_name" : "Lastname" ,
"uid" : 123456 ,
"image" : "/profile_photo_path.jpg" ,
"time_removed" : 0 ,
"basic_info" : {
"weight" : 65 ,
"dob" : "yyyymmdd" ,
"gender" : "Gender" ,
"metric" : 1 ,
"height" : 2.5 ,
"locale" : "en"
},
"share_move" : true ,
"up_member_since" : 1372962266 ,
"birth_day" : "21" ,
"share_sleep" : true ,
"text_1" : "" ,
"first_name" : "Firstname" ,
"xid" : "XXXXXXXXXXXXXXXXXXX" ,
"smart_alarm" : {
"stopTimeMinsPastMidnight" : 550 ,
"dayMask" : 446 ,
"enable" : true ,
"startTimeMinsPastMidnight" : 530
},
"apps" : [],
"share_eat" : true ,
"birth_month" : "7" ,
"type" : 0 ,
"email" : "[email protected] " ,
"birth_year" : "2013" ,
"band_name" : "Your Band" ,
"up_goals" : {
"move" : {
"steps" : 10000 ,
"workout_time" : null
},
"sleep" : {
"total" : 28800 ,
"bedtime" : null ,
"deep" : null
},
"meals" : {
"calcium" : 0 ,
"carbs" : 0 ,
"fiber" : 0 ,
"unsat_fat" : 0 ,
"sodium" : 0 ,
"cholesterol" : 0 ,
"protein" : 0 ,
"sugar" : 0 ,
"sat_fat" : 0
}
},
"share_mood" : true ,
"primary_address" : null ,
"time_created" : 1372962266 ,
"power_nap" : {
"use_optimal_duration" : true ,
"custom_duration" : 1590 ,
"maximum_duration" : 2700
},
"active_alert" : {
"stopTimeMinsPastMidnight" : 1200 ,
"threshold" : 0 ,
"durationMins" : 45 ,
"type" : 0 ,
"startTimeMinsPastMidnight" : 540
},
"last" : "Lastname" ,
"name" : "Firstname Lastname" ,
"gender" : "Gender" ,
"profile_privacy" : "friends" ,
"data_2" : 0 ,
"data_1" : 0 ,
"flags" : 1 ,
"goals" : {
"move" : 3500 ,
"sleep" : 21600 ,
"eat" : 2
},
"mail_opts" : {
"mail_opt_in_deals_n_promotions" : null ,
"mail_opt_in" : null ,
"mail_opt_in_products_owned_updates" : null ,
"mail_opt_in_customer_surveys" : null ,
"mail_opt_in_new_products" : null
},
"first" : "Firstname"
},
"token" : "SecretTokenXXXXXXXXXXXXXXXXXXXXXXXXXX" ,
"rc" : 0
}
The important values in the response are token and the user’s xid . Those two are needed for further authentication. However, you can use @me instead of the xid.
Unauthorized Access Exactly the same response as before , which suggests they have not changed anything in the authentication flow (except for the additional data in the response on logging in).
Notifications The app pulls for notifications from time to time (almost at every view update).
Resource URL https://jawbone.com/nudge/api/v.1.33/users/@me/notifications
Method GET
Parameters
Response {
"meta" : {
"user_xid" : "XXXXXXXXXXXXXXXXXXX" ,
"message" : "OK" ,
"code" : 200 ,
"time" : 1373664933
},
"data" : {
"requests_unread_count" : 0 ,
"read_count" : 0 ,
"requests_total_count" : 0 ,
"total_count" : 0 ,
"notifications_total_count" : 0 ,
"unread_count" : 0 ,
"notifications_read_count" : 0 ,
"inbox" : [],
"requests_read_count" : 0 ,
"notifications_unread_count" : 0 ,
"unacknowledged_count" : 0
}
}
Features Resource URL https://jawbone.com/nudge/api/v.1.33/features
Method GET
Parameters None
{
"meta" : {
"user_xid" : "XXXXXXXXXXXXXXXXXXX" ,
"message" : "OK" ,
"code" : 200 ,
"time" : 1373664933
},
"data" : {
"items" : [
{
"status" : "on" ,
"data" : null ,
"feature" : "system"
},
{
"status" : "on" ,
"data" : null ,
"feature" : "up_food_gallery"
},
{
"status" : "on" ,
"data" : null ,
"feature" : "up_twitter_share"
},
{
"status" : "on" ,
"data" : null ,
"feature" : "up_fooditem_search_typeahead"
},
{
"status" : "on" ,
"data" : null ,
"feature" : "up_addressbook_import"
},
{
"status" : "on" ,
"data" : {},
"feature" : "up_slideshow"
},
{
"status" : "on" ,
"data" : null ,
"feature" : "barcode_search"
},
{
"status" : "off" ,
"data" : null ,
"feature" : "up_daily_dashboards"
},
{
"status" : "on" ,
"data" : null ,
"feature" : "up_search"
},
{
"status" : "off" ,
"data" : null ,
"feature" : "up_cheers"
},
{
"status" : "on" ,
"data" : null ,
"feature" : "up_fb_share"
},
{
"status" : "on" ,
"data" : null ,
"feature" : "up_app_gallery"
},
{
"status" : "on" ,
"data" : null ,
"feature" : "daily_dashboard"
},
{
"status" : "off" ,
"data" : null ,
"feature" : "up_passive_location"
},
{
"status" : "on" ,
"data" : null ,
"feature" : "up_twitter_import"
},
{
"status" : "on" ,
"data" : null ,
"feature" : "up_twitter_friend_suggestions"
},
{
"status" : "on" ,
"data" : null ,
"feature" : "up_fb_import"
},
{
"status" : "on" ,
"data" : null ,
"feature" : "up_fb_friend_suggestions"
},
{
"status" : "on" ,
"data" : null ,
"feature" : "app_gallery"
}
],
"message" : "" ,
"size" : 19
}
}
Friends I currently do not have any friends using Jawbone UP, so I cannot tell what the response would look like if it was populated by other users you have befriended. But my guess it that it would be their profile image, xid and name.
Resource URL https://jawbone.com/nudge/api/v.1.33/users/@me/friends
Method GET
Parameters
{
"meta" : {
"user_xid" : "XXXXXXXXXXXXXXXXXXX" ,
"message" : "OK" ,
"code" : 200 ,
"time" : 1373664933
},
"data" : {
"requests" : {
"items" : [],
"size" : 0
},
"friends" : {
"items" : [],
"size" : 0
},
"unacknowledged_count" : 0
}
}
Activity Feed Resource URL https://jawbone.com/nudge/api/v.1.33/users/@me/social
Method GET
Parameters
{
"meta" : {
"user_xid" : "XXXXXXXXXXXXXXXXXXX" ,
"message" : "OK" ,
"code" : 200 ,
"time" : 1373666183
},
"data" : {
"feed" : [
{
"time_updated" : 1373641104 ,
"xid" : "EJpCkyAtwoPDzXj42JED4w" ,
"title" : "13,288 steps today" ,
"image" : "/nudge/api/v.1.33/moves/EJpCkyAtwoPDzXj42JED4w/image/11373641104" ,
"reached_goal" : true ,
"comments" : {
"items" : [],
"size" : 0
},
"activity_xid" : "tLEqzPIug09d0yPd2gTrZw" ,
"app_generated" : false ,
"emotions" : {
"items" : [],
"size" : 0
},
"time_created" : 1373641104 ,
"date" : 20130712 ,
"tz" : "Europe/Stockholm" ,
"type" : "move" ,
"networks" : [],
"is_private" : false ,
"user" : {
"xid" : "XXXXXXXXXXXXXXXXXXX" ,
"name" : "Firstname Lastname" ,
"short_name" : "Firstname" ,
"image" : "/profile_photo_path.jpg" ,
"last" : "Lastname" ,
"type" : "user" ,
"first" : "Firstname"
}
},
{
"user" : {
"last" : "Lastname" ,
"name" : "Firstname Lastname" ,
"short_name" : "Firstname" ,
"image" : "user/image/i/51d5d363e1a4b94bf8bcdb88_XXXXXXXXXXXXXXXXXXX_137296777995_2801669_photo.png" ,
"xid" : "XXXXXXXXXXXXXXXXXXX" ,
"type" : "user" ,
"first" : "Firstname"
},
"reaction" : null ,
"time_updated" : 1373641048 ,
"subtitle" : null ,
"title" : "Workout" ,
"km" : 7.701 ,
"is_completed" : 1 ,
"emotions" : {
"items" : [],
"size" : 0
},
"sub_type" : null ,
"activity_xid" : "tLEqzPIug08t1CrjMsjf_g" ,
"app_generated" : false ,
"steps" : 9671 ,
"time_created" : 1373641048 ,
"image" : "/nudge/api/v.1.33/workouts/EJpCkyAtwoPdq82esOHMuA/image/11373641104" ,
"tz" : "Europe/Stockholm" ,
"duration" : 4963 ,
"xid" : "EJpCkyAtwoPdq82esOHMuA" ,
"type" : "workout" ,
"networks" : [],
"is_private" : false ,
"comments" : {
"items" : [],
"size" : 0
}
},
{
"time_updated" : 1373611766 ,
"subtitle" : null ,
"title" : "for 8h 42m" ,
"type" : "sleep" ,
"image" : "/nudge/api/v.1.33/sleeps/EJpCkyAtwoPSxmSfL0XozQ/image/11373611885" ,
"reached_goal" : true ,
"comments" : {
"items" : [],
"size" : 0
},
"emotions" : {
"items" : [],
"size" : 0
},
"activity_xid" : "tLEqzPIug084jGNlSLo4JQ" ,
"app_generated" : false ,
"awake" : 1053 ,
"time_created" : 1373611766 ,
"xid" : "EJpCkyAtwoPSxmSfL0XozQ" ,
"duration" : 32400 ,
"tz" : "Europe/Stockholm" ,
"quality" : 81 ,
"networks" : [],
"is_private" : false ,
"user" : {
"last" : "Lastname" ,
"name" : "Firstname Lastname" ,
"short_name" : "Firstname" ,
"image" : "user/image/i/51d5d363e1a4b94bf8bcdb88_XXXXXXXXXXXXXXXXXXX_137296777995_2801669_photo.png" ,
"xid" : "XXXXXXXXXXXXXXXXXXX" ,
"type" : "user" ,
"first" : "Firstname"
}
}
],
"links" : {
"next" : "/nudge/api/v.1.33/users/XXXXXXXXXXXXXXXXXXX/social?page_token=1373004962&limit=20"
}
}
}
Daily Summary Resource URL https://jawbone.com/nudge/api/v.1.33/users/@me/score
Method GET
Parameters
{
"meta" : {
"user_xid" : "XXXXXXXXXXXXXXXXXXX" ,
"message" : "OK" ,
"code" : 200 ,
"time" : 1373664935
},
"data" : {
"mood" : null ,
"move" : {
"active_time" : 6898 ,
"longest_idle" : 3300 ,
"calories" : 781.753758364 ,
"bg_steps" : 13288 ,
"goals" : {
"steps" : [
13288 ,
10000
],
"workout_time" : [
4963 ,
null
]
},
"longest_active" : 5142 ,
"hidden" : false ,
"bmr_calories_day" : 1743.03149865 ,
"bmr_calories" : 1187.90637543 ,
"distance" : 11.198
},
"sleep" : {
"awakenings" : 0 ,
"light" : 21614 ,
"time_to_sleep" : 1053 ,
"goals" : {
"total" : [
31394 ,
28800
],
"bedtime" : [
1429 ,
null
],
"deep" : [
9780 ,
null
]
},
"qualities" : [
81
],
"awake" : 1053 ,
"hidden" : false
},
"user_metrics" : {
"dob" : "yyyymmdd" ,
"gender" : 0 ,
"pal" : null ,
"weight" : 65 ,
"height" : 2.5
},
"meals" : {
"num_meals" : 0 ,
"calories" : 0 ,
"num_drinks" : 0 ,
"goals" : {
"calcium" : [
0 ,
0
],
"carbs" : [
0 ,
0
],
"fiber" : [
0 ,
0
],
"unsat_fat" : [
0 ,
0
],
"sodium" : [
0 ,
0
],
"cholesterol" : [
0 ,
0
],
"protein" : [
0 ,
0
],
"sugar" : [
0 ,
0
],
"sat_fat" : [
0 ,
0
]
},
"hidden" : false ,
"num_foods" : 0
},
"insights" : {
"items" : []
}
}
}
Detailed Sleep Data This is used to generate the plots in the app.
Resource URL https://jawbone.com/nudge/api/v.1.33/sleeps/XID /snapshot
The XID for the sleep session can be found in the activity feed.
Method GET
Parameters None
{
"meta" : {
"user_xid" : "XXXXXXXXXXXXXXXXXXX" ,
"message" : "OK" ,
"code" : 200 ,
"time" : 1373666895
},
"data" : [
[ 1373579366 , 1 ],
[ 1373580266 , 2 ],
[ 1373580566 , 3 ],
[ 1373583266 , 2 ],
[ 1373584766 , 3 ],
[ 1373585966 , 2 ],
[ 1373588666 , 3 ],
[ 1373590166 , 2 ],
[ 1373594666 , 3 ],
[ 1373597066 , 2 ],
[ 1373603066 , 3 ],
[ 1373603666 , 2 ],
[ 1373609666 , 3 ],
[ 1373610866 , 2 ],
[ 1373611766 , 1 ]
]
}
Detailed Activity Data This is used to generate the plots in the app. Resource URL https://jawbone.com/nudge/api/v.1.33/moves/XID /snapshot
The XID for the activity session can be found in the activity feed.
Method GET
Parameters
{
"meta" : {
"user_xid" : "XXXXXXXXXXXXXXXXXXX" ,
"message" : "OK" ,
"code" : 200 ,
"time" : 1373667224
},
"data" : [
[ 1373089920 , 19.0 ],
[ 1373089980 , 0 ],
[ 1373090040 , 0 ],
[ 1373090100 , 0 ],
[ 1373090160 , 0 ],
[ 1373090220 , 0 ],
[ 1373090280 , 0 ],
[ 1373090340 , 0 ],
[ 1373090400 , 0 ],
[ 1373090460 , 0 ],
[ 1373090520 , 0 ],
[ 1373090580 , 0 ],
[ 1373090640 , 0 ],
[ 1373090700 , 0 ],
[ 1373090760 , 0 ],
[ 1373090820 , 0 ],
[ 1373090880 , 0 ],
[ 1373090940 , 0 ],
[ 1373091000 , 0 ],
[ 1373091060 , 0 ],
[ 1373091120 , 0 ],
[ 1373091180 , 0 ],
[ 1373091240 , 0 ],
[ 1373091300 , 0 ],
[ 1373091360 , 0 ],
[ 1373091420 , 0 ],
[ 1373091480 , 0 ],
[ 1373091540 , 0 ]
]
}
Reviving the Jawbone Ruby Gem There is a fork of the original Jawbone UP API gem by Kevin Poorman with a patch addressing some of the changes .
I took the liberty of forking the original and making sure it works as intended with the new API.
Apparently you do not need the API version (v.1.33) in the URL (see the code for the URL structures used).