What this SDK does
Synheart Core connects a Flutter app to the native Synheart Runtime. It:- collects user-consented wearable, phone, and behavior signals;
- sends those signals to the on-device runtime;
- exposes Human State Interface (HSI) 1.3 output as Dart streams;
- optionally stores, synchronizes, and uploads derived state.
HSI is the public output. Most applications should use
Synheart.onStateUpdate for typed values or Synheart.onHSIUpdate for the
canonical JSON. Internal HSV data does not cross the public SDK boundary.Requirements
- Dart
>=3.8.0 <4.0.0 - Flutter
>=3.32.0 - iOS 15 or later
- Android API 24 or later
- A Synheart Runtime binary installed in the host application
Installation
1. Add the Flutter package
pubspec.yaml:
2. Install the native runtimes
The package alone loads no runtime and produces no HSI. Native artifacts are provisioned by the Synheart CLI, not by pub. Install and authenticate the CLI once:synheart.lock, which pins each artifact by SHA-256.
Other developers and CI can restore the pinned artifacts with:
- iOS:
synheart/vendor/runtime/ios/SynheartCoreRuntime.xcframework/ - iOS:
synheart/vendor/syni-runtime/SyniRuntime.xcframework/ - Android:
synheart/vendor/runtime/android/jniLibs/<abi>/
3. Configure the platforms
iOS
SetSYNHEART_APP_ROOT near the top of your application’s ios/Podfile:
<app>/synheart/vendor/ during
pod install. Without it they walk up from the pod’s own source directory,
which either fails to find an application root (pods resolved from pub-cache)
or reaches a different project that happens to have a synheart/vendor/
directory — linking a runtime your synheart.lock does not pin.
Enable the HealthKit capability when using health data. Add usage descriptions
to ios/Runner/Info.plist:
Android
Declare only the permissions required by the sources you enable:FlutterFragmentActivity:
compileSdk. The package
compiles against 36, matching Flutter’s default and the sibling AndroidX
dependencies. The minimum supported Android version is unchanged at API 24.
Start here
The minimum integration has five steps:- Initialize the SDK.
- Ask the user for consent.
- Subscribe to HSI output.
- Start a collection session.
- Stop the session and release resources.
Initialization
SynheartConfig.validate() requires:
- a non-empty
appId; - a non-empty
subjectId; - a
subjectIdthat does not contain|; PrivacyConfig(allowResearch: true)when using research mode.
userId: to initialize() does not populate config.subjectId. Set
subjectId on the config itself.
Initialization is idempotent. Concurrent callers share the in-progress
initialization, and calls made after initialization are no-ops.
By default, initialization does not collect data. Call startSession() after
consent is ready. Use autoStart: true only when consent has already been
completed.
Modes
When the signed-in identity changes, keep the runtime identity aligned without
reinitializing:
Running without cloud credentials
The SDK is usable with no platform account. OmitCloudConfig and
DeviceAuthConfig, and everything on-device works: collection, HSI
computation, consent, local storage, and baselines. Nothing leaves the device
and no attestation is attempted.
The runtime consent-form flow needs a ConsentConfig to stamp submissions:
Consent
Consent and capability are different:- Capability says what the application is authorized to use.
- Consent says what the user allows.
biosignalsphoneContextbehaviorcloudUploadvendorSyncresearchsyni
Local development consent
hasConsent() reports whether a channel is currently enforceable, not what the
user chose. Once cloud is configured, the runtime denies every channel until a
consent token is issued.
For hosted consent profiles and JWT lifecycle, see
Consent System.
Feature activation and sessions
Module config enables the corresponding module. Features may also be activated explicitly:
Start and stop the full collection lifecycle:
startSession() requires both halves of a pair: a collection feature enabled
in SynheartConfig (wearConfig / behaviorConfig / phoneConfig) and
its matching consent granted (biosignals / behavior / phoneContext).
Neither alone is enough, and cloudUpload, vendorSync, research, and
syni never qualify — they govern what happens to data once gathered. A
session that could collect nothing throws a StateError instead of starting.Reading HSI
Typed state
Most Flutter applications should use:HSIAxes.hasDigital to check whether the window carried
any of them.
onStateUpdate parses each HSI window once and shares the result across
subscribers. Synheart.currentHSIState reuses the same parse, so it is cheap
to read repeatedly.
Canonical JSON
Use the raw stream when forwarding or validating the exact HSI 1.3 envelope:HSIState.rawJson preserves the same JSON. See
HSI in Synheart Core for mapping details.
Raw source streams
Synheart.getSessionHsiWindows() and Synheart.getSessionWearSamples(). Both
are capped ring buffers — see maxSessionHsiWindows and
maxSessionWearSamples.
Production device authentication
Production applications should configure hardware-backed device identity:initialize().
Configuring DeviceAuthConfig only makes it possible. Device registration is
deferred until a cloud-bound action needs it:
Synheart.reregisterDeviceAuth() as an explicit repair action if the server
has lost or revoked an otherwise valid local device identity.
Endpoints
The platform origin ishttps://api.synheart.ai, but the SDK does not bake
it in. SYNHEART_BASE_URL is empty unless you set it, and with nothing
configured the native runtime applies its own default. Set it explicitly on any
build that talks to the cloud:
SYNHEART_AUTH_BASE_URLSYNHEART_CONSENT_BASE_URLSYNHEART_INGEST_BASE_URL
Cloud upload
Cloud upload requires:CloudConfig;DeviceAuthConfigin production;cloudUploadconsent;- an issued consent token and a registered device.
CloudConfig.uploadInterval. No host
code is required to move data.
Inspect the queue and user-facing status:
cloudSyncStatus for user interface copy. Queue depth is more useful for
diagnostics than for end users. If HSI is produced but nothing uploads, the
cause is almost always a closed consent gate — lastUploadError names it.
See Cloud Protocol for wire-level details.
Syni chat and sessions
Runtime 0.21.0 and later expose device-signed, non-streaming Syni service calls. ConfigureSYNHEART_BASE_URL and register the device before calling
them. The SDK keeps the active session id after each successful turn, so
subsequent calls continue the same conversation until startNewSession().
SyniServiceException with deliveryUnknown == true,
inspect the session messages before offering a retry; resending immediately
could duplicate a turn.
On an older native runtime isAvailable is false and the rest of the SDK
continues to work. On-device model installation and streaming chat are covered
in Syni for Flutter.
Errors and diagnostics
Configuration validation throwsSynheartError with a stable code. Lifecycle
preconditions commonly throw StateError; invalid arguments throw
ArgumentError; native sync failures throw SyncNativeException.
missingSymbols lists optional native symbols the loaded runtime does not
export. Empty is the healthy state. Anything in it means the vendored runtime
predates this SDK release, so the features behind those symbols are disabled
and return null, -1, or an empty list rather than throwing. The list fills
lazily, so check it after exercising the features you depend on, or pass
probeAll: true for a full audit.
If isAvailable is false, or symbols are missing:
synheart/vendor/runtime/.
Threading
Network-touching calls —syncNow(), flushUploads(),
fetchCloudHsiWindows(), requestDataDeletion(), device registration, and the
consent mutations — run on a background isolate and return a Future. The
per-sample push calls (pushWearHr, pushRr, pushAccel, tick,
ingestBatch) are synchronous and safe on the UI isolate at sensor rates.
Diagnostic getters are cheap synchronous FFI reads, but they are still FFI
calls: do not poll them per frame.
Testing
Flutter example application
Initialization, consent, sessions, HSI, watch integration, and runtime diagnostics
Upgrading
Notable changes since 0.10:
The bundle-secret configuration fields —
SynheartConfig.capabilityToken and
.capabilitySecret, CloudConfig.apiKey, and ConsentConfig.appApiKey — are
deprecated and pending removal. The native runtime dropped bundle-secret
configuration as a security fix, so these values are no longer forwarded to it.
Use deviceAuthConfig instead, and never ship an API key or signing secret
inside an application bundle.
See the changelog
for the full list.
Advanced APIs
The package also provides:- local session storage and retention;
- cross-device sync and baseline transfer;
- sleep, recovery, readiness, resilience, and breathing models;
- Apple Health and Health Connect backfill;
- watch-to-phone
EdgeIngest; - lab protocols and research-study enrolment;
- secondary
SynheartInstanceruntime handles; - Syni adaptive AI integration.
Architecture
Runtime, modules, and data flow
Consent System
Consent channels and JWT lifecycle
Scoring Models
Sleep, recovery, and readiness
Health Backfill
Historical HealthKit and Health Connect import