Telemetry API Endpoints
All Telemetry endpoints live under the same Core API server. Authentication uses the same JWT tokens. The compliance middleware enriches every request with geo, device, and consent context before processing.
Media Events
Track Media Event
POST /v1/media/eventsPrimary endpoint for all video/exercise session tracking. The frontend sends events throughout the playback lifecycle.
Request:
{
"event": "session_start",
"session_id": "550e8400-e29b-41d4-a716-446655440000",
"media_id": "exercise-uuid-hashed",
"media_type": "video",
"timestamp": "2026-02-17T10:00:00Z",
"data": {
"total_duration_seconds": 120.5,
"connection_type": "wifi",
"ttfb_ms": 340,
"video_load_time_ms": 1200,
"cdn_response_time_ms": 280
}
}Supported events: See media-events.md for the full event specification.
Response: 202 Accepted (async processing)
{
"status": "accepted",
"event_id": "...",
"session_id": "550e8400-e29b-41d4-a716-446655440000"
}Consent requirement: Level 2+ (analytics consent — media session data). For error-only troubleshooting at Level 1, use POST /v1/errors/report instead.
Get Bandwidth Statistics
GET /v1/media/bandwidth/stats?period=7d&group_by=country_codeQuery Parameters:
period(string) — Time window:1h,24h,7d,30d(default:7d)group_by(string) — Grouping dimension:country_code,device_type,connection_type,browser_familymedia_id(string) — Filter by specific exercise/video (optional)
Response:
{
"period": "7d",
"group_by": "country_code",
"stats": [
{
"country_code": "RO",
"total_sessions": 1250,
"avg_ttfb_ms": 280,
"avg_load_time_ms": 950,
"avg_buffering_count": 0.8,
"avg_buffering_duration_ms": 400,
"avg_bitrate": 2800000,
"completion_rate": 0.82,
"error_rate": 0.02
},
{
"country_code": "IT",
"total_sessions": 340,
"avg_ttfb_ms": 1200,
"avg_load_time_ms": 3400,
"avg_buffering_count": 3.2,
"avg_buffering_duration_ms": 4500,
"avg_bitrate": 1200000,
"completion_rate": 0.54,
"error_rate": 0.12
}
]
}Get Session Statistics
GET /v1/media/sessions/stats?period=7dQuery Parameters:
period(string) — Time window:1h,24h,7d,30dstatus(string) — Filter by session status:completed,abandoned,active
Response:
{
"period": "7d",
"total_sessions": 4580,
"completed": 3280,
"abandoned": 1100,
"active": 200,
"avg_watch_time_seconds": 85.4,
"avg_completion_percent": 72.3,
"performance": {
"p50_ttfb_ms": 300,
"p95_ttfb_ms": 1800,
"p50_load_time_ms": 900,
"p95_load_time_ms": 4500,
"p50_buffer_duration_ms": 200,
"p95_buffer_duration_ms": 5000
}
}Analytics
Track Analytics Event
POST /v1/analytics/trackRequest:
{
"event_name": "page.view",
"event_category": "navigation",
"timestamp": "2026-02-17T10:00:00Z",
"resource_type": "page",
"resource_id": "treatment-plan-library",
"page_url": "/library",
"referrer_url": "/dashboard",
"numeric_value": null,
"properties": {
"filter_condition": "neck_pain",
"results_count": 12
}
}Response: 202 Accepted
Consent requirement: Level 2+ (analytics consent)
Pose Tracking
Track Pose Frame (Batch)
POST /v1/pose/framesAccepts batched pose data (frontend buffers frames and sends every 1-2 seconds).
Request:
{
"session_id": "550e8400-...",
"media_id": "exercise-uuid-hashed",
"frames": [
{
"frame_number": 450,
"elapsed_ms": 15000,
"landmark_x": [0.52, 0.51, 0.50, ...],
"landmark_y": [0.32, 0.35, 0.38, ...],
"landmark_z": [-0.1, -0.09, -0.08, ...],
"landmark_visibility": [0.99, 0.98, 0.95, ...],
"pose_confidence": 0.96,
"landmarks_detected": 33,
"rep_count": 5,
"form_score": 0.85,
"rom_degrees": 42.5,
"active_exercise_phase": "concentric",
"camera_resolution": "640x480",
"processing_time_ms": 12
}
]
}Response: 202 Accepted
{
"status": "accepted",
"frames_accepted": 30,
"session_id": "550e8400-..."
}Consent requirement: Level 2+ (analytics consent — pose data is considered analytics, not essential)
Audit
Ingest Audit Entry
POST /v1/audit/ingestCalled internally by Core API middleware on every authenticated request. Not exposed to frontend.
Request:
{
"action": "patient.view",
"resource_type": "patient",
"resource_id": "patient-123",
"status": "success",
"status_code": 200,
"metadata": {
"fields_accessed": ["name", "treatment_plans"]
}
}Headers enriched by middleware:
X-Request-Id— correlation IDX-Actor-Hash— hashed user identityX-Actor-Type— user, admin, specialist, systemX-Organization-Id— org contextX-Consent-Level— 0-3X-Client-IP— real IP (via trusted proxy chain)
Response: 202 Accepted (async via audit-worker)
Error Tracking
Report Error
POST /v1/errors/reportFrontend reports errors for debugging. Support can correlate with patient complaints.
Request:
{
"error_type": "video_error",
"error_code": "MEDIA_ERR_NETWORK",
"error_message": "Failed to load video segment",
"feature_name": "video_player",
"media_id": "exercise-uuid-hashed",
"media_position_seconds": 23.5,
"stack_trace": "Error: fetch failed at...",
"response_time_ms": 30000,
"memory_usage_mb": 245.6,
"cpu_usage_percent": 78.3
}Response: 202 Accepted
Consent requirement: Level 1+ (legitimate interest for customer support)
Admin
Update Geolocation Database
POST /v1/admin/geo/updateTriggers re-download of MaxMind GeoLite2 database. Admin only.
Response:
{
"status": "updated",
"database_version": "2026-02-15",
"entries": 4200000
}Get Geo Database Status
GET /v1/admin/geo/statusResponse:
{
"database_type": "GeoLite2-City",
"build_date": "2026-02-15",
"loaded": true,
"entries": 4200000
}Get Privacy Exclusions
GET /v1/admin/privacy/exclusions?page=1&per_page=50Response:
{
"exclusions": [
{
"id": "...",
"ip_network": "198.51.100.0/24",
"exclusion_type": "ccpa_do_not_sell",
"is_active": true,
"last_updated_by_maxmind": "2026-02-10T00:00:00Z"
}
],
"total": 2340,
"page": 1,
"per_page": 50
}Sync Privacy Exclusions
POST /v1/admin/privacy/exclusions/syncTriggers manual sync with MaxMind API (normally runs weekly via cron).
Response:
{
"sync_batch_id": "...",
"status": "running",
"started_at": "2026-02-17T10:00:00Z"
}Check IP Exclusion Status
GET /v1/admin/privacy/exclusions/check?ip=198.51.100.45Response:
{
"ip": "198.51.100.45",
"is_excluded": true,
"exclusion": {
"type": "ccpa_do_not_sell",
"network": "198.51.100.0/24",
"legal_basis": "legal_obligation_ccpa"
}
}Dashboard (Internal)
Development/admin dashboard endpoints. Not exposed to patients.
| Method | Endpoint | Description |
|---|---|---|
| GET | /dashboard/ | Dashboard home |
| GET | /dashboard/audit | Audit log viewer |
| GET | /dashboard/analytics | Analytics event viewer |
| GET | /dashboard/media | Media session viewer |
| GET | /dashboard/security | Security events viewer |
| GET | /dashboard/detail/:type/:id | Detailed entry view |
Endpoint Summary
| Category | Endpoints | Consent Level |
|---|---|---|
| Media Events | 3 (track, bandwidth stats, session stats) | 1+ |
| Analytics | 1 (track) | 2+ |
| Pose Tracking | 1 (batch frames) | 2+ |
| Audit | 1 (ingest) | Internal |
| Error Tracking | 1 (report) | 1+ |
| Admin | 5 (geo, privacy) | Admin only |
| Dashboard | 6 (viewers) | Admin only |
| Total | 18 |