Overview

Every time Fitbit owners walk by their wireless base station (Bluetooth dongle and computer), data from their Fitbit device is silently uploaded in the background to fitbit.com. The average user uploads activity data several times every day and manually log additional activities and foods. Meanwhile, other users may go on vacation and upload a week's worth of activity data all at once.

Because of the frequency of updates, Fitbit has developed the Subscriptions API that allows third-party applications to be notified when Fitbit user data changes. This allows apps to have a user's latest data without having to implement a polling or scheduling system to retrieve user's data. This process is illustrated in the following diagram.

API workflow

Subscription notifications are sent in near real-time to an endpoint of your choosing. You can also choose to specify multiple endpoints, each receiving change notifications for a subset of members or a subset of data types. These notifications are essentially HTTP POST requests made by Fitbit to URLs that you register. These URL's must be accessible to our servers and must be able to handle the incoming HTTP POST request and process the content of the request (JSON).

Also, these notifications just alert you to the fact that certain data has been updated. Your application must then make the appropriate API calls to retrieve the actual data. See Resource Access API for details on the appropriate API calls.

Definitions of Subscription Components

SubscriberA client service endpoint that is notified by Fitbit when member data changes. Subscribers are identified by a Subscriber ID.
SubscriptionAn association between a Fitbit member collection and client subscriber that lets us know you're interested in being notified of changes. Subscriptions are identified by a Subscription ID.
StreamA sequence of changes to member data.
Collection TypeA grouping of related resources. For example, all Fitbit members have activities that are summarized by date. Presently, Fitbit supports the following collection types: activities, foods, sleep, and body.
NotificationA request sent by Fitbit to a subscriber indicating that a Fitbit resource has been added, modified, or deleted.

Implementing Fitbit Subscription API

Use the following step to implement Subscription API:

  1. Configure a simple notification URL as described in Receiving Update Notifications.
  2. Make sure your subscriber endpoint is accessible from fitbit.com servers.
  3. Configure your subscriber endpoints as described in Configure A Subscriber.
  4. Verify your subscriber endpoint as described in Verify A Subscriber.
  5. Authenticate Fitbit users on your site as described in the OAuth authentication API.
  6. Add subscriptions as described in Add A Subscription.

Your application needs only read access to be able to create subscriptions to user resources and receive notifications. Note that updated an application's access type for extended permissions (such as changing from Read to Read & Write) resets ALL existing access tokens for your application, which also removes ALL existing subscriptions to user resources.

The following sections describe the subscriptions flow and subscription API endpoint in detail.

Resilient Application Design

Your application must rely on the Subscriptions API when end users are not actively engaged with the application. When the user initiates a new session with your application, your application must fetch the most recent resources to be certain that the best data is presented.

The Subscriptions API does not attempt to send a notification more than once. Many factors can contribute to a subscription notification being missed: Fitbit API outages, general connectivity across the internet, your application being unavailable when Fitbit attempts to send the notification, or your application not responding within three seconds to a notification request.

The responsibility of creating an 'awesome' experience for Fitbit users falls equally upon Fitbit and the application developer. This working cooperation is the best approach in making your application sychronized with Fitbit.

Debugging Your Subscription API Implementation

See Subscriptions API Debugging for additional information debugging your Subscription API implementation.

Configuring A Subscriber

Before you can subscribe, you must provide Fitbit with one or more subscriber endpoints. This can be done as part of your initial account configuration, or via the application management view on dev.fitbit.com.

A subscriber endpoint is a callback URL where near real-time updates are sent. This step is required only if you wish to subscribe to near real-time streams. Eventually, you will be able to manage this by logging into your Fitbit account.

One subscriber endpoint must be designated as the default subscriber. If you specify only one subscriber, it is automatically the default. The default subscriber is used if no subscriber is specified when issuing a subscription request (see below.)

You can assign a subscriber ID to your subscribers, which is the ID you will use when issuing a subscription request. If you don't specify a subscriber ID, one will be assigned for you.

