Accessing the Fitbit API

Fitbit uses OAuth 2.0 for user authorization and API authentication. The OAuth 2.0 framework requires your application to obtain an Access Token when the Fitbit user authorizes your app to access their data. The Access Token is used for making HTTP request to the Fitbit API.

You don't need a Fitbit-specific library to use the Fitbit Web API. Instead, we recommend that you use the best OAuth 2.0 or HTTP client library available for your platform. If you don't have a favorite OAuth 2.0 or HTTP library yet, we've listed some here.

Note: All API requests must use HTTPS.

Fitbit supports the Authorization Code Grant and Implicit Grant flows as defined in RFC 6749.

The Authorization Code Grant flow is recommended for applications that have a web service. This flow requires server-to-server communication using an application's client secret.

Note: Never put your client secret in distributed code, such as apps downloaded through an app store or client-side JavaScript.

Applications that do not have a web service should use the Implicit Grant flow.

WARNING - DO NOT embed the Authorization Page

Any attempt to embed the OAuth 2.0 authentication page will result in your application being banned from the Fitbit API.

For security consideration, the OAuth 2.0 authorization page must be presented in a dedicated browser view. Fitbit users can only confirm they are authenticating with the genuine Fitbit.com site if they have the tools provided by the browser, such as the URL bar and Transport Layer Security (TLS) certificate information.

For native applications, this means the authorization page must open in the default browser. Native applications can use custom URL schemes as redirect URIs to redirect the user back from the browser to the application requesting permission.

iOS applications may use the SFSafariViewController class instead of app switching to Safari. Use of the WKWebView or UIWebView class is prohibited.

Android applications may use Chrome Custom Tabs instead of app switching to the default browser. Use of WebView is prohibited.

For web applications, do not use an iframe. Web applications may use a pop-up window, so long as the URL bar is visible.

Authorization Code Grant Flow

Fitbit follows the OAuth 2.0 Authorization Code Grant as specified in RFC 6749. Fitbit strongly recommends that you review the specification and use an OAuth 2 client library for your programming language.

The Authorization Code Grant flow has the following steps:

  1. Your application redirects the user to Fitbit's authorization page. See Authorization Page below.

  2. Upon user consent, Fitbit redirects the user back to your application's redirect URL with an authorization code as a URL parameter.

  3. Your application exchanges the authorization code for an access token and refresh token. See Access Token Request below.

  4. Your application stores the access token and refresh token. It will use the access token to make requests to the Fitbit API. It will use the refresh token to obtain a new access token when the access token expires without having to re-prompt the user. (More information on the refresh token is below in the "Refreshing Tokens" section.)

Implicit Grant Flow

Fitbit follows the OAuth 2.0 Implicit Code Grant as specified in RFC 6749. Fitbit strongly recommends that you review the specification and use an OAuth client library for your programming language.

The Implicit Code Grant Flow has the following steps:

  1. Your application redirects the user to Fitbit's authorization page. See Authorization Page below.

  2. Upon user consent, Fitbit redirects the user back to your application's redirect URL with an access token as a URL fragment.

  3. Your application stores the access token client side. It will use the access token to make requests to the Fitbit API.

Unlike the Authorization Code Grant Flow, the refresh tokens are not issued with the Implicit Grant flow. Refreshing a token requires use of the client secret, which cannot safely be stored in distributed application code. When the access token expires, users will need to re-authorize your app.

Access tokens from the Implicit Grant Flow are longer lived than tokens from the Authorization Code Grant flow. Users may specify the lifetime of the access token from the authorization page when an application uses the Implicit Grant flow. The access token lifetime options are 1 day, 1 week, and 30 days. Applications can pre-select a token lifetime option, but the user ultimately decides.

If an application using the Implicit Grant Flow sends a user to the authorization page before the previously issued access token has expired, the user will not be prompted unless the scope has increased. The user will be redirected immediately to the application with an access token.

Access tokens obtained via the Implicit Grant Flow should only be stored on the device used to obtain the authorization. If your application has a web server component, your application should use the Authorization Code Grant Flow.

Using Implicit Grant Flow

To use the Implicit Grant flow, you must set your OAuth 2.0 Application Type to Client in your application settings at dev.fitbit.com.

Authorization Page

Example screenshot of the Fitbit OAuth 2.0 consent authorization page

Redirect the user to the Fitbit OAuth 2.0 authorization page with the following parameters:

URI Parameter Description
client_id required This is your Fitbit API application id from your settings on dev.fitbit.com
Type: string
response_type required code for Authorization Code Grant flow
token for Implicit Grant flow
Type: string
scope required A space-delimited list of the permissions you are requesting. See Scope below.
Type: string
redirect_uri required Where Fitbit should send the user after the user grants or denies consent. Recommended. Required unless you have specified only one redirect URI for your application in the settings on dev.fitbit.com. See Redirect URIs below.
Type: URI
expires_in

For use with the Implicit Grant flow only. Pre-select the desired access token lifetime. Defaults to 86400.

86400 for 1 day
604800 for 1 week
2592000 for 30 days
31536000 for 1 year

Optional
Type: string

prompt

Specify if you need to force the Fitbit authentication or the OAuth 2.0 authorization page to be displayed. When used, the redirect_uri parameter must be specified.

none for default behavior.
consent to require consent from the user, even if they have previously authorized your application.
login to require the user to sign in, but request consent according to the default behavior.
login consent to require the user to sign in and authorize your application.

Optional
Type: string

state recommended

Provides any state that might be useful to your application when the user is redirected back to your application. This parameter will be added to the redirect URI exactly as your application specifies. Fitbit strongly recommend including an anti-forgery token in this parameter and confirming its value in the redirect to mitigate against cross-site request forgery (CSRF).

Optional
Type: string

All parameter values must be URI encoded.

Examples

Authorization Code Flow:

https://www.fitbit.com/oauth2/authorize?response_type=code&client_id=22942C&redirect_uri=http%3A%2F%2Fexample.com%2Ffitbit_auth&scope=activity%20nutrition%20heartrate%20location%20nutrition%20profile%20settings%20sleep%20social%20weight

Implicit Grant Flow:

https://www.fitbit.com/oauth2/authorize?response_type=token&client_id=22942C&redirect_uri=http%3A%2F%2Fexample.com%2Ffitbit_auth&scope=activity%20nutrition%20heartrate%20location%20nutrition%20profile%20settings%20sleep%20social%20weight&expires_in=604800

Scope

Applications must only request permission for resources they intend to access or modify. OAuth 2.0 refers to these permissions as scopes. All Fitbit API endpoints require one or more scopes, which are listed in each endpoint's documentation.

Applications must specify a list of scopes when redirecting the user to the authorization page. The access token issued will only contain the scopes the application requested.

Scope Description
activity The activity scope includes activity data and exercise log related features, such as steps, distance, calories burned, and active minutes
heartrate The heartrate scope includes the continuous heart rate data and related analysis
location The location scope includes the GPS and other location data
nutrition The nutrition scope includes calorie consumption and nutrition related features, such as food/water logging, goals, and plans
profile The profile scope is the basic user information
settings The settings scope includes user account and device settings, such as alarms
sleep The sleep scope includes sleep logs and related sleep analysis
social The social scope includes friend-related features, such as friend list, invitations, and leaderboard
weight The weight scope includes weight and related information, such as body mass index, body fat percentage, and goals

Access Modes

Applications operate in a read-only or read and write manner. This is an application-level setting and applies to all scopes. This can be configured in application settings on dev.fitbit.com.

WARNING: Changing the read-only/read and write settings will immediately invalidate all existing access tokens.

Redirect URIs

When a user grants or denies access from the authorization screen, they are redirected back to your application with information necessary to complete the authorization. An error_description URI parameter may also be returned to help diagnose errors in the authorization. (Redirect URIs were known as "callback URLs" in OAuth 1.0a.)

You must specify the full redirect URI in your application settings on dev.fitbit.com. An application may have multiple redirect URIs registered by putting one redirect URI per line in your application settings. Fitbit strongly recommends that you always specify the intended redirect URI as the redirect_uri when sending users to the authorization page. The redirect_uri must be an exact match one of the values specified in your application settings. (Use the state parameter if you need variability in your redirect URI.)

The redirect URI may use any protocol. If HTTP is used, Fitbit strongly recommends (and may require in the future) the use of a Transport Layer Security (TLS) protocol.

Note: When using the Authorization Code Grant Flow, Fitbit will also append #_=_ at the end of your redirect URI upon success or failure of the authorization.

Implicit Grant Redirect URI Parameters

Fitbit will pass the following information to your application's redirect URI as parameters in the URL fragment (after the #) when using the Implicit Grant Flow.

Parameter Description
access_token The access token your application should use to make requests on behalf of the user.
expires_in How long in seconds the access token will be valid for
scope A space-separated list of scopes the user authorized. May be fewer than the application requested.
state recommended

Provides any state that might be useful to your application when the user is redirected back to your application. This parameter will be added to the redirect URI exactly as your application specifies in the authorization request. Fitbit strongly recommend including an anti-forgery token in this parameter and confirming its value in the redirect to mitigate against cross-site request forgery (CSRF).

Optional
Type: string
token_type Will always be Bearer.
user_id The id (sometimes referred to as encoded_id)of the Fitbit user that authorized your application

Authorization Errors

The OAuth 2.0 authorization errors are listed below in their respective status code category.

All errors except for Authorization Request Errors will be suffixed with:

"Visit https://dev.fitbit.com/reference/web-api/oauth2 for more information on the Fitbit Web API authorization process."

Like so:

{"errors":[{"errorType":"invalid_request","message":"Missing parameters: refresh_token. Visit https://dev.fitbit.com/reference/web-api/oauth2 for more information on the Fitbit Web API authorization process."}],"success":false}

Authorization Request Errors

200 OK

According to the OAuth 2.0 RFC, if the redirect_uri is valid, the user is redirected to the app redirect_uri, and any errors are appended to the URI as a query string. However, this behavior could be used in a phishing attack. Therefore, Fitbit’s OAuth 2.0 implementation diverges from the spec in that the user will remain on https://www.fitbit.com/oauth2/authorize, and any errors will be displayed on the page. An error_description URI parameter may also be provided to help diagnose the issue.

Error Response
response_type - missing invalid_request - Missing response_type parameter value
response_type - invalid unsupported_response_type - Invalid response_type parameter value
response_type - unauthorized unauthorized_client - The client is not authorized to request an access token using this method.
scope - missing invalid_request - Missing scope parameter value
scope - invalid invalid_scope - The requested scope is invalid, unknown, or malformed: [scope]
client_id - missing invalid_request - Missing parameters: client_id
client_id - invalid unauthorized_client - Invalid client_id
redirect_uri - missing and app has multiple redirect URIs invalid_request - Missing redirect_uri parameter value
redirect_uri - invalid invalid_request - Invalid redirect_uri parameter value

Access Token Request Errors

400 Bad Request

Error Response
grant_type - missing {"errors":[{"errorType":"invalid_request","message":"Missing ‘grant_type’ parameter value."}],"success":false}
grant_type - invalid {"errors":[{"errorType":"unsupported_grant_type", "message":"The authorization grant_type is not supported."}],"success":false}
code - missing {"errors":[{"errorType":"invalid_request", "message":"Missing parameters: code."}],"success":false}
code - expired {"errors":[{"errorType":"invalid_grant", "message":"Authorization code expired: [code]."}],"success":false}
code - invalid {"errors":[{"errorType":"invalid_grant", "message":"Authorization code invalid: [code]."}],"success":false}
code - used more than once (even if within 10 minutes) {"errors":[{"errorType":"invalid_request", "message":"Authorization code invalid: [code]."}],"success":false}
redirect_uri - missing if specified in the redirect to the authorization page {"errors":[{"errorType":"invalid_request", "message":"Redirect_uri mismatch: null."}],"success":false}
redirect_uri - invalid {"errors":[{"errorType":"invalid_request", "message":"Redirect_uri mismatch: [redirect_uri]."}],"success":false}

401 Unauthorized

401 errors occur when the "Authorization" header is invalid or missing. In addition to an "errors" JSON object, the API will respond with a WWW-Authenticate header with a value of Basic realm="api.fitbit.com". However, if the API cannot determine the authentication scheme due to the Authorization header missing or the word "Basic" being misspelled, the WWW-Authenticate header will have a value of Bearer realm="api.fitbit.com".

Error Response
authorization header - missing {'errors': [{'errorType': invalid_client, 'message': 'Authorization header required.' }], "success": false}
authorization header invalid - "Basic" misspelled [{'errorType': invalid_client, "message": "Invalid authorization header format."}], "success": false}
client_id - missing {"errors":[{"errorType":"invalid_client","message": Invalid authorization header format."}],"success":false}
client_id - invalid {"errors":[{"errorType":"invalid_client","message": "Invalid authorization header. Client id invalid."}],"success":false}
client_secret - missing {"errors":[{"errorType":"invalid_client","message": "Invalid authorization header format."}],"success":false}
client_secret - invalid {"errors":[{"errorType":"invalid_client","message": "Invalid authorization header. Client secret invalid."}],"success":false}

Refresh Token Errors

See the Access Token Request - 401 Unauthorized section above for error descriptions that are not specific to refresh token requests. However, for 401 errors that occur during a refresh token request, the API will respond with a WWW-Authenticate header with a value of Bearer realm="api.fitbit.com", rather than a value of Basic realm="[redirect_uri]".

400 Bad Request

Error Response
refresh_token - invalid {"errors":[{"errorType":"invalid_grant","message":"Refresh token invalid: [access_token]"}],"success":false}
refresh_token - missing {"errors":[{"errorType":"invalid_request","message":"Missing parameters: refresh_token"}],"success":false}
grant_type - missing {"errors":[{"errorType":"invalid_request","message":"Missing 'grant_type' parameter value."}],"success":false}
grant_type - invalid {"errors":[{"errorType":"unsupported_grant_type", "message":"The authorization grant_type is not supported."}],"success":false}

API Request Errors

400 Bad Request

Error Response
Request to invalid api domain {"errors":[{"errorType":"request", "fieldName": "n/a", "message":"Request to invalid domain: [domain]"}],"success":false}
Invalid request body {"errors":[{"errorType":"invalid_request", "fieldName": "n/a", "message":"There was an error reading the request body."}],"success":false}

401 Unauthorized

Along with the 401 Unauthorized errors, the API responds with a WWW-Authenticate header with a value of Bearer realm="api.fitbit.com".

Error Response
access token - expired {"errors":[{"errorType":"expired_token","message":"Access token expired: [access_token]"}],"success":false}
access token - invalid {"errors":[{"errorType":"invalid_token","message":"Access token invalid: [access_token]"}],"success":false}
access token - missing {"errors":[{"errorType":"invalid_client","message":"Incorrect authorization method."}],"success":false}
authorization header - missing {"errors":[{"errorType":"invalid_request","message":"Authorization header required."}],"success":false}

403 Forbidden

Error Response
Missing one or more required scopes for a resource {"errors":[{"errorType":"insufficient_scope","message":"This application does not have permission to [access-type] [resource-type] data."}],"success":false}
Read-only client attempting to update resources {"errors":[{"errorType":"insufficient_permissions","message":"Read-only API client is not authorized to update resources."}],"success":false}
Insufficient permissions granted by resource owner {"errors":[{"errorType":"insufficient_permissions","message":"API client is not authorized by the resource owner to access the resource requested."}],"success":false}
Insufficient permissions granted by Fitbit {"errors":[{"errorType":"insufficient_permissions","message":"API client is not authorized by Fitbit to access the resource requested."}],"success":false}

404 Not Found

Error Response
Resource not found {"errors":[{"errorType":"not_found", "fieldName": "n/a", "message":"The API you are requesting could not be found."}],"success":false}

Access Token Request

When a user authorizes your application in the Authorization Code Grant flow, your application must exchange the authorization code for an access token. The code is only valid for 10 minutes.

Authorization Header

The Authorization header must be set to Basic followed by a space, then the Base64 encoded string of your application's client id and secret concatenated with a colon. For example, the Base64 encoded string, Y2xpZW50X2lkOmNsaWVudCBzZWNyZXQ=, is decoded as "client_id:client secret".

Body Parameters

Form Parameter Description
code required

The authorization code received in the redirect as a URI parameter

Type: string
grant_type required authorization_code
Type: string
client_id

This is your Fitbit API application id from your settings on dev.fitbit.com

Type: string
redirect_uri recommended Required if specified in the redirect to the authorization page. Must be exact match.
Type: URI
state recommended

Required if specified in the redirect to the authorization page. Must be an exact match.

Type: string
expires_in optional

Specify the desired access token lifetime. Defaults to 28800.

3600 for 1 hour
28800 for 8 hours
Type: integer

Authorization Header Example

This example assumes that the code URI parameter value in the redirect URI was 1234567890.

POST https://api.fitbit.com/oauth2/token
Authorization: Basic Y2xpZW50X2lkOmNsaWVudCBzZWNyZXQ=
Content-Type: application/x-www-form-urlencoded

client_id=22942C&grant_type=authorization_code&redirect_uri=http%3A%2F%2Fexample.com%2Ffitbit_auth&code=1234567890

Example Response:

{
    "access_token": "eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE0MzAzNDM3MzUsInNjb3BlcyI6Indwcm8gd2xvYyB3bnV0IHdzbGUgd3NldCB3aHIgd3dlaSB3YWN0IHdzb2MiLCJzdWIiOiJBQkNERUYiLCJhdWQiOiJJSktMTU4iLCJpc3MiOiJGaXRiaXQiLCJ0eXAiOiJhY2Nlc3NfdG9rZW4iLCJpYXQiOjE0MzAzNDAxMzV9.z0VHrIEzjsBnjiNMBey6wtu26yHTnSWz_qlqoEpUlpc",
    "expires_in": 3600,
    "refresh_token": "c643a63c072f0f05478e9d18b991db80ef6061e4f8e6c822d83fed53e5fafdd7",
    "token_type": "Bearer",
    "user_id": "26FWFL"
}

Making Requests

To make a request to the Fitbit API using OAuth 2.0, simply add an Authorization header to the HTTP request with the user's access token.

Example Request:

GET https://api.fitbit.com/1/user/-/profile.json
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE0MzAzNDM3MzUsInNjb3BlcyI6Indwcm8gd2xvYyB3bnV0IHdzbGUgd3NldCB3aHIgd3dlaSB3YWN0IHdzb2MiLCJzdWIiOiJBQkNERUYiLCJhdWQiOiJJSktMTU4iLCJpc3MiOiJGaXRiaXQiLCJ0eXAiOiJhY2Nlc3NfdG9rZW4iLCJpYXQiOjE0MzAzNDAxMzV9.z0VHrIEzjsBnjiNMBey6wtu26yHTnSWz_qlqoEpUlpc

Refreshing Tokens

An access token intentionally is short lived. This is an important security mechanism of OAuth 2.0. When using the Authorization Code Grant flow, the access tokens have an eight-hour lifetime by default.

When an access token expires, an HTTP 401 error will be returned:

{
    "errors": [
        {
            "errorType": "expired_token",
            "message": "Access token expired: eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE0MzAzNDM3MzUsInNjb3BlcyI6Indwcm8gd2xvYyB3bnV0IHdzbGUgd3NldCB3aHIgd3dlaSB3YWN0IHdzb2MiLCJzdWIiOiJBQkNERUYiLCJhdWQiOiJJSktMTU4iLCJpc3MiOiJGaXRiaXQiLCJ0eXAiOiJhY2Nlc3NfdG9rZW4iLCJpYXQiOjE0MzAzNDAxMzV9.z0VHrIEzjsBnjiNMBey6wtu26yHTnSWz_qlqoEpUlpc"
        }
    ]
}

Your application will need to refresh the access token. The Fitbit API follows the OAuth 2.0 specification for refreshing access tokens. A refresh token does not expire until it is used. A refresh token can only be used once, as a new refresh token is returned with the new access token.

If a client makes identical refresh token requests within a two-minute period, the Fitbit Web API will return the same response. This is to assist applications unable to coordinate the refresh token flow between processes.

Resource URLs

POST https://api.fitbit.com/oauth2/token

Authorization Header

The Authorization header must be set to Basic followed by a space, then the Base64 encoded string of your application's client id and secret concatenated with a colon. For example, the Base64 encoded string, Y2xpZW50X2lkOmNsaWVudCBzZWNyZXQ=, is decoded as [client_id]:[client_secret].

Body Parameters

Form Parameter Description
grant_type required refresh_token
Type: string
refresh_token required

The refresh token issued to you by Fitbit.


Type: string
expires_in optional

Specify the new desired access token lifetime. Defaults to 28800.

3600 for 1 hour
28800 for 8 hours
Type: integer

Example Refresh Token:

POST https://api.fitbit.com/oauth2/token
Authorization: Basic Y2xpZW50X2lkOmNsaWVudCBzZWNyZXQ=
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token&refresh_token=abcdef01234567890abcdef01234567890abcdef01234567890abcdef0123456

Alternatively, your application could redirect the user to the authentication flow. If the user is signed in and the scopes requested match the previously granted scopes, the user will be redirected to your redirect URI with a new access token without being prompted.

Revoking Access Tokens

An application can revoke the access that a Fitbit user has granted it. This endpoint conforms to RFC 7009.

Resource URL

POST https://api.fitbit.com/oauth2/revoke

Authorization Header

The Authorization header must be set to Basic followed by a space, then the Base64 encoded string of your application's client id and secret concatenated with a colon. For example, the Base64 encoded string, Y2xpZW50X2lkOmNsaWVudCBzZWNyZXQ=, is decoded as [client_id]:[client_secret].

Body Parameters

URI Parameter Description
token required

The access token to be revoked.


Type: string

Fitbit API Notes

Fitbit API access tokens use the JSON Web Token (JWT) format. Fitbit reserves the right to change the contents and format of these tokens at any time. Client applications should not create dependencies upon the token format.

Access tokens and refresh tokens may be up to 1,024 bytes in size.

Web Browser Compatibility

The Fitbit API and its implementation of OAuth 2.0 are designed to work with the current and one previous version of Apple Safari, Google Chrome, Microsoft Edge, and Mozilla Firefox. When a new version of a web browser is released, Fitbit begins supporting that version and stop supporting the third most recent version.