Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Added FCrDNS info

Table of Contents

Quick Start

To get started quickly:

  1. Implement a simple subscriber endpoint 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 your account with a subscriber endpoint.
  4. Authenticate Fitbit users on your site as described in the OAuth Authentication API.
  5. Add subscriptions as described in Add a subscription.
Panel

Your application needs only Read Access Type to be able to create subscriptions to user resources and receive notifications. Note, that updating application's Access Type for extended permissions (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 more detail.

...

Subscriber

A client service endpoint that is notified by Fitbit when member data changes. Subscribers are identified by a Subscriber ID.

Subscription

An 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.

Stream

A sequence of changes to member data.

Collection Type

A 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, body

Notification

A request sent by Fitbit to a subscriber indicating that a Fitbit resource has been added, modified, or deleted.

Resilient Application Design

An application should 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 should fetch the most recent resources to be certain that the best data is presented.

The Fitbit 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 3 seconds to a notification request.

We're both responsible for creating an awesome experience for Fitbit users. This hybrid approach is the best way for your application to be synchronized with Fitbit.

Discovering Feeds

As discussed below, subscriptions can be created on any user-based collection by appending "/apiSubscriptions" to the end of the URL.

...

Subscriber endpoints have the following parameters:

url

required

the full URL to the subscriber endpoint where update notifications will be sent (e.g. "http://www.example.com/fitbit")

format

required

the serialization format (xml or json) that update notifications will use

apiVersion

required

the version of the API used by update notifications

default=true|false

optional

whether 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.

id

optional

the ID you will use 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; we encourage you to choose an ID that makes the most sense to you

Info
titleHTTPS

We support TLS(v 1.0)/SSL protocol for the subscriber endpoints. Please, note that we are not supporting self-signed certificates. We support only HTTPS connections to port 443. TLS+SNI is not supported at this time. Note that TLS v. 1.1. and 1.2 are not supported at this point.

Add a subscription

Add a subscription for the user to get notifications and get a response in the format requested. As explained below, the <subscription-id> provides a way to associate an update notification with a particular user stream in your application.

Access Type: Read

Resource URL

POST /<api-version>/user/-/<collection-path>/apiSubscriptions/<subscription-id>.<response-format>

api-version

The API version. Currently 1.

collection-path

Collection resource URL; collection to receive notifications from (foods, activities, sleep, body). If not present subscribing to changes from all collections. Note, that if you have both "all" and specific collection subscriptions, you will get duplicate notifications on that collection's update. Also each subscriber may have only one subscription for specific user's collection.

subscription-id

Unique ID of the subscription created by the API client application. Note, that you can have only one subscription with unique id across the whole set of subscribers and collections. The Fitbit servers will pass this id back to you when you are notified about that the user indicated by the user parameter in the URL path has new data for you to pull. It will be available in the <subscriptionId> field of the notification. Valid characters: a-z, A-Z, 0-9, -, _

response-format

The response format. Currently supported response formats are json and xml for responses in JSON and XML, respectively.

Code Block
bgColor#eeeeee
titleBGColor#3ec1c1
borderStylesolid
titleExamples

POST /1/user/-/apiSubscriptions/320.xml
POST /1/user/-/activities/apiSubscriptions/320-activities.xml
POST /1/user/-/foods/apiSubscriptions/320-foods.json
POST /1/user/-/sleep/apiSubscriptions/320-sleep.json
POST /1/user/-/body/apiSubscriptions/320-body.json

...

X-Fitbit-Subscriber-Id

optional

The ID of the subscriber. Defined on dev.fitbit.com, this subscriber would receive notifications for this subscription. If not present, the default subscriber is used.

 

POST Parameters

None

Response

API Response in format requested: JSON or XML.

200 OK

if the given subscriber is already subscribed to this stream

201 Created

if a new subscription was created in response to your request

409 Conflict

  • if the given subscriber 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
Info
titleAbout Conflicts

A single subscriber may 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. In this case, the response elements tell you about the subscription that already exists, so that you may take corrective action as necessary.

 

Response body format

The following elements are returned for all response codes listed above.

subscriberId

Id of subscriber that will receive notifications; defined on dev.fitbit.com

ownerId

Id of the resource owner

ownerType

Type of the resource owner; currently "user"

collectionType

Collection whose stream has been subscribed to; when subscribing to all of a user's updates value of this element is "user"

subscriptionId

Subscription Id; subscription ids are treated as opaque strings up to 50 unicode characters long

In the case of a 409 Conflict response, this is the ID of the subscription already associated with this stream.

 