Subscriber endpoints have the following parameters:

urlThe full URL to the subscriber endpoint where update notifications will be sent (e.g. "https://www.example.com/fitbit-notifications").
formatThe serialization format (XML or JSON) that update notifications will use. "JSON" recommended. "XML" is deprecated as of October 2016.
defaultWhether this subscriber should be used as the default on requests where no subscriber is specified. Changing the default subscriber only affects new subscriptions after the change.
idAn optional identifier to refer to this subscriber. If none specified, we assign one for you (starting with 1,2,3...) Subscriber IDs are treated as opaque strings up to 50 unicode characters long. Fitbit encourages you to choose an ID that makes the most sense to you.

Using HTTPS

Fitbit supports Transport Layer Security protocol - TLSv1.2 for the subscriber endpoints. HTTPS connections must use port 443.

Note: TLS+SNI is not supported. Self-signed certificates and all versions of SSL are also not supported.

Disabled Subscribers

Your application's subscriber will be disabled automatically by Fitbit if it does not properly respond to notification requests with an HTTP 204 status within three seconds consistently.

A subscriber is disabled when:

  • It has an error rate of 10% or higher with at least 100 errors in 10 hours
  • It has not successfully delivered messages within a month

These tolerances are subject to change without notice as necessary to protect the overall health of the Subscriptions API.

How to re-enable a subscriber

  1. Go to your application settings page
  2. Click on 'details' beside your subscriber to review the logs of the most recent attempted subscription notification requests
  3. Resolve the issue with your application
  4. Click on 'edit application settings'
  5. Check the 'enabled' checkbox for your subscriber
  6. Click 'save'

Verify A Subscriber

All new or edited subscriber endpoints must be verified in order to receive subscription updates. Verification is necessary for both your security and that of Fitbit's, to ensure that you are the owner of the subscriber endpoint. Subscriber endpoints created before December 1st, 2015 are encouraged to implement the following verification test, but are not required to do so.

When a subscriber is added, or when its URL is changed, Fitbit sends 2 GET requests to the subscriber endpoint, each with a "verify" query string parameter. One request has the subscriber verification code (which you can find on your app details page) as the "verify" query string parameter value, and expects the subscriber to respond with a 204. Another request has an intentionally invalid verification code, and expects the subscriber to respond with a 404. For example:

GET https://yourapp.com/fitbit/webhook?verify=correctVerificationCode should result in a 204. GET https://yourapp.com/fitbit/webhook?verify=incorrectVerificationCode should result in a 404.

If both requests succeed, the subscriber is marked as verified on the app details page. Otherwise, the subscriber is marked as not verified, and an option is given to retry verification.

Adding A Subscription

You must add a subscription in your application so that users will get notifications and return a response in the format requested. The subscription-id value provides a way to associate an update with a particular user stream in your application.

Here is the syntax to add a subscription:

POST https://api.fitbit.com/1/user/-/[collection-path]/apiSubscriptions/[subscription-id].json

where:

collection-path

This is the resource of the collection to receive notifications from (foods, activities, sleep, or body). If not present, subscription will be created for all collections. If you have both all and specific collection subscriptions, you will get duplicate notifications on that collections' updates. Each subscriber can have only one subscription for a specific user's collection.

In order to create a subscription to activity types, your application must have the proper OAuth 2.0 scope.

  • activities collection requires activity scope
  • body collection requires weight scope
  • foods collection requires nutrition
  • sleep collection requires sleep
  • If no collection specified, activity, nutrition, profile, settings, sleep, weight scope required.
subscription-idThis is the unique ID of the subscription created by the API client application. Each ID must be unique across the entire set of subscribers and collections. The Fitbit servers will pass this ID back along with any notifications about the user indicated by the user parameter in the URL path.

Examples of adding subscriptions

