Communitygithub.com

vellum-ai/vellum-assistant

Integración con Oura Ring: registro de aplicación, intercambio de tokens y almacenamiento de credenciales mediante OAuth2.

¿Qué es vellum-assistant?

Este skill habilita la conexión de un anillo Oura (Gen 3 o Ring 4) con aplicaciones de IA como Claude Code, Cursor o Codex, permitiendo obtener datos de salud como sueño, frecuencia cardíaca, preparación, actividad y más a través de la API Cloud de Oura V2. Es especialmente útil para desarrolladores que desean incorporar métricas biométricas en sus flujos de trabajo automatizados o en asistentes de IA. La integración utiliza OAuth2 con un script Python que se ejecuta localmente para atrapar el código de autorización automáticamente, evitando la expiración rápida del código (~30 segundos). El skill soporta plataformas basadas en bash y almacena de forma segura los tokens de acceso y actualización en el vault de credenciales del asistente. Los tokens expiran cada ~30 días, por lo que se incluye documentación para renovarlos fácilmente. Además, proporciona una tabla completa con los endpoints disponibles (sueño, frecuencia cardíaca, actividad, SPO2, estrés, etc.) y consejos prácticos para interpretar los datos correctamente.

Compatible con~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/vellum-ai/vellum-assistant/tree/HEAD/skills/oura-setup

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

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 de api.ouraring.com (prefijo Bearer) y allowed_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).

EndpointDatosNotas
/v2/usercollection/daily_sleepPuntuación de sueño, duración, eficiencia, etapasMejor consultar después de la hora de despertar
/v2/usercollection/sleepPeriodos de sueño detallados con FC, VFC, movimientoDatos brutos del periodo de sueño
/v2/usercollection/daily_readinessPuntuación de preparación, balance VFC, recuperaciónMétrica de revisión matutina
/v2/usercollection/daily_activityPasos, calorías, movimiento, inactividadResumen de actividad
/v2/usercollection/heartrateFC continua (usar start_datetime/end_datetime en formato ISO)Puede ser grande — limitar el rango de fechas
/v2/usercollection/daily_spo2Niveles de oxígeno en sangrePromedio nocturno
/v2/usercollection/daily_stressPuntuación de estrés y recuperaciónSeguimiento del estrés diurno
/v2/usercollection/workoutEntrenamientos detectados con FC, caloríasDetectados automática o manualmente
/v2/usercollection/personal_infoEdad, peso, altura, correo electrónicoBuena 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.

Skills relacionados