Understanding the technical difference between platform APIs (HealthKit, Health Connect) and direct device OAuth is critical for choosing the right health data aggregation strategy.

The Core Question

Do you integrate with platform APIs that unify device data (HealthKit on iOS, Health Connect on Android)? Or do you build direct OAuth connections to each device manufacturer (Fitbit, Garmin, Oura, etc.)?

This decision impacts coverage, implementation complexity, data precision, and long-term maintenance burden.

The Two Approaches Explained

📱 Platform API Approach

What it is: Use Apple HealthKit (iOS) and Google Health Connect (Android) as unified data sources

Data flow:

  1. Wearables sync to HealthKit/Health Connect
  2. Your app requests permission once
  3. Data flows from platform API to your app
  4. No direct device authentication needed

Supported by: Sahha, Rook, some Terra implementations

🔗 Direct OAuth Approach

What it is: Build individual OAuth integrations with each device manufacturer

Data flow:

  1. User authenticates with Fitbit, Garmin, Oura, etc.
  2. Your app stores OAuth tokens per device
  3. Poll each manufacturer API separately
  4. Manage token refresh for each connection

Supported by: Terra (300+ devices), custom implementations

Technical Comparison

Factor Platform API (HealthKit/Health Connect) Direct OAuth (Device-by-device)
Implementation Complexity Low - 2 platform SDKs (iOS + Android) Very High - 300+ device-specific APIs
User Coverage (iOS) ~70% (any device syncing to HealthKit) ~30% (only supported devices)
User Coverage (Android) ~50% (Health Connect adoption growing) ~30% (only supported devices)
Onboarding Friction 1 permission prompt Device selection + OAuth flow per device
Token Management Platform handles refresh Manual refresh per device (hourly/daily)
Data Latency Hours (device → platform → app) Minutes (device → API → app)
Data Precision Platform-normalized (some loss) Device-native (full fidelity)
Maintenance Burden Low - Platform updates handled by OS High - Track 300+ API changes
Device Support Automatic (any HealthKit/Health Connect device) Manual (build each integration separately)
Smartphone Data ✓ Built-in (accelerometer, etc.) ✗ Not available

Code Examples: Implementation Complexity

Platform API Approach (HealthKit - iOS)

Step 1: Request permissions (one-time)

import HealthKit

let healthStore = HKHealthStore()
let typesToRead: Set = [
  HKObjectType.quantityType(forIdentifier: .stepCount)!,
  HKObjectType.categoryType(forIdentifier: .sleepAnalysis)!,
  HKObjectType.quantityType(forIdentifier: .heartRate)!
]

healthStore.requestAuthorization(toShare: nil, read: typesToRead) { success, error in
  // Access granted - data flows automatically
}

Step 2: Query data (universal for all devices)

let stepType = HKQuantityType.quantityType(forIdentifier: .stepCount)!
let query = HKStatisticsQuery(quantityType: stepType, ...) { _, result, _ in
  let steps = result?.sumQuantity()?.doubleValue(for: .count())
  // Works for Apple Watch, Fitbit, Garmin, etc. - all via HealthKit
}
healthStore.execute(query)

Total implementation: ~200 lines of code for full HealthKit integration

Direct OAuth Approach (Fitbit + Garmin + Oura)

Step 1: Build OAuth flow for Fitbit

// Redirect to Fitbit OAuth
const fitbitAuthUrl = `https://www.fitbit.com/oauth2/authorize?
  client_id=${FITBIT_CLIENT_ID}&
  response_type=code&
  scope=activity heartrate sleep`

// Handle callback, exchange code for token
const tokenResponse = await fetch('https://api.fitbit.com/oauth2/token', {
  method: 'POST',
  headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
  body: `grant_type=authorization_code&code=${code}&...`
})

// Store access_token + refresh_token
// Set up refresh logic (expires every 8 hours)

Step 2: Query Fitbit API