POST https://api.fitbit.com/1/user/-/apiSubscriptions/320.json
POST https://api.fitbit.com/1/user/-/activities/apiSubscriptions/320json
POST https://api.fitbit.com/1/user/-/foods/apiSubscriptions/320.json
POST https://api.fitbit.com/1/user/-/sleep/apiSubscriptions/320.json
POST https://api.fitbit.com/1/user/-/body/apiSubscriptions/320.json

Request Headers

X-Fitbit-Subscriber-IdoptionalThe ID of the subscriber to receive notifications, as defined on dev.fitbit.com. If not present, the default subscriber is used.

Response

200 OKReturned if the given user is already subscribed to the stream.
201 CreatedReturned if a new subscription was created in response to your request.
405 Method Not AllowedReturned if a GET is attempted on an endpoint where only POST can be used.
409 ConflictReturned if the given user is already subscribed to this stream using a different subscription ID, OR if the given subscription ID is already used to identify a subscription to a different stream.

About Conflicts: A single user can only subscribe to the same stream once. If a conflict arises trying to add a subscription, the server will respond with an HTTP 409 Conflict. It will still return the same response elements, but in this case, the body will tell you that the subscription already exists so that corrective action must be taken.

Response Body Format

{
    "collectionType": "activities",
    "ownerId": "22PT4L",
    "ownerType": "user",
    "subscriberId": "3",
    "subscriptionId": "123"
}

Deleting A Subscription

Deletes a subscription for a user. A successful request will return a 204 status code and empty response body.

Here is the syntax to delete a subscription:

DELETE https://api.fitbit.com/1/user/-/[collection-path]/apiSubscriptions/[subscription-id].json

where:

api-versionThe API version. Currently version 1.
collection-pathCollection to delete subscription form. If not present, subscriptions will be deleted from all collections.
subscription-idThe ID of the subscription.
response-formatFormat of the returned data. JSON.

Examples of deleting subscriptions

DELETE https://api.fitbit.com/1/user/-/apiSubscriptions/320.json
DELETE https://api.fitbit.com/1/user/-/activities/apiSubscriptions/320.json
DELETE https://api.fitbit.com/1/user/-/foods/apiSubscriptions/320.json
DELETE https://api.fitbit.com/1/user/-/sleep/apiSubscriptions/320.json
DELETE https://api.fitbit.com/1/user/-/body/apiSubscriptions/320.json

Request Headers

X-Fitbit-Subscriber-IdrecommendedThe ID of the subscriber to receive notifications, as defined on dev.fitbit.com. If not present, the default subscriber is used.

Getting A List of Subscriptions

Get a list of a user's subscriptions for your application in the format requested. You can either fetch subscriptions for a specific collection or the entire list of subscriptions for the user. For best practice, make sure that your application maintains this list on your side and use this endpoint only to periodically ensure data consistency.

Here is the syntax for getting a list of subscriptions:

GET https://api.fitbit.com/1/user/-/<collection-path>/apiSubscriptions.json

where:

api-versionThe API version. Currently version 1.
collection-pathCollection to get subscriptions for (foods, activities, sleep, or body.) If not present, list will include all subscriptions for the user.
response-formatFormat of the returned data. JSON.

Examples of getting list of subscription

GET https://api.fitbit.com/1/user/-/apiSubscriptions.json
GET https://api.fitbit.com/1/user/-/activities/apiSubscriptions.json
GET https://api.fitbit.com/1/user/-/foods/apiSubscriptions.json
GET https://api.fitbit.com/1/user/-/sleep/apiSubscriptions.json
GET https://api.fitbit.com/1/user/-/body/apiSubscriptions.json

Example Response

{
    "collectionType": "activities",
    "ownerId": "22PT4L",
    "ownerType": "user",
    "subscriberId": "3",
    "subscriptionId": "123"
}

Receiving Update Notifications

Aggregation of Updates

Fitbit makes a best effort to aggregate multiple updates within a short time frame into a single notification.

Responding to a Notification

A notification indicates that a resource has been added, modified, or deleted. As a developer, make sure that your application fetches the specified resource to obtain the latest version of the resource. Your application must know which part of the resource have changed. This is determined by comparing the new resource representation with the old resource representation.

