> ## Documentation Index
> Fetch the complete documentation index at: https://docs.synheart.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Vendor Adapters

> Per-vendor flow, capabilities, and RAMEN 🍜 delivery semantics

`synheart-wear` ships a stable adapter layer per vendor. This page is the reference for what each adapter does, what it produces, and how it interacts with cloud streaming.

## Adapter matrix

| Vendor                   | Local source                               | Cloud / push source                          | RAMEN delivery hint            | Status                   |
| ------------------------ | ------------------------------------------ | -------------------------------------------- | ------------------------------ | ------------------------ |
| Apple Watch              | HealthKit (`apple_healthkit`)              | —                                            | n/a                            | Ready                    |
| Health Connect (Android) | Health Connect API                         | —                                            | n/a                            | Ready                    |
| BLE HRM (any)            | GATT 0x180D Heart Rate Profile             | —                                            | n/a                            | Ready                    |
| WHOOP                    | Broadcast HR via BLE                       | OAuth + webhooks                             | `stream` (full payload inline) | Ready                    |
| Garmin (Cloud)           | —                                          | OAuth + Connect API webhooks                 | `ping` (REST pull required)    | Ready                    |
| Garmin Health SDK (RTS)  | Native real-time streaming                 | —                                            | n/a                            | On-demand, license-gated |
| Fitbit                   | —                                          | OAuth via Synheart Wear API                  | `ping`                         | Ready                    |
| Oura                     | HealthKit / Health Connect proxy (Flutter) | OAuth via Synheart Wear API (Kotlin / Swift) | `ping`                         | Ready                    |
| Samsung Watch            | (planned)                                  | —                                            | n/a                            | Planned                  |

The Dart `DeviceAdapter` enum lists `platformHealth`, `fitbit`, `garmin`, `whoop`, `samsungHealth`. The Swift and Kotlin enums additionally include `bleHrm` / `BLE_HRM`. Across all three platforms, Oura has no enum entry and is reached via `OuraProvider`; BLE HRM on Dart is reached via `BleHrmBridge`.

## Apple HealthKit

Capabilities:

* HR (instantaneous + samples).
* HRV (RMSSD, SDNN; SDNN derived on-device when only RR is exposed).
* Steps, calories, distance.
* RR intervals via the HealthKit RR channel (workout-mode only on most Apple Watch models).
* Health profile snapshot (DOB, sex, height, weight) for personalization context.
* Workout events.

Permissions: standard HealthKit `HKObjectType` set, requested once via `requestPermissions`.

`source` field on `WearMetrics`: `"apple_healthkit"`.

## Health Connect (Android)

Capabilities:

* HR, HRV (when the recording app provides it; otherwise SDNN/RMSSD are unavailable).
* Steps, calories, distance.
* Sleep records (sleep stages from compatible apps).

Health Connect retention is capped per record type by the platform (typically \~30 days for HR, longer for sleep). Hosts that need older data must use the Apple XML backfill path (Apple users) or an OAuth cloud adapter.

`source` field: `"health_connect"`.

## BLE HRM

Direct connection over BLE GATT Heart Rate Profile (0x180D). No vendor cloud, no OAuth.

Compatible devices:

* WHOOP (Broadcast HR mode).
* Polar chest straps (H10, OH1).
* Wahoo TICKR family.
* Garmin HRM-Pro / HRM-Dual.
* Any HRM advertising 0x180D Heart Rate Service.

Capabilities:

* HR (every second per Bluetooth profile).
* RR intervals when the device advertises the optional RR field.

The bridge runs its own permission/scan/connect/disconnect lifecycle independent of `requestPermissions`. See [BLE Heart Rate Monitor](/synheart-wear/ble-hrm) for the detailed flow.

`source` field: `"ble_hrm"`.

## WHOOP

Two modes:

| Mode             | Path                                                                                                                                       |
| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| OAuth + webhooks | Cloud-side handles OAuth + webhook ingest, publishes `wear.events`, RAMEN delivers to client. `DeliveryHint.stream` (full payload inline). |
| BLE Broadcast HR | Local-only via `BleHrmBridge`. No cloud round-trip; no recovery/strain/sleep.                                                              |

`WhoopProvider` exposes:

* `fetchRawDataForFlux(start, end)` — pulls raw vendor data for HSI 1.3 transformation.
* Real-time HR via webhooks (mode A) or BLE (mode B).
* Workout events.

`source` field: `"whoop"` for the OAuth path. The cloud-vs-BLE distinction lives in `meta.source_type` (`"whoop_cloud"`); WHOOP via BLE Broadcast HR uses the shared BLE HRM adapter (`source = "ble_hrm"`).

## Garmin (Cloud)

Path: OAuth → Garmin Connect API webhooks → cloud → RAMEN. Delivery hint: `ping` — vendor only sends a notification; client must pull the full record via REST when needed.

`GarminProvider` exposes:

* `fetchRawDataForFlux(start, end)` — REST pull for Flux input.
* Wellness, sleep, activity data classes (`GarminWellnessData`, `GarminSleepData`, `GarminActivityData`).
* Connection state (`GarminConnectionState`) for UI.
* Realtime data shape (`GarminRealtimeData`) when a session is active.

`source` field: `"garmin"` for the OAuth Connect API path; `meta.source_type` carries the more specific `"garmin_cloud"`.

## Garmin Health SDK (Real-Time Streaming)

Native RTS path — direct device pairing without going through Garmin Connect cloud. **Requires a separate Garmin license** and is bundled on demand for licensed integrations only. The underlying Garmin Health SDK code is proprietary; this SDK exposes a `GarminHealth` provider façade that wraps it.

`source` field: `"garmin_sdk"` (the adapter id from `GarminSdkAdapter`).

## Fitbit

OAuth flow mediated by the Synheart Wear API — the device never sees Fitbit access tokens. Cloud delivers a `vendor_user_id` to the app via deep-link callback (`?vendor=fitbit&user_id=...&status=success`); pass that as the `code` argument to `connectWithCode(...)`.

`FitbitProvider` exposes:

* `fetchHrv`, `fetchSleep`, `fetchActivity` — date-range record queries.
* `fetchUserProfile` — Fitbit profile snapshot.

`source` field: `"fitbit"`.

## Oura

Two paths depending on platform:

* **Flutter**: data flows through HealthKit (iOS) and Health Connect (Android) when an Oura companion app syncs there.
* **Kotlin / Swift**: dedicated `OuraProvider` with mediated OAuth via the Synheart Wear API (same `vendor_user_id`-via-deep-link contract as Fitbit).

`OuraProvider` exposes `fetchReadiness`, `fetchSleep`, `fetchHrv`, `fetchActivity`. `source` field: `"oura"`.

## Streaming model

Today, cloud providers (Whoop, Garmin, Fitbit, Oura) are **polled**: `streamHR` / `streamHRV` run a timer (Combine `Timer.publish` on Swift, `kotlinx.coroutines.flow.flow { delay(...) }` on Kotlin) that calls `readMetrics(isRealTime: true)` on each tick. There is no push channel for these vendors yet.

`BleHrmProvider` is **push-based** — the BLE characteristic notification feeds a SharedFlow / AsyncStream and `streamHR` picks up the latest sample.

Future work: a `RamenEventDispatcher` on Kotlin / Swift (Flutter already has one) will materialize cloud-side `ping` events into REST pull-backs, replacing the timer-based polling for cloud providers.

## Apple Health XML backfill

When a user exports `export.zip` from the iOS Health app:

```text theme={null}
User exports export.zip from iOS Health app
        │
        ▼
parse via AppleHealthXmlParser
        │
        ▼
batch into AppleHealthSample records
        │
        ▼
synheart_core_backfill_open(db_path, import_id)
        │
        ▼ insert_batch (batched)
synheart_core_backfill_insert_batch(import_id, samples_json)
        │
        ▼
synheart_core_backfill_finalize(import_id)
```

Idempotency keys ensure repeated imports don't duplicate samples in the runtime's SQLite store.

The high-level path through `synheart-core` aggregates samples per day and replays them via `Synheart.srmPushWearableDaily(...)` so the imported data populates the user's runtime baselines.

## RAMEN 🍜 integration

Each cloud adapter participates in the RAMEN stream when Synheart's cloud ingestion publishes events:

```text theme={null}
vendor webhook
    ↓
Synheart ingestion persists and publishes wear.events
    ↓
RAMEN gRPC stream → synheart-stream-runtime client
    ↓
Synheart runtime broadcasts RamenEvent
    ↓
synheart-core wires WearableEventProcessor onto WearModule
    ↓
WearModule routes by vendor → adapter handler
    ↓
WearMetrics emitted on streamHR / streamHRV / readMetrics
```

Each adapter handler decides how to consume `RamenEvent.payload_json`:

* `DeliveryHint.stream`: parse inline, emit immediately.
* `DeliveryHint.ping`: schedule a REST pull (via the adapter's provider) to fetch the body.
* `DeliveryHint.unknown`: treat as `stream` (best-effort) and log.

## Permission flow

`SynheartWear.requestPermissions(permissions, reason)`:

1. Maps Synheart `PermissionType` values to OS permission scopes.
2. Routes to the appropriate adapter (HealthKit on iOS, Health Connect on Android, OAuth flow for cloud adapters).
3. Returns `Map<PermissionType, ConsentStatus>` per type.

Adapters that don't have OS-level permissions (BLE HRM relies on Bluetooth Manager prompts; cloud OAuth requires app navigation) handle their own UX outside this method.

## Related

* [Wear Overview](/synheart-wear/overview) — full SDK surface.
* [Data Schema](/synheart-wear/data-schema) — what each adapter writes into the unified `WearMetrics`.
* [BLE Heart Rate Monitor](/synheart-wear/ble-hrm) — direct BLE HRM flow.