const steps = await fetch('https://api.fitbit.com/1/user/-/activities/steps/date/today/1d.json', {
  headers: { 'Authorization': `Bearer ${fitbitToken}` }
})

Step 3: Repeat for Garmin (different OAuth, different API)

// Garmin uses OAuth 1.0a (different flow!)
const garminAuthUrl = `https://connect.garmin.com/oauthConfirm?
  oauth_token=${requestToken}`
// ... completely different implementation

Step 4: Repeat for Oura (different OAuth, different API)

const ouraAuthUrl = `https://cloud.ouraring.com/oauth/authorize?
  client_id=${OURA_CLIENT_ID}&response_type=code`
// ... yet another different implementation

Step 5: Build token refresh scheduler for all devices
Step 6: Handle device-specific errors and rate limits
Step 7: Normalize data formats across 300+ devices

Total implementation: ~10,000+ lines of code for 300+ device integrations

Implementation Time Comparison

  • Platform API (HealthKit + Health Connect): 1-2 weeks for both platforms
  • Direct OAuth (10 major devices): 2-3 months
  • Direct OAuth (300+ devices like Terra): 12-18 months + ongoing maintenance

This is why platforms like Terra exist - they've already built the 300+ integrations so you don't have to.

Token Management: The Hidden Complexity

Platform API: Zero Token Management

Direct OAuth: Complex Token Lifecycle

Device Token Expiry Refresh Strategy Edge Cases
Fitbit 8 hours Refresh token (expires in 60 days) User must re-auth if 60 days pass
Garmin 1 year OAuth 1.0a (no refresh, manual re-auth) Annual re-authentication required
Oura 24 hours Refresh token (no expiry) Refresh daily or lose access
Whoop 1 hour Refresh token (expires in 30 days) Hourly refresh or 30-day re-auth
Polar 10 days No refresh token (re-auth every 10 days) User interruption every 10 days

With 300 devices, you're managing 300 different token lifecycles.

The Token Refresh Problem at Scale

If you have 10,000 users with 3 devices each (30,000 connections):

  • Fitbit: 30,000 tokens × 3 refreshes/day = 90,000 refresh operations/day
  • Oura: 30,000 tokens × 1 refresh/day = 30,000 refresh operations/day
  • Whoop: 30,000 tokens × 24 refreshes/day = 720,000 refresh operations/day

Total: ~850,000 token operations per day just to maintain connections. Platform APIs eliminate this entirely.

Data Flow: Latency vs Coverage Trade-off

Platform API Flow (HealthKit Example)

  1. Device sync: Apple Watch syncs to iPhone HealthKit (real-time when nearby, hourly when apart)
  2. Platform storage: HealthKit stores data locally on device
  3. App query: Your app queries HealthKit (instant, local access)
  4. Total latency: 1-60 minutes (depends on device sync)

Coverage: Any device that syncs to HealthKit (Apple Watch, Fitbit, Garmin, Oura, 100+ devices) ✅

Direct OAuth Flow (Fitbit Example)

  1. Device sync: Fitbit syncs to Fitbit cloud (every 15 minutes when connected)
  2. API polling: Your app polls Fitbit API (rate limit: 150 req/hour)
  3. Data transfer: Fitbit API returns data via REST
  4. Total latency: 15-30 minutes (depends on sync + poll frequency)

Coverage: Only Fitbit devices (must build separate integrations for Garmin, Oura, etc.) ❌

Latency Misconception

Many assume direct OAuth is "faster" because you're closer to the device API. In practice:

  • Platform API: 1-60 min latency, but 100% coverage (all synced devices)
  • Direct OAuth: 15-30 min latency, but ~5% coverage per device (must build each integration)

The coverage penalty far outweighs the latency benefit for most use cases.

When to Use Each Approach

✅ Use Platform API (HealthKit/Health Connect) When:

Consumer Apps

  • Need broad device coverage (any brand)
  • Want low onboarding friction
  • Prefer simple implementation
  • Can tolerate 1-hour data latency

Examples: Fitness apps, habit trackers, mental health apps