Note: Text within <> is a descriptive place holder for a value.

Code Block
bgColor#eeeeee
titleBGColor#3ec1c1
borderStylesolid
titleJSON Response

{
    "collectionType":<value>,
    "ownerId":<value>,
    "ownerType":"user",
    "subscriberId":<value>,
    "subscriptionId":<value>
}

 

Note: Text within [] is a descriptive place holder for a value.

Code Block
bgColor#eeeeee
titleBGColor#3ec1c1
borderStylesolid
titleXML Response

<?xml version="1.0" encoding="UTF-8"?>
<result>
    <collectionType>[value]</collectionType>
    <ownerId>[value]</ownerId>
    <ownerType>user</ownerType>
    <subscriberId>[value]</subscriberId>
    <subscriptionId>[value]</subscriptionId>
</result>

 

Examples

Code Block
bgColor#eeeeee
titleBGColor#3ec1c1
borderStylesolid
titleJSON Response

{
    "collectionType":"user",
    "ownerId":"227YZL",
    "ownerType":"user",
    "subscriberId":"1",
    "subscriptionId":"323"
}
Code Block
bgColor#eeeeee
titleBGColor#3ec1c1
borderStylesolid
titleXML Response

<?xml version="1.0" encoding="UTF-8"?>
<result>
    <collectionType>user</collectionType>
    <ownerId>227YZL</ownerId>
    <ownerType>user</ownerType>
    <subscriberId>1</subscriberId>
    <subscriptionId>323</subscriptionId>
</result>

 

Remove a subscription

Delete a subscription for the user and get a response in the format requested.

Access Type: Read

Resource URL

DELETE /<api-version>/user/-/<collection-path>/apiSubscriptions/<subscription-id>.<response-format>

api-version

The API version. Currently 1.

user-id

User's encoded id or "-" (dash) to indicate user currently authenticated via the token credentials provided.

collection-path

