# polar-flow-server Documentation for LLMs This is an aggregated, LLM-friendly version of the polar-flow-server documentation. For human-readable docs, visit: https://stumason.github.io/polar-flow-server/ --- ## Overview polar-flow-server is a self-hosted health analytics backend for Polar devices. **What it does:** - Syncs data from Polar API (sleep, activity, HRV, exercises, biosensing) - Stores data in PostgreSQL - Calculates personal baselines and detects patterns - Exposes REST API for downstream consumers (dashboards, mobile apps) **Tech stack:** - Python 3.12+ with Litestar async web framework - PostgreSQL database with SQLAlchemy - APScheduler for background sync jobs - Pydantic for data validation --- ## Quick Start ```bash # 1. Run with Docker docker run -d -p 8000:8000 stumason/polar-flow-server:latest # 2. Connect Polar account via admin UI open http://localhost:8000/admin # 3. Fetch data curl http://localhost:8000/api/v1/users/{user_id}/sleep?days=7 ``` --- ## API Authentication All data endpoints require API key authentication: ```bash curl -H "X-API-Key: pfk_your_key_here" \ http://localhost:8000/api/v1/users/{user_id}/sleep ``` --- ## Key Endpoints ### Data Endpoints | Endpoint | Description | |----------|-------------| | `GET /users/{user_id}/sleep` | Sleep data (sleep_score, stages, HRV) | | `GET /users/{user_id}/activity` | Daily activity (steps, calories, distance) | | `GET /users/{user_id}/recharge` | Nightly recharge/HRV data | | `GET /users/{user_id}/exercises` | Workouts/exercises | | `GET /users/{user_id}/cardio-load` | Training load ratios | | `GET /users/{user_id}/heart-rate` | Continuous heart rate | ### Biosensing Endpoints (Vantage V3) | Endpoint | Description | |----------|-------------| | `GET /users/{user_id}/spo2` | Blood oxygen | | `GET /users/{user_id}/ecg` | ECG recordings | | `GET /users/{user_id}/temperature/body` | Body temperature | | `GET /users/{user_id}/temperature/skin` | Skin temperature | ### Analytics Endpoints | Endpoint | Description | |----------|-------------| | `GET /users/{user_id}/insights` | **Unified insights (recommended)** | | `GET /users/{user_id}/baselines` | Personal baselines | | `GET /users/{user_id}/patterns` | Detected patterns | | `GET /users/{user_id}/anomalies` | Anomaly scan | ### Sync Endpoints | Endpoint | Description | |----------|-------------| | `POST /users/{user_id}/sync/trigger` | Manual sync (requires X-Polar-Token) | --- ## Unified Insights Endpoint `GET /users/{user_id}/insights` is the main endpoint for dashboards. It returns: - **current_metrics**: Latest HRV, sleep score, resting HR, training load ratio - **baselines**: Personal baseline comparisons for each metric - **patterns**: Detected patterns (sleep-HRV correlation, overtraining risk, trends) - **anomalies**: Values outside normal IQR bounds - **observations**: Natural language observations for coaching - **suggestions**: Actionable recommendations - **feature_availability**: Which features are unlocked based on data history ### Feature Unlock Timeline | Days | Features | |------|----------| | 0-6 | Raw data only | | 7+ | 7-day baselines | | 21+ | Patterns, anomaly detection | | 30+ | 30-day baselines | | 60+ | ML predictions (future) | ### Example Response ```json { "user_id": "12345", "status": "ready", "data_age_days": 45, "current_metrics": { "hrv": 45.2, "sleep_score": 78, "resting_hr": 52, "training_load_ratio": 1.1 }, "baselines": { "hrv_rmssd": { "current": 45.2, "baseline": 52.0, "percent_of_baseline": 86.9, "trend": "declining" } }, "patterns": [ { "name": "overtraining_risk", "score": 35, "significance": "medium" } ], "observations": [ { "category": "recovery", "priority": "high", "fact": "HRV is 13% below baseline" } ], "suggestions": [ { "action": "prioritize_recovery", "description": "Prioritize sleep and recovery today", "confidence": 0.85 } ] } ``` --- ## Personal Baselines Baselines are calculated from historical data and include: - **baseline_value**: Overall baseline (all data) - **baseline_7d**: 7-day rolling average - **baseline_30d**: 30-day rolling average - **baseline_90d**: 90-day rolling average - **std_dev**: Standard deviation - **q1, q3**: Quartiles for IQR-based anomaly detection - **min_value, max_value**: Observed range ### Available Metrics - `hrv_rmssd` - Heart Rate Variability - `sleep_score` - Sleep quality score - `resting_hr` - Resting heart rate - `training_load` - Training load - `training_load_ratio` - Acute:chronic load ratio --- ## Pattern Detection Detected patterns include: ### Correlations - `sleep_hrv_correlation` - Sleep quality vs HRV correlation ### Composite Scores - `overtraining_risk` - Multi-metric overtraining risk (0-100) - `recovery_readiness` - Recovery readiness score ### Trends - `hrv_trend` - 7-day vs 30-day HRV trend - `sleep_trend` - Sleep score trend ### Significance Levels - `high` - p < 0.01 - `medium` - p < 0.05 - `low` - p < 0.1 - `insufficient` - Not enough data --- ## Anomaly Detection Values outside IQR bounds are flagged: - **warning**: Value outside Q1 - 1.5×IQR to Q3 + 1.5×IQR - **critical**: Value outside Q1 - 3×IQR to Q3 + 3×IQR --- ## Laravel Integration Example ```php // Service class class PolarFlowService { public function __construct() { $this->client = Http::baseUrl(config('services.polar_flow.url') . '/api/v1') ->withHeaders(['X-API-Key' => config('services.polar_flow.api_key')]); } public function getInsights(string $userId): array { return $this->client->get("/users/{$userId}/insights")->json(); } public function getSleep(string $userId, int $days = 7): array { return $this->client->get("/users/{$userId}/sleep", ['days' => $days])->json(); } } // Controller usage $insights = app(PolarFlowService::class)->getInsights($user->polar_user_id); ``` --- ## Background Sync polar-flow-server automatically syncs data every hour (configurable). ### Configuration ```bash SYNC_ENABLED=true SYNC_INTERVAL_MINUTES=60 SYNC_ON_STARTUP=false SYNC_MAX_USERS_PER_RUN=10 ``` ### Priority Queue Users are synced in priority order: - **CRITICAL**: Not synced in 48h+ or expiring tokens - **HIGH**: Active users, not synced in 12h+ - **NORMAL**: Regular users, not synced in 24h+ - **LOW**: Dormant users --- ## Error Codes | Status | Description | |--------|-------------| | 401 | Invalid or missing API key | | 404 | User not found | | 429 | Rate limited | | 500 | Server error | --- ## GitHub Repository https://github.com/StuMason/polar-flow-server --- ## Version Current version: 1.2.0