Skip to main content

Wearable Integration

The bot collects physiological data from wearable devices through two mechanisms: webhooks for real-time data delivery, and a daily sync cron job at 00:00 UTC as a safety net to catch any missed data. All wearable data is stored in the device_data table.

Architecture​

The wearable system uses a provider-based architecture with a registry pattern (PROVIDER_REGISTRY in src/wearables/). Each provider handles:

  • OAuth token management -- tokens are encrypted at rest via Fernet (cryptography package)
  • Webhook processing -- receives and parses incoming data from device APIs
  • Data sync -- periodic pull of historical data via daily_sync.py

Supported Providers​

Withings​

Create an app at developer.withings.com and configure the webhook callback URL to point to your server.

Data types: weight, blood_pressure, temperature, glucose, activity, sleep, ecg, bed_in/bed_out events

Required environment variables:

WITHINGS_CLIENT_ID=your_client_id
WITHINGS_CLIENT_SECRET=your_client_secret

Fitbit​

Create an app at dev.fitbit.com and configure the webhook callback URL.

Data types: activity (1-min intraday), heartrate, hrv, spo2, breathing_rate, sleep, weight, temperature, nutrition

Required environment variables:

FITBIT_CLIENT_ID=your_client_id
FITBIT_CLIENT_SECRET=your_client_secret
FITBIT_SUBSCRIPTION_VERIFICATION_CODE=your_verification_code
note

Intraday access (1-minute granularity for activity and heart rate) requires Fitbit premium or explicit API approval. The provider automatically falls back to daily summaries if intraday requests return a 403 error.

Oura​

Create an app at cloud.ouraring.com/v2/docs.

Data types: daily_sleep, daily_activity, daily_readiness, daily_spo2, daily_stress, heartrate (5-min intervals), workout, session

Required environment variables:

OURA_CLIENT_ID=your_client_id
OURA_CLIENT_SECRET=your_client_secret

Common Setup​

1. Generate an encryption key​

All OAuth tokens are encrypted at rest. Generate a Fernet key and add it to your .env:

python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
DEVICE_TOKEN_ENCRYPTION_KEY=your_generated_fernet_key

2. Set the base URL​

Webhooks need to reach your API from the public internet. Set BASE_URL to your server's public URL:

BASE_URL=https://your-server.example.com

For local development, start.sh handles this automatically by creating a localtunnel.

Participants link their wearable devices by sending the /devices command in Telegram. This initiates the OAuth flow for the selected provider. Once authorized, the bot begins receiving webhook data and running daily syncs for that participant.

Rules Engine​

The rules engine provides event-driven survey triggering based on incoming wearable data. Rules are evaluated after each webhook data save, allowing you to react to physiological events in near real-time.

Example use cases:

  • Send a morning survey when sleep data arrives (indicating the participant has woken up)
  • Trigger an activity survey when step count exceeds a threshold
  • Deliver a stress check-in when heart rate variability drops

Rules are defined in src/rules/models.py and evaluated by src/rules/engine.py. The engine supports cross-provider data type aliases, so a rule targeting "sleep" data will match both Withings sleep events and Oura daily_sleep events.