Guide · 9 min read
Garmin Health API access: what it takes and what to do meanwhile
Why Garmin data is gated behind a business agreement, what the Health and Activity APIs actually provide, and how to design so Garmin can be added later.
Published · By the WearLink engineering team

Ask a room of fitness product teams which wearable their users request most and Garmin comes up every time. Ask which one was missing at launch and the answer is usually the same. This is not because the integration is technically impossible. It is because access to Garmin data is a business process before it is a technical one, and teams discover that after the roadmap has been written.
This guide explains what Garmin actually offers developers, what obtaining access involves, how to design your product so Garmin can be added later without a rewrite, and what to do for your users in the meantime. It is written by engineers who have implemented the adapter and are currently in the access process ourselves.
What Garmin actually offers developers
Garmin exposes wearable data to third parties through its developer programme, and the two parts most product teams care about are usually described as the Health API and the Activity API.
The Health API is the wellness side: daily summaries (steps, active time, calories), sleep with stages, heart rate variability, stress and Garmin’s body battery style energy metric, respiration, and pulse oximetry where the device supports it. This is the data you need for a recovery, readiness or general wellbeing product.
The Activity API is the workout side: summaries of recorded activities (runs, rides, swims, strength sessions and so on) and, where enabled, the detailed data derived from the FIT file the device recorded. This is what a training, coaching or endurance product needs.
The delivery model matters more than the list of data types. Garmin is push-based. Once a user has authorised your application, Garmin sends new data to an endpoint you register. There is no general polling model for most data; you do not ask Garmin “what is new since yesterday”. Historical data on first connect is handled through a separate backfill mechanism that also delivers asynchronously to your endpoint. Authentication on the Health API has historically used OAuth 1.0a request signing rather than the bearer tokens most teams are used to.
Two consequences fall out of the push model. First, your ingestion endpoint has to be reliable, because a delivery you miss is not sitting in a queue you can drain later. Second, your data model has to be idempotent, because a delivery you receive twice must not become two records. Both of these are design choices you can make now, before you have access.
What the access process involves
Unlike Strava, Fitbit or Oura, where a developer can register an application and start testing the same day, Garmin gates data access behind a business relationship. In broad terms the process involves:
- A business application through Garmin’s developer programme, identifying your organisation rather than an individual developer.
- A description of the use case: what product the data feeds, which data types you need, who the end users are, and how the data will be stored, protected and deleted.
- A commercial agreement whose terms are set by Garmin and vary by organisation.
- Review and provisioning of production credentials, on a timeline Garmin controls.
We do not know, and will not guess at, the fees or turnaround that apply to your organisation. What we can say is that approval is a real gate: Garmin reviews applications and does not approve all of them, and a thin or vague use case description makes rejection more likely. Treat the application as a document worth writing properly.
Where WearLink stands. The Garmin adapter is implemented, including the OAuth 1.0a signing, push ingestion and the normalisation of Garmin’s data types into the same objects every other provider produces. Production credentials are pending, so Garmin is listed as onboarding on the provider status page and is not connectable through WearLink today. If your organisation already holds its own Garmin developer credentials, WearLink can run the adapter with those credentials; the docs describe bringing your own provider credentials and the contact form has a category for it.
Design so Garmin can be added later
The expensive mistake is not the missing integration. It is building the first two integrations in a way that assumes they are the only two, so that the third one forces a schema migration and a rewrite of the sync layer. Five decisions avoid that.
1. A provider-agnostic user model
Your user is your user. A provider connection is an attribute of that user, not the other way round. Store a per-user list of connected providers (with tokens, scopes and connection state) rather than a per-provider table of users. A person with a Garmin watch, a Strava account and an iPhone is one user with three sources, and adding Garmin to that list should be a row insert, not a new join table.
2. Normalised workout and sleep objects
Define your own workout, sleep, daily summary and recovery objects and map every provider into them at the edge. The rest of your system should never see a Garmin-shaped or Strava-shaped payload. When Garmin lands, the only new code is the mapping. The illustrative shape below is the idea, not a WearLink schema.
{
"type": "workout",
"user_id": "usr_...", // your user, not the provider's
"provider": "strava", // later: "garmin"
"provider_record_id": "1234567", // idempotency key, per provider
"source_device": "Garmin Forerunner",
"started_at": "2026-08-30T06:12:00+05:30",
"duration_s": 2710,
"distance_m": 8940,
"sport": "run"
}3. Idempotent ingestion keyed on the provider record id
Every provider gives each record an identifier. Store it alongside the provider name and enforce uniqueness on the pair. A push you receive twice, a backfill that overlaps a live delivery, or a retry from your own queue then collapses to one record. This is the single most important property for a push-based provider and it is free to add on day one.
4. A cross-provider dedup rule for the same physical workout
Many Garmin users also sync to Strava. Once both are connected, the same run will arrive twice with different provider record ids, so the idempotency key alone will not catch it. You need a rule that recognises the same physical activity from two sources.
// Illustrative. Same person, same sport, start times within a small
// window and distance within a small tolerance => one physical workout.
function sameWorkout(a, b) {
return a.user_id === b.user_id
&& a.sport === b.sport
&& Math.abs(a.started_at - b.started_at) <= 120 * 1000
&& Math.abs(a.distance_m - b.distance_m) <= 0.02 * Math.max(a.distance_m, b.distance_m);
}
// Keep one canonical record; retain the other as a linked source.
// Prefer the provider that owns the original device when both exist.Keep one canonical record and retain the other as a linked source rather than discarding it; users occasionally want to know which app a session came from, and you may prefer the richer copy when detailed streams differ. Decide the preference order now (device owner first is a sensible default) so that switching Garmin on does not silently double every historical run.
5. Sources map onto needs, not the other way round
Write down what your product actually needs and which connectable source covers it today. The table is illustrative and your rows will differ.
| Data you need | Interim source today | When Garmin lands |
|---|---|---|
| Workouts (runs, rides, swims) | Strava (cloud OAuth), or Apple Health / Health Connect via the mobile SDK | Garmin activities into the same workout object; dedup against the Strava copy |
| Sleep and sleep stages | Oura, WHOOP, Fitbit, Withings | Garmin sleep summaries, same sleep object |
| HRV and recovery | Oura, WHOOP | Garmin HRV; body battery normalised into the stress category |
| Steps and daily activity | Fitbit, Withings, or Apple Health / Health Connect via the mobile SDK | Garmin daily summaries |
| Stress and body battery | No direct equivalent; Oura and WHOOP recovery scores cover part of the need | Garmin stress and body battery |
| SpO2 (where the device supports it) | Fitbit, Withings, device dependent | Garmin pulse ox, device dependent |
The point of the exercise is that most of the left-hand column has a source today. The gap is narrower than “we do not have Garmin” suggests, and it is mostly the wellness metrics that only a Garmin device measures for Garmin users.
What to do meanwhile
In rough order of how much of the gap each step closes:
- Connect Strava for activities. Strava is connectable now through cloud OAuth, and a large share of Garmin users already sync their activities to it. For a training or coaching product this covers the bulk of what you would have wanted from the Activity API. Make the Strava connect step prominent in onboarding and tell Garmin users explicitly that this is how to get their workouts in. See the workouts data page for what the normalised object carries.
- Connect Oura, WHOOP, Fitbit or Withings for sleep and recovery. All four are connectable now. They will not give you sleep from a Garmin watch, but they cover users on those devices with the same sleep and HRV objects Garmin will later populate, so the product logic you build against them carries over unchanged.
- Read Apple Health and Health Connect if you ship a mobile app. When the user has enabled it in Garmin Connect, the Garmin app writes to Apple Health on iOS and Health Connect on Android. Reading those stores through the mobile SDK is an on-device route for Garmin-originated workouts, steps, heart rate and sleep. It depends on a setting the user controls, so some users will have it and some will not; design the connect screen to explain the option rather than assuming it.
- Ship the dedup rule before you need it. A user with Strava connected and Health Connect enabled will already produce two copies of the same run. Solving that now means Garmin arriving as a third copy is a non-event.
- Apply to Garmin in parallel. If Garmin is on your roadmap, start the developer programme application now rather than after the interim sources ship. The elapsed time is Garmin’s, not yours, and it runs while you build.
How WearLink handles it
WearLink is a single API over multiple wearable providers, and the design choices above are the ones we made. Every provider maps into the same normalised objects, a user holds a list of connections, ingestion is idempotent on the provider record id, and the same webhook events (workout.created, sleep.created, stress.created, heart_rate_variability.created, steps.created) fire regardless of which provider produced the record. The Garmin adapter is implemented against that contract, including OAuth 1.0a signing and push ingestion, and is waiting on production credentials. Until then it is listed as onboarding on the provider status page, Strava, Oura, WHOOP, Fitbit and Withings are connectable through cloud OAuth, and Apple Health, Health Connect and Samsung Health are available on-device through the mobile SDK. Organisations that already hold Garmin credentials can run the adapter with them. The full Garmin integration page lists the data types and the gotchas we hit while building it.