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.
Overview
The Synheart Core Flutter SDK provides a unified API for collecting HSI-compatible data, processing human state on-device, and generating focus/emotion signals in Flutter applications.
Key Features:
- Cross-platform support (iOS + Android)
- On-device HSI Runtime
- Real-time state updates
- Modular design (enable only what you need)
- Privacy-first architecture
Installation
Add to your pubspec.yaml:
dependencies:
synheart_core: ^0.0.4
Install dependencies:
iOS Configuration
Add to ios/Runner/Info.plist:
<!-- Health data access (if using Wear module) -->
<key>NSHealthShareUsageDescription</key>
<string>This app needs access to your health data to provide insights.</string>
<!-- Motion & Fitness (if using Phone module) -->
<key>NSMotionUsageDescription</key>
<string>This app uses motion data to understand your activity patterns.</string>
Android Configuration
Add to android/app/src/main/AndroidManifest.xml:
<!-- Required permissions -->
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" />
<!-- Health Connect Permissions (if using Wear module) -->
<uses-permission android:name="android.permission.health.READ_HEART_RATE"/>
<uses-permission android:name="android.permission.health.READ_HEART_RATE_VARIABILITY"/>
Basic Usage
Initialize the SDK
import 'package:synheart_core/synheart_core.dart';
// Initialize with basic modules
await Synheart.initialize(
userId: 'anon_user_123',
config: SynheartConfig(
allowUnsignedCapabilities: true, // Use capabilityToken in production
),
);
Subscribe to HSI Updates
The HSI (Human State Intelligence) stream emits raw JSON from the on-device runtime:
// onHSIUpdate emits raw HSI JSON from the Synheart Runtime
Synheart.onHSIUpdate.listen((hsiJson) {
print('HSI JSON: $hsiJson');
});
Activate optional modules
The SynheartFeature enum gates collection by feature. Activation is one
of four conditions a feature needs (the others are consent, capability
tier, and an active session — see Capability System).
// Available features:
// SynheartFeature.wear — biosignals from wearables
// SynheartFeature.behavior — interaction telemetry
// SynheartFeature.phoneContext — motion / screen / app context
// SynheartFeature.cloud — HSI upload connector
Synheart.activate(SynheartFeature.wear);
Synheart.activate(SynheartFeature.cloud);
// Stop a feature without uninitializing the SDK.
Synheart.deactivate(SynheartFeature.cloud);
State signals (focus, emotion, recovery, etc.) are not separate features
— they’re axes inside the HSI JSON emitted by Synheart.onHSIUpdate.
Parse the JSON or use the typed Synheart.onStateUpdate stream to read
them.
Enable the cloud connector
Upload HSI 1.3 snapshots when the host has been granted cloudUpload
consent:
await Synheart.initialize(
userId: 'anon_user_123',
config: SynheartConfig(
allowUnsignedCapabilities: true, // use capabilityToken in production
cloudConfig: CloudConfig(
appId: 'your_app_id',
subjectId: 'user_123',
instanceId: 'device_abc',
baseUrl: 'https://api.synheart.ai',
maxQueueSize: 100,
),
),
);
// Uploads happen automatically when consent is granted, the queue has
// pending snapshots, and the network is reachable. Inspect upload state
// via the diagnostics getters:
final pending = Synheart.uploadQueueLength;
final lastBatch = Synheart.lastUploadBatchId;
final lastError = Synheart.lastUploadError;
Synheart.deactivate(SynheartFeature.cloud); // pause uploads
Complete example
import 'package:flutter/material.dart';
import 'package:synheart_core/synheart_core.dart';
class HumanStateMonitor extends StatefulWidget {
@override
State<HumanStateMonitor> createState() => _HumanStateMonitorState();
}
class _HumanStateMonitorState extends State<HumanStateMonitor> {
HSIState? _state;
String? _rawHsi;
bool _ready = false;
@override
void initState() {
super.initState();
_bootstrap();
}
Future<void> _bootstrap() async {
await Synheart.initialize(
userId: 'user_123',
config: SynheartConfig(allowUnsignedCapabilities: true),
);
Synheart.activate(SynheartFeature.wear);
Synheart.activate(SynheartFeature.behavior);
Synheart.onHSIUpdate.listen((json) => setState(() => _rawHsi = json));
Synheart.onStateUpdate.listen((s) => setState(() => _state = s));
setState(() => _ready = true);
}
@override
void dispose() {
Synheart.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
if (!_ready) return const Center(child: CircularProgressIndicator());
final axes = _state?.hsi;
return Scaffold(
appBar: AppBar(title: const Text('Human State')),
body: ListView(padding: const EdgeInsets.all(16), children: [
Text('Focus: ${axes?.focus?.value.toStringAsFixed(2) ?? '—'}'),
Text('Arousal: ${axes?.arousal?.value.toStringAsFixed(2) ?? '—'}'),
Text('Capacity: ${axes?.capacity?.value.toStringAsFixed(2) ?? '—'}'),
const SizedBox(height: 16),
if (_rawHsi != null)
Text('Raw HSI: ${_rawHsi!.substring(0, 100)}…'),
]),
);
}
}
HSI state reference
Synheart.onHSIUpdate emits raw HSI 1.3 JSON strings. The typed
projection of that JSON is HSIState, surfaced via
Synheart.onStateUpdate. Most apps use the typed stream; reach for the
raw JSON only when you need fields the typed projection doesn’t expose
(for example, the 64D embedding vector).
class HSIState {
final String subjectId;
final int timestampMs;
final HSIAxes hsi;
final Modalities modalities;
final Tiers tiers;
final String rawJson;
}
class HSIAxes {
final HSIAxisValue? focus;
final HSIAxisValue? arousal;
final HSIAxisValue? capacity;
final HSIAxisValue? sleep;
}
class HSIAxisValue {
final double value; // 0.0–1.0
final double confidence; // 0.0–1.0
}
modalities and tiers carry per-axis source attribution and capability gating. The exact shape can drift between HSI versions; treat the typed fields as best-effort and the rawJson as authoritative. See the HSI specification and Synheart Core HSI mapping.
Cloud connector
The cloud connector uploads HSI 1.3 snapshots to the Synheart Platform
when the host has been granted cloudUpload consent.
await Synheart.initialize(
userId: 'anon_user_123',
config: SynheartConfig(
allowUnsignedCapabilities: true, // use capabilityToken in production
cloudConfig: CloudConfig(
appId: 'your_app_id',
subjectId: 'user_123',
instanceId: 'device_abc',
baseUrl: 'https://api.synheart.ai',
maxQueueSize: 100,
),
),
);
// Once activated, the connector handles uploads automatically:
// - flushes when HSI windows close and consent is granted
// - queues during offline windows (FIFO, capped by maxQueueSize)
// - retries failed uploads with exponential backoff
//
// Inspect state through diagnostic getters:
final pending = Synheart.uploadQueueLength;
final lastBatch = Synheart.lastUploadBatchId;
final lastError = Synheart.lastUploadError;
// Pause / resume:
Synheart.deactivate(SynheartFeature.cloud);
Synheart.activate(SynheartFeature.cloud);
Authentication is hardware-backed device ECDSA per
RFC-AUTH-MOBILE-0001.
The runtime owns request signing via the host’s synheart-auth
integration — CloudConfig does not carry shared secrets or
HMAC keys. See Synheart Auth overview for
the device-identity flow.
Upload Payload (HSI 1.3 format):
{
"subject": {
"subject_type": "pseudonymous_user",
"subject_id": "user_123"
},
"snapshots": [
{
"hsi_version": "1.3",
"observed_at_utc": "2025-12-28T10:30:00Z",
"computed_at_utc": "2025-12-28T10:30:10Z",
"producer": {
"name": "Synheart Core SDK",
"version": "1.0.0",
"instance_id": "device_abc"
},
"windows": {
"micro": {
"start_utc": "2025-12-28T10:29:30Z",
"end_utc": "2025-12-28T10:30:00Z",
"duration_seconds": 30
}
},
"axes": {
"affect": {
"arousal_index": 0.72,
"valence_stability": 0.65
},
"engagement": {
"engagement_stability": 0.81,
"interaction_cadence": 0.55
},
"behavior": {
"motion_index": 0.45,
"posture_stability": 0.78,
"screen_active_ratio": 0.90,
"session_fragmentation": 0.22
}
},
"embeddings": [
{
"dimension": 64,
"model": "synheart-jl-64",
"vector": [0.12, 0.34, ...]
}
],
"privacy": {
"contains_pii": false
}
}
]
}
Configuration Options
final config = SynheartConfig(
// Update interval for HSV processing
updateInterval: Duration(seconds: 30),
// Cloud configuration (optional).
cloudConfig: CloudConfig(
appId: 'your_app_id',
subjectId: 'user_123',
instanceId: 'device_abc',
baseUrl: 'https://api.synheart.ai',
),
// Capability JWT (optional, for extended/research access).
capabilityToken: null,
// Log level
logLevel: LogLevel.info,
);
await Synheart.initialize(
userId: 'user_123',
config: config,
);
Error Handling
try {
await Synheart.initialize(
userId: userId,
config: config,
);
} on PermissionDeniedError catch (e) {
print('Permission denied: ${e.message}');
} on InitializationError catch (e) {
print('Initialization failed: ${e.message}');
} on SynheartError catch (e) {
print('SDK error: ${e.message}');
}
Privacy & Consent
The SDK enforces consent at multiple levels:
// Coarse status — granted | pending | expired | denied
final status = await Synheart.consentStatus();
// Per-type check (wire strings: biosignals, phoneContext, behavior,
// cloudUpload, vendorSync, research)
final canUpload = await Synheart.hasConsent('cloudUpload');
final canRead = await Synheart.hasConsent('biosignals');
// Request consent — opens the cloud consent flow when configured.
final token = await Synheart.requestConsent();
if (await Synheart.hasConsent('cloudUpload')) {
Synheart.activate(SynheartFeature.cloud);
}
// Revoke a single type or everything
await Synheart.revokeConsentType('cloudUpload');
await Synheart.revokeConsent();
For the full consent model (granular channels, tiers, JWT lifecycle), see Consent System.
These are design targets, not measured runtime numbers — profile
your own app for ground truth on the current build. Use the
diagnostic getters to inspect what the SDK is actually doing.
Diagnostics & upload inspection
// Live counters and last-error strings.
final diag = Synheart.runtimeDiagnostics();
print(diag);
// Synchronous getters — safe to read from UI code.
final depth = Synheart.uploadQueueLength;
final lastMs = Synheart.lastIngestSuccessAtMs;
// Manually flush queued snapshots when consent + network are eligible.
final result = await Synheart.ingestion.flushIfEligible();
API reference
Synheart
Main SDK class.
Static methods:
| Method | Description | Returns |
|---|
initialize(...) | Initialize the SDK | Future<void> |
activate(feature) | Activate a feature | void |
deactivate(feature) | Deactivate a feature | void |
dispose() | Tear down the SDK and release resources | Future<void> |
runtimeDiagnostics() | Live counters / last-error strings | Map<String, dynamic> |
Streams:
| Stream | Type | Description |
|---|
onHSIUpdate | Stream<String> | Raw HSI 1.3 JSON, emitted per window close |
onStateUpdate | Stream<HSIState> | Typed projection of onHSIUpdate |
Resources