Key Takeaways
- Apple Health does not expose a server-side REST API. All access requires an on-device SDK that pushes health records to your backend.
- Open Wearables provides the mobile SDK (iOS Swift, Flutter, React Native) along with the self-hosted backend that receives and normalizes that data.
- Your backend generates a short-lived token via
POST /api/v1/users/{user_id}/token. The SDK uses this token. Yourapp_idandapp_secretnever leave the server. - Apple Health API offers the broadest coverage: steps, heart rate, HRV, VO2 max, sleep stages, workouts, blood oxygen, body composition, respiratory rate, and 100+ additional metrics.
- For users who want to export their full Health history, Open Wearables supports XML import for both small and large files.
- Cloud sync is not available for Apple Health. If your product is web-only or has no iOS app, Apple Health is not a viable source.
- The stack is MIT-licensed with no per-user fees.
Why There Is No Apple Health API in the Traditional Sense
If you search for "Apple Health API", you will find HealthKit documentation. HealthKit is an on-device framework. There is no server-side endpoint you can call with a token to pull a user's step count or sleep data. Apple does not expose that data to third-party backends directly.
Apple Health data lives in the HealthKit store on the user's iPhone and is accessible only to apps running on that device with explicit user permission. The standard integration pattern is: your iOS app reads from HealthKit, then sends the data to your backend.
The work that lands on you: parsing HealthKit objects, handling background delivery, managing token refresh, deduplicating records across sync sessions, normalizing units. All of that happens before you write a single line of business logic.
Open Wearables handles that entire layer.
What Open Wearables Does Under the Hood
The architecture has two layers.
SDK layer (on-device). The Open Wearables mobile SDK runs inside your iOS app. It requests HealthKit permissions, reads the relevant data types, and pushes records to your backend at POST {host}/api/v1/sdk/users/{userId}/sync. Background sync is handled by the SDK including automatic token refresh and retry logic. Credentials are stored in Keychain on iOS.
Backend normalization layer (self-hosted). The Open Wearables backend receives raw HealthKit payloads, normalizes them into a unified schema, deduplicates records by external_id, and makes them available through a consistent REST API.
Backend Setup: Token Generation
Your backend generates a token pair for each user:
POST /api/v1/users/{user_id}/token
This returns an access_token and a refresh_token. Pass these tokens to the mobile SDK. The SDK handles all subsequent refreshes automatically.
Never embed app_id or app_secret in the mobile app binary. Token generation must happen server-side.
SDK Integration
iOS (Swift)
sdk.configure(host: "https://your-backend.com")
sdk.signIn(
userId: credentials.userId,
accessToken: credentials.accessToken,
refreshToken: credentials.refreshToken
)
sdk.startBackgroundSync(syncDaysBack: 90)
Flutter (Dart)
await OpenWearablesHealthSdk.configure(
host: 'https://your-backend.com',
);
final user = await OpenWearablesHealthSdk.signIn(
userId: credentials['userId'],
accessToken: credentials['accessToken'],
refreshToken: credentials['refreshToken'],
);
await OpenWearablesHealthSdk.startBackgroundSync(syncDaysBack: 90);
The HealthDataType enum covers the data types the SDK will request: steps, heartRate, restingHeartRate, sleep, workout, activeEnergy, bodyMass, and more.
What the Backend Receives and How to Query It
After sync, data is available through the Open Wearables REST API:
GET /api/v1/users/{user_id}/timeseries
GET /api/v1/users/{user_id}/events/workouts
GET /api/v1/users/{user_id}/events/sleep
All responses use a normalized schema regardless of the source provider.
XML Import Path
Apple allows users to export their full Health history as an XML archive.
Small files (under 10 MB):
POST /api/v1/users/{user_id}/import/apple/xml/direct
Large files:
POST /api/v1/users/{user_id}/import/apple/xml/s3
The S3 endpoint accepts filename (max 200 chars), expiration_seconds (60-3600), max_file_size (default 50 MB). Import processing is asynchronous. Records with the same external_id will not be duplicated.
Quickstart
git clone https://github.com/the-momentum/open-wearables
cd open-wearables
docker compose up -d
API at http://localhost:8000. Auth via X-Open-Wearables-API-Key header.
See Related Articles
- How to integrate Apple Health data into your app
- Getting Apple Health data into your backend
- How to sync wearable data from multiple devices
- How to normalize wearable data across providers
- Wearable API integration: comparing SaaS, custom build, and open source
FAQ
Is there a way to access Apple Health API data without a mobile SDK?
No. Apple does not provide a server-side API for HealthKit data. Open Wearables handles the SDK side of this; you embed it into your existing iOS app.
What happens if the user's phone is offline when a sync is scheduled?
The SDK queues pending syncs locally and retries when connectivity is restored. Background sync is managed by iOS's background task scheduling.
Does Open Wearables support Android alongside iOS?
Yes. The Android SDK reads from Google Health Connect using the same token flow and backend endpoint. Apple Health specifically is iOS-only.
How does deduplication work across multiple sync sessions?
Each health record has an external_id derived from HealthKit's internal UUID. When the SDK sends a batch, the backend checks whether a record with that external_id already exists. If it does, the record is skipped.
Can I control which health data types the SDK requests access to?
Yes. You configure the set of HealthDataType values during SDK initialization. The SDK will only request HealthKit permissions for the types you specify.