Skip to main content

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.

WearMetrics is the single shape every adapter writes into. Downstream layers (synheart-session, synheart-core, the runtime ingest queue) read this shape; they do not consume vendor-specific JSON.

WearMetrics

class WearMetrics {
  final DateTime timestamp;
  final String deviceId;
  final String source;
  final Map<String, num?> metrics;
  final Map<String, Object?> meta;
  final List<double>? rrIntervalsMs;
}
JSON shape (canonical):
{
  "timestamp": "2025-10-20T18:30:00Z",
  "device_id": "applewatch_1234",
  "source": "apple_healthkit",
  "metrics": {
    "hr": 72,
    "hrv_rmssd": 45,
    "hrv_sdnn": 62,
    "steps": 1045,
    "calories": 120.4,
    "distance": 2.5,
    "stress": 23
  },
  "meta": {
    "battery": 0.82,
    "synced": true
  },
  "rr_ms": [800, 850, 820]
}

Top-level fields

FieldTypeNotes
timestampISO-8601 UTC stringTime the measurement applies to (sample time, not emit time). Always UTC.
device_idstringStable identifier for this physical device. Format is vendor-shaped (e.g. "applewatch_1234", "whoop_<uuid>", BLE MAC for HRM).
sourcestringLowercase snake_case adapter id. Stable across versions of the same adapter.
metricsobjectKeyed by metric short-name (see below). Values may be null when the adapter knows the metric is not available; missing keys mean “not produced by this sample”.
metaobjectFree-form per-sample metadata. Stable keys are documented below; adapters may add vendor-specific keys.
rr_msarray of doubles | absentInter-beat intervals in milliseconds when the source provides them. Absent when not available.

metrics keys

Maps from the MetricType enum:
KeyTypeUnitSource
hrnumberbpmHR sample.
hrv_rmssdnumbermsRMSSD over the adapter’s window.
hrv_sdnnnumbermsSDNN over the adapter’s window.
stepsnumbercountPeriod total (since the previous sample, or per-day depending on adapter).
caloriesnumberkcalActive energy.
distancenumberkmTotal distance over the period.
stressnumberunitlessVendor-specific score (e.g. Garmin 0–100); adapters do not normalise this across vendors.
Adapters MAY emit additional vendor-specific metric keys but downstream consumers MUST tolerate unknown keys. Stable keys above are the normalised contract.

meta keys (stable)

KeyTypeNotes
batterynumber 0–1Device battery level.
syncedboolWhether this sample arrived via real-time path (true) or backlog/sync (false).
Adapter-specific meta: Garmin adds connection_state; WHOOP adds recovery_score, strain, etc. — refer to the per-vendor models.

rr_ms semantics

When present:
  • Each value is one inter-beat interval in milliseconds.
  • Order is the order observed by the device (chronological).
  • The list is per sample, not cumulative — multiple samples at the same timestamp can share an rr_ms payload via the meta field.
  • Range gates apply downstream: the runtime’s RR push rejects values outside [200, 6000].

Adapter source IDs

The top-level source field carries the adapter id — typically the bare vendor/source name. More specific flavor information (cloud vs BLE, etc.) lives in meta.source_type.
source valueAdaptermeta.source_type flavor
"apple_healthkit"Apple HealthKit
"health_connect"Android Health Connect
"ble_hrm"BLE Heart Rate Profile
"whoop"WHOOP"whoop_cloud" for OAuth + webhooks; WHOOP via BLE Broadcast HR uses source = "ble_hrm"
"garmin"Garmin via Connect API"garmin_cloud"
"garmin_sdk"Garmin Health SDK (RTS, license-gated)
"fitbit"Fitbit(planned)
"oura"Ouraproxied through HealthKit / Health Connect today
Consumers MUST tolerate unknown source and meta.source_type values. When new adapters land, they take new stable strings. Existing strings do not change meaning.

Compatibility rules

The shape is unversioned. Compatibility rules:
  • Producers MAY add new metric keys, new meta keys, and new source values.
  • Producers MUST NOT remove or rename existing keys.
  • Consumers MUST tolerate unknown metric keys and unknown source values.
  • A future change to the top-level shape would be a breaking change; the SDK would expose both producers in parallel during migration.

Vendor → schema mapping (informal)

This table is informational only. Each adapter is the authoritative source for its mapping; this is a reading aid.
Vendor fieldMaps toNotes
HealthKit HKQuantityTypeIdentifierHeartRatemetrics.hrAverage per query window.
HealthKit RR samplesrr_msWorkout-mode only on most Apple Watch models.
Health Connect HeartRateRecordmetrics.hrOne sample per record.
WHOOP webhook recovery_scoremeta.recovery_scoreNot part of the canonical metric set.
Garmin Connect restingHeartRatemetrics.hrDaily resting HR baseline.
BLE GATT 0x180D HR characteristicmetrics.hrPlus optional RR field → rr_ms.
Apple XML HKQuantityTypeIdentifierHeartRateVariabilitySDNNmetrics.hrv_sdnnBackfill only.

How downstream uses this

synheart-session’s WearBiosignalProvider wraps streamHR / streamHRV and converts each WearMetrics into a BiosignalSample:
BiosignalSample(
  timestampMs: metrics.timestamp.millisecondsSinceEpoch,
  bpm: metrics.getMetric(MetricType.hr) ?? 0.0,
  rrIntervalMs: metrics.rrIntervalsMs?.first,
  accelerometer: ...,
)
synheart-core forwards the same shape into the runtime via pushHr / pushRr after consent gating.