Adding Wearable Providers
This guide walks you through integrating a new fitness data provider (e.g., Strava, Samsung Health, Xiaomi, WHOOP) into the Open Wearables platform. The architecture uses the Strategy, Factory, and Template Method design patterns to make adding providers straightforward and consistent.Architecture Overview
Each provider integration consists of three main components:Data Flow Patterns
Providers support one or both patterns:PULL
Fetch data from provider’s cloud API using OAuth tokens (Garmin, Strava, WHOOP).
PUSH
Receive data via webhooks or file uploads (Suunto, Polar, Apple Health).
Garmin supports both PULL and PUSH patterns, while Suunto and Polar are PUSH-only.
Prerequisites
Before starting, gather information about your provider:Provider API Information
Provider API Information
- Base API URL (e.g.,
https://apis.garmin.com) - Authentication method (typically OAuth 2.0)
- Available data endpoints (activities, workouts, health metrics)
- Rate limits and pagination details
- API documentation URL
OAuth Configuration (if applicable)
OAuth Configuration (if applicable)
- Authorization URL
- Token exchange URL
- Required scopes
- PKCE requirement (yes/no)
- Credentials transmission method (header vs. body)
- Client ID and Secret
- Redirect URL registration location
Data Format
Data Format
- Workout/activity data structure
- Timestamp format (Unix, ISO 8601, etc.)
- Available metrics (heart rate, distance, calories, cadence, etc.)
- Workout type enumeration
- Time series data format (if available)
Step 1: Create Provider Directory
Create a new directory for your provider inbackend/app/services/providers/:
Use lowercase for the provider name to maintain consistency with existing providers.
Step 2: Implement the Strategy Class
The strategy class is the entry point that defines the provider’s identity and initializes components. Createbackend/app/services/providers/whoop/strategy.py:
Key Properties
name
Unique lowercase identifier used in URLs and database.
api_base_url
Base URL for API client to construct requests.
display_name
Optional override for UI display (defaults to
name.capitalize()).
BaseProviderStrategy initializes all required repositories, so you don’t need to handle database operations directly.Step 3: Implement OAuth Handler
For cloud-based providers using OAuth 2.0, implement the OAuth handler. Createbackend/app/services/providers/whoop/oauth.py:
Configuration Options
use_pkce
Set to
True if provider requires PKCE (Proof Key for Code Exchange). Garmin enforces PKCE; Polar and Suunto don’t.auth_method
BASIC_AUTH: Credentials in Authorization header (Polar, Suunto)BODY: Credentials in request body (Garmin)
Add Environment Variables
Add OAuth credentials tobackend/config/.env:
backend/app/config.py:
Step 4: Implement Workouts Handler
The workouts handler fetches and normalizes workout data into the unified schema. Createbackend/app/services/providers/whoop/workouts.py:
Key Methods
_normalize_workout()
Most important! Converts provider’s data format to the unified schema.
Use
app/services/providers/api_client.py for making authenticated API requests with automatic retry logic.Step 5: Create Workout Type Mapping
Create a mapping to convert provider-specific workout types to unified types. Createbackend/app/constants/workout_types/whoop.py:
Step 6: Register Provider in Factory
Add your provider to the factory for system-wide instantiation. Editbackend/app/services/providers/factory.py:
Step 7: Add Provider to Schema Enums
Update theProviderName enum to include your provider.
Edit backend/app/schemas/oauth.py:
- Type validation in API endpoints
- Auto-generated API documentation
- Enum-based routing
Step 8: Test Your Integration
1. Test OAuth Flow
2. Test Data Sync
3. Verify Database
Check that workouts are saved correctly:4. Monitor Logs
5. Run Tests
Create unit tests for your provider:Advanced: Webhook Support
For providers supporting webhooks (PUSH pattern), implement webhook handling:Create Webhook Endpoint
Createbackend/app/api/routes/v1/webhooks.py:
Troubleshooting
OAuth flow fails
OAuth flow fails
- Verify
client_id,client_secret, andredirect_uriare correct - Check that redirect URI is registered with the provider
- Ensure PKCE is enabled/disabled correctly based on provider requirements
- Review provider’s OAuth documentation for specific requirements
Data not normalizing correctly
Data not normalizing correctly
Add detailed logging in Compare against provider’s API documentation.
_normalize_workout() to inspect raw data:Duplicate workouts created
Duplicate workouts created
Implement duplicate detection based on
provider_id:Missing workout types
Missing workout types
- Add missing types to your mapping file
- Use
WorkoutType.OTHERas fallback - Log unmapped types for future updates:
Summary Checklist
Use this checklist to ensure completion:- Created provider directory structure
- Implemented
ProviderStrategywith required properties - Implemented
ProviderOAuth(if PULL provider) - Implemented
ProviderWorkoutswith normalization logic - Created workout type mapping file
- Registered provider in
ProviderFactory - Added provider to
ProviderNameenum - Added provider icon SVG to
static/provider-icons/ - Added environment variables to
.envandconfig.py - Tested OAuth flow end-to-end
- Tested data synchronization
- Verified data in database
- Set up webhook handling (if applicable)
- Added error handling and logging
- Created unit tests
- Updated API documentation
Congratulations! You’ve successfully integrated a new provider into Open Wearables.
Next Steps
Submit Pull Request
Follow the contributing guidelines to submit your integration.
Add 24/7 Data Handler
Extend your provider to sync continuous health data (sleep, heart rate, etc.).
Implement Webhooks
Add real-time data sync via webhooks for instant updates.
Write Tests
Create comprehensive tests for OAuth, normalization, and edge cases.
