When you turn cloud upload on, Synheart Core hands HSI snapshots to the runtime’s unified ingest connector. The connector batches, signs, and uploads them to Synheart Platform. This page is the developer-facing reference for what crosses the wire and how to authenticate.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.
The runtime owns the upload queue and signing. You enable cloud upload in your config — most apps never touch the lower-level paths described here.
Architecture
The connector is part of the Synheart runtime (native). The Dart/Swift/Kotlin SDKs do not maintain their own queues.Core principles
- Consent-gated — every upload checks the runtime’s consent state before sending.
- Derived data only — only HSI snapshots leave the device. No raw biosignals, no clipboard contents, no notification bodies.
- Hardware-backed authentication — every request is signed by an ECDSA P-256 key in the device’s Secure Enclave (iOS) or Android Keystore.
- Per-request consent token — every upload carries a JWT issued by the consent service.
- Tenant-isolated — payloads route to per-
org_idstorage; no cross-tenant access. - Offline-resilient — the runtime persists its queue in SQLite; uploads resume after restart and reconnect.
- Rate-limited — the runtime caps outbound flow at 10 uploads/sec, burst 20.
Endpoint
The runtime POSTs to:Research consent is granted, the runtime also POSTs to:
<api_base_url> is https://api.synheart.ai by default; enterprise customers can override via the SYNHEART_API_URL environment variable or synheart.json.
Authentication
Every request carries two pieces of authentication:X-Synheart-Proof
A compact JWS (JSON Web Signature) bound to this specific request. Built by the runtime via synheart_core_sdk_build_proof_header(method, url).
The proof binds:
- The HTTP method.
- The signing path (the runtime strips the
/ingest/prefix; signing is over/v1/hsi). - The device’s registered
device_id. - A subject hash.
- A fresh nonce.
The runtime signs
/v1/hsi even though the request is POSTed to /ingest/v1/hsi. If you build clients that talk to /ingest/... endpoints from outside the runtime, mirror this prefix-stripping rule.X-Consent-Token
A JWT issued by the consent service when the user grants cloudUpload consent. Carries:
profile_id— which consent profile the user accepted.expires_at— token validity (refreshed at the 5-minute threshold).scopes— granted channels (e.g.bio:vitals,cloud:upload).
Why not HMAC?
Earlier drafts described an HMAC-SHA256 flow with shared secrets. The shipping implementation uses hardware-backed ECDSA P-256 with attestation perRFC-AUTH-MOBILE-0001. HMAC is not used for cloud ingest. See the Synheart Auth section for the full device-identity flow.
Pre-conditions for upload
Before any HSI window leaves the device, the runtime checks:IngestConfig.enabled = trueandIngestConfig.hsi = true(orlab = truefor lab uploads).- The capability level permits cloud upload.
cloudUploadconsent is granted with a valid token.- The account-deletion override is not active.
- Device-bound crypto callbacks are registered (the host’s
synheart-authintegration). - Network reachability (best-effort).
Cold-start consent buffer
The runtime opens an HSI session immediately, but the consent token may take a few seconds to fetch on cold start. To avoid losing the first window:- The auto-enqueue bridge holds up to 8 pending HSI windows in a FIFO buffer when consent is
pending. - On grant, the buffer drains and replays into the queue.
- If consent never arrives within the buffer window, the oldest windows drop FIFO.
Payload shape
Every upload is an HSI 1.3 JSON envelope produced by the engine. The exact field set follows the canonical HSI specification; the SDK does not reshape it before sending.subject_id you supply in SynheartConfig is never sent in the clear — the runtime hashes it into a per-tenant subject_hash for identity routing, and that’s what reaches the cloud.
Endpoint selection by capability
| Capability level | HSI endpoint | Lab endpoint |
|---|---|---|
core | /ingest/v1/hsi | (lab not available) |
extended | /ingest/v1/hsi (richer payload fields) | /ingest/v1/lab/session |
research | /ingest/v1/hsi (full fields) | /ingest/v1/lab/session |
Lab session uploads
Whenenable lab ingest is set in the SDK config and the user grants research consent, the runtime auto-enqueues the JSON returned by Synheart.labFinalize(...). The runtime stamps the active lab metadata id into session_metadata.extra_data.metadata_id before sending.
Backlog and offline behavior
- Persistent queue: the runtime’s queue is SQLite at
<data_dir>/ingest_upload_queue_<subject_id>.sqlite. Survives app restarts. - Network monitor: the runtime watches
<api_base_url>/healthand exposes reachability viaSynheart.isNetworkReachable. - Backoff: failed uploads use exponential backoff with jitter. Persistent 4xx failures (malformed payload, rejected token) are quarantined and surfaced through the connector’s metadata.
Inspecting upload state
Synheart.ingestion.flushIfEligible() is the canonical entry point for manually draining the queue. Synheart.ingestion.enqueueHsiWindows(...) enqueues HSI JSON windows directly. The Kotlin and Swift SDKs expose the same surface with platform-idiomatic names.
Errors
Common failures and how to handle them:| Failure | Cause | Recovery |
|---|---|---|
| Queue grows but never drains | Consent token expired or never issued | Call Synheart.ensureCloudConsentReady() and confirm consentStatus() is granted. |
| Upload rejected with auth error | Device not registered or proof invalid | Call Synheart.ensureDeviceAuthRegistered(). |
| Upload returns 4xx with malformed payload | Engine emitted a payload the gateway rejects | File a bug — the runtime should not produce invalid HSI. |
Construction errors mentioning org_id | cloudConfig.orgId empty when HSI ingest enabled | Set CloudConfig.orgId in your config. |
Privacy guarantees enforced in code
- Raw
subject_idnever leaves the device — onlysubject_hash. - Raw biosignals never leave the device — only HSI snapshots (and lab session JSON when explicitly enabled).
- Cloud-bound traffic gates on consent at every flush; revocation immediately pauses the connector via the runtime’s consent-check hook.
- TLS 1.2+ for HTTPS; gRPC streams (RAMEN) use
tonicwithtls-webpki-roots. - Account-deletion mode (set via
Synheart.requestAccountDeletion()) fully suspends outbound traffic.
Wipe vs. account deletion
Synheart.wipeLocalData()clears the runtime’s local stores (queue, history, sessions, HSI windows). Does not delete cloud data.Synheart.requestAccountDeletion()puts the runtime in wind-down mode and signals the platform to delete cloud data. CallcancelAccountDeletion()to undo before the platform confirms.
Related
- Synheart Auth — Request Signing — the
X-Synheart-Proofcontract. - Consent System —
cloudUploadconsent, token lifecycle. - Capability System — what each level unlocks.
- HSI Specification — payload schema (HSI 1.3).