Developer FAQ
Built for engineers integrating Sahha. Covers SDK setup, identity/auth, permissions, data delivery (API/Webhooks/Widgets), and common debugging pitfalls.
- Mobile SDK: collect and stream device data.
- Webhooks: push computed outputs (scores, biomarkers, archetypes, insights, logs) to your backend.
- API: use for pull-style access or admin workflows.
- Mobile: configure SDK → authenticate user profile → request sensor permission → stream data.
- Backend: receive webhook events → map via
X-External-Id→ store with idempotency → trigger product logic (nudges, segmentation, analytics).
- Use the Sahha Demo App and sync it to your dashboard via the QR flow.
- This validates end-to-end ingestion and dashboard visibility before you write code.
- Yes. Have multiple teammates sync the demo app into the same dashboard account.
- This generates diverse real-world data quickly for QA and internal spikes.
- Use the Example Apps to bootstrap a working integration (platform-specific).
- Webhooks: best for always-on pipelines and near real-time updates.
- API polling: best for dashboards, occasional sync jobs, or if you can’t receive inbound webhooks.
- They are separate environments.
- If SDK is sandbox but backend/webhooks are production (or vice versa), you’ll see missing data.
- Always align environment end-to-end.
- iOS: 14+
- Swift: 5+
- Follow Android setup requirements for Sahha + Health Connect compatibility.
- Includes required permissions and project setup.
- Install guides exist for iOS, Android, Flutter, React Native, Expo, and Ionic Capacitor.
- Configure once at app startup.
- Authenticate a profile per user.
- This avoids sensor/auth state issues and keeps environment routing consistent.
- Set
SahhaEnvironmentcorrectly. - Sandbox for testing, production for release.
- Environment mismatch is a top “no data” cause.
- Sensor status is
pendinguntil the SDK is configured. - Call
getSensorStatusafterconfigure(often in the configure callback).
Your stable, unique user identifier (string). It’s the join key between your user and Sahha data delivery, and appears in webhooks via X-External-Id.
Strongly discouraged. Use an anonymous stable ID (UUID-like). Emails/usernames change and can create privacy + lifecycle headaches.
Treat it like a new identity unless you have a deliberate migration plan. Best practice: keep externalId immutable; if you must change it, expect data to map to a new profile.
They mint an account token (server credential) for admin-style API actions (e.g., profile registration via API).
A server-side credential obtained by exchanging clientId/clientSecret. Use it for account-level actions like registering/authenticating profiles via API.
A user-scoped token returned when you authenticate/register a profile. Use it to access that user’s data and to load widgets for that user.
Yes. Call POST /oauth/profile/register with Authorization: Account <ACCOUNT_TOKEN> + { externalId }, then store the returned profileToken + refreshToken.
No. Do not ship app credentials in client code. Fetch credentials/tokens from your server on app launch.
Use enableSensors to trigger the permission dialog. You should also provide an in-app explanation of “why” you’re requesting access and how scores work for transparency.
Use enableSensors, and ensure Health Connect is available on-device. Provide a pathway to open settings so users can adjust permissions later.
Route them to device settings. On Android, you can open Health Connect and instruct the user to enable data types for your app.
For Android, every sensor you request via getSensorStatus/enableSensors needs matching manifest permissions. Misalignment can cause build errors and review issues.
Sahha abstracts device sensors via the SDK (bridge to Apple Health / Health Connect). You typically: configure → check sensor status → request via enableSensors.
iOS may terminate apps if health permissions change while the app is in the background. Your UX should anticipate relaunch and re-check sensor status on next open.
Scores: normalized 0–1 health indices (with factors). Biomarkers: standardized/deduplicated health metrics. Data Logs: raw/unfiltered event stream for deep analysis and auditing.
Use getScores for the authenticated profile. If you need server-side ingestion, consume score webhook events instead of polling.
Use getBiomarkers for the authenticated profile. For backend ingestion, subscribe to biomarker webhook events.
Stats are real-time rolling calculations over the current day (useful for “today so far” metrics like steps). They’re great for in-app live feedback.
getSamples can be slow for large date ranges. Keep ranges tight (e.g., poll only the last few minutes if you’re using a timer), and run off the UI thread.
Use the Data Dictionary to discover all available outputs across scores, biomarkers, archetypes, insights, and logs.
- Use the Data Dictionary for the full, up-to-date list of captured data points.
- It includes scores, biomarkers, archetypes, insights, and data logs, plus whether a wearable is required and how each metric is delivered.
- Any metric marked Requires Wearable = No in the Data Dictionary can be captured from phone-only sources.
- Scores also work with smartphone data alone; wearables add additional factors.
- The Data Dictionary lists which metrics do not require a wearable.
- Biomarkers include activity and engagement metrics (e.g., steps, active duration, app sessions) that can come from phone-only sources.
- Data Logs include exercise session duration by type (e.g., biking, running, walking).
- See the Exercise Logs list for supported exercise types.
- Exercise logs focus on session duration by type (e.g., running, walking, biking).
- For distance-related metrics, confirm availability in the Data Dictionary and Biomarkers list, which reflect the current supported outputs.
- Scores and biomarkers update throughout the day; webhooks let you control delivery frequency using the interval setting.
- Real-time is available, or you can batch updates (1–720 minutes).
- Data logs are always delivered in real time.
Use UI Widgets in a webview: call a widget endpoint using the user’s profileToken. Great for MVPs and faster UI shipping.
Widgets follow system theme by default; override via a theme query parameter in the widget URL when needed.
Archetypes: segmentation labels derived from longer-term patterns. Insights: trends/comparisons over time. Both are available via webhooks/events for backend automation.
Sahha pushes events you subscribe to (scores, biomarkers, archetypes, insights, raw logs) so you don’t have to poll. This is the preferred approach for most production pipelines.
At minimum: X-Signature (verification) and X-External-Id (identity mapping).
Compute an HMAC over the raw request body bytes using your webhook secret and compare to X-Signature. Common failure: re-serializing JSON (whitespace/order changes) instead of hashing the raw payload.
The interval is a deduplication/batching window for scores + biomarkers. Updates within the window are held; only the final value is delivered at interval end.
No. Data log events (e.g., DataLogReceivedIntegrationEvent) are always delivered immediately because each log is new raw data.
Use the Event Reference for field-by-field payload structure and examples.
Make handlers idempotent and fast: accept duplicates/retries, return 2xx quickly, and use event id (or a deterministic key) for de-duping in storage/queues.
Log inbound headers (X-External-Id, X-Signature) + request body, validate signature logic, and confirm event parsing against the Event Reference.
Check: (1) environment match (sandbox/prod), (2) profile authenticated, (3) permissions granted (Apple Health/Health Connect), (4) verify device actually has data, (5) if using webhooks, confirm interval expectations.
Classic environment mismatch: SDK sending to sandbox while backend/webhooks configured for production (or vice versa). Align environments and tokens across systems.
Often near real-time, but webhooks can be delayed by interval batching for scores/biomarkers. Raw logs remain immediate, so they’re a good signal for “data is flowing.”
Usually not a bug—your webhook interval is batching updates and delivering the final value at window end. If you need every update, set interval to real-time.
Use X-External-Id header to map to your user record. This is why externalId must be stable and unique.
Ensure you HMAC the raw request body exactly as received. Avoid parsing + re-stringifying JSON before hashing.
Most common causes: wrong token type (Account vs Profile), expired/invalid token, or environment mismatch. Confirm you’re using the correct auth scheme for the endpoint.
Confirm Health Connect is installed/available, permissions are granted for the requested data types, and your app provides a path to open Health Connect settings.
Follow Sahha’s app submission guidance. Common requirements: clearly explain what health data you access and why, and provide transparency resources for displayed scores.
Describe which health data you collect and why (purpose + benefit to user), and ensure App Privacy answers align with actual data usage.
Pay attention to permissions that require review (e.g., Foreground Service Health / Health Connect), and ensure requested permissions match your manifest + in-app behavior.
If you present health scores in a “medical-ish” context, include accessible scientific references/links for transparency (Sahha provides recommended references).
Garmin requires attribution (e.g., “Garmin [device model]”) next to Garmin-sourced data. Implement by storing device/source info from raw log events and showing it in UI/exports.
Position scores as indicative insights, not diagnoses. For compliance-sensitive apps, link to Sahha’s scientific positioning and validation context.
Use the score’s factors and “health states” concept in your UX to improve transparency and reduce user confusion (“what changed?”).