Communitygithub.com

vellum-ai/vellum-assistant

Connectez une bague Oura via OAuth2 — enregistrement d'application, échange de jetons et stockage des identifiants

Qu'est-ce que vellum-assistant ?

Cette compétence permet à un assistant IA (comme Claude Code, Cursor ou Codex) d'intégrer une bague Oura (Gen 3 ou Ring 4) en automatisant le flux OAuth2 complet. L'utilisateur doit disposer d'un abonnement Oura actif et d'un compte cloud. La compétence guide l'enregistrement d'une application développeur Oura, exécute un script Python local pour échanger le code d'autorisation contre des jetons d'accès et de rafraîchissement, puis stocke ces identifiants de manière sécurisée dans le coffre de l'assistant. Une fois connectée, elle expose des endpoints API REST pour récupérer des données de sommeil, fréquence cardiaque, activité, SpO2, stress et plus encore, avec gestion du rafraîchissement des jetons (valides ~30 jours). L'ensemble est conçu pour être rapide (échange en <1 seconde) et sécurisé, évitant toute manipulation manuelle de codes.

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

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

Intégration de la bague Oura

Connectez la bague Oura de l'utilisateur pour récupérer les données de sommeil, fréquence cardiaque, état de préparation, activité et autres données de santé via l'API Cloud Oura V2.

Prérequis

  • Une bague Oura (Gen 3 ou Ring 4) avec un abonnement Oura actif (6 $/mois requis pour l'accès API)
  • L'application Oura installée et couplée avec la bague
  • Un compte Oura Cloud sur https://cloud.ouraring.com

Configuration

1. Enregistrer une application développeur

Demandez à l'utilisateur d'aller sur https://developer.ouraring.com/applications et de créer une nouvelle application :

  • Nom d'affichage : Le nom préféré de l'utilisateur pour l'intégration
  • Description : Brève description de l'intégration
  • Email de contact : L'email de l'utilisateur
  • Site Web : N'importe quelle URL valide (ex. un site personnel)
  • Politique de confidentialité / Conditions de service : N'importe quelles URL valides (champs obligatoires mais non vérifiés pour les applications personnelles)
  • URI de redirection : http://localhost:3000/callback
  • Portées (scopes) : Activez toutes les portées nécessaires. Recommandé : personal, daily, heartrate, sleep, workout, spo2, stress, heart_health, session, ring_configuration

Enregistrez le Client ID et le Client Secret.

2. Exécuter le flux OAuth

Stockez le secret client de manière sécurisée en utilisant assistant credentials prompt, puis écrivez et exécutez le script d'aide OAuth sur la machine de l'utilisateur :

#!/usr/bin/env python3
"""Oura Ring OAuth2 helper — catches auth code and exchanges for tokens instantly."""
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>Connecté ! Vous pouvez fermer cet onglet.</h1></body></html>')
                    print(f'\nJetons sauvegardés dans /tmp/oura_tokens.json')
                except Exception as e:
                    self.send_response(500)
                    self.end_headers()
                    self.wfile.write(f'Échec de l\'échange des jetons : {e}'.encode())
    def log_message(self, *a): pass

print('Ouverture du navigateur pour l\'autorisation Oura...')
webbrowser.open('http://localhost:3000')
HTTPServer(('localhost', 3000), Handler).serve_forever()

Exécutez avec python3 /chemin/vers/script.py sur la machine de l'utilisateur (host_bash). L'utilisateur autorise dans son navigateur, le script capture le code et l'échange contre des jetons en moins d'une seconde.

Important : Les codes d'autorisation expirent en ~30 secondes. Ne demandez PAS à l'utilisateur de coller des codes manuellement — utilisez ce script pour les capturer et les échanger automatiquement.

3. Stocker les jetons

Après le flux OAuth, lisez les jetons depuis /tmp/oura_tokens.json et stockez-les :

  • access_token — stockez dans le coffre d'identifiants avec un modèle d'injection pour l'en-tête Authorization de api.ouraring.com (préfixe Bearer) et allowed_tools: ["bash"]
  • refresh_token — stockez dans le coffre d'identifiants pour le rafraîchissement des jetons
  • Les jetons expirent dans ~30 jours. Définissez un rappel pour les rafraîchir avant l'expiration.

4. Vérifier la connexion

Testez avec le point de terminaison des informations personnelles :

curl -s -H "Authorization: Bearer $TOKEN" "https://api.ouraring.com/v2/usercollection/personal_info"

Points de terminaison disponibles

Tous les points de terminaison utilisent GET https://api.ouraring.com/v2/usercollection/{type} avec les paramètres de requête start_date et end_date (format AAAA-MM-JJ).

Point de terminaisonDonnéesNotes
/v2/usercollection/daily_sleepScore de sommeil, durée, efficacité, phasesIdéal après l'heure de réveil habituelle
/v2/usercollection/sleepPériodes de sommeil détaillées avec FC, VRC, mouvementDonnées brutes des périodes de sommeil
/v2/usercollection/daily_readinessScore de préparation, équilibre VRC, récupérationMétrique de vérification matinale
/v2/usercollection/daily_activityPas, calories, mouvements, inactivitéRésumé de l'activité
/v2/usercollection/heartrateFC continue (utilisez start_datetime/end_datetime au format ISO)Peut être volumineux — limitez la plage de dates
/v2/usercollection/daily_spo2Niveaux d'oxygène dans le sangMoyenne nocturne
/v2/usercollection/daily_stressScore de stress et récupérationSuivi du stress diurne
/v2/usercollection/workoutSéances détectées avec FC, caloriesDétection automatique ou manuelle
/v2/usercollection/personal_infoÂge, poids, taille, emailBon test de connexion

Rafraîchissement des jetons

Les jetons expirent après 30 jours. Rafraîchissez-les avec :

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"

Stockez le nouveau access_token et refresh_token depuis la réponse.

Conseils

  • Les nouvelles bagues ont besoin de 1 à 2 nuits pour se calibrer avant que les données soient significatives
  • Les données de sommeil apparaissent généralement quelques heures après le réveil de l'utilisateur
  • Les données de fréquence cardiaque pendant les séances apparaissent après la synchronisation via l'application Oura
  • Limite de débit : 5000 requêtes toutes les 5 minutes
  • Les utilisateurs de Ring 4 et Gen 3 DOIVENT avoir un abonnement Oura actif pour l'accès API

Skills associés