Oura Ring Integration
The Oura Ring measures 20+ biosignals from the finger — a location far more reliable than the wrist for overnight heart rate and temperature trends. vitalera integrates with Oura API v2 via the unified connected_accounts framework.
Data types
| Category | Endpoints | Signal highlights |
|---|---|---|
| Sleep | /usercollection/sleep, /daily_sleep | Stages (light/deep/REM/awake), efficiency, latency, midpoint |
| Readiness | /usercollection/daily_readiness | Score 0–100, HRV balance, recovery index |
| Activity | /usercollection/daily_activity | Steps, calories, METs, targets |
| Heart rate | /usercollection/heartrate | Continuous HR time series |
| SpO2 | /usercollection/daily_spo2 | Overnight average |
| Stress | /usercollection/daily_stress | Day-level stress score |
| VO2 max | /usercollection/vo2_max | Cardio capacity |
| Workouts | /usercollection/workout | Self-reported or detected sessions |
Connection
OAuth 2.0 with a non-standard quirk: Oura expects client_id and client_secret in the token request body (application/x-www-form-urlencoded), not HTTP Basic auth.
Initiate
curl -X POST https://api.vitalera.io/api/connected-accounts/oura/oauth/initiate/ \
-H "Authorization: Bearer <user_token>"
Disconnect
curl -X POST https://api.vitalera.io/api/connected-accounts/oura/oauth/disconnect/ \
-H "Authorization: Bearer <user_token>"
Webhook signature
Oura signs webhook deliveries with HMAC-SHA256, delivered in the X-Oura-Signature header. vitalera rejects any payload whose signature does not match the subscription secret.
X-Oura-Signature: sha256=af5b2c...
Sleep sub-stages example
{
"user_id": "subject_88",
"source": "oura",
"session_id": "oura_2026_04_11",
"start": "2026-04-11T23:42:00Z",
"end": "2026-04-12T07:18:00Z",
"stages": {
"light_s": 13320,
"deep_s": 5280,
"rem_s": 4500,
"awake_s": 420
},
"efficiency": 0.93,
"resting_hr_bpm": 52,
"hrv_rmssd_ms": 68,
"temperature_deviation_c": -0.12,
"spo2_avg": 0.97
}