Collection to delete subscription from. If not present delete subscription from the whole collection (this will not delete additional subscriptions

subscription-id

The ID of the subscription

response-format

The response format. Currently supported response formats are json and xml for responses in JSON and XML, respectively.

Code Block
bgColor#eeeeee
titleBGColor#3ec1c1
borderStylesolid
titleExamples

DELETE /1/user/-/apiSubscriptions/320.xml
DELETE /1/user/-/activities/apiSubscriptions/320-activities.xml
DELETE /1/user/-/foods/apiSubscriptions/320-foods.json
DELETE /1/user/-/sleep/apiSubscriptions/320-sleep.json
DELETE /1/user/-/body/apiSubscriptions/320-body.json

 

Authentication

Via token credentials. All authentication header parameters are required.

Request Headers

None

Response

API Response in format requested: JSON or XML.

in the first place

204 No Content

if the given  subscription given subscription was successfully deleted or

404 Not Foundif the given subscription ID did not exist for this application (for example, if your application already unsubscribed)

 

List existing subscriptions

...

Access Type: Read

Rate Limited: Yes

Resource URL

GET /<api-version>/user/-/<collection-path>/apiSubscriptions.<response-format>

api-version

The API version. Currently 1.

collection-path

Collection to get subscriptions for (foods, activities, sleep, body). If not present list will include whole list of subscriptions for the user

response-format

The response format. Currently supported response formats are json and xml for responses in JSON and XML, respectively.

Code Block
bgColor#eeeeee
titleBGColor#3ec1c1
borderStylesolid
titleExamples

GET /1/user/-/apiSubscriptions.xml
GET /1/user/-/activities/apiSubscriptions.xml
GET /1/user/-/foods/apiSubscriptions.json
GET /1/user/-/sleep/apiSubscriptions.json
GET /1/user/-/body/apiSubscriptions.json

 

Authentication

Via token credentials. All authentication header parameters are required.

Request Headers:

None

Response

API Response in format requested: JSON or XML.

Response body format

Note: Text within <> is a descriptive place holder for a value.

Code Block
bgColor#eeeeee
titleBGColor#3ec1c1
borderStylesolid
titleJSON Response

{
    apiSubscriptions:[
        {
            "collectionType":<value>,
            "ownerId":<value>,
            "ownerType":"user",
            "subscriberId":<value>,
            "subscriptionId":<value>
        },
        <...>
    ]
}

 

Note: Text within [] is a descriptive place holder for a value.

Code Block
bgColor#eeeeee
titleBGColor#3ec1c1
borderStylesolid
titleXML Response

<?xml version="1.0" encoding="UTF-8"?>
<result>
    <apiSubscriptions>
        <apiSubscription>
            <collectionType>[value]</collectionType>
            <ownerId>[value]</ownerId>
            <ownerType>user</ownerType>
            <subscriberId>[value]</subscriberId>
            <subscriptionId>[value]</subscriptionId>
        </apiSubscription>
        [...]
    </apiSubscriptions>
</result>

 

Examples

Code Block
bgColor#eeeeee
titleBGColor#3ec1c1
borderStylesolid
titleJSON Response

{
    apiSubscriptions:[
        {
            "collectionType":"user",
            "ownerId":"227YZL",
            "ownerType":"user",
            "subscriberId":"1",
            "subscriptionId":"323"
        }
    ]
}
Code Block
bgColor#eeeeee
titleBGColor#3ec1c1
borderStylesolid
titleXML Response

<?xml version="1.0" encoding="UTF-8"?>
<result>
    <apiSubscriptions>
        <apiSubscription>
            <collectionType>user</collectionType>
            <ownerId>227YZL</ownerId>
            <ownerType>user</ownerType>
            <subscriberId>1</subscriberId>
            <subscriptionId>323</subscriptionId>
        </apiSubscription>
    </apiSubscriptions>
</result>

 

Receiving Update Notifications
Anchor
receivingUpdateNotifications
receivingUpdateNotifications

Info
titleConfigure your firewall

Notifications from Fitbit may come from any IP in the range 67.228.35.128/26. Be sure to configure your firewall rules accordingly.

Aggregation of Updates

We make a best effort to aggregate multiple updates within a short time frame into a single notification. We also make a best effort to ensure there is only a single notification in progress at any given time to a particular subscriber. In this way, your service need be neither scalable nor even multi-threaded, as long as it can respond to notifications quickly. 

...

A notification indicates that a resource has been added, modified, or deleted. It is up to you to fetch the specified resource to obtain the latest version of it. If it is important for your application to know which parts of the resource have changed, you must compare the new representation with the old representation to make this determination.

Your server must respond to a subscription notification with HTTP 204 No Content and close the connection within 3-seconds or Fitbit will abort the connection. You should always store notifications locally and later fetch the resources. It's never acceptable to fetch changed resources before responding to a notification. Doing so will cause your application to respond slowly, and could cause our server to think your endpoint is unavailable and eventually stop your subscription without warning.

...

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

HTTP Method

POST

Content-Type

multipart/form-data

Parameter/part name

updates 

Parameter/part Content-Type

text/xml or text/javascript

...

Security and Authenticated Notifications

Info

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 XML or 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_keysecret&" – consumer key secret concatenated with the "&" symbol). No headers or request parameters are included in the signature.

...

If signature verification fails, you MUST nevertheless return the same success code you would if the signature had been valid and you were able to parse and act upon all messages in the notification. 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 OS X, 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

(Windows users can use 'nslookup'.)

Example Notifications

Code Block
bgColor#eeeeee
titleBGColor#3ec1c1
borderStylesolid
titleExample XML Notification

<?xml version="1.0" encoding="UTF-8"?>
<updates>
	<updatedResource>
		<collectionType>foods</collectionType>
		<date>2010-03-01</date>
		<ownerType>user</ownerType>
		<ownerId>228S74</ownerId>
		<subscriptionId>1234</subscriptionId>
	</updatedResource>
	<updatedResource>
		<collectionType>foods</collectionType>
		<date>2010-03-02</date>
		<ownerType>user</ownerType>
		<ownerId>228S74</ownerId>
		<subscriptionId>1234</subscriptionId>
	</updatedResource>
	<updatedResource>
		<collectionType>activities</collectionType>
		<date>2010-03-01</date>
		<ownerType>user</ownerType>
		<ownerId>184X36</ownerId>
		<subscriptionId>2345</subscriptionId>
	</updatedResource>
</updates>

In this example, the 3rd updated resource is for Fitbit user 184X36's activities. To get the data for this update, your application constructs and invokes the URL http://api.fitbit.com/user/184X36/activities/date/2010-03-01.xml as defined in the Resource Access API. If you followed our tip about using your internal user ID's as the subscription id, then you know to update your site user 2345 with the response from http://api.fitbit.com/user/184X36/activities/date/2010-03-01.xml.

 

Code Block
bgColor#eeeeee
titleBGColor#3ec1c1
borderStylesolid
titleExample JSON Notification

[
                {
                  "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",
                }
            ]