Your server must respond to a subscription notification with HTTP 204 No Content and close the connection within three seconds or Fitbit will abort the connection. You must store notifications locally and later fetch the resources. Do not fetch changed resouces before responding to a notification. Doing so will cause your application to respond slowly and more importantly, trigger the Fitbit server to think your endpoint is unavailable and eventually stop your subscription without warning.

There are two strategies for updating your database. The first approach is to immediately retrieve the changes and update your database. The second approach is to mark the copy of the resource as dirty and retrieve the change only when the user visits your website to view the latest data. Depending on the design of your application, use the appropriate strategy. In either case, you must follow the Fitbit API throttling policy. See Rate Limit API documentation for details on the throttling policy.

Notification Format

An update notification request to your endpoint is defined as follows:

HTTP MethodPOST
Content-Typeapplication/json or multipart/form-data
Parameter/part nameupdates
Parameter/part Content-Typetext/xml or text/javascript

Note: Your server must return a 204 No Content response code.

Security

Do not attempt to create a "whitelist" of Fitbit IP addresses for your subscriber endpoint. The subscriptions API is scaled dynamically as necessary to deliver notifications in real time. Instead, use HTTPS on your subscriber, verify the IP address of the request using FCrDNS, and verify the X-Fitbit-Signature header in requests.

X-Fitbit-Signature Header

Update notifications are signed using your OAuth client secret using the standard HMAC-SHA1 generation method and placed in the X-Fitbit-Signature HTTP header. The signature is first BASE64 encoded and then URL encoded, as with the OAuth signature.

To verify the incoming signature, you compute an expected signature from the JSON contents of the "updates" request entity using your OAuth client secret and a null OAuth access token secret (in this case the key for the HMAC-SHA1 method should be the "consumer_secret&" – consumer secret concatenated with the "&" symbol). No headers or request parameters are included in the signature.

Signature verification is optional, but recommended.

If signature verification fails, you should respond with a 404 to avoid revealing your app to a potential attacker. We recommend that you log the remote IP of the host sending the incorrect signature, as well as the incoming signature and incoming message content. We also ask that you send us copies of this information.

Forward-Confirmed Reverse DNS

FCrDNS allows your firewall or application to verify that an IP address making a request to your subscriber endpoint is a legitimate fitbit.com server. For example, your subscriber endpoint receives a request from the IP address 75.126.122.162. First, do a reverse DNS lookup to retrieve the hostname of the server. Verify that this returns a subdomain on fitbit.com. Then, do a DNS lookup on that hostname to verify it resolves to the IP address of the request.

In Linux, Unix, and Mac OSX, this looks like:

$ host 75.126.122.162
162.122.126.75.in-addr.arpa domain name pointer api-75-126-122-162.fitbit.com.
$ host api-75-126-122-162.fitbit.com
api-75-126-122-162.fitbit.com has address 75.126.122.162

Note: For users using Windows, use the nslookup command.

Example Notifications

The following example is a JSON notification, where the third updated resource is for the Fitbit user, 184X36, and associated activities.

[
    {
        "collectionType": "foods",
        "date": "2010-03-01",
        "ownerId": "228S74",
        "ownerType": "user",
        "subscriptionId": "1234"
    }, {
        "collectionType": "foods",
        "date": "2010-03-02",
        "ownerId": "228S74",
        "ownerType": "user",
        "subscriptionId": "1234"
    }, {
        "collectionType": "activities",
        "date": "2010-03-01",
        "ownerId": "184X36",
        "ownerType": "user",
        "subscriptionId": "2345"
    }
]

To get the data for this update, your application constructs and invokes the URL:

https://api.fitbit.com/1/user/184X36/activities/date/2010-03-01.json

Note: This notification URL is defined in the Resource Access API.

TIP: If you use your internal user ID's as the subscription id, then update your web site user, 2345 with the response from:

https://api.fitbit.com/1/user/184X36/activities/date/2010-03-01.json