Enterprise Programs

  • Insurance wellness programs
  • Corporate health initiatives
  • Research studies (observational)
  • Population health monitoring

Why: 70% user coverage vs 30% with device-specific integrations

⚠️ Use Direct OAuth When:

Device-Specific Features

  • Need proprietary metrics (Whoop recovery score, Oura readiness)
  • Require real-time data (<5 min latency)
  • Access device-native analytics
  • Support specific device brands only

Examples: Whoop coaching platform, Oura analytics tools

Clinical Trials

  • Controlled device list (all participants use same device)
  • Need device-native precision (no platform normalization)
  • Require audit trails per device
  • Compliance mandates specific devices

Why: Clinical trials control the device, so coverage isn't a concern

The Hybrid Approach (Recommended)

Sahha and Rook support both strategies:

  • Primary: Platform APIs (HealthKit/Health Connect) for 70% coverage
  • Fallback: Direct OAuth for device-specific features (Whoop, Oura proprietary scores)
  • Smartphone: Built-in sensors for 100% coverage (no wearable required)

This maximizes coverage while still allowing access to proprietary device features when needed.

Platform Support Comparison

Platform Platform API Support Direct OAuth Support Smartphone Sensors Best For
Sahha ✓ HealthKit + Health Connect Limited (major devices) ✓ Full support Consumer apps, insurance, 100% coverage strategy
Rook ✓ HealthKit + Health Connect ✓ Select devices ~ Limited Platform-first with selective OAuth
Terra ✓ Optional (via HealthKit/Health Connect) ✓ 300+ devices (primary) ✗ None Device breadth, enthusiast apps, device-specific features
Spike ✗ None ✓ Medical devices only ✗ None Clinical trials, medical equipment integration

Implementation Checklist

For Platform API Implementation:

  1. ✅ Add HealthKit capability to iOS app (Xcode)
  2. ✅ Add Health Connect dependency to Android app (Gradle)
  3. ✅ Request user permissions (one-time prompt)
  4. ✅ Query data types needed (steps, sleep, heart rate, etc.)
  5. ✅ Handle background updates (optional for real-time)
  6. ✅ Test with various devices syncing to platform

Estimated time: 1-2 weeks for both platforms

For Direct OAuth Implementation:

  1. ✅ Register developer accounts (Fitbit, Garmin, Oura, Whoop, etc.)
  2. ✅ Build OAuth flows for each device (different per manufacturer)
  3. ✅ Implement token storage and refresh logic
  4. ✅ Build API clients for each device (different endpoints, formats)
  5. ✅ Normalize data formats across devices
  6. ✅ Handle rate limits, errors, edge cases per device
  7. ✅ Monitor token expiry and trigger re-auth flows
  8. ✅ Test with physical devices for each brand

Estimated time: 2-3 months for 10 devices, 12-18 months for 300+ devices

Why Use an Aggregator?

Platforms like Sahha, Terra, and Rook have already built these integrations. By using an aggregator:

  • Save 12-18 months of development time
  • Avoid token management complexity (handled by aggregator)
  • Get automatic updates when device APIs change
  • Access unified data format regardless of source

Cost: ~$50-500/month vs $400k-1.6M to build in-house

Decision Framework

Your Use Case Recommended Approach Why
Consumer fitness app Platform API (HealthKit/Health Connect) Broad coverage, low friction, simple implementation
Insurance wellness program Platform API + Smartphone 70-100% member coverage (vs 30% wearable-only)
Mental health platform Smartphone + Platform API Behavioral data from smartphone, activity from platform
Device-specific app (Whoop/Oura only) Direct OAuth (single device) Access proprietary metrics, controlled device list
Clinical trial (controlled devices) Direct OAuth or Spike Device-native precision, audit trails, compliance
Multi-device aggregator (like Terra) Hybrid: Platform API + Direct OAuth Maximum coverage + device-specific features
🔧 Read Full Integration Guide →

Next Steps