Set up wearable providers

Register an OAuth app at Oura, WHOOP, Strava, Withings, Polar, Suunto or Ultrahuman, then save it in the Ovok Console or through the API so your patients can connect.

Before a patient can connect a provider, your project needs an OAuth app at that provider, saved in Ovok. Do this once per provider and per Ovok environment. Only a project admin can see or change provider setup.

1. Find your callback URL

The provider sends the patient back to Ovok's callback after consent. Every provider has its own, and it is the same for every project on an Ovok environment. On the sandbox it is:

https://api.sandbox.ovok.com/v1/wearables/oauth/<provider>/callback

Copy the exact value from the console (Callback URL, with a Copy URL button on each provider card) or from redirectUri in GET /v1/wearables/providers. Register it exactly, with no trailing slash.

Webhook URLs

Withings, Polar and Suunto also notify Ovok when a patient has new data, and Ovok syncs that connection about 30 seconds later. Each project has its own notification URL per provider, shown as webhookUrl in GET /v1/wearables/providers once the provider is saved:

https://api.sandbox.ovok.com/v1/wearables/webhooks/<project id>/<provider>

Withings does not sign its notifications, so its URL ends with a secret token: …/withings/<token>. Only project admins can read it; keep it private. You only paste a webhook URL for Suunto: Ovok registers Withings' and Polar's itself. Oura, WHOOP, Strava, Ultrahuman and Garmin send no notifications to Ovok, and their webhookUrl is null.

webhookReady in the same answer says whether notifications will be accepted: true once Ovok holds the secret that checks them. If it stays false for Polar, the webhook setup at Polar failed or the client's webhook belongs to another project; save Polar again. For Suunto, it turns true once you send webhookSecret.

2. Register an app at the provider

Follow the quickstart for the provider below. Every provider asks for an app name, and most for a website and a privacy policy: these are shown to your patients on the consent page, so use your product's.

Oura

Developer portalcloud.ouraring.com, My Applications
Redirect URIhttps://api.sandbox.ovok.com/v1/wearables/oauth/oura/callback
Scopes Ovok requestspersonal daily heartrate workout session spo2 ring_configuration heart_health
Ovok needsThe app's client ID and client secret
SyncedYes, see the matrix

WHOOP

Developer portaldeveloper.whoop.com, Developer Dashboard
Redirect URLhttps://api.sandbox.ovok.com/v1/wearables/oauth/whoop/callback
Scopes Ovok requestsoffline read:profile read:cycles read:sleep read:recovery read:workout
Ovok needsThe app's client ID and client secret
SyncedYes, see the matrix

Select every scope above when you create the app. offline is what lets Ovok refresh the token; without it, every connection needs reconnecting once its first token expires.

Strava

Developer portalstrava.com/settings/api
Authorization Callback Domainapi.sandbox.ovok.com. Strava asks for the domain only, not the full URL.
Scopes Ovok requestsactivity:read_all,profile:read_all
Ovok needsThe app's client ID and client secret
SyncedYes: each workout's average heart rate

Ovok always shows Strava's consent screen (approval_prompt=force), so a consent link forwarded to someone else cannot connect silently. Strava limits how many athletes a new app can connect until Strava reviews it; request the review before you roll out.

Withings

Developer portaldeveloper.withings.com, Developer Dashboard
Callback URLhttps://api.sandbox.ovok.com/v1/wearables/oauth/withings/callback
Scopes Ovok requestsuser.info,user.metrics,user.activity
Ovok needsThe app's client ID and client secret
NotificationsAutomatic: Ovok subscribes each patient when they connect. Nothing to paste.

Register a new app. The client ID of Ovok's legacy Withings device integration is refused with 422 CLIENT_ID_RESERVED.

Polar

Developer portalPolar AccessLink
Redirect URLhttps://api.sandbox.ovok.com/v1/wearables/oauth/polar/callback
Scopes Ovok requestsaccesslink.read_all
Ovok needsThe app's client ID and client secret
NotificationsAutomatic: saving Polar creates the client's webhook at Polar. Nothing to paste.
  • Patients must accept Polar's consents. Polar shares data only for users registered to your app, so Ovok registers the patient right after they consent. A patient who has not accepted Polar's mandatory data-sharing consents in their Polar account is refused, and the connection ends with result=failed.
  • Use one Polar client per Ovok project. A Polar client has one webhook. Ovok points it at the project that saved it and never touches a webhook pointing elsewhere, so a second project on the same client shows webhookReady: false, gets no notifications and relies on the daily sync.
  • Polar's access tokens cannot be refreshed. When Polar stops accepting one, the connection needs reconnecting.

Suunto

