Browse the docs

Provider guide

Oura: register your app (API v2)

Access Self-serve; more than 10 users needs Oura's approval [OFF]
Cost Free
Account An Oura account. To test you also need a ring with an active Oura membership (an expired one returns 403) [OFF]
Managed app No: bring your own keys. Oura's 2026 terms require one registration per end customer [2ND]
AI use Forbidden. Oura data never reaches Latido's MCP
Latido slug oura
Time ~10 minutes

Terms that matter

API & MCP Agreement effective 8 Jun 2026 [2ND; section numbers UNVERIFIED]:

  • No prompting or feeding AI models with API data (§4(d)); training, fine-tuning, evaluation and embeddings need prior written consent (§4(a)).
  • Charging users for features built on the API needs written consent (§4(a)(xiii)).
  • Aggregators may not supply Oura data to AI systems (§2(c)) and need a separate registration per end customer (§3(e)). That is why each Latido customer registers their own Oura app.
  • Personal access tokens were removed in Dec 2025 [OFF]: OAuth only.

Read the current agreement at https://cloud.ouraring.com/legal/api-agreement before registering.

Steps

  1. Sign in at https://cloud.ouraring.com and open the OAuth applications page (developer portal, https://developer.ouraring.com) [OFF].

  2. Create a new application [MEM: field names]:

    • Display name, description, contact email, website.
    • Privacy policy URL and terms of service URL (public pages).
    • Redirect URI: https://api.getlatido.com/connect/callback/oura. Must be public HTTPS, no localhost [OW docs].
    • Scopes: tick the ones below.
  3. Copy Client ID and Client Secret.

  4. In Latido, Providers → Oura → Custom app: paste both and set webhookVerificationToken to a long random string. Save, and copy the webhook URL https://api.getlatido.com/providers/oura/webhook/{providerAppId}.

  5. Webhook subscriptions are app-level and created through the API, not the portal, one per data type and event [OFF]. Latido answers the handshake: Oura calls GET callback?verification_token=…&challenge=… and expects {"challenge": "…"} back.

    bash
    for type in workout sleep daily_sleep daily_activity daily_readiness daily_spo2; do
      for event in create update; do
        curl -X POST https://api.ouraring.com/v2/webhook/subscription \
          -H "x-client-id: $OURA_CLIENT_ID" -H "x-client-secret: $OURA_CLIENT_SECRET" \
          -H "Content-Type: application/json" \
          -d "{\"callback_url\":\"<webhook URL>\",\"verification_token\":\"<webhookVerificationToken>\",\"event_type\":\"$event\",\"data_type\":\"$type\"}"
      done
    done

    Use the dashboard's action instead if it offers one. Subscriptions expire after about 90 days [OW]: renew them (monthly is safe).

Scopes

Tick in the portal and requested space-separated [OFF/OW]: email personal daily heartrate workout session spo2 (tag, stress, heart_health, ring_configuration exist too).

Going to production

Up to 10 users works without review. Above that, request approval from Oura (time UNVERIFIED).

Gotchas

  • Refresh tokens are single-use [OFF].
  • Signature: x-oura-signature = uppercase hex HMAC-SHA256(client secret, x-oura-timestamp + raw body) [OFF/OW]. Nothing extra to paste.
  • Notifications arrive ~30 s after the ring syncs; respond within 10 s [OFF].
  • Rate limit 5,000 requests per 5 minutes per app [OFF].

Sources