Device Integration — Wearables, Bluetooth Devices & Health Stores
This section explains how to integrate health data sources with vitalera — from consumer wearables like Garmin, Oura, WHOOP, and Dexcom (cloud API) to clinical Bluetooth devices like blood pressure monitors and glucometers (SDK).
Consumer Wearables (API-Based)
Connect popular consumer wearables and medical devices via server-to-server API integrations. No mobile SDK required for these — users link their accounts once via OAuth (or an equivalent authentication flow), and data flows automatically into vitalera as FHIR R5 Observation resources.
Fitness trackers & smartwatches
| Provider | Connection | Data Types | Status | Learn More |
|---|---|---|---|---|
| Garmin | Garmin Health API (OAuth 2.0 + PKCE) | Workouts, HR zones, sleep stages, SpO2, stress, steps, HRV, BP, skin temp | Available | Garmin |
| Fitbit (legacy) | Fitbit Web API (OAuth) | Activity, HR, sleep, SpO2, weight | Deprecated (2026-05-31) — migrate to Google Health | Google Health (Fitbit) |
| Apple Watch | HealthKit (on-device SDK) | HR, SpO2 | Available | SDK Reference |
| Polar | AccessLink v3 (OAuth) | Exercises, daily activity, sleep, HR | Available | Polar |
| Suunto | Suunto Partner API (OAuth) | Workouts, sleep, activity, recovery | Partnership required | Suunto |
| COROS | COROS Open API (OAuth) | Workouts, HR, sleep, SpO2, VO2 max, pace, cadence, running power | Partnership required | COROS |
| Wahoo | Wahoo Cloud (OAuth) | Workouts, HR, power, distance, calories | Available | Wahoo |
| Samsung Health | Samsung Partnership API | HR, sleep, activity, SpO2, BP, weight | Partnership required (skeleton) | Samsung Health |
| Amazfit / Zepp | Huami API (reverse-engineered) | HR, steps, sleep, SpO2, stress, calories | Reverse-engineered | Amazfit / Zepp |
| Peloton | onepeloton.com (reverse-engineered) | Workouts, HR, calories, performance (output/cadence/resistance) | Reverse-engineered | Peloton |
| Strava | Strava v3 (OAuth + push subs) | Activities, HR streams, distance, elevation | Available | Strava |
Sleep & recovery
| Provider | Connection | Data Types | Status | Learn More |
|---|---|---|---|---|
| Oura Ring | Oura v2 (OAuth) | HR, sleep stages, activity, readiness, SpO2, stress, VO2 max | Available | Oura |
| WHOOP | WHOOP API v2 (OAuth) | Recovery 0–100%, sleep, strain 0–21, cycles, body measurements | Available | WHOOP |
| Ultrahuman | Partner API (OAuth) | Sleep, activity, recovery, HRV, HR, SpO2, skin temp | Partnership required | Ultrahuman |
| Biostrap | Biostrap v2 (OAuth) | Resting HR, HRV, SpO2, respiratory rate, sleep, recovery | Available | Biostrap |
| Eight Sleep | client-api.8slp.net (email+password → JWT) | Sleep, HR, HRV, respiratory rate, bed temperature | Reverse-engineered | Eight Sleep |
Medical / clinical
| Provider | Connection | Data Types | Status | Learn More |
|---|---|---|---|---|
| Dexcom CGM | Dexcom v3 (OAuth) | Glucose, insulin events, carbs, exercise events (FDA-cleared) | Partnership required | Dexcom |
| FreeStyle Libre | LibreView (reverse-engineered) | Continuous glucose | Reverse-engineered | FreeStyle Libre |
| Omron Cloud | Omron Connect (OAuth) | BP (systolic + diastolic + pulse), weight, activity | Available | Omron |
| iHealth | iHealth (OAuth + SC/SV) | BP, glucose, SpO2, weight, temperature, activity | Available | iHealth |
| InBody | Partnership API (API key + OTP) | Body fat %, muscle mass, BMI, BMR, body water, visceral fat | Partnership (NDA) | InBody |
| Withings | Withings v2 (OAuth) | Weight, BP, HR, sleep, activity, SpO2, temperature | Available | Withings |
| BodyTrace | API key + push | Weight with battery/signal metadata | Available | BodyTrace |
Migration paths
| Provider | Replaces | Deadline | Learn More |
|---|---|---|---|
| Google Health | Fitbit Web API | 2026-05-31 | Google Health (Fitbit) |
Status legend
| Symbol / label | Meaning |
|---|---|
| Available | Production-ready, on-demand sign-up. |
| Partnership required | Provider-issued partner credentials needed. vitalera onboards per-organisation. |
| Partnership (NDA) | As above, plus NDA required before access is granted. |
| Reverse-engineered | No official developer API. Best-effort; endpoints may change. Not recommended for clinical SLAs. |
| Deprecated | Legacy integration scheduled for shutdown. Migrate to the replacement. |
Connected Accounts Framework
All provider integrations above are exposed through a single, provider-agnostic API so adding a new wearable source never requires a schema change or a new client. Each provider has the same set of endpoints, parameterised by the service_id (e.g. fitbit, garmin, oura, dexcom).
Catalog and discovery
| Endpoint | Purpose |
|---|---|
GET /api/connected-accounts/services/ | Service catalog — every provider the caller's organisation is entitled to use |
GET /api/connected-accounts/status/ | Bulk per-user status across every connected provider |
GET /api/connected-accounts/{service_id}/status/ | Single-provider status (connected, disconnected, reauth_required) |
Connect flows
| Endpoint | Purpose |
|---|---|
POST /api/connected-accounts/{service_id}/oauth/initiate/ | Start an OAuth / API-key setup — returns the URL to redirect the user to |
GET /api/connected-accounts/{service_id}/oauth/callback/ | Redirect target — vitalera completes the token exchange |
POST /api/connected-accounts/{service_id}/oauth/disconnect/ | Revoke tokens and disable the connection |
POST /api/connected-accounts/{service_id}/webhook/ | Provider-facing push endpoint (HMAC-SHA256 or JWT-verified per provider) |
Embedded connect widget
For third-party apps that don't host their own OAuth UX, vitalera offers a hosted widget:
| Endpoint | Purpose |
|---|---|
POST /api/connected-accounts/connect-session/ | Issue a short-lived, single-user connect-session token |
GET /api/connected-accounts/connect/?token=... | Hosted connect widget — users pick a provider and complete OAuth inline |
Entitlements
Every provider is gated by a per-organisation entitlement of the form connected_accounts:<service_id> (e.g. connected_accounts:dexcom). The service catalog filters by entitlement, so users only see providers the organisation has paid for / been approved to use. Partnership-gated providers (COROS, Suunto, Samsung Health, InBody, Dexcom) ship disabled by default.
Medical Devices (SDK — Bluetooth)
| Provider | Module (Android) | Module (iOS) | Devices |
|---|---|---|---|
| Omron | provider-omron | VitaleraSdkProviderOmron | Evolv BPM (HEM-7600T), MC-280B Thermometer |
| Polar | provider-polar | VitaleraSdkProviderPolar | H10, Verity Sense (heart rate) |
| Lifevit | provider-lifevit | VitaleraSdkProviderLifevit | BPM 160, BPM 260, Pulse Oximeter (OL750), Scale (BL2000), Thermometer (IT45B) |
| Beurer | provider-beurer | VitaleraSdkProviderBeurer | BM85 BPM, PO60 Pulse Oximeter |
| Smart Peak Flow | provider-smart-peak-flow | VitaleraSdkProviderSmartPeakFlow | Smart Peak Flow Meter |
| HealthKit | N/A | VitaleraSdkProviderHealthKit | Apple Watch (heart rate, SpO2) |
| Health Connect | provider-health-connect | N/A | Google Health Connect (Android) |
| Standard BLE | sdk-ble | VitaleraSdkBle | Any device using standard Bluetooth SIG health profiles |
See the Supported Devices page for the complete device list.
General BLE Workflow
For all BLE devices, the integration follows three steps:
1. Discover
Scan for nearby BLE devices using DiscoveryFilter to filter by provider, capability, or device name:
// Android (Kotlin)
val filter = DiscoveryFilter(
capabilities = setOf(DeviceCapability.BLOOD_PRESSURE)
)
sdk.devices.discover(filter, timeoutMs = 15_000L).collect { descriptor ->
println("Found: ${descriptor.name} (${descriptor.provider})")
}
// iOS (Swift)
let filter = DiscoveryFilter(
providers: nil,
capabilities: [DeviceCapability.bloodPressure],
namePrefix: nil
)
for try await descriptor in sdk.devices.discover(filter: filter, timeoutMs: 15_000) {
print("Found: \(descriptor.name) (\(descriptor.provider))")
}
2. Connect
Create a device from the discovered descriptor and connect:
// Android
val device = sdk.devices.createDevice(descriptor)
device.connect(timeoutMs = 10_000L)
// iOS
let device = sdk.devices.createDevice(descriptor: descriptor)
try await device.connect(timeoutMs: 10_000)
3. Collect
Read typed observations from the connected device:
// Android
device.collect().collect { observation ->
when (observation) {
is BloodPressureObservation ->
println("BP: ${observation.systolic}/${observation.diastolic}")
is HeartRateObservation ->
println("HR: ${observation.heartRate} bpm")
}
}
device.disconnect()
// iOS
for try await observation in device.collect() {
if let bp = observation as? BloodPressureObservation {
print("BP: \(bp.systolic)/\(bp.diastolic) mmHg")
} else if let hr = observation as? HeartRateObservation {
print("HR: \(hr.heartRate) bpm")
}
}
try await device.disconnect()
Device-Specific Notes
Blood Pressure Monitors
- Beurer BM85: Ensure the device is charged and turned off before scanning. Turn on the device after scanning starts and wait for Bluetooth discovery.
- Lifevit BPM 160/260: Turn on the device, then start scanning. Once connected, call read and wait for the observation.
- Omron Evolv (HEM-7600T): Turn on the device and start scanning. The SDK handles pairing automatically.
Pulse Oximeters
- Lifevit OL750 / Beurer PO60: Place your finger in the oximeter and turn it on, then start scanning. Data streams continuously until you disconnect.
Thermometers
- Lifevit IT45B / Omron MC-280B: Turn on the thermometer, start scanning, and take a measurement. The observation is returned after the reading completes.
Scales
- Lifevit BL2000: Step on the scale when prompted. The weight observation is returned once the reading stabilizes.
Glucometers
- Contour Next: The device must be pre-paired via system Bluetooth settings before scanning from the SDK.
Heart Rate Sensors
- Polar H10: Wear the chest strap, start scanning, and the SDK streams heart rate data continuously.
Further Reading
- SDK Overview -- Architecture, modules, and quick start.
- Android SDK Usage -- Full Android code examples.
- iOS SDK Usage -- Full iOS code examples.
- Supported Devices -- Complete device compatibility list.