Integrations

beta

Your users connect a provider account once; Sahha syncs their data continuously — server-side, no SDK to ship.

Introduction

Integrations pull health data straight from a provider's cloud — Garmin , Oura , WHOOP — into Sahha, with no SDK on the device . The user connects their provider account once; Sahha syncs their data continuously onto the same profile. It's the third way to get data into Sahha, alongside the SDK and REST API .

Public beta

Integrations are in public beta and are Sandbox only . We're still refining the API surface as it matures and will call out any breaking changes here as they land.


Supported providers

Provider Slug Device Connection Status
Garmin garmin Watch Cloud OAuth Beta Garmin approval required
Oura oura Ring Cloud OAuth Beta self sign-up
WHOOP whoop Band Cloud OAuth Beta self sign-up
Samsung Health Phone / watch On-device SDK Coming soon collected via the SDK

The slug is the value you pass as {provider} throughout the API (see Connect a user ).

Need another provider?

Request one in the Slack Community — tell us the provider and the data you need. Demand drives our priority.


Data coverage

What you get depends on the provider, the user's device, and the scopes you enable. Sahha normalizes every provider into the same data logs , biomarkers , scores and archetypes — so once data is in, you consume it the same way regardless of source.

The matrix below is indicative . See each provider's page for the authoritative, scope-by-scope list.

Data GarminOuraWHOOP
Steps & activity
Sleep & sleep stages
Heart rate
Heart rate variability
Blood oxygen (SpO₂)
Respiratory rate
Body temperature
Workouts & exercise
VO₂ max / fitness
Body composition
Menstrual cycle
Blood pressure
Demographics

available · not provided. Exact availability depends on the user's device and the scopes you enable — see each provider's page.

Scores are computed from whatever you collect

Sahha Scores (Sleep, Activity, Readiness, Wellbeing, Mental) are derived from the underlying data — so a connected provider contributes to scores automatically, even if it doesn't expose a matching raw metric. More data sources generally mean more complete scores.


Data freshness & history

Every provider is webhook-driven : the provider notifies Sahha over webhooks as new data is recorded, so data usually lands within minutes of the user's device syncing to the provider's cloud. Sahha does not poll on a fixed schedule.

When a user first connects, Sahha backfills the last 30 days of available history, then syncs continuously from then on.

Provider Live sync Backfill on connect
Garmin Push (webhooks) 30 days — Requires the user to grant Garmin's historical-data permission
Oura Pull (webhooks) 30 days
WHOOP Pull (webhooks) 30 days

Latency depends on the device

End-to-end freshness is bounded by when the user's device syncs to the provider — e.g. an Oura ring that syncs once each morning delivers the night's data at that point, not in real time. Sahha forwards it within minutes of receiving it.

Garmin historical permission

If a Garmin user does not grant historical-data permission during authorization, the 30-day backfill is skipped and only data recorded after connection flows in. Going-forward sync is unaffected.


How it works

Integrations use three concepts. The same vocabulary appears in the dashboard and the API:

Term What it is
Provider A data source you can connect — Garmin, Oura, WHOOP.
Integration Your configured app for a provider — the OAuth credentials and scopes you set up once in the Sahha Dashboard.
Connection One end-user's authorized link to a provider, created when they complete the OAuth flow.

Setting up a provider is three steps:

  1. Create an app with the provider — register in the provider's developer console to obtain OAuth credentials.
  2. Create an integration in Sahha — add those credentials to your project in the Sahha Dashboard .
  3. Connect an end user — start the OAuth flow for a user via the Sahha API or SDK. Once they authorize, Sahha begins syncing automatically.

Follow the provider-specific guide above for exact console steps and scopes.


Connect a user

Once an integration is configured, you trigger the connection flow per end user. There are two ways: the API (server-driven or web flows) and the SDK (native mobile).

Before you start

You need:

  • A configured integration for the provider (the three steps above).
  • A profile token for the end user — this scopes the connection to that specific user. See Authentication for how tokens work and Getting Started to obtain one.
  • The end user to have an account with the provider (e.g. a Garmin Connect or Oura account).

Examples use the sandbox environment ( sandbox-api.sahha.ai). Swap to api.sahha.ai for production — see Environments .

Option A — Sahha API

The connection is a standard OAuth redirect round-trip:

  1. You call Sahha's authorize endpoint with the user's profile token. Sahha returns an authorizationUrl.
  2. You redirect the user's browser to that authorizationUrl (the provider's consent screen).
  3. The user approves access on the provider's site.
  4. The provider redirects back to Sahha's callback; Sahha stores the connection and starts syncing.
  5. Sahha redirects the user to your redirectUrl so your app can show a success state.

The optional redirectUrl must match an entry in the integration's Redirect URL Whitelist; if omitted, Sahha uses the first whitelisted URL.

curl -X GET "https://sandbox-api.sahha.ai/api/v1/integration/oauth/{provider}/authorize?redirectUrl=https://yourapp.com/integrations/callback" \
-H "Authorization: profile {your-profile-token}"
{
"authorizationUrl": "https://connect.garmin.com/oauthConfirm?..."
}

Replace {provider} with the provider's slug from the Supported providers table (e.g. garmin). Each provider's page has the full request and language-specific snippets.

Once a user is connected, you read their data the same way as any other Sahha data — via the REST API or Webhooks . There's nothing integration-specific about consuming it.

Handling the redirect

After the OAuth flow, Sahha redirects the user to your redirectUrl with query parameters describing the outcome — handle them however your app needs.

Success

Parameter Reason
status=success Authorization completed and the connection was created.

Errors

Error redirects include status=error and an error message. This covers a user denying access on the provider's consent screen, which is returned as provider denied authorization:

error value Reason
provider denied authorization: <provider_error> The user denied consent, or the provider returned an error. <provider_error> is the provider's own value (e.g. access_denied).
authorization code is missing The provider redirected back without an authorization code.
integration not found No integration is configured for this account and provider.
provider not supported The provider is not supported.
failed to process integration credentials The stored client credentials could not be processed.
failed to exchange authorization code Exchanging the authorization code for a token failed.
failed to resolve provider user identity The provider user could not be identified from the token.
failed to store provider user Persisting the provider user failed.
failed to create connection Creating the connection record failed.

Parameter values are URL-encoded — e.g. error=authorization code is missing comes back as error=authorization+code+is+missing.

The user has 10 minutes to authorize after the authorizationUrl is generated; after that the session expires and they'll need a fresh authorizationUrl to try again. If the state parameter is missing, expired, or already used, the callback responds with HTTP 400 Bad Request instead of redirecting — there's no trusted redirectUrl to return to in that case.

Option B — Sahha SDK

Coming soon

SDK support for Integrations is in development. The connection flow will be initiated from the native SDK; the API above is available today.


Managing connections

A connection moves through a simple lifecycle: connected → (token expires) needs re-auth → disconnected . You can see and manage every connection in the Sahha Dashboard under Integrations → Connections .

Deleting a connection

Deleting a connection revokes a single end-user's link to a provider — Sahha stops ingesting their data immediately. A connection can be deleted in two ways:

  • You , from the Sahha Dashboard under Integrations → Connections .
  • The user , from their own provider account settings.

Deleting an integration

Deleting an integration removes your configured app for a provider — its OAuth credentials and scopes. Do this from the Sahha Dashboard under Integrations → Integrations .

This deletes every connection

Deleting an integration deletes every connection created under it, so their data stops syncing. If you recreate an integration with the same credentials, those users will need to reauthenticate to reconnect.


Troubleshooting

A user connected but no data is arriving

A successful connection can still fail to deliver data for a few reasons:

  • The user denied certain scopes. They approved the connection but declined specific data permissions during authorization, so those categories never sync.

  • The webhook URL is misconfigured. Check that the webhook URL from your Sahha integration is set correctly in the provider's developer console — see the provider's page.

  • A push/pull provider isn't set to push. Providers that offer both push and pull delivery (e.g. Garmin) must have their endpoints set to push — pull-mode endpoints deliver nothing.

  • Rate limiting is throttling delivery. Hitting the provider's rate limits for your app can delay or drop data; request higher limits from the provider if you need them. (Sahha will add alerts for excessive rate limiting in a future release.)

    undefined
The OAuth flow fails immediately

The most common cause is a redirect URL mismatch. Make sure the Sahha callback URL is registered in your provider app's allowed redirect URIs, and that any redirectUrl you pass matches an entry in your integration's Redirect URL Whitelist.

How far back does data go when a user first connects?

The historical backfill window depends on the provider. See the provider page for specifics; new data flows continuously once connected.


Support

Need help? Contact support@sahha.ai or join the Slack Community . </content> </invoke>

Next
SDK