Garmin Health API Analysis

SCRUM-84, Option B — Complete technical analysis for removing Strava dependency

1. Executive Summary

The Garmin Connect Developer Program provides official APIs for accessing cycling activity data including GPS tracks, speed, heart rate, power, cadence, and elevation — all fields that Strava's club endpoint lacks. The program is free, approval takes 2 business days, and production keys have no rate limits. This is the recommended path for Garmin users in the club.

Recommendation: Apply to Garmin Developer Program

Free, fast approval, complete data access, push-based architecture. Covers the majority of DCC members who use Garmin devices.

2. Data Field Comparison

FieldStrava Club APIGarmin Activity APIImpact
DistanceYes (meters)Yes (meters)Equivalent
DurationYes (moving_time)Yes (seconds)Equivalent
ElevationYes (total gain)Yes (ascent + descent)Garmin has descent too
Activity TypeYes (type, sport_type)Yes (activityType)Equivalent
Start Date/TimeNoYes (startTimeInSeconds + offset)Fixes SCRUM-69 — no more fingerprint workaround
Average SpeedNoYes (averageSpeedInMetersPerSecond)Fixes SCRUM-63 — device-measured, not calculated
GPS TrackNoYes (full route via FIT file)Enables real route-based POIs (SCRUM-83)
Heart RateNoYes (avg, max, zones with durations)New: effort/intensity analytics
PowerNoYes (avg, max, by zone)New: power-based coaching
CadenceNoYes (avg, max RPM)New: pedalling efficiency analysis
TemperatureNoYes (ambient from device)New: real weather, not estimated
FIT File DownloadNoYes (raw binary file)Complete second-by-second data
Athlete NameYesYes (from OAuth profile)Equivalent
Rate Limits100/15min, 1000/dayNone (production key)Unlimited refreshes

3. Architecture: Push-Based Webhook

Garmin Device
records ride
Garmin Connect
sync via Bluetooth/WiFi
Garmin Cloud
sends Ping POST
Cloudflare Worker
/garmin-webhook
Worker fetches
activity details + FIT
KV Cache
aggregated stats
How the Ping/Pull Architecture Works
  1. User completes a ride and syncs their Garmin device
  2. Garmin processes the activity and sends an HTTPS POST Ping notification to our webhook URL
  3. Our Worker receives the ping containing the user ID and activity ID
  4. Worker fetches the activity details (summary + FIT file) from Garmin's API
  5. Worker parses the data, extracts all metrics (GPS, speed, HR, power, cadence, elevation)
  6. Worker aggregates into club stats and stores in KV — same format as current /club-data response
  7. iOS app fetches from /club-data as before — no app changes needed for basic stats

4. Partner Application Process

StepDetailsTimeline
1. ApplySubmit application at developer.garmin.com/gc-developer-program. Requires business name, use case description, expected user count.30 minutes
2. ReviewGarmin reviews the application. Most approvals within 2 business days.1-2 days
3. CredentialsReceive Consumer Key + Consumer Secret. Access to evaluation environment + full API docs.Immediate after approval
4. IntegrationBuild OAuth flow, webhook handler, FIT parser. Test with 2+ real Garmin accounts.1-2 weeks dev work
5. VerificationPass Partner Verification Tool: (a) only call summary endpoints after Ping, (b) webhook responds HTTP 200, (c) data from 2+ real accounts.1-2 days testing
6. Production KeyReceive production key with no rate limits. Go live.Immediate after verification

Total timeline: ~2-3 weeks from application to production.

5. Authentication Flow (OAuth 2.0)

User Authorisation (One-Time)
  1. User taps "Connect Garmin" in the DCC app
  2. App opens Garmin's OAuth page in a browser: https://connect.garmin.com/oauthConfirm
  3. User logs in to Garmin Connect and grants permission
  4. Garmin redirects back to the app with an authorisation code
  5. Worker exchanges the code for an access token (valid 3 months) + refresh token
  6. Tokens stored in KV per user. Auto-refresh when expired — no user action needed.
  7. From this point, all rides sync automatically via webhook. User never touches it again.

6. Implementation Plan

PhaseWorkEffortFiles
Phase 1Apply to Garmin Developer Program30 minNone (web form)
Phase 2Add POST /garmin-webhook endpoint to Worker. Handle Ping notifications, fetch activity details, parse into club data format.2-3 dayscloudflare-club-data-worker.js
Phase 3Add FIT file parser to Worker (binary format). Extract GPS track, speed, HR, power, cadence per data point.2-3 daysNew: fit-parser.js or use garmin-fit-parser npm
Phase 4Add "Connect Garmin" button in iOS app. OAuth flow via ASWebAuthenticationSession. Store tokens via Worker.1-2 daysNew: GarminAuthView.swift
Phase 5Merge Garmin data with existing Strava data in /club-data response. Both sources feed the same stats.1-2 dayscloudflare-club-data-worker.js
Phase 6Partner Verification Tool + production key1-2 daysTesting only

Total effort: ~2 weeks of development + 2 days for Garmin approval.

7. Privacy & GDPR

Requirements

8. Risk Assessment

RiskLikelihoodImpactMitigation
Garmin rejects applicationLowHighApplication is free and straightforward. Cycling club use case is standard.
FIT parsing complexityMediumMediumUse established npm package (garmin-fit-parser). FIT SDK is well-documented.
User adoption frictionMediumMediumOne-time OAuth. After that, fully automatic. Strava stays as fallback.
Garmin API changesLowMediumOfficial API with versioning. More stable than Strava's undocumented club endpoint.
GDPR compliance burdenMediumLowStandard consent flow. Same pattern as existing Strava OAuth (but we use club code now).

9. What This Unlocks

Features enabled by Garmin data that are impossible with Strava

10. Recommendation

Proceed with Official Garmin API

Apply today. Free, 2-day approval, 2 weeks to integrate. Keeps Strava as fallback. Unlocks GPS, HR, power, cadence — transforming the app from a stats viewer into a proper training platform.