Developer portalapizone.suunto.com
Redirect URIhttps://api.sandbox.ovok.com/v1/wearables/oauth/suunto/callback
ScopesSet in Suunto's portal
Ovok needsThe app's client ID and client secret, the subscription key, and optionally the notification secret
NotificationsManual: paste Ovok's webhookUrl as the app's notification URL in Suunto's portal
  1. Register the app and subscribe it to the Cloud API product. Your Suunto profile page then shows the app's credentials and its subscription key. Suunto approves apps before they work.
  2. Save Suunto in Ovok with the subscription key.
  3. Read webhookUrl from GET /v1/wearables/providers/suunto. In the Suunto portal, paste it as the app's notification URL and set a notification secret.
  4. Give Ovok the same secret as webhookSecret, with PATCH /v1/wearables/providers/suunto. Until it is stored, Ovok refuses Suunto's notifications with 401 and syncs Suunto only daily and on demand.

Ovok syncs Suunto's daily steps only. Whether Suunto signs notifications with the secret set in its portal is unconfirmed without partner access.

Ultrahuman

Developer portalvision.ultrahuman.com
Redirect URIhttps://api.sandbox.ovok.com/v1/wearables/oauth/ultrahuman/callback
Scopes Ovok requestsring_data cgm_data profile
Ovok needsThe app's client ID and client secret
NotificationsNone: synced daily and on demand only

Ovok asks Ultrahuman for one day at a time, so a first sync makes 31 requests. Ultrahuman's partner endpoints are partly unconfirmed: see the warning.

Garmin

You can save Garmin and patients can connect it, but Ovok does not sync Garmin data yet: a sync answers 501 SYNC_NOT_SUPPORTED. Garmin's Connect Developer Program admits business applicants only and approves each app; Garmin sync waits for Ovok's partner access.

Fitbit is not supported: its Web API shuts down on 2026-10-30.

3. Save the app in Ovok

In the console

  1. Open the Ovok Console and select the project.
  2. Under Platform, open Wearables. Every provider has a card with its status (Not configured, Enabled or Disabled), a link to its developer portal and its Callback URL.
  3. On the provider's card, select Set up.
  4. Enter the Client ID and Client secret. For Suunto, also enter the Suunto subscription key.
  5. Leave Enable after setup checked to let patients connect right away, then select Save provider settings.

After setup, the card shows the client ID and offers Edit setup, Disable or Enable, and Remove. To rotate the secret, select Edit setup and enter the new one; leave the field blank to keep the saved secret. The console never shows a saved secret.

The console does not show webhookUrl or webhookReady, or take Suunto's notification secret, yet. For those two, use the API.

The page needs a project admin. Other members see "A project administrator is required to view and manage wearable providers."

Through the API

Use a project admin's access token.

export OVOK_TOKEN='<access token of a project admin>'

Save the provider:

curl --request POST \
  --url 'https://api.sandbox.ovok.com/v1/wearables/providers' \
  --header "Authorization: Bearer ${OVOK_TOKEN}" \
  --header 'Content-Type: application/json' \
  --data '{"provider":"oura","clientId":"<client id>","secret":"<client secret>"}'

The answer is 201, with Location: /v1/wearables/providers/oura:

{
  "provider": "oura",
  "configured": true,
  "enabled": true,
  "clientId": "<client id>",
  "redirectUri": "https://api.sandbox.ovok.com/v1/wearables/oauth/oura/callback"
}

For Suunto, add "subscriptionKey":"<subscription key>", and optionally "webhookSecret":"<notification secret>". No other provider takes either.

The answer also carries webhookUrl, null for providers that send no notifications.

Then, as needed:

# Rotate the secret
curl --request PATCH \
  --url 'https://api.sandbox.ovok.com/v1/wearables/providers/oura' \
  --header "Authorization: Bearer ${OVOK_TOKEN}" \
  --header 'Content-Type: application/json' \
  --data '{"secret":"<new client secret>"}'

# Stop new connections; connected patients stay connected
curl --request PATCH \
  --url 'https://api.sandbox.ovok.com/v1/wearables/providers/oura' \
  --header "Authorization: Bearer ${OVOK_TOKEN}" \
  --header 'Content-Type: application/json' \
  --data '{"enabled":false}'

The API reference lists every field and error. The @ovok/core client has the same operations: createWearableProvider(), updateWearableProvider(), deleteWearableProvider(), listWearableProviders() and getWearableProvider().

4. Check it

  • The provider's card shows Enabled, or GET /v1/wearables/providers/<provider> answers "configured": true, "enabled": true.
  • PATIENT_APP_URL is set on the project. Without it, patients cannot connect.

Then connect a patient.

What disabling and removing do

ActionNew connectionsPatients already connectedDaily sync of connected patients
Disable (enabled: false)Refused with 404 PROVIDER_NOT_AVAILABLEStay connected and can disconnectStops: a sync answers 404 PROVIDER_NOT_AVAILABLE
Remove (DELETE)RefusedStay connected until they disconnectStops, as above

Patients' grants are not revoked either way; they remove your app's access in their provider account. For Polar, disabling leaves the webhook at Polar and its notifications answer 404 until you enable Polar again; removing Polar also deletes the webhook if it points at this project.

Keep the credentials safe

  • Ovok encrypts the secret and subscription key before storing them and never returns them, in the console or the API.
  • The stored credentials are bound to the project: copied into another project, they read as not configured.
  • A server that cannot encrypt refuses to store anything and answers 501 FEATURE_NOT_CONFIGURED.

Last updated on

On this page