Integración con Oura Ring
Conecta el anillo Oura del usuario para obtener datos de sueño, frecuencia cardíaca, preparación, actividad y otra información de salud a través de la API Cloud de Oura V2.
Requisitos Previos
- Un anillo Oura (Gen 3 o Ring 4) con una suscripción activa a Oura Membership ($6/mes requerida para acceso a la API).
- La aplicación Oura instalada y emparejada con el anillo.
- Una cuenta en Oura Cloud en https://cloud.ouraring.com
Configuración
1. Registrar una Aplicación de Desarrollador
Pide al usuario que vaya a https://developer.ouraring.com/applications y cree una nueva aplicación:
- Nombre para mostrar: El nombre preferido del usuario para la integración.
- Descripción: Breve descripción de la integración.
- Correo electrónico de contacto: Correo del usuario.
- Sitio web: Cualquier URL válida (por ejemplo, un sitio web personal).
- Política de privacidad / Términos de servicio: Cualquier URL válida (campos obligatorios, no se verifican en aplicaciones personales).
- URI de redirección:
http://localhost:3000/callback - Ámbitos: Habilitar todos los ámbitos necesarios. Recomendados:
personal,daily,heartrate,sleep,workout,spo2,stress,heart_health,session,ring_configuration
Guarda el ID de cliente y el Secreto de cliente.
2. Ejecutar el Flujo OAuth
Almacena el secreto de cliente de forma segura usando assistant credentials prompt, luego escribe y ejecuta el script auxiliar OAuth en la máquina del usuario:
#!/usr/bin/env python3
"""Auxiliar OAuth2 para Oura Ring: captura el código de autorización y lo intercambia por tokens al instante."""
from http.server import HTTPServer, BaseHTTPRequestHandler
from urllib.parse import urlparse, parse_qs, urlencode
import urllib.request, json, webbrowser, ssl
CLIENT_ID = 'YOUR_CLIENT_ID'
CLIENT_SECRET = 'YOUR_CLIENT_SECRET'
REDIRECT_URI = 'http://localhost:3000/callback'
SCOPES = 'email personal daily heartrate workout tag session spo2 ring_configuration stress heart_health'
class Handler(BaseHTTPRequestHandler):
def do_GET(self):
parsed = urlparse(self.path)
if parsed.path == '/':
params = urlencode({
'response_type': 'code', 'client_id': CLIENT_ID,
'redirect_uri': REDIRECT_URI, 'scope': SCOPES, 'state': 'assistant'
})
self.send_response(302)
self.send_header('Location', f'https://cloud.ouraring.com/oauth/authorize?{params}')
self.end_headers()
elif parsed.path == '/callback':
code = parse_qs(parsed.query).get('code', [''])[0]
if code:
token_data = urlencode({
'grant_type': 'authorization_code', 'code': code,
'redirect_uri': REDIRECT_URI, 'client_id': CLIENT_ID,
'client_secret': CLIENT_SECRET,
}).encode()
try:
req = urllib.request.Request('https://api.ouraring.com/oauth/token',
data=token_data,
headers={'Content-Type': 'application/x-www-form-urlencoded'},
method='POST')
resp = urllib.request.urlopen(req, context=ssl.create_default_context())
result = json.loads(resp.read())
with open('/tmp/oura_tokens.json', 'w') as f:
json.dump(result, f, indent=2)
self.send_response(200)
self.send_header('Content-Type', 'text/html')
self.end_headers()
self.wfile.write(b'<html><body><h1>¡Conectado! Puedes cerrar esta pestaña.</h1></body></html>')
print(f'\nTokens guardados en /tmp/oura_tokens.json')
except Exception as e:
self.send_response(500)
self.end_headers()
self.wfile.write(f'Error al intercambiar el token: {e}'.encode())
def log_message(self, *a): pass
print('Abriendo navegador para autorización de Oura...')
webbrowser.open('http://localhost:3000')
HTTPServer(('localhost', 3000), Handler).serve_forever()
Ejecuta con python3 /ruta/al/script.py en la máquina del usuario (host_bash). El usuario autoriza en su navegador, el script captura el código y lo intercambia por tokens en menos de un segundo.
Importante: Los códigos de autorización expiran en ~30 segundos. NO pidas al usuario que pegue los códigos manualmente; usa este script para capturarlos e intercambiarlos automáticamente.
3. Almacenar Tokens
Después del flujo OAuth, lee los tokens de /tmp/oura_tokens.json y guárdalos:
access_token— guárdalo en el vault de credenciales con la plantilla de inyección para el encabezado Authorization deapi.ouraring.com(prefijo Bearer) yallowed_tools: ["bash"].refresh_token— guárdalo en el vault de credenciales para la renovación de tokens.- Los tokens expiran en ~30 días. Establece un recordatorio para renovarlos antes de que caduquen.
4. Verificar Conexión
Prueba con el endpoint de información personal:
curl -s -H "Authorization: Bearer $TOKEN" "https://api.ouraring.com/v2/usercollection/personal_info"
Endpoints Disponibles
Todos los endpoints usan GET https://api.ouraring.com/v2/usercollection/{tipo} con los parámetros de consulta start_date y end_date (formato YYYY-MM-DD).
| Endpoint | Datos | Notas |
|---|---|---|
/v2/usercollection/daily_sleep | Puntuación de sueño, duración, eficiencia, etapas | Mejor consultar después de la hora de despertar |
/v2/usercollection/sleep | Periodos de sueño detallados con FC, VFC, movimiento | Datos brutos del periodo de sueño |
/v2/usercollection/daily_readiness | Puntuación de preparación, balance VFC, recuperación | Métrica de revisión matutina |
/v2/usercollection/daily_activity | Pasos, calorías, movimiento, inactividad | Resumen de actividad |
/v2/usercollection/heartrate | FC continua (usar start_datetime/end_datetime en formato ISO) | Puede ser grande — limitar el rango de fechas |
/v2/usercollection/daily_spo2 | Niveles de oxígeno en sangre | Promedio nocturno |
/v2/usercollection/daily_stress | Puntuación de estrés y recuperación | Seguimiento del estrés diurno |
/v2/usercollection/workout | Entrenamientos detectados con FC, calorías | Detectados automática o manualmente |
/v2/usercollection/personal_info | Edad, peso, altura, correo electrónico | Buena prueba de conexión |
Renovación de Tokens
Los tokens expiran después de 30 días. Renueva con:
curl -s -X POST "https://api.ouraring.com/oauth/token" \
-d "grant_type=refresh_token&refresh_token=$REFRESH_TOKEN&client_id=$CLIENT_ID&client_secret=$CLIENT_SECRET"
Guarda los nuevos access_token y refresh_token de la respuesta.
Consejos
- Los anillos nuevos necesitan de 1 a 2 noches de calibración antes de que los datos sean significativos.
- Los datos de sueño suelen aparecer unas horas después de que el usuario se despierte.
- Los datos de frecuencia cardíaca durante los entrenamientos aparecen después de que el entrenamiento se sincroniza a través de la aplicación Oura.
- Límite de tasa: 5000 solicitudes cada 5 minutos.
- Los usuarios de Ring 4 y Gen 3 DEBEN tener una suscripción activa a Oura Membership para acceder a la API.