API Reference
REST API for accessing synced Polar health data.
Base URL
{base_url}/api/v1
Replace {base_url} with your server address:
- Local development: http://localhost:8000
- Docker: http://localhost:8000 or your configured port
- Production: Your deployed server URL (e.g., https://polar.example.com)
OpenAPI Specification
The full OpenAPI 3.1 specification is available at:
- JSON:
GET /schema/openapi.json - Interactive Docs:
GET /schema/swagger(Swagger UI) - ReDoc:
GET /schema/redoc
# Download OpenAPI spec
curl {base_url}/schema/openapi.json > openapi.json
Authentication
API Key Authentication
If an API key is configured (recommended for production), include it in the X-API-Key header:
curl -H "X-API-Key: your_api_key_here" {base_url}/api/v1/users/12345/sleep
API keys can be created and managed from the Admin Dashboard → API Keys section.
User ID
All data endpoints require a user_id in the URL path. For self-hosted deployments, this is your Polar user ID (visible in the admin dashboard). For SaaS integrations, this is your application's user identifier.
Sync Endpoints
Sync endpoints additionally require a Polar API access token via the X-Polar-Token header.
Endpoints
Sleep
| Method | Endpoint | Description |
|---|---|---|
| GET | /users/{user_id}/sleep |
List sleep data |
| GET | /users/{user_id}/sleep/{date} |
Get sleep by date |
Query Parameters:
- days (int, default: 7) - Number of days to fetch (1-365)
Example:
curl {base_url}/api/v1/users/12345/sleep?days=30
Response:
[
{
"date": "2026-01-11",
"sleep_score": 85,
"total_sleep_hours": 7.5,
"deep_sleep_hours": 1.8,
"rem_sleep_hours": 1.9,
"light_sleep_hours": 3.8,
"hrv_avg": 45.2,
"heart_rate_avg": 52
}
]
Activity
| Method | Endpoint | Description |
|---|---|---|
| GET | /users/{user_id}/activity |
List daily activity |
| GET | /users/{user_id}/activity/{date} |
Get activity by date |
Query Parameters:
- days (int, default: 30) - Number of days to fetch (1-365)
Example:
curl {base_url}/api/v1/users/12345/activity?days=7
Response:
[
{
"date": "2026-01-11",
"steps": 8542,
"calories_active": 450,
"calories_total": 2150,
"distance_km": 6.2,
"active_minutes": 45.5,
"activity_score": 78
}
]
Nightly Recharge (HRV)
| Method | Endpoint | Description |
|---|---|---|
| GET | /users/{user_id}/recharge |
List nightly recharge data |
Query Parameters:
- days (int, default: 30) - Number of days to fetch (1-365)
Example:
curl {base_url}/api/v1/users/12345/recharge?days=14
Response:
[
{
"date": "2026-01-11",
"hrv_avg": 48.5,
"ans_charge": 4.2,
"ans_charge_status": "WELL_RECOVERED",
"breathing_rate_avg": 14.2,
"heart_rate_avg": 51
}
]
Exercises
| Method | Endpoint | Description |
|---|---|---|
| GET | /users/{user_id}/exercises |
List exercises |
| GET | /users/{user_id}/exercises/{id} |
Get exercise detail |
Query Parameters:
- days (int, default: 30) - Number of days to fetch (1-365)
Example:
curl {base_url}/api/v1/users/12345/exercises?days=30
Response:
[
{
"id": 1,
"polar_exercise_id": "abc123",
"start_time": "2026-01-11 07:30:00",
"sport": "RUNNING",
"duration_minutes": 45.5,
"distance_km": 8.2,
"calories": 520,
"average_heart_rate": 145,
"max_heart_rate": 172,
"training_load": 85
}
]
Cardio Load
| Method | Endpoint | Description |
|---|---|---|
| GET | /users/{user_id}/cardio-load |
List cardio load data |
Query Parameters:
- days (int, default: 30) - Number of days to fetch (1-365)
Response:
[
{
"date": "2026-01-11",
"strain": 125.5,
"tolerance": 180.2,
"cardio_load": 85.3,
"cardio_load_ratio": 0.70,
"cardio_load_status": "PRODUCTIVE"
}
]
Heart Rate
| Method | Endpoint | Description |
|---|---|---|
| GET | /users/{user_id}/heart-rate |
List daily HR summaries |
Query Parameters:
- days (int, default: 30) - Number of days to fetch (1-365)
Response:
[
{
"date": "2026-01-11",
"hr_min": 48,
"hr_avg": 62,
"hr_max": 165,
"sample_count": 1440
}
]
SleepWise
| Method | Endpoint | Description |
|---|---|---|
| GET | /users/{user_id}/sleepwise/alertness |
Hourly alertness predictions |
| GET | /users/{user_id}/sleepwise/bedtime |
Optimal bedtime recommendations |
Query Parameters:
- days (int, default: 7) - Number of days to fetch (1-30)
Alertness Response:
[
{
"period_start_time": "2026-01-11 08:00:00",
"period_end_time": "2026-01-11 09:00:00",
"grade": 4.2,
"grade_classification": "GOOD"
}
]
Bedtime Response:
[
{
"period_start_time": "2026-01-11 00:00:00",
"period_end_time": "2026-01-12 00:00:00",
"preferred_sleep_start": "22:30:00",
"preferred_sleep_end": "06:30:00",
"sleep_gate_start": "22:00:00",
"sleep_gate_end": "23:00:00",
"quality": "GOOD"
}
]
Biosensing (Vantage V3)
Requires compatible device with Elixir sensor platform.
| Method | Endpoint | Description |
|---|---|---|
| GET | /users/{user_id}/spo2 |
Blood oxygen measurements |
| GET | /users/{user_id}/ecg |
ECG recordings |
| GET | /users/{user_id}/temperature/body |
Body temperature |
| GET | /users/{user_id}/temperature/skin |
Skin temperature |
Query Parameters:
- days (int, default: 30) - Number of days to fetch (1-365)
SpO2 Response:
[
{
"test_time": "2026-01-11 22:30:00",
"blood_oxygen_percent": 98,
"spo2_class": "NORMAL",
"avg_heart_rate": 62,
"hrv_ms": 45.2,
"altitude_meters": 150
}
]
Sync
| Method | Endpoint | Description |
|---|---|---|
| POST | /users/{user_id}/sync/trigger |
Trigger data sync |
Headers:
- X-Polar-Token (required) - Polar API access token
Query Parameters:
- days (int, optional) - Days to sync (default from config)
Example:
curl -X POST \
-H "X-Polar-Token: your_polar_token" \
{base_url}/api/v1/users/12345/sync/trigger?days=30
Response:
{
"status": "success",
"user_id": "12345",
"results": {
"sleep": 28,
"recharge": 28,
"activity": 28,
"exercises": 15,
"cardio_load": 28,
"sleepwise_alertness": 168,
"sleepwise_bedtime": 7,
"spo2": 5,
"ecg": 3,
"body_temperature": 7,
"skin_temperature": 7
}
}
Export
| Method | Endpoint | Description |
|---|---|---|
| GET | /users/{user_id}/export/summary |
Export summary manifest |
| GET | /users/{user_id}/export/sleep.csv |
Export sleep data as CSV |
| GET | /users/{user_id}/export/activity.csv |
Export activity data as CSV |
| GET | /users/{user_id}/export/recharge.csv |
Export recharge/HRV data as CSV |
| GET | /users/{user_id}/export/cardio-load.csv |
Export cardio load data as CSV |
Query Parameters:
- days (int, default: 30) - Number of days to include (1-365)
Export Summary
Response:
{
"user_id": "12345",
"days": 30,
"from_date": "2025-12-12",
"to_date": "2026-01-11",
"record_counts": {
"sleep": 30,
"activity": 30,
"recharge": 30,
"cardio_load": 28,
"heart_rate": 30,
"exercises": 12
},
"total_records": 160
}
CSV Exports
Download data as CSV files for use in spreadsheets, data analysis tools, or external systems.
Example:
curl -H "X-API-Key: pfk_..." \
"{base_url}/api/v1/users/12345/export/sleep.csv?days=90" \
-o sleep_data.csv
Sleep CSV columns: date, sleep_score, total_hours, deep_hours, light_hours, rem_hours, hrv_avg, heart_rate_avg, breathing_rate_avg
Activity CSV columns: date, steps, calories_active, calories_total, distance_km, active_minutes
Recharge CSV columns: date, hrv_avg, ans_charge, status, breathing_rate, heart_rate_avg
Cardio Load CSV columns: date, strain, tolerance, cardio_load, load_ratio, status
Baselines & Analytics
Personal baselines computed from historical data. Use these for anomaly detection and personalized insights.
| Method | Endpoint | Description |
|---|---|---|
| GET | /users/{user_id}/baselines |
Get all computed baselines |
| GET | /users/{user_id}/baselines/{metric_name} |
Get specific baseline |
| POST | /users/{user_id}/baselines/calculate |
Trigger baseline calculation |
| GET | /users/{user_id}/baselines/check/{metric_name}/{value} |
Check if value is anomalous |
| GET | /users/{user_id}/analytics/status |
Get analytics readiness status |
Valid Metric Names:
- hrv_rmssd - Heart Rate Variability (RMSSD)
- sleep_score - Overall sleep quality score
- resting_hr - Resting heart rate
- training_load - Training load (cardio load)
- training_load_ratio - Acute:chronic load ratio
Get All Baselines
curl {base_url}/api/v1/users/12345/baselines
Response:
[
{
"metric_name": "hrv_rmssd",
"baseline_value": 42.5,
"baseline_7d": 44.2,
"baseline_30d": 41.8,
"baseline_90d": 40.5,
"median": 42.0,
"q1": 38.5,
"q3": 48.2,
"iqr": 9.7,
"std_dev": 8.3,
"min": 28.0,
"max": 65.0,
"lower_bound": 24.0,
"upper_bound": 62.8,
"sample_count": 45,
"status": "ready",
"data_start_date": "2025-11-01",
"data_end_date": "2026-01-11",
"calculated_at": "2026-01-11T08:00:00Z"
}
]
Baseline Status:
- ready - Full baseline (21+ days of data)
- partial - Limited baseline (7-20 days)
- insufficient - Not enough data (<7 days)
Check for Anomaly
Uses IQR-based anomaly detection: - Warning: value outside Q1 - 1.5×IQR to Q3 + 1.5×IQR - Critical: value outside Q1 - 3×IQR to Q3 + 3×IQR
curl {base_url}/api/v1/users/12345/baselines/check/hrv_rmssd/25.5
Response:
{
"value": 25.5,
"metric_name": "hrv_rmssd",
"is_anomaly": true,
"severity": "warning",
"baseline": 42.5,
"baseline_7d": 44.2,
"lower_bound": 24.0,
"upper_bound": 62.8,
"status": "ready"
}
Calculate Baselines
Trigger baseline recalculation from historical data:
curl -X POST {base_url}/api/v1/users/12345/baselines/calculate
Response:
{
"user_id": "12345",
"baselines_calculated": {
"hrv_rmssd": "ready",
"sleep_score": "ready",
"resting_hr": "ready",
"training_load": "partial",
"training_load_ratio": "partial"
}
}
Analytics Status
Check feature availability based on data history:
curl {base_url}/api/v1/users/12345/analytics/status
Response:
{
"user_id": "12345",
"data_days": {
"sleep": 45,
"recharge": 45,
"activity": 45,
"cardio_load": 30
},
"min_data_days": 30,
"features_available": {
"basic_stats": true,
"trend_analysis": true,
"personalized_baselines": true,
"predictive_models": true,
"advanced_ml": false,
"long_term_patterns": false
},
"unlock_progress": {
"advanced_ml": {
"unlocked": false,
"days_required": 60,
"days_remaining": 30,
"progress_percent": 50.0
}
},
"recommendations": [
"Great progress! Advanced ML features unlock after 60 days of data."
]
}
Feature Unlock Timeline: | Days | Features Unlocked | |------|-------------------| | 7 | Basic statistics, daily tracking | | 14 | Trend analysis, basic anomaly alerts | | 21 | Reliable correlations, personalized baselines | | 30 | Predictive models, outcome forecasting | | 60 | Advanced ML models, behavior patterns | | 90 | Long-term pattern recognition |
Patterns & Anomalies
Advanced pattern detection for correlations, trends, and risk assessment.
| Method | Endpoint | Description |
|---|---|---|
| GET | /users/{user_id}/patterns |
Get all detected patterns |
| GET | /users/{user_id}/patterns/{pattern_name} |
Get specific pattern |
| POST | /users/{user_id}/patterns/detect |
Trigger pattern detection |
| GET | /users/{user_id}/anomalies |
Scan all metrics for anomalies |
Pattern Types:
- correlation - Statistical relationships between metrics
- trend - Directional changes over time
- composite - Multi-metric risk scores
Available Patterns:
- sleep_hrv_correlation - Correlation between sleep quality and HRV
- overtraining_risk - Multi-metric overtraining risk score (0-100)
- hrv_trend - 7-day HRV trend vs 30-day baseline
- sleep_trend - 7-day sleep score trend vs 30-day baseline
Get All Patterns
curl {base_url}/api/v1/users/12345/patterns
Response:
[
{
"pattern_type": "correlation",
"pattern_name": "sleep_hrv_correlation",
"score": 0.72,
"confidence": 0.95,
"significance": "high",
"metrics_involved": ["sleep_score", "hrv_rmssd"],
"sample_count": 28,
"details": {
"correlation_coefficient": 0.72,
"p_value": 0.001,
"interpretation": "Strong positive correlation between sleep quality and HRV"
},
"analyzed_at": "2026-01-13T08:00:00Z"
},
{
"pattern_type": "composite",
"pattern_name": "overtraining_risk",
"score": 35,
"confidence": 0.88,
"significance": "medium",
"metrics_involved": ["hrv_rmssd", "sleep_score", "resting_hr", "training_load_ratio"],
"sample_count": 7,
"details": {
"risk_factors": ["HRV trending 8% below baseline"],
"recommendations": [
"Monitor your body's response to training",
"Consider adding an extra recovery day this week"
]
},
"analyzed_at": "2026-01-13T08:00:00Z"
}
]
Significance Levels:
- high - Statistically significant pattern (p < 0.01)
- medium - Moderate significance (p < 0.05)
- low - Weak pattern (p < 0.1)
- insufficient - Not enough data for reliable analysis
Get Specific Pattern
curl {base_url}/api/v1/users/12345/patterns/overtraining_risk
Trigger Pattern Detection
Analyzes historical data and stores pattern results:
curl -X POST {base_url}/api/v1/users/12345/patterns/detect
Response:
{
"user_id": "12345",
"patterns_detected": {
"sleep_hrv_correlation": "high",
"overtraining_risk": "medium",
"hrv_trend": "low",
"sleep_trend": "insufficient"
}
}
Bulk Anomaly Scan
Scans all metrics against stored baselines and returns any values outside normal bounds:
curl {base_url}/api/v1/users/12345/anomalies
Response:
{
"user_id": "12345",
"anomaly_count": 2,
"anomalies": [
{
"metric_name": "hrv_rmssd",
"current_value": 22.5,
"baseline_value": 42.5,
"lower_bound": 24.0,
"upper_bound": 62.8,
"severity": "critical",
"direction": "below",
"deviation_percent": -47.1
},
{
"metric_name": "resting_hr",
"current_value": 68,
"baseline_value": 55,
"lower_bound": 48,
"upper_bound": 65,
"severity": "warning",
"direction": "above",
"deviation_percent": 23.6
}
]
}
Anomaly Severity:
- warning - Value outside Q1 - 1.5×IQR to Q3 + 1.5×IQR
- critical - Value outside Q1 - 3×IQR to Q3 + 3×IQR
Unified Insights
The unified insights endpoint aggregates all analytics into a single response optimized for downstream consumers (dashboards, coaching apps, etc.).
| Method | Endpoint | Description |
|---|---|---|
| GET | /users/{user_id}/insights |
Get complete insights package |
Response includes: - Current metric values - Personal baseline comparisons - Detected patterns (correlations, trends, risk scores) - Anomalies (values outside normal bounds) - Natural language observations - Actionable suggestions - Feature availability based on data history
Feature Unlock Timeline
Features unlock progressively as more data becomes available:
| Days of Data | Features Available |
|---|---|
| 0-6 | Raw data only, no analytics |
| 7+ | 7-day baselines |
| 21+ | Pattern detection, anomaly detection |
| 30+ | Full 30-day baselines |
| 60+ | ML predictions (future) |
Example Request
curl {base_url}/api/v1/users/12345/insights
Example Response (30+ days of data)
{
"user_id": "12345",
"generated_at": "2026-01-13T10:30:00Z",
"data_freshness": "2026-01-13T06:00:00Z",
"data_age_days": 45,
"status": "ready",
"feature_availability": {
"baselines_7d": {"available": true, "message": null},
"baselines_30d": {"available": true, "message": null},
"patterns": {"available": true, "message": null},
"anomaly_detection": {"available": true, "message": null},
"ml_predictions": {"available": false, "message": "Unlocks in 15 days", "unlock_at_days": 60}
},
"unlock_progress": {
"next_unlock": "ml_predictions",
"days_until_next": 15,
"percent_to_next": 75.0
},
"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,
"baseline_7d": 48.5,
"baseline_30d": 52.0,
"percent_of_baseline": 86.9,
"trend": "declining",
"status": "ready"
},
"sleep_score": {
"current": 78,
"baseline": 82.0,
"percent_of_baseline": 95.1,
"trend": "stable",
"status": "ready"
}
},
"patterns": [
{
"name": "sleep_hrv_correlation",
"pattern_type": "correlation",
"score": 0.72,
"significance": "high",
"factors": [],
"interpretation": "Strong positive correlation between sleep quality and HRV"
},
{
"name": "overtraining_risk",
"pattern_type": "composite",
"score": 35,
"significance": "medium",
"factors": ["HRV trending below baseline"],
"interpretation": null
}
],
"anomalies": [],
"observations": [
{
"category": "recovery",
"priority": "high",
"fact": "HRV is 13% below personal baseline",
"context": "Current: 45ms, Baseline: 52ms",
"trend": "declining"
},
{
"category": "recovery",
"priority": "info",
"fact": "Strong connection between your sleep quality and HRV detected",
"context": "Better sleep directly improves your recovery metrics",
"trend": null
}
],
"suggestions": [
{
"action": "prioritize_recovery",
"description": "Prioritize sleep and recovery today",
"confidence": 0.85,
"reason": "HRV is 13% below baseline"
}
]
}
Example Response (New User - 5 days)
{
"user_id": "12345",
"generated_at": "2026-01-13T10:30:00Z",
"data_age_days": 5,
"status": "unavailable",
"feature_availability": {
"baselines_7d": {"available": false, "message": "Unlocks in 2 days", "unlock_at_days": 7},
"baselines_30d": {"available": false, "message": "Unlocks in 25 days", "unlock_at_days": 30},
"patterns": {"available": false, "message": "Unlocks in 16 days", "unlock_at_days": 21},
"anomaly_detection": {"available": false, "message": "Unlocks in 16 days", "unlock_at_days": 21},
"ml_predictions": {"available": false, "message": "Unlocks in 55 days", "unlock_at_days": 60}
},
"unlock_progress": {
"next_unlock": "baselines_7d",
"days_until_next": 2,
"percent_to_next": 71.4
},
"current_metrics": {
"hrv": 48.0,
"sleep_score": 75,
"resting_hr": 55,
"training_load_ratio": null
},
"baselines": {},
"patterns": [],
"anomalies": [],
"observations": [
{
"category": "onboarding",
"priority": "info",
"fact": "Building your personal baselines (5/7 days)",
"context": "Keep wearing your device. Basic insights unlock in 2 days.",
"trend": null
}
],
"suggestions": []
}
Response Fields
| Field | Description |
|---|---|
status |
Overall status: ready, partial, or unavailable |
data_age_days |
Number of days of data available |
feature_availability |
Which analytics features are unlocked |
unlock_progress |
Progress toward unlocking the next feature |
current_metrics |
Most recent values of key health metrics |
baselines |
Personal baseline comparisons by metric |
patterns |
Detected patterns (correlations, trends, risk scores) |
anomalies |
Values outside normal IQR bounds |
observations |
Natural language observations for coaching |
suggestions |
Actionable suggestions based on current state |
Observation Categories
| Category | Description |
|---|---|
recovery |
Recovery and HRV-related observations |
sleep |
Sleep quality observations |
training |
Training load and overtraining observations |
anomaly |
Detected anomalies in metrics |
onboarding |
New user guidance |
trend |
Trend-related observations |
Observation Priorities
| Priority | Description |
|---|---|
critical |
Requires immediate attention |
high |
Important observation |
medium |
Moderate importance |
low |
Minor observation |
info |
Informational |
positive |
Good news |
Health
| Method | Endpoint | Description |
|---|---|---|
| GET | /health |
Server health check |
Response:
{
"status": "healthy",
"database": "connected"
}