Integração com Oura Ring
Conecte o Oura Ring do usuário para obter dados de sono, frequência cardíaca, prontidão, atividade e outros dados de saúde por meio da Oura Cloud API V2.
Pré-requisitos
- Um Oura Ring (Gen 3 ou Ring 4) com uma assinatura ativa do Oura Membership (US$ 6/mês necessária para acesso à API)
- O aplicativo Oura instalado e pareado com o anel
- Uma conta Oura Cloud em https://cloud.ouraring.com
Configuração
1. Registrar um Aplicativo de Desenvolvedor
Peça ao usuário para acessar https://developer.ouraring.com/applications e criar um novo aplicativo:
- Nome de Exibição: O nome preferido do usuário para a integração
- Descrição: Breve descrição da integração
- Email de Contato: Email do usuário
- Site: Qualquer URL válida (ex.: um site pessoal)
- Política de Privacidade / Termos de Serviço: Qualquer URL válida (campos obrigatórios, mas não rigorosamente exigidos para aplicativos pessoais)
- URIs de Redirecionamento:
http://localhost:3000/callback - Escopos: Ative todos os escopos necessários. Recomendado:
personal,daily,heartrate,sleep,workout,spo2,stress,heart_health,session,ring_configuration
Salve o ID do Cliente e o Segredo do Cliente.
2. Executar o Fluxo OAuth
Armazene o segredo do cliente de forma segura usando assistant credentials prompt, depois escreva e execute o script auxiliar OAuth na máquina do usuário:
#!/usr/bin/env python3
"""Auxiliar OAuth2 para Oura Ring — captura o código de autorização e troca por tokens instantaneamente."""
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! Você pode fechar esta aba.</h1></body></html>')
print(f'\nTokens salvos em /tmp/oura_tokens.json')
except Exception as e:
self.send_response(500)
self.end_headers()
self.wfile.write(f'Falha na troca de tokens: {e}'.encode())
def log_message(self, *a): pass
print('Abrindo navegador para autorização Oura...')
webbrowser.open('http://localhost:3000')
HTTPServer(('localhost', 3000), Handler).serve_forever()
Execute com python3 /path/to/script.py na máquina do usuário (host_bash). O usuário autoriza no navegador, o script captura o código e o troca por tokens em menos de um segundo.
Importante: Os códigos de autorização expiram em ~30 segundos. NÃO peça ao usuário para colar códigos manualmente — use este script para capturá-los e trocá-los automaticamente.
3. Armazenar Tokens
Após o fluxo OAuth, leia os tokens de /tmp/oura_tokens.json e armazene-os:
access_token— armazenar no cofre de credenciais com modelo de injeção para o cabeçalho Authorization deapi.ouraring.com(prefixo Bearer) eallowed_tools: ["bash"]refresh_token— armazenar no cofre de credenciais para renovação de token- Os tokens expiram em ~30 dias. Defina um lembrete para renovar antes da expiração.
4. Verificar Conexão
Teste com o endpoint de informações pessoais:
curl -s -H "Authorization: Bearer $TOKEN" "https://api.ouraring.com/v2/usercollection/personal_info"
Endpoints Disponíveis
Todos os endpoints usam GET https://api.ouraring.com/v2/usercollection/{type} com parâmetros de consulta start_date e end_date (formato YYYY-MM-DD).
| Endpoint | Dados | Observações |
|---|---|---|
/v2/usercollection/daily_sleep | Pontuação de sono, duração, eficiência, estágios | Melhor verificar após o horário típico de despertar |
/v2/usercollection/sleep | Períodos detalhados de sono com FC, VFC, movimento | Dados brutos do período de sono |
/v2/usercollection/daily_readiness | Pontuação de prontidão, equilíbrio da VFC, recuperação | Métrica de verificação matinal |
/v2/usercollection/daily_activity | Passos, calorias, movimento, inatividade | Resumo de atividade |
/v2/usercollection/heartrate | FC contínua (usar start_datetime/end_datetime no formato ISO) | Pode ser grande — limite o intervalo de datas |
/v2/usercollection/daily_spo2 | Níveis de oxigênio no sangue | Média noturna |
/v2/usercollection/daily_stress | Pontuação de estresse e recuperação | Rastreamento de estresse diurno |
/v2/usercollection/workout | Treinos detectados com FC, calorias | Detectado automaticamente ou manual |
/v2/usercollection/personal_info | Idade, peso, altura, email | Bom teste de conexão |
Renovação de Token
Os tokens expiram após 30 dias. Renove com:
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"
Armazene o novo access_token e refresh_token da resposta.
Dicas
- Anéis novos precisam de 1 a 2 noites para calibrar antes que os dados sejam significativos
- Os dados de sono geralmente aparecem algumas horas após o usuário acordar
- Os dados de frequência cardíaca durante os treinos aparecem após a sincronização do treino via aplicativo Oura
- Limite de taxa: 5000 requisições a cada 5 minutos
- Usuários do Ring 4 e Gen 3 DEVEM ter uma assinatura ativa do Oura Membership para acesso à API