Jawbone UP API

Skip to end of metadata
Go to start of metadata
Blog post: http://eric-blue.com/2011/11/28/jawbone-up-api-discovery/

ActiveOS - The Wearables Insights Platform

Table of Contents

Overview

This page contains information on getting access to your Jawbone UP data using their undocumented JSON API. This API was discovered by sniffing traffic between the iPhone/Jawbone UP applications and Jawbone's servers. An official API is supposedly available to partners and in the works. Until that time this method could be used, however there is no gaurantee on how long this approach will work (UP may disable this ability or change their protocol/schema at any time). This information should be used for gaining access to your own data and saving for your own use. This should by no means be used in any way that would violate the Jawbone UP TOS/AUP. Please note the information listed here is a work in progress and is by no means accurate (use at your own risk!). Have fun :)

High-level API Summary

Although the Jawbone UP requires the iPhone app to sync and there is no web-based interface, there is a server-side dependency for saving all synchronized data and fetching information on daily activity, workouts, sleep data, food, goals, searches, and social interactions. The API is used internally by the Jawbone UP application and interacts with the server (https://jawbone.com) over HTTPS/SSL and returns data in JSON format. The API appears to be broken down into the following categories:

  • Users (Most features under the Profile Tab)
    • Getting settings and profile info
    • Aliases (not sure what this is for yet)
    • Feeds (social feeds that contain workout, sleep, food, and other data)
    • Inbox (messages from other team members?)
    • Data sync
      • Used by Sync feature to POST data to the Jawbone servers
      • App also communicates battery level info
    • Meals, Sleeps, Workouts, Health Credits (?)
  • Service
    • Gets Manifest (.zip file) with resources used by the app (Javascript, images, css, language resource bundles, etc.)
  • Aliases
    • TBD - need to research this more
  • Search
    • Queries for challenges and other team members
  • Workouts
    • A snapshot of the recorded workout
  • Sleeps
    • A snapshot of the recorded sleep

Timestamps

Most of the JSON requests/responses deal with times in epoch seconds (e.g. 1322353872). A quick cheat on the *nix side is to run 'date -d @1322353872' to get a timestamp in human readable format "
Sat Nov 26 16:31:12 PST 2011". Time offsets (e.g. time_offset) are in minutes. -28800 = (28,800/3,600) = -8 Hours (PST).

Notable HTTP Headers

The following HTTP headers appear to be in most requests. With the exception of x-nudge-token (optional since it can be passed in the query string), none of the other values appear to be validated:

User-Agent
Nudge/1.3.1 CFNetwork/548.0.4 Darwin/11.0.0
x-nudge-token
2QjnIfD_7a29Vdty-r4IL93)ldkqD7eiDll1hbolxDPavesPCdpCVfqWjrR6SUCtDGB-ZQsWnAT-dS4BO5qefyGZxC-0Luw-TPSVv_r1IClL4VdyyybDCLDtaoVXHCCunIbb8gLtV142rO9JFK1rH88okcnzTn0GNrXktiJDoN85YmFR9apO-6ogLc5cntZwvWMKEtEzxs
x-nudge-platform
iPhone 4; 5.0.1
x-nudge-request-id
1322427258 (appears to increment each request)
x-nudge-device-id
1c35e728b7d0d36eb400f5621efb3ba2ca20xyzc

JawBone App

I thought it was interesting that the UP app was making a number of requests to localhost (on the iPhone), port 8000. This is probably a web server that serves the files from the manifest.zip. Directories in that .zip:

|-- css
| |-- common
| `-- nudge
| `-- mobile
| `-- nom
|-- images
| |-- common
| | `-- facebook
| |-- nudge
| `-- up
|-- js
| |-- common
| |-- jquery
| |-- nudge
| | |-- bindings
| | |-- mobile
| | `-- nom
| `-- user
|-- nudge
| `-- mobile
|-- res
| `-- lang
| `-- load
`-- res_de
`-- lang
`-- load

Authentication

Each API request needs to be validated and requires that a secure token be passed. This token can be retrieved by performing a login request:

Request

METHOD
POST
URL
https://jawbone.com/user/signin/login
INPUT PARAMS
[email protected]
pwd=YourPassword
service=nudge

Response

{
    "newly": false,
    "rc": 0,
    "token": "2QjnIfD_7a29Vdty-r4IL93)ldkqD7eiDll1hbolxDPavesPCdpCVfqWjrR6SUCtDGB-ZQsWnAT-dS4BO5qefyGZxC-0Luw-TPSVv_r1IClL4VdyyybDCLDtaoVXHCCunIbb8gLtV142rO9JFK1rH88okcnzTn0GNrXktiJDoN85YmFR9apO-6ogLc5cntZwvWMKEtEzxs",
    "user": {
        "data_1": 0,
        "data_2": 0,
        "first": "First",
        "flags": 0,
        "href": "/nudge/profile?uid=1234567",
        "image": "",
        "last": "Last",
        "mobile_href": "/nudge/mobile/profile#qYTkyeUXXXX",
        "name": "First Last",
        "text_1": "",
        "time_created": 1322353872,
        "time_removed": 0,
        "type": 0,
        "uid": 1234567,
        "xid": "qYTkyeUXXXX"
    }
}

This token value is used to either populate the x-nudge-token HTTP header, or the _token query string parameter. It appears that if you don't populate the HTTP header, you can alternatively populate the query string value and the request will be processed OK.

Unauthorized Access

Any invalid requests (requesting with an invalid token or a user resource that you don't have access to) results in the following error:

{"meta": {"error_type": "authentication_error", "message": "Unauthorized", "code": 401, "error_detail": "You must be logged in to perform that action"}, "data": {}}

Feed Summary

The following request is issued each time the Feed tab is viewed. This tab contains high-level info and a graphic for your Workouts, Sleep, and Food.

Request

METHOD
GET
URL
https://jawbone.com/nudge/api/users/@me/social
INPUT PARAMS
after=null
limit=30
_token=<your auth token>

Response

{
    "data": {
        "feed": [
            {
                "activity_xid": "OFBeT_bTXN0",
                "duration": 4659,
                "image": "/mod/workout_340x104/nudge/api/workouts/N6Tz4XoJDMo/image",
                "is_completed": 1,
                "km": 3.672,
                "reaction": 2,
                "steps": 4483,
                "subtitle": "First added 4483 steps",
                "time_created": 1322421880,
                "time_updated": 1322421880,
                "title": "1h 17m Workout",
                "type": "workout",
                "user": {
                    "first": "First",
                    "image": "",
                    "last": "Last",
                    "name": "First Last",
                    "type": "user",
                    "xid": "qYTkyeUXXXX"
                },
                "xid": "N6Tz4XoJDMo"
            },
            {
                "activity_xid": "sxTVFCZwkqs",
                "awake": 801,
                "duration": 28101,
                "image": "/mod/sleep_340x104/nudge/api/sleeps/-QXJrBASWvo/image",
                "quality": 91,
                "subtitle": "First's sleep quality was 91",
                "time_created": 1322410838,
                "time_updated": 1322410838,
                "title": "Slept for 7:35",
                "type": "sleep",
                "user": {
                    "first": "First",
                    "image": "",
                    "last": "Last",
                    "name": "First Last",
                    "type": "user",
                    "xid": "qYTkyeUXXXX"
                },
                "xid": "-QXJrBASWvo"
            },
            {
                "activity_xid": "uMH7MKQvBk4",
                "image": "/user/image/i/4ed1a7f238c04b359718e39f_GD7LW_3xtJc_132236286634_6401806_image.jpg",
                "note": "Wine",
                "place_name": "",
                "reaction": 2,
                "subtitle": "First felt OK",
                "time_created": 1322362848,
                "time_updated": 1322362848,
                "title": "Wine",
                "type": "meal",
                "user": {
                    "first": "First",
                    "image": "",
                    "last": "Last",
                    "name": "First Last",
                    "type": "user",
                    "xid": "qYTkyeUXXXX"
                },
                "xid": "GD7LW_3xtJc"
            },
            {
                "activity_xid": "W_1oE95qi9M",
                "duration": 2712,
                "image": "/mod/workout_340x104/nudge/api/workouts/2xK2B_mW6Vs/image",
                "is_completed": 1,
                "km": 1.022,
                "reaction": null,
                "steps": 1293,
                "subtitle": "First added 1293 steps",
                "time_created": 1322356451,
                "time_updated": 1322356451,
                "title": "45m 12s Workout",
                "type": "workout",
                "user": {
                    "first": "First",
                    "image": "",
                    "last": "Last",
                    "name": "First Last",
                    "type": "user",
                    "xid": "qYTkyeUXXXX"
                },
                "xid": "2xK2B_mW6Vs"
            }
        ]
    },
    "meta": {
        "code": 200,
        "message": "OK",
        "user_xid": "qYTkyeUXXXX"
    }
}

Daily Summary (Activity + Sleep + Food) Data

The following request is issued when the Me tab is selected (the Today screen).

Request

METHOD
GET
URL
https://jawbone.com/nudge/api/users/qYTkyeUXXXX/healthCredits
INPUT PARAMS
date=2011-11-27
timezone=-28800
move_goal=0
sleep_goal=0
eat_goal=0
check_levels=1
_token=<your auth token>

Response

{
    "data": {
        "date": "2011-11-27T00:00:00-08:00",
        "eat": 0,
        "eat_goal": 200,
        "eat_percent": 0,
        "eat_summary": {
            "meals": []
        },
        "meal_photos": [],
        "meal_xids": [],
        "move": 5052,
        "move_goal": 5000,
        "move_kilometers": 4.132,
        "move_percent": 101,
        "move_seconds": 4968,
        "move_steps": 5052,
        "move_summary": {
            "move_calories": 396.325954,
            "move_kilometers": 4.132,
            "move_seconds": 4968,
            "move_steps": 5052,
            "workouts": [
                {
                    "completed": 1,
                    "details": {
                        "calories": 358.20608,
                        "duration": 3.672,
                        "duration_type": 2,
                        "steps": 4483,
                        "time": 4659
                    },
                    "reaction": 2,
                    "route": "",
                    "sub_type": 0,
                    "time_created": 1322421880,
                    "time_removed": 0,
                    "title": "1h 17m Workout",
                    "xid": "N6Tz4XoJDMo"
                }
            ]
        },
        "sleep": 27300,
        "sleep_goal": 25200,
        "sleep_percent": 108,
        "sleep_summary": {
            "deep": 13680,
            "light": 13620,
            "sleeps": [
                {
                    "details": {
                        "awake": 801,
                        "body": 0,
                        "deep": 13680,
                        "duration": 28101,
                        "light": 13620,
                        "mind": 0,
                        "quality": 91,
                        "smart_alarm_fire": 0,
                        "tz": "GMT-0800"
                    },
                    "time_created": 1322382737,
                    "time_removed": 0,
                    "title": "Slept for 7:35",
                    "xid": "-QXJrBASWvo"
                }
            ],
            "total": 27300
        },
        "sleep_total": 27300,
        "total": 32352,
        "total_goal": 30400
    },
    "meta": {
        "code": 200,
        "message": "OK",
        "user_xid": "qYTkyeUXXXX"
    }
}

Detailed Activity Data

The following request is issued when an activity/workout graph is viewed. Intervals are 60 seconds apart. Note that a given profile ID (user_xid such as

https://jawbone.com/nudge/api/users/qYTkyeUkNXM/band

?) can also be substituted with @me

Request

METHOD
GET
URL
https://jawbone.com/nudge/api/users/qYTkyeUXXXX/band
INPUT PARAMS
start_time=1322380800 (epoch)
end_time=1322442000 (epoch)
_token=<your auth token>

Response

{
    "data": {
        "ticks": [
            {
                "value": {
                    "active_time": 10,
                    "aerobic": true,
                    "bid": "A756944628000F00",
                    "calories": 1.486014,
                    "distance": 16,
                    "speed": 1.6,
                    "steps": 19,
                    "time": 1322381100,
                    "time_offset": -28800,
                    "type": 0
                }
            },
            {
                "value": {
                    "active_time": 17,
                    "aerobic": true,
                    "bid": "A756944628000F00",
                    "calories": 2.008668,
                    "distance": 25,
                    "speed": 1.470588,
                    "steps": 31,
                    "time": 1322381160,
                    "time_offset": -28800,
                    "type": 0
                }
            },
            {
                "value": {
                    "active_time": 13,
                    "aerobic": true,
                    "bid": "A756944628000F00",
                    "calories": 2.728756,
                    "distance": 27,
                    "speed": 2.076923,
                    "steps": 30,
                    "time": 1322427180,
                    "time_offset": -28800,
                    "type": 0
                }
            }
        ]
    },
    "meta": {
        "code": 200,
        "message": "OK",
        "user_xid": "qYTkyeUkNXM"
    }
}

Sleep Summary Data

The following request is issued when an sleep graph is viewed. Note that the xid returned for the sleep data can be used to get more detailed data (snapshot)

Request

METHOD
GET
URL
https://jawbone.com/nudge/api/users/qYTkyeUXXXX/sleeps
INPUT PARAMS
start_time=1322380800 (epoch)
end_time=1322442000 (epoch)
limit=100
_token=<your auth token>

Response

{
    "data": {
        "items": [
            {
                "details": {
                    "awake": 801,
                    "body": 0,
                    "deep": 13680,
                    "duration": 28101,
                    "light": 13620,
                    "mind": 0,
                    "quality": 91,
                    "smart_alarm_fire": 0,
                    "tz": "GMT-0800"
                },
                "links": {
                    "image": "/nudge/api/sleeps/-QXJrBASWvo/image",
                    "self": "/nudge/api/sleeps/-QXJrBASWvo",
                    "snapshot": "/nudge/api/sleeps/-QXJrBASWvo/snapshot"
                },
                "time_created": 1322382737,
                "title": "Slept for 7:35",
                "user_xid": "qYTkyeUkNXM",
                "xid": "-QXJrBASWvo"
            }
        ],
        "links": {
            "self": "/nudge/api/users/qYTkyeUkNXM/sleeps"
        },
        "size": 1
    },
    "meta": {
        "code": 200,
        "message": "OK",
        "user_xid": "qYTkyeUXXXX"
    }
}

Sleep Detailed Data (Snapshot)

The following request is issued when an sleep graph is viewed. Each sleep data entry is added whenever a state change happens (1, 2 or 3):

1 = awake
2 = deep
3 = light

Request

METHOD
GET
URL
/nudge/api/sleeps/-QXJrBASWvo/snapshot
INPUT PARAMS
_token=<your auth token>

Response

{
    "data": [
        [
            1322382737,
            1
        ],
        [
            1322383517,
            3
        ],
        [
            1322387297,
            2
        ],
        [
            1322388497,
            3
        ],
        [
            1322390297,
            2
        ],
        [
            1322392397,
            3
        ],
        [
            1322395997,
            2
        ],
        [
            1322397197,
            3
        ],
        [
            1322399297,
            2
        ],
        [
            1322402597,
            3
        ],
        [
            1322403197,
            2
        ],
        [
            1322405597,
            3
        ],
        [
            1322406797,
            2
        ],
        [
            1322408297,
            3
        ],
        [
            1322408897,
            2
        ],
        [
            1322410817,
            1
        ]
    ],
    "meta": {
        "code": 200,
        "message": "OK",
        "user_xid": "qYTkyeUXXXX"
    }
}

Workout Summary Data

The following request is issued when a workout graph is viewed. Note that the xid returned for the workout data can be used to get more detailed data (snapshot)

Request

METHOD
GET
URL
https://jawbone.com/nudge/api/users/qYTkyeUXXXX/workouts
INPUT PARAMS
start_time=1322380800 (epoch)
end_time=1322442000 (epoch)
limit=100
_token=<your auth token>

Response

{
    "data": {
        "items": [
            {
                "completed": 1,
                "contributions": {
                    "items": [],
                    "links": {
                        "self": "/nudge/api/workouts/N6Tz4XoJDMo/contributions"
                    },
                    "size": 0
                },
                "details": {
                    "calories": 358.20608,
                    "duration": 3.672,
                    "duration_type": 2,
                    "steps": 4483,
                    "time": 4659
                },
                "links": {
                    "cheers": "/nudge/api/workouts/N6Tz4XoJDMo/cheers",
                    "contributions": "/nudge/api/workouts/N6Tz4XoJDMo/contributions",
                    "image": "/nudge/api/workouts/N6Tz4XoJDMo/image",
                    "reaction": "/nudge/api/workouts/N6Tz4XoJDMo/reaction",
                    "route": "/nudge/api/workouts/N6Tz4XoJDMo/route",
                    "self": "/nudge/api/workouts/N6Tz4XoJDMo",
                    "snapshot": "/nudge/api/workouts/N6Tz4XoJDMo/snapshot",
                    "title": "/nudge/api/workouts/N6Tz4XoJDMo/title"
                },
                "reaction": 2,
                "route": "",
                "sub_type": 0,
                "time_created": 1322421880,
                "time_removed": 0,
                "title": "1h 17m Workout",
                "user": {
                    "first": "",
                    "href": "/nudge/profile?uid=8606237",
                    "image": "",
                    "last": "",
                    "links": {
                        "challenges": "/nudge/api/users/qYTkyeUkNXM/plans/today",
                        "meals": "/nudge/api/users/qYTkyeUkNXM/meals",
                        "self": "/nudge/api/users/qYTkyeUkNXM",
                        "workouts": "/nudge/api/users/qYTkyeUkNXM/workouts"
                    },
                    "mobile_href": "/nudge/mobile/profile#qYTkyeUkNXM",
                    "name": " ",
                    "settings": {
                        "profile_privacy": "friends",
                        "share_eat": true,
                        "share_move": true,
                        "share_sleep": true
                    },
                    "type": "user",
                    "xid": "qYTkyeUkNXM"
                },
                "xid": "N6Tz4XoJDMo"
            }
        ],
        "links": {
            "self": "/nudge/api/users/qYTkyeUkNXM/workouts"
        },
        "size": 1
    },
    "meta": {
        "code": 200,
        "message": "OK",
        "user_xid": "qYTkyeUXXXX"
    }
}

Workout Detailed Data (Snapshot)

The following request is issued when an sleep graph is viewed. Each sleep data entry is added whenever a state change happens (1, 2 or 3):

The value for each item returned appears to be estimated calories burned.

Request

METHOD
GET
URL
/nudge/api/workouts/2xK2B_mW6Vs/snapshot
INPUT PARAMS
_token=<your auth token>

Response

{
    "data": [
        [
            1322356501,
            39.0
        ],
        [
            1322356561,
            81.0
        ],
        [
            1322356621,
            80.0
        ],
        [
            1322356681,
            83.0
        ],
        [
            1322356741,
            68.0
        ],
        [
            1322356801,
            22.0
        ],
        [
            1322356861,
            10.0
        ],
        [
            1322356921,
            45.0
        ],
        [
            1322356981,
            0
        ],
        [
            1322357041,
            0
        ],
        [
            1322357101,
            0
        ],
        [
            1322357161,
            0
        ],
        [
            1322357221,
            0
        ],
        [
            1322357281,
            0
        ],
        [
            1322357341,
            38.0
        ],
        [
            1322357401,
            0
        ],
        [
            1322359141,
            0
        ]
    ],
    "meta": {
        "code": 200,
        "message": "OK",
        "user_xid": "qYTkyeUXXXX"
    }
}

Updated: Sun 11/27/11