---
title: "The fitness API openness index"
canonical: "https://aifitnessapi.com/openness-index"
markdown: "https://aifitnessapi.com/openness-index.md"
type: "record"
last_reviewed: "2026-11-06"
description: "Which developer basics 13 wearable and health-data APIs document: self-serve access, sandbox, pricing, rate limits, signed webhooks, PKCE and more."
publisher: "AIFitnessAPI — funded by KinesteX; first-party pages disclose it"
cite_as: "\"The fitness API openness index\", AIFitnessAPI, https://aifitnessapi.com/openness-index"
---

# The fitness API openness index

> This index counts which of eight developer basics 13 wearable and health-data APIs document on their own pages: a self-serve start, a sandbox or test mode, public pricing, published rate limits, signed webhooks, PKCE, refresh tokens, and a call that disconnects a user or deletes their data. The most often documented is published rate limits (11 of 13); the least is pkce (2 of 12). Every mark links the vendor's own sentence. A basic the pages read do not mention is shown as not documented, never as missing, and each score is a plain count with no weighting and no rank.

- Canonical: https://aifitnessapi.com/openness-index
- Last reviewed: 2026-11-06
- Publisher: AIFitnessAPI (https://aifitnessapi.com)
- Cite as: "The fitness API openness index", AIFitnessAPI, https://aifitnessapi.com/openness-index

---

Compiled November 6, 2026 · 13 APIs · 8 checks · CC BY 4.0

## The index

Alphabetical, so the order says nothing. A mark links the vendor’s sentence further down the page.

| API | Self-serve start | Sandbox or test mode | Public pricing | Published rate limits | Signed webhooks | PKCE | Refresh tokens | Disconnect or deletion call | Count |
|---|---|---|---|---|---|---|---|---|---|
| Concept2 Logbook | ✓ | ✓ | n.d. | ✓ | n.d. | n.d. | ✓ | ✓ | 5/8 |
| COROS | ✗ | n.d. | n.d. | ✓ | n.d. | n.d. | ✓ | ✓ | 3/8 |
| Dexcom | ✓ | ✓ | n.d. | ✓ | n.d. | n.d. | ✓ | n.d. | 4/8 |
| Garmin | ✗ | ✓ | n.d. | n.d. | n.d. | n.d. | n.d. | n.d. | 1/8 |
| Google Health API | ✓ | n.d. | n.d. | ✓ | ✓ | n.d. | ✓ | ✓ | 5/8 |
| Oura | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 8/8 |
| Polar AccessLink | ✓ | n.d. | ✓ | ✓ | ✓ | n.d. | n/a | ✓ | 5/7 |
| Strava | ✓ | ✓ | ✓ | ✓ | n.d. | n.d. | ✓ | ✓ | 6/8 |
| Suunto | ✗ | ✓ | ✓ | n.d. | n.d. | n.d. | n.d. | n.d. | 2/8 |
| Terra | n.d. | ✓ | ✓ | ✓ | ✓ | n/a | n/a | n.d. | 4/6 |
| Wahoo | ✗ | ✓ | ✓ | ✓ | ✗ | ✓ | ✓ | ✓ | 6/8 |
| WHOOP | ✓ | ✓ | ✓ | ✓ | ✓ | n.d. | ✓ | ✓ | 7/8 |
| Withings | ✓ | ✓ | ✓ | ✓ | ✗ | n.d. | ✓ | n.d. | 5/8 |
| Documented by | 8 of 13 | 10 of 13 | 8 of 13 | 11 of 13 | 5 of 13 | 2 of 12 | 9 of 11 | 8 of 13 |  |

- ✓ Documented: the vendor's page states it (the mark links the quote)
- ✗ The vendor's page says otherwise, for example that access needs approval (the mark links the quote)
- n.d. Not documented in the pages read, which is not the same as no
- n/a Does not apply to how this API authenticates or issues tokens

## What each check asks

**Self-serve start** Can a developer create credentials and start building without an application being approved first? Documented when the vendor's page says you can register an app or client yourself, or that a new app works for a small number of users before review. Absent when the page says access starts with a request the vendor approves.

**Sandbox or test mode** Is there a sandbox, demo user, test environment or development tier? Documented when the vendor's page names a sandbox, demo user, test or development environment, or a development-only tier.

**Public pricing** Does the vendor state on a public page what API access costs, including that it is free? Documented when a vendor page states a price or states that access is free or at no charge. A page that says terms are tailored, with no number, is not counted.

**Published rate limits** Does the vendor publish its request limits, or state that there are none? Read from the rate-limit calculator: documented when it lists at least one limit with its number, or the vendor's statement that the API is not rate limited; not documented when the calculator lists the vendor as publishing no number.

**Signed webhooks** Are webhook requests cryptographically signed, so a receiver can verify the body? Read from the webhook library: documented when the vendor's scheme is an HMAC the verifier recomputes, or its page says the payload is signed. Absent when the vendor documents a shared token instead, which proves the sender knows a secret but not that the body is untouched.

**PKCE** Does the OAuth documentation describe PKCE (code_challenge and code_verifier)? Read from the OAuth playground: documented when PKCE is recommended or supported on the vendor's page.

**Refresh tokens** Is the refresh-token flow documented? Read from the OAuth playground: documented when the vendor's page describes refreshing (the call, or that refresh tokens rotate). Not applicable when the vendor says access tokens do not expire.

**Disconnect or deletion call** Is there a documented API call that disconnects a user (revoke, deauthorize, deregister) or deletes their data? Documented when the vendor's page names an endpoint or API method that revokes a user's authorization, deregisters the user, or deletes their data. A setting the user changes on the vendor's site is not counted.

## Each API, check by check

### Concept2 Logbook: 5/8 documented

[The Concept2 Logbook guide](https://aifitnessapi.com/integrate/concept2-api) lists every page read.

| Check | State | What the vendor’s page says | Quote | Source |
|---|---|---|---|---|
| Self-serve start | Documented | You set up and manage your own client on the API Keys page. | To use it, you’ll need to set up an API key on the "API Keys" page. There, you can set up and manage your own client and get the client information needed to authenticate users using OAuth. | [log.concept2.com](https://log.concept2.com/developers/home) |
|  |  | Apps that write data develop on log-dev and need Concept2's approval for the live API. | If you are writing data to the Logbook, before using the live API, you must first develop against the development server and database on https://log-dev.concept2.com . When ready, please contact Concept2 for approval for the live API. | [log.concept2.com](https://log.concept2.com/developers/documentation/) |
| Sandbox or test mode | Documented | A development server and database at log-dev.concept2.com. | Applications requesting write permissions should be set up on log-dev.concept2.com . | [log.concept2.com](https://log.concept2.com/developers/home) |
| Public pricing | Not documented in the pages read | The developer pages read state no price. |  |  |
| Published rate limits | Documented | Concept2 says the API is not currently rate limited, that this may change, and that abuse will bring rate limits or removal of access. | The API is not currently rate limited. This may change in the future. Abuse of the API will result in either rate limits or removal of access. | [log.concept2.com](https://log.concept2.com/developers/documentation/) |
| Signed webhooks | Not documented in the pages read | Concept2 has a webhook for results added, updated or deleted; the pages read describe no signature. | Through your self-service developer portal, you can register and manage a webhook that will fire when a relevant result is added, updated, or deleted. | [log.concept2.com](https://log.concept2.com/developers/documentation/) |
| PKCE | Not documented in the pages read | Not mentioned on the Logbook API pages read. |  |  |
| Refresh tokens | Documented | Every application gets the authorization-code and refresh grants. | All applications have access to the Authorization Code and Refresh grant types. | [log.concept2.com](https://log.concept2.com/developers/documentation/) |
| Disconnect or deletion call | Documented | DELETE on a result deletes that workout. | DELETE api/users/me/results/123 will delete a specific workout | [log.concept2.com](https://log.concept2.com/developers/documentation/) |

### COROS: 3/8 documented

[The COROS guide](https://aifitnessapi.com/integrate/coros-api) lists every page read.

| Check | State | What the vendor’s page says | Quote | Source |
|---|---|---|---|---|
| Self-serve start | The docs say otherwise | Partner API access is by application: a form and an email to COROS. | To apply, submit your platform details using the form below and email | [support.coros.com](https://support.coros.com/api/v2/help_center/en-us/sections/53180979524884/articles.json) |
|  |  | COROS lists a registered company among the requirements. | Registered company with authorized technical representative | [support.coros.com](https://support.coros.com/api/v2/help_center/en-us/sections/53180979524884/articles.json) |
| Sandbox or test mode | Not documented in the pages read | The help-center articles read name no sandbox or test environment. |  |  |
| Public pricing | Not documented in the pages read | The help-center articles read state no price. |  |  |
| Published rate limits | Documented | 1,000 per minute. | Rate limit: 1,000 calls/minute | [support.coros.com](https://support.coros.com/api/v2/help_center/en-us/sections/53180979524884/articles.json) |
| Signed webhooks | Not documented in the pages read | COROS lists webhook push in its Partner API but the articles read show no payload or signature. |  |  |
| PKCE | Not documented in the pages read | Not mentioned in the help-center articles read. |  |  |
| Refresh tokens | Documented | The Partner API's OAuth 2.0 list includes refresh. | OAuth 2.0 (authorize, access token, refresh, deauthorize, bind state) | [support.coros.com](https://support.coros.com/api/v2/help_center/en-us/sections/53180979524884/articles.json) |
| Disconnect or deletion call | Documented | The Partner API lists a deauthorize call. | OAuth 2.0 (authorize, access token, refresh, deauthorize, bind state) | [support.coros.com](https://support.coros.com/api/v2/help_center/en-us/sections/53180979524884/articles.json) |

### Dexcom: 4/8 documented

[The Dexcom guide](https://aifitnessapi.com/integrate/dexcom-api) lists every page read.

| Check | State | What the vendor’s page says | Quote | Source |
|---|---|---|---|---|
| Self-serve start | Documented | Registration is free and gives you app credentials. | Registration is simple and free, however, and provides access to app credentials and Support Requests . | [developer.dexcom.com](https://developer.dexcom.com/docs/dexcom/scopes-access) |
|  |  | Limited Access covers up to 5 users for testing with real data; more needs Dexcom's review. | Limited access allows you to authenticate up to 5 users for testing with real data. | [developer.dexcom.com](https://developer.dexcom.com/docs/dexcom/getting-started) |
| Sandbox or test mode | Documented | A sandbox environment at sandbox-api.dexcom.com with sandbox users. | To target the sandbox environment, use https://sandbox-api.dexcom.com as the base URL for requests. | [developer.dexcom.com](https://developer.dexcom.com/docs/dexcom/sandbox-data) |
| Public pricing | Not documented in the pages read | Registration is free; the pages read state no price for full access, which follows a technical and commercial review. | Once application is complete, Dexcom will setup a technical and commercial review of your app. | [developer.dexcom.com](https://developer.dexcom.com/docs/dexcom/scopes-access) |
| Published rate limits | Documented | 60,000 per hour. | Request frequency is limited to 60,000 calls per app per hour. If the limit is exceeded, an HTTP 429 response is returned. | [developer.dexcom.com](https://developer.dexcom.com/docs/dexcomv3/endpoint-overview) |
| Signed webhooks | Not documented in the pages read | Dexcom's webhook documentation was not among the pages read. |  |  |
| PKCE | Not documented in the pages read | Not mentioned. Dexcom also requires tokens and the client secret to live on your server, not on a phone. |  |  |
| Refresh tokens | Documented | Each refresh token works once and is replaced by a new one; each lasts at most a year. A 400 on refresh means it is no longer valid: send the user through login again. | Each refresh_token can be used only once. | [developer.dexcom.com](https://developer.dexcom.com/docs/dexcom/authentication) |
| Disconnect or deletion call | Not documented in the pages read | Users can revoke access on Dexcom.com; the pages read name no API call for it. | Users can revoke their authorization at any time at Dexcom.com by signing in to their account and changing their authorizations in Permissions. | [developer.dexcom.com](https://developer.dexcom.com/docs/dexcom/authentication) |

### Garmin: 1/8 documented

[The Garmin guide](https://aifitnessapi.com/integrate/garmin-api) lists every page read.

| Check | State | What the vendor’s page says | Quote | Source |
|---|---|---|---|---|
| Self-serve start | The docs say otherwise | Access starts with a request Garmin approves. | After you request access to the Garmin Connect Developer Program and your request has been approved, you will be granted access to the Garmin Developer Portal and can get started on your integration right away. | [developer.garmin.com](https://developer.garmin.com/gc-developer-program/enterprise/program-faq/) |
| Sandbox or test mode | Documented | An evaluation environment for testing, after approval. | After approval, you will have access to an evaluation environment to test the Garmin Connect Health API. | [developer.garmin.com](https://developer.garmin.com/gc-developer-program/enterprise/health-api/) |
| Public pricing | Not documented in the pages read | Enterprise terms are tailored; the current program pages read state no Starter price. | Designed for companies operating at scale requiring capabilities beyond Starter Access. Available options and commercial terms are tailored based on business and technical requirements. | [developer.garmin.com](https://developer.garmin.com/gc-developer-program/overview/) |
| Published rate limits | Not documented in the pages read | Garmin's public program pages publish no request limits; the overview gives Starter a "Limited" user capacity without a number. | Push only Historical Data Not included User Capacity Limited | [developer.garmin.com](https://developer.garmin.com/gc-developer-program/overview/) |
| Signed webhooks | Not documented in the pages read | No public Garmin page read shows a push payload or how it is signed. |  |  |
| PKCE | Not documented in the pages read | Garmin's OAuth reference was not among the pages read; the program FAQ says only that the APIs use OAuth 2.0. |  |  |
| Refresh tokens | Not documented in the pages read | Garmin's OAuth reference was not among the pages read. |  |  |
| Disconnect or deletion call | Not documented in the pages read | The program pages read name no deregistration or deletion call. |  |  |

### Google Health API: 5/8 documented

[The Google Health API guide](https://aifitnessapi.com/google-health-api) lists every page read.

| Check | State | What the vendor’s page says | Quote | Source |
|---|---|---|---|---|
| Self-serve start | Documented | A new OAuth client works unverified, capped at 100 users. | By default, newly created OAuth clients are in an unverified state with a cap of 100 users for both testing and production purposes. | [developers.google.com](https://developers.google.com/health/setup) |
| Sandbox or test mode | Not documented in the pages read | The unverified state is the same for testing and production; the pages read name no separate sandbox. |  |  |
| Public pricing | Not documented in the pages read | The pages read state no price for the API. |  |  |
| Published rate limits | Documented | Default quotas, per project (daily): 86.4M requests / day; per project (minutely): 120,000 requests / minute; per user (minutely): 300 requests / minute. | 300 requests / minute | [developers.google.com](https://developers.google.com/health/rate-limits) |
| Signed webhooks | Documented | Google sends the endpointAuthorization secret you configured in the Authorization header. It also signs the raw JSON with Tink (ECDSA P-256, SHA-256), base64 in GOOGLE-HEALTH-API-SIGNATURE, keys rotated every 30 days and published as a JSON keyset. | the raw JSON payload of every outgoing webhook notification is signed with a private key using Tink's PublicKeySign | [developers.google.com](https://developers.google.com/health/webhooks) |
| PKCE | Not documented in the pages read | Not described on Google's web-server OAuth page, which the OAuth playground follows. |  |  |
| Refresh tokens | Documented | access_type=offline gets a refresh token on the first exchange only. Refresh tokens last until revoked or expired, and Google caps how many it issues per client and user. | Refresh tokens are valid until the user revokes access or the refresh token expires. | [developers.google.com](https://developers.google.com/identity/protocols/oauth2/web-server) |
| Disconnect or deletion call | Documented | batchDelete deletes a user's data points. | Use the `batchDelete` method to delete an array of a user's Fitbit app data. | [developers.google.com](https://developers.google.com/health/endpoints) |

### Oura: 8/8 documented

[The Oura guide](https://aifitnessapi.com/integrate/oura-api) lists every page read.

| Check | State | What the vendor’s page says | Quote | Source |
|---|---|---|---|---|
| Self-serve start | Documented | A new app works for up to 10 users; Oura's approval is needed beyond that. | By default, API Applications have a ten user limit. If you want to release your application to a wider audience, your application needs to be approved. | [cloud.ouraring.com](https://cloud.ouraring.com/docs/) |
| Sandbox or test mode | Documented | A sandbox endpoint with fake data for every data type. | Fake user data that you can access without an Oura account. There is a corresponding sandbox endpoint to each available data type. | [cloud.ouraring.com](https://cloud.ouraring.com/v2/static/json/openapi-1.43.json) |
| Public pricing | Documented | Free for personal and commercial applications. | Yes, the Oura API is free to use for both personal and commercial applications. | [cloud.ouraring.com](https://cloud.ouraring.com/v2/static/json/openapi-1.43.json) |
| Published rate limits | Documented | 5,000 per 5 minutes. | The Oura API is limited to 5000 requests per 5-minute period. | [cloud.ouraring.com](https://cloud.ouraring.com/v2/static/json/openapi-1.43.json) |
| Signed webhooks | Documented | HMAC-SHA256 keyed by your client secret over the x-oura-timestamp value followed by JSON.stringify(body), hex, upper-case, in x-oura-signature. | hmac.update(timestamp + JSON.stringify(body)); | [cloud.ouraring.com](https://cloud.ouraring.com/v2/static/json/openapi-1.43.json) |
| PKCE | Documented | Recommended. code_challenge_method must be S256; the verifier is 43 to 128 characters, hashed with SHA-256 and base64url-encoded without padding. | between 43 and 128 characters long (inclusive), then hash it with SHA256 and encode the digest in base64url format without padding | [cloud.ouraring.com](https://cloud.ouraring.com/docs/authentication) |
| Refresh tokens | Documented | grant_type=refresh_token at the token URL returns a new access token and a new refresh token; each refresh token works once. | The refresh token is single-use, meaning it is invalidated after being used. | [cloud.ouraring.com](https://cloud.ouraring.com/docs/authentication) |
| Disconnect or deletion call | Documented | A token revocation endpoint. | https://api.ouraring.com/oauth/revoke?access_token={access_token} | [cloud.ouraring.com](https://cloud.ouraring.com/docs/authentication) |

### Polar AccessLink: 5/7 documented

[The Polar AccessLink guide](https://aifitnessapi.com/integrate/polar-api) lists every page read.

| Check | State | What the vendor’s page says | Quote | Source |
|---|---|---|---|---|
| Self-serve start | Documented | Any registered Polar Flow user can create an API client. | Any registered Polar Flow user can create API client to AccessLink by filling application details at https://admin.polaraccesslink.com | [polar.com](https://www.polar.com/accesslink-api/) |
| Sandbox or test mode | Not documented in the pages read | The AccessLink reference read names no sandbox or test environment. |  |  |
| Public pricing | Documented | Free of charge at the moment; Polar reserves the right to charge. | At the moment Polar offers the use and activation of Polar API's free of charge. | [polar.com](https://www.polar.com/en/legal/polar-api-agreement) |
| Published rate limits | Documented | 500 + 20 per user per 15 minutes; 5,000 + 100 per user per 24 hours. | 15min rate limit: 500 + number of users x 20 | [polar.com](https://www.polar.com/accesslink-api/) |
| Signed webhooks | Documented | HMAC-SHA256 of the payload, keyed by the signature_secret_key returned once when you create the webhook, hex, in Polar-Webhook-Signature; the event type is in Polar-Webhook-Event. | Hash-based message authentication code (HMAC SHA-256) is used to sign every webhook payload Accesslink sends. | [polar.com](https://www.polar.com/accesslink-api/) |
| PKCE | Not documented in the pages read | Not mentioned on the AccessLink reference. |  |  |
| Refresh tokens | Not applicable | No refresh flow is documented: the token response lists no refresh_token, and the reference says access tokens do not expire unless revoked. | Access tokens will not expire unless explicitly revoked by partners or users. | [polar.com](https://www.polar.com/accesslink-api/) |
| Disconnect or deletion call | Documented | Deregistering a user revokes the token. | When partner wishes no longer to receive user data, user can be de-registered. This will revoke the access token authorized by user. | [polar.com](https://www.polar.com/accesslink-api/swagger.yaml) |

### Strava: 6/8 documented

[The Strava guide](https://aifitnessapi.com/integrate/strava-api) lists every page read.

| Check | State | What the vendor’s page says | Quote | Source |
|---|---|---|---|---|
| Self-serve start | Documented | Any registered Strava user can create an application. | Any registered Strava user can obtain an access_token by first creating an application at https://www.strava.com/settings/api . | [developers.strava.com](https://developers.strava.com/docs/) |
|  |  | Strava calls a Strava subscription a prerequisite for creating an app. | A Strava subscription is a prerequisite for creating an app. | [developers.strava.com](https://developers.strava.com/docs/getting-started/) |
| Sandbox or test mode | Documented | New apps start in single-player mode, to build and test against your own data. | All new applications start in single-player mode. This is the default state where only your own Strava account can authenticate with the app, which lets you build and test your integration against your own data. | [developers.strava.com](https://developers.strava.com/docs/getting-started/) |
| Public pricing | Documented | Currently at no charge. | Access to and use of the Strava API Materials and the Strava Platform are currently provided at no charge. | [strava.com](https://www.strava.com/legal/api) |
| Published rate limits | Documented | 100 non-upload, per 15 minutes; 1,000 non-upload, per day; 200 overall, per 15 minutes; 2,000 overall, per day (New app (default); 2 tiers published). | rate limit allows 100 requests every 15 minutes, with up to 1,000 requests per day. | [developers.strava.com](https://developers.strava.com/docs/rate-limits/) |
| Signed webhooks | Not documented in the pages read | No signature is documented for event POSTs. Subscription validation is a GET with hub.mode, hub.challenge and hub.verify_token; echo hub.challenge as JSON. | The query string of this GET request will contain a "hub.challenge" field that you must use to validate your callback address. | [developers.strava.com](https://developers.strava.com/docs/webhooks/) |
| PKCE | Not documented in the pages read | Not mentioned on Strava's Authentication page. |  |  |
| Refresh tokens | Documented | Refresh with grant_type=refresh_token. If the current access token expires in more than an hour, the same one comes back; once a new refresh token is returned the old one stops working. | Once a new refresh token is returned, the older refresh token is invalidated immediately. | [developers.strava.com](https://developers.strava.com/docs/authentication/) |
| Disconnect or deletion call | Documented | Deauthorizing invalidates every token the app holds for the athlete. | Applications can revoke access to an athlete’s data. This will invalidate all refresh tokens and access tokens that the application has for the athlete | [developers.strava.com](https://developers.strava.com/docs/authentication/) |

### Suunto: 2/8 documented

[The Suunto guide](https://aifitnessapi.com/integrate/suunto-api) lists every page read.

| Check | State | What the vendor’s page says | Quote | Source |
|---|---|---|---|---|
| Self-serve start | The docs say otherwise | Applications are reviewed weekly; the wait is up to two weeks. | The applications are reviewed on weekly bases, so you have to wait few days prior getting the acceptance. There is maximum two week waiting period. | [apizone.suunto.com](https://apizone.suunto.com/) |
| Sandbox or test mode | Documented | A Development API with every endpoint and smaller request limits. | The Development API includes all the endpoints but has smaller request limits. | [apizone.suunto.com](https://apizone.suunto.com/) |
| Public pricing | Documented | Suunto does not charge for the API. | We do not charge from the use of the API. | [apizone.suunto.com](https://apizone.suunto.com/) |
| Published rate limits | Not documented in the pages read | Suunto says the developer API is rate-limited and has smaller limits than production, but publishes neither number. | There developer API has same capabilities as the production API. However, the number of calls you can do with developer API are rate-limited. | [apizone.suunto.com](https://apizone.suunto.com/faq) |
| Signed webhooks | Not documented in the pages read | Not documented on Suunto's FAQ. The webhook address is set in your app's OAuth settings in Suunto API Zone and must be publicly reachable. | You can setup the webhook in your app oauth settings under your profile in Suunto Apizone | [apizone.suunto.com](https://apizone.suunto.com/faq) |
| PKCE | Not documented in the pages read | Not mentioned on Suunto's quick-start or FAQ. |  |  |
| Refresh tokens | Not documented in the pages read | The token response includes a refresh_token, but the pages read here document no refresh request, so the OAuth playground prints none. | "refresh_token": "<JWT_REFRESH_TOKEN>" | [apizone.suunto.com](https://apizone.suunto.com/how-to-start) |
| Disconnect or deletion call | Not documented in the pages read | The API Zone pages read name no deauthorization or deletion call. |  |  |

### Terra: 4/6 documented

[The Terra guide](https://aifitnessapi.com/integrate/terra-api) lists every page read.

| Check | State | What the vendor’s page says | Quote | Source |
|---|---|---|---|---|
| Self-serve start | Not documented in the pages read | The pages read describe the dashboard's credentials but not whether a new account is reviewed. |  |  |
| Sandbox or test mode | Documented | Testing and staging environments, each capped at 50 users. | Note that for testing & staging, there is a user limit of 50 users on each environment. | [docs.tryterra.co](https://docs.tryterra.co/unified-api/integration-setup/understanding-terra-environments) |
| Public pricing | Documented | Published plans from $399 a month billed annually. | Subscriptions start from $399 per month billed annually, or $499 per month billed monthly. That includes 100,000 Unified API credits each month, and you only pay extra if your usage goes beyond them. | [tryterra.co](https://tryterra.co/pricing) |
| Published rate limits | Documented | 6,000 requested days per hour, per user. | your code has issued requests for this user totalling more than 6,000 days in the current hour | [docs.tryterra.co](https://docs.tryterra.co/reference/health-and-fitness-api/rate-limits) |
| Signed webhooks | Documented | terra-signature: t=<timestamp>,v1=<signature>; HMAC-SHA256 keyed by the webhook's signing secret over the timestamp, a "." and the raw body. Ignore schemes other than v1. | Compute an HMAC with the SHA256 hash function. Use the endpoint’s signing secret as the key, and use the signed_payload string as the message. | [docs.tryterra.co](https://docs.tryterra.co/unified-api/integration-setup/setting-up-data-destinations/webhooks) |
| PKCE | Not applicable | Your server calls Terra with a dev-id and an API key; the pages read describe no OAuth client on your side. | dev-id string Required Your developer ID for authentication and tracking | [docs.tryterra.co](https://docs.tryterra.co/reference) |
| Refresh tokens | Not applicable | Your server calls Terra with a dev-id and an API key; the pages read describe no OAuth client on your side. | dev-id string Required Your developer ID for authentication and tracking | [docs.tryterra.co](https://docs.tryterra.co/reference) |
| Disconnect or deletion call | Not documented in the pages read | Terra sends a deauth event when a user disconnects; the pages read name no call your app makes for it. | deauth Occurs when a user deauthenticates through the Terra | [docs.tryterra.co](https://docs.tryterra.co/reference/health-and-fitness-api/event-types) |

### Wahoo: 6/8 documented

[The Wahoo guide](https://aifitnessapi.com/integrate/wahoo-api) lists every page read.

| Check | State | What the vendor’s page says | Quote | Source |
|---|---|---|---|---|
| Self-serve start | The docs say otherwise | Wahoo limits the API to those who request it. | Wahoo Fitness is currently limiting use of the API to those who request it, as well as provide more information about the scopes involved and the purpose of the application. | [developers.wahooligan.com](https://developers.wahooligan.com/cloud) |
| Sandbox or test mode | Documented | Sandbox and Production are separate applications. | Sandbox and Production are separate applications. A Sandbox app cannot later be converted into a Production app. | [developers.wahooligan.com](https://developers.wahooligan.com/cloud) |
| Public pricing | Documented | Currently at no charge; Wahoo reserves the right to charge. | Access to and use of the Wahoo API Materials and Wahoo Platform are currently provided at no charge. | [wahoofitness.com](https://www.wahoofitness.com/wahoo-api-agreement) |
| Published rate limits | Documented | 25 per 5 minutes; 100 per hour; 250 per day (Sandbox; 2 tiers published). | Requests every 5 Min: 25 200 | [cloud-api.wahooligan.com](https://cloud-api.wahooligan.com/) |
| Signed webhooks | The docs say otherwise | No signature. Wahoo sends the webhook_token you set in the app's webhook settings inside the JSON body; ignore any request without it. | Specify a token that you would like us to send. Any request that doesn't include this token should be ignored. | [cloud-api.wahooligan.com](https://cloud-api.wahooligan.com/) |
| PKCE | Documented | Supported once the app's Confidential field is set to No; S256 or plain. With PKCE the token and refresh calls send code_verifier instead of client_secret. | The Wahoo API does allow users to use the PKCE flow for authorization. | [cloud-api.wahooligan.com](https://cloud-api.wahooligan.com/) |
| Refresh tokens | Documented | Refresh returns a new access and refresh token. The previous pair is revoked only when an API call uses the new access token, so refresh just before a request: apps are limited to 10 unrevoked tokens per user. | Access tokens should only be refreshed immediately prior to making an API request. | [cloud-api.wahooligan.com](https://cloud-api.wahooligan.com/) |
| Disconnect or deletion call | Documented | DELETE /v1/permissions deauthorizes the user. | DELETE https://api.wahooligan.com/v1/permissions | [cloud-api.wahooligan.com](https://cloud-api.wahooligan.com/) |

### WHOOP: 7/8 documented

[The WHOOP guide](https://aifitnessapi.com/integrate/whoop-api) lists every page read.

| Check | State | What the vendor’s page says | Quote | Source |
|---|---|---|---|---|
| Self-serve start | Documented | Build and test on the 10-member Sandbox tier without a request. | Every new app starts on the Sandbox tier, which allows up to 10 WHOOP members to connect. You can build and test on Sandbox without submitting a request. When you need more members, request the next tier from the Developer Dashboard . | [developer.whoop.com](https://developer.whoop.com/docs/developing/app-approval/) |
|  |  | A WHOOP membership is required to develop an app. | You must have a WHOOP membership to develop an app on the Developer Platform. Your WHOOP account is also your WHOOP developer login. | [developer.whoop.com](https://developer.whoop.com/docs/developing/overview/) |
| Sandbox or test mode | Documented | Every new app starts on the Sandbox tier. | Every new app starts on the Sandbox tier, which allows up to 10 WHOOP members to connect. | [developer.whoop.com](https://developer.whoop.com/docs/developing/app-approval/) |
| Public pricing | Documented | Currently at no charge, with notice before that changes. | Access to and use of the APIs is currently provided at no charge. In the event WHOOP decides to start charging for use of the APIs in the future, WHOOP will provide Company with prior notice. | [developer.whoop.com](https://developer.whoop.com/api-terms-of-use/) |
| Published rate limits | Documented | 100 per minute; 10,000 per day. | All clients are subject to two sets of rate limiting for requests. By default, clients may only send: 100 requests per minute. 10,000 requests per day. | [developer.whoop.com](https://developer.whoop.com/docs/developing/rate-limiting/) |
| Signed webhooks | Documented | Base64 of HMAC-SHA256, keyed by your client secret, over the X-WHOOP-Signature-Timestamp value (milliseconds since epoch) followed by the raw body, in X-WHOOP-Signature. | calculated_signature_string = base64Encode(HMACSHA256(timestamp_header + raw_http_request_body, client_secret)) | [developer.whoop.com](https://developer.whoop.com/docs/developing/webhooks/) |
| PKCE | Not documented in the pages read | Not mentioned on the WHOOP OAuth page or API reference read here. |  |  |
| Refresh tokens | Documented | Using the refresh token invalidates the existing access tokens; the refresh token in the response replaces the old one, and of two simultaneous refreshes only the first succeeds. | Existing access tokens are invalidated once your app uses the refresh token to generate a new access token. | [developer.whoop.com](https://developer.whoop.com/docs/developing/oauth/) |
| Disconnect or deletion call | Documented | The revokeUserOauthAccess endpoint. | To revoke an access token, you can use the revokeUserOauthAccess API endpoint. | [developer.whoop.com](https://developer.whoop.com/docs/developing/oauth/) |

### Withings: 5/8 documented

[The Withings guide](https://aifitnessapi.com/integrate/withings-api) lists every page read.

| Check | State | What the vendor’s page says | Quote | Source |
|---|---|---|---|---|
| Self-serve start | Documented | No prerequisites to get access. | There are no prerequisites, and free access is provided. | [developer.withings.com](https://developer.withings.com/developer-guide/v3/integration-guide/public-health-data-api/developer-account/create-your-accesses-no-medical-cloud/) |
| Sandbox or test mode | Documented | mode=demo signs in a demo user. | you can use the optional parameter mode with the value demo . You will be redirected to the authorisation page and automatically logged in as a demo user. | [developer.withings.com](https://developer.withings.com/developer-guide/v3/integration-guide/public-health-data-api/get-access/oauth-authorization-url/) |
| Public pricing | Documented | Free access on the public API. | There are no prerequisites, and free access is provided. | [developer.withings.com](https://developer.withings.com/developer-guide/v3/integration-guide/public-health-data-api/developer-account/create-your-accesses-no-medical-cloud/) |
|  |  | Withings' developer site, as captured on October 16, 2026, said Withings+ becomes required on the free plan from October 12, 2026. | Withings+ becomes required on the Start for Free API plan from October 12, 2026. | [web.archive.org](https://web.archive.org/web/20261016222934id_/https://developer.withings.com/) |
| Published rate limits | Documented | 120 per minute. | The standard Withings API enforces a 120 requests-per-minute limit across your application | [developer.withings.com](https://developer.withings.com/developer-guide/v3/integration-guide/public-health-data-api/data-api/notifications/notification-overview/) |
| Signed webhooks | The docs say otherwise | No body signature. Append a secret query parameter to the callback URL (Withings' example: ?token=<random-secret>) and check it, plus an allowlist of the IP ranges Withings publishes as DNS TXT records. | Your handler reads token from the incoming request and rejects any value that doesn't match the secret you configured. | [developer.withings.com](https://developer.withings.com/developer-guide/v3/integration-guide/public-health-data-api/data-api/notifications/notification-overview/) |
| PKCE | Not documented in the pages read | Not mentioned on the Withings authorization or token pages. |  |  |
| Refresh tokens | Documented | Withings says to call the same requesttoken service with the refresh token and always keep the new refresh token, but its snippet shows only the code exchange, so the OAuth playground prints no refresh command rather than guess its parameters. | To request a new access_token using the refresh_token, call the requesttoken webservice | [developer.withings.com](https://developer.withings.com/developer-guide/v3/integration-guide/public-health-data-api/get-access/access-and-refresh-tokens-no-recover/) |
| Disconnect or deletion call | Not documented in the pages read | The developer-guide pages read name no revoke or deletion call. |  |  |

## How the index is built

Four checks are read straight from data the site already keeps for its tools. PKCE and refresh tokens come from the [OAuth playground](https://aifitnessapi.com/tools/oauth-playground)’s per-vendor facts; published rate limits from the [rate-limit calculator](https://aifitnessapi.com/tools/rate-limit-calculator) (and Google’s generated quota table); signed webhooks from the [webhook payload library](https://aifitnessapi.com/webhooks) and the check each vendor gets in the [webhook verifier](https://aifitnessapi.com/tools/webhook-verifier). When one of those changes, the index changes with it at the next build.

The other four, self-serve start, sandbox, public pricing and a disconnect or deletion call, are one quote each, copied verbatim from an evidence file the site already holds for an integration guide or a pricing page. Those files are re-read against the live vendor pages every week by the source-quotes check, so a sentence a vendor removes turns the check red.

The count is documented basics over the basics that apply. A basic the pages read do not mention scores nothing and is labeled as not documented: it is a statement about what was read, not a finding that the vendor lacks it. Nothing is weighted and nothing is ranked; the table is alphabetical. KinesteX, which funds this site, makes a motion SDK rather than a wearable-data API, so it is not in the index.

### Not scored

- [Apple HealthKit, Health Connect and the Samsung Health Data SDK](https://aifitnessapi.com/integrate): On-device frameworks: there is no developer account, request limit, webhook or OAuth client to check.
- [Fitbit Web API](https://aifitnessapi.com/fitbit-api-shutdown): Google set its turn-off for November 2, 2026; its successor, the Google Health API, is scored.
- [ROOK, Junction, Spike, Thryve, Sahha and Open Wearables](https://aifitnessapi.com/pricing/health-data-aggregator-pricing): The site has read their pricing pages but not their developer documentation in the depth the other eight checks need, so a score would measure our reading, not their docs.

Every vendor’s count is also a README badge, and every API in the graveyard has a status badge: [embeds and badges](https://aifitnessapi.com/badges#status-badges).

## Frequently asked questions

### How is the openness score counted?

One point for each of the eight basics the vendor's own pages document, divided by the basics that apply to that API. Nothing is weighted, so a sandbox counts the same as PKCE. A basic counts only when a quoted vendor sentence states it; Polar AccessLink is scored out of 7 and Terra is scored out of 6, because some basics do not apply to how they authenticate or issue tokens.

### Does “not documented” mean a vendor lacks that feature?

No. It means the pages this site read for its integration guides, OAuth playground, webhook library and rate-limit calculator do not state it. A vendor may support PKCE or sign webhooks without saying so on those pages. Where a vendor's page does say something else, such as access needing approval or a shared token instead of a signature, the cell quotes it and is marked separately.

### Which wearable APIs describe PKCE in their OAuth documentation?

2 of the 12 APIs here with an OAuth flow: Oura and Wahoo. The others' authorization pages, as read for the OAuth playground, do not mention it.

### Which wearable APIs sign the webhooks they send?

Google Health API, Oura, Polar AccessLink, Terra and WHOOP: 5 of 13. Wahoo and Withings document a shared token instead, which proves the sender knows a secret but not that the body is unchanged.

### Why are HealthKit and Health Connect not in the openness index?

They are on-device frameworks. There is no developer account to apply for, request limit, webhook or OAuth client to check, so the eight basics do not describe them.

By AIFitnessAPI. Cite as: AIFitnessAPI, “The fitness API openness index,” https://aifitnessapi.com/openness-index, compiled November 6, 2026.

## Next step

Turning this into a choice of API:

- [The Best Wearable Fitness & Health-Data APIs (2026)](https://aifitnessapi.com/fitness-apis/wearable-data-apis)
- [The Best Wearable Health-Data Aggregator APIs (2026)](https://aifitnessapi.com/fitness-apis/health-data-aggregator-apis)
- [Health data aggregator API pricing: what Terra, Junction, Rook, Spike and four more charge](https://aifitnessapi.com/pricing/health-data-aggregator-pricing)
