{"openapi":"3.1.0","info":{"title":"Coach Watts API","version":"0.5.24","description":"AI-powered endurance coaching platform API"},"servers":[{"url":"https://coachwatts.com","description":"Local Development Server","variables":{}}],"paths":{"":{"get":{"tags":["App Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/activity/highlights":{"get":{"tags":["Activity"],"parameters":[{"name":"days","in":"query","schema":{"type":["integer","string"],"default":30}},{"name":"sport","in":"query","schema":{"type":"string"}},{"name":"tags","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"period":{"type":"object","properties":{"days":{"type":"integer"},"totalDuration":{"type":"integer"},"totalDistance":{"type":"number"},"totalTSS":{"type":"number"},"workoutCount":{"type":"integer"},"avgTSS":{"type":"number"}}},"load":{"type":"object","properties":{"acuteLoad":{"type":"number"},"chronicLoad":{"type":"number"},"workloadRatio":{"type":"number"}}}}}}}},"401":{"description":"Unauthorized"}},"summary":"Get activity highlights","description":"Returns aggregated activity statistics and workload ratios (ACWR)."}},"/api/activity/recent":{"get":{"tags":["Activity"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"count":{"type":"integer"},"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string","enum":["workout","nutrition","wellness"]},"date":{"type":"string","format":"date-time"},"icon":{"type":"string"},"color":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"link":{"type":"string","nullable":true}}}}}}}}},"401":{"description":"Unauthorized"}},"summary":"Get recent activity","description":"Returns a combined timeline of recent workouts, nutrition, and wellness data."}},"/api/admin/ai/logs":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/admin/audit-logs":{"get":{"tags":["Admin"],"parameters":[{"name":"page","in":"query","schema":{"type":"integer","default":1}},{"name":"limit","in":"query","schema":{"type":"integer","default":50}},{"name":"userId","in":"query","schema":{"type":"string"}},{"name":"action","in":"query","schema":{"type":"string"}},{"name":"resourceType","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"logs":{"type":"array"},"total":{"type":"integer"},"pages":{"type":"integer"}}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"}},"summary":"Get Audit Logs","description":"Retrieve system audit logs with pagination and filtering"}},"/api/admin/database":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/admin/debug/env":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/admin/debug/ping":{"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/admin/debug/trigger-test":{"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/admin/emails/{id}/send":{"post":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/admin/emails":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/admin/impersonate":{"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/admin/issues/{id}":{"delete":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}},"get":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}},"put":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/admin/issues/{id}/comments":{"get":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}},"post":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/admin/issues/{id}/comments/{commentId}":{"delete":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"commentId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}},"patch":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"commentId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/admin/issues/{id}/comments/{commentId}/acknowledge":{"post":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"commentId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/admin/issues/{id}/comments/{commentId}/reaction":{"post":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"commentId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/admin/issues/{id}/reaction":{"post":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/admin/issues":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/admin/llm/settings":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}},"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/admin/oauth/apps/{id}":{"get":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/admin/queues/status":{"get":{"tags":["Admin"],"parameters":[],"responses":{"200":{"description":"OK"},"401":{"description":"Unauthorized"}},"summary":"Get Queue Status","description":"Returns the current status and metrics for all background job queues."}},"/api/admin/stats":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/admin/stats/developers":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/admin/stats/email":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/admin/stats/llm/{id}":{"get":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/admin/stats/llm/operations":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/admin/stats/llm/overview":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/admin/stats/llm/quotas":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/admin/stats/llm/users":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/admin/stats/messaging":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/admin/stats/tickets":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/admin/stats/users":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/admin/stats/webhooks":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/admin/stats/workouts":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/admin/stop-impersonation":{"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/admin/subscriptions":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/admin/system-messages":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}},"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/admin/system-messages/{id}":{"delete":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}},"put":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/admin/users":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/admin/users/{id}":{"delete":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}},"get":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/admin/users/{id}/feature-flags":{"post":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/admin/users/{id}/tickets":{"get":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/admin/webhook-stats":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/admin/webhooks":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/analytics/dashboards":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}},"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/analytics/dashboards/reorder":{"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/analytics/fields":{"get":{"tags":["Analytics"],"parameters":[],"responses":{"200":{"description":"OK"}},"summary":"List available fields","description":"Returns available standard and custom fields for analytics querying."}},"/api/analytics/fields/definitions/{id}":{"delete":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/analytics/fields/definitions":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}},"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/analytics/llm-usage":{"get":{"tags":["Analytics"],"parameters":[{"name":"days","in":"query","schema":{"type":"integer","default":30}},{"name":"groupBy","in":"query","schema":{"type":"string","enum":["operation","date","model"],"default":"operation"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"summary":{"type":"object","properties":{"totalCalls":{"type":"integer"},"successfulCalls":{"type":"integer"},"failedCalls":{"type":"integer"},"totalCost":{"type":"number"},"totalTokens":{"type":"integer"}}},"groupedData":{"type":"array"},"recentUsage":{"type":"array"},"dateRange":{"type":"object"}}}}}},"401":{"description":"Unauthorized"}},"summary":"Get LLM usage stats","description":"Returns usage statistics for AI model calls."}},"/api/analytics/llm-usage/{id}":{"get":{"tags":["Analytics"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"operation":{"type":"string"},"model":{"type":"string"},"promptFull":{"type":"string","nullable":true},"responseFull":{"type":"string","nullable":true}}}}}},"401":{"description":"Unauthorized"},"404":{"description":"Usage record not found"}},"summary":"Get LLM usage detail","description":"Returns detailed information for a specific LLM call."}},"/api/analytics/llm-usage/history":{"get":{"tags":["Analytics"],"parameters":[{"name":"page","in":"query","schema":{"type":"integer","default":1}},{"name":"pageSize","in":"query","schema":{"type":"integer","default":20}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array"},"pagination":{"type":"object","properties":{"page":{"type":"integer"},"pageSize":{"type":"integer"},"total":{"type":"integer"},"totalPages":{"type":"integer"}}}}}}}},"401":{"description":"Unauthorized"}},"summary":"Get LLM usage history","description":"Returns a paginated history of AI model calls."}},"/api/analytics/presets/{preset}":{"post":{"tags":["API Routes"],"parameters":[{"name":"preset","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/analytics/query":{"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/analytics/weekly-zones":{"get":{"tags":["Analytics"],"parameters":[{"name":"weeks","in":"query","schema":{"type":["integer","string"],"default":12}},{"name":"sport","in":"query","schema":{"type":"string"}},{"name":"tags","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}},"summary":"Get weekly zone distribution","description":"Returns time spent in power and heart rate zones aggregated weekly."}},"/api/analytics/widgets/{id}":{"delete":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}},"get":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/analytics/widgets":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}},"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/analytics/workout-comparison/browse":{"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/analytics/workout-comparison/intervals":{"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/analytics/workout-comparison/streams":{"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/analytics/workout-comparison/workouts":{"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/analytics/workout-explorer/density":{"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/analytics/workout-explorer/intervals":{"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/analytics/workout-explorer/streams":{"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/analytics/workout-explorer/summary":{"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/analytics/workout-explorer/workout":{"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/auth/{*param1}":{"get":{"tags":["API Routes"],"parameters":[{"name":"*param1","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/auth/unsubscribe":{"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/availability":{"get":{"tags":["Availability"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"dayOfWeek":{"type":"integer","description":"0=Sunday, 6=Saturday"},"morning":{"type":"boolean"},"afternoon":{"type":"boolean"},"evening":{"type":"boolean"},"indoorOnly":{"type":"boolean"},"outdoorOnly":{"type":"boolean"}}}}}}},"401":{"description":"Unauthorized"}},"summary":"Get training availability","description":"Returns the user's weekly training availability preferences."},"post":{"tags":["Availability"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"count":{"type":"integer"}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Unauthorized"}},"summary":"Update training availability","description":"Updates the user's weekly training availability preferences.","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["availability"],"properties":{"availability":{"type":"array","items":{"type":"object","required":["dayOfWeek"],"properties":{"dayOfWeek":{"type":"integer","description":"0=Sunday, 6=Saturday"},"morning":{"type":"boolean"},"afternoon":{"type":"boolean"},"evening":{"type":"boolean"},"indoorOnly":{"type":"boolean"},"outdoorOnly":{"type":"boolean"},"bikeAccess":{"type":"boolean"},"gymAccess":{"type":"boolean"},"slots":{"type":"array","items":{"type":"object"}}}}}}}}}}}},"/api/body-measurements/{id}":{"patch":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/body-measurements":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}},"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/calendar":{"get":{"tags":["Calendar"],"parameters":[{"name":"startDate","in":"query","required":true,"schema":{"type":"string","format":"date-time"}},{"name":"endDate","in":"query","required":true,"schema":{"type":"string","format":"date-time"}}],"responses":{"200":{"description":"Success"},"400":{"description":"Invalid date parameters"},"401":{"description":"Unauthorized"}},"summary":"Get calendar activities","description":"Returns a combined list of completed and planned workouts, along with nutrition and wellness data."}},"/api/calendar/notes/{id}":{"get":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/changelog":{"get":{"tags":["System"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"content":{"type":"string"}}}}}}},"summary":"Get changelog","description":"Returns the contents of the CHANGELOG.md file."}},"/api/chat/memory/{id}":{"delete":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}},"patch":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/chat/memory/extract":{"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/chat/memory/forget":{"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/chat/memory":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}},"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/chat/memory/remember":{"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/chat/messages":{"get":{"tags":["Chat"],"parameters":[{"name":"roomId","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"role":{"type":"string"},"parts":{"type":"array"},"metadata":{"type":"object"}}}}}}},"401":{"description":"Unauthorized"}},"summary":"List chat messages","description":"Returns the message history for a specific chat room."},"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/chat/messages/{id}":{"patch":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/chat/rooms":{"get":{"tags":["Chat"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"roomId":{"type":"string"},"roomName":{"type":"string"},"avatar":{"type":"string"},"unreadCount":{"type":"integer"},"lastMessage":{"type":"object","nullable":true}}}}}}},"401":{"description":"Unauthorized"}},"summary":"List chat rooms","description":"Returns the list of chat rooms for the authenticated user."},"post":{"tags":["Chat"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"roomId":{"type":"string"},"roomName":{"type":"string"},"avatar":{"type":"string"},"users":{"type":"array"}}}}}},"401":{"description":"Unauthorized"}},"summary":"Create chat room","description":"Creates a new chat room for the authenticated user."}},"/api/chat/rooms/{id}":{"delete":{"tags":["Chat"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}}}}}},"401":{"description":"Unauthorized"},"404":{"description":"Not Found"}},"summary":"Delete a chat room (soft delete)","description":"Marks a chat room as deleted for the authenticated user."},"patch":{"tags":["Chat"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"room":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}}}}}}}},"400":{"description":"Bad Request"},"401":{"description":"Unauthorized"},"404":{"description":"Not Found"}},"summary":"Rename a chat room","description":"Updates the name of a chat room for the authenticated user.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"}},"required":["name"]}}}}}},"/api/chat/rooms/{id}/memory":{"get":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/chat/rooms/{id}/state":{"get":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/chat/rooms/{id}/summarize":{"post":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/chat/transcribe":{"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/chat/tts":{"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/chat/turns/{id}/resume":{"post":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/chat/turns/{id}/retry":{"post":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/checkin/{id}":{"delete":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}},"patch":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/checkin/answer":{"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/checkin/generate":{"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/checkin/history":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/checkin/today":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/coaching/athletes":{"get":{"tags":["Coaching"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"email":{"type":"string"},"status":{"type":"string"}}}}}}},"401":{"description":"Unauthorized"}},"summary":"List athletes","description":"Returns the list of athletes coached by the authenticated user."}},"/api/coaching/athletes/{id}":{"get":{"tags":["Coaching"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden (Not coaching this athlete)"},"404":{"description":"Athlete not found"}},"summary":"Get athlete profile","description":"Returns the details of a specific athlete coached by the authenticated user."}},"/api/coaching/athletes/{id}/calendar":{"get":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/coaching/athletes/{id}/planned-workouts/{workoutId}":{"delete":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"workoutId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}},"get":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"workoutId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}},"patch":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"workoutId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/coaching/athletes/{id}/planned-workouts/{workoutId}/move":{"post":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"workoutId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/coaching/athletes/{id}/planned-workouts":{"post":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/coaching/athletes/{id}/workouts/{workoutId}":{"get":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"workoutId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/coaching/athletes/connect":{"post":{"tags":["Coaching"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"athlete":{"type":"object"}}}}}},"400":{"description":"Invalid code or request"},"401":{"description":"Unauthorized"}},"summary":"Connect athlete","description":"Connects a coach to an athlete using an invite code.","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","description":"The 6-character invite code"}}}}}}}},"/api/coaching/athletes/invites":{"get":{"tags":["Coaching"],"parameters":[],"responses":{"200":{"description":"Success"},"401":{"description":"Unauthorized"}},"summary":"List athlete invites","description":"Returns the pending coach-generated athlete invites for the authenticated coach."},"post":{"tags":["Coaching"],"parameters":[],"responses":{"201":{"description":"Created"},"401":{"description":"Unauthorized"}},"summary":"Create athlete invite","description":"Creates a coach-generated athlete invite. If an email is provided, the join link is emailed to the athlete; otherwise a shareable public invite link is created."}},"/api/coaching/athletes/invites/{inviteId}":{"delete":{"tags":["Coaching"],"parameters":[{"name":"inviteId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success"},"401":{"description":"Unauthorized"},"404":{"description":"Invite not found"}},"summary":"Revoke athlete invite","description":"Revokes a pending coach-generated athlete invite."}},"/api/coaching/coaches":{"get":{"tags":["Coaching"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"email":{"type":"string"},"status":{"type":"string"}}}}}}},"401":{"description":"Unauthorized"}},"summary":"List coaches","description":"Returns the list of coaches for the authenticated athlete."}},"/api/coaching/coaches/{id}":{"delete":{"tags":["Coaching"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The ID of the coach to remove"}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}}}}}},"401":{"description":"Unauthorized"},"404":{"description":"Coach not found"}},"summary":"Remove coach","description":"Removes a coaching relationship, disconnecting from the specified coach."}},"/api/coaching/groups/{id}":{"get":{"tags":["Coaching","Groups"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Group not found"}},"summary":"Get athlete group details","description":"Returns the details and members of a specific athlete group."}},"/api/coaching/groups/{id}/members":{"post":{"tags":["Coaching","Groups"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"201":{"description":"Added"},"400":{"description":"Invalid input"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Group or Athlete not found"}},"summary":"Add athlete to group","description":"Adds an athlete to a specific athlete group."}},"/api/coaching/groups/{id}/members/{athleteId}":{"delete":{"tags":["Coaching","Groups"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The ID of the group"},{"name":"athleteId","in":"path","required":true,"schema":{"type":"string"},"description":"The ID of the athlete to remove"}],"responses":{"200":{"description":"Success"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Group or member not found"}},"summary":"Remove athlete from group","description":"Removes an athlete from a specific athlete group."}},"/api/coaching/groups":{"get":{"tags":["Coaching","Groups"],"parameters":[{"name":"teamId","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success"},"401":{"description":"Unauthorized"}},"summary":"List athlete groups","description":"Returns the list of athlete groups owned by the coach, and optionally team-scoped groups."},"post":{"tags":["Coaching","Groups"],"parameters":[],"responses":{"201":{"description":"Created"},"400":{"description":"Invalid input"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"}},"summary":"Create athlete group","description":"Creates a new athlete group for the authenticated coach, optionally scoped to a team."}},"/api/coaching/invite":{"get":{"tags":["Coaching"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","nullable":true},"code":{"type":"string","nullable":true},"expiresAt":{"type":"string","format":"date-time","nullable":true},"status":{"type":"string"}}}}}},"401":{"description":"Unauthorized"}},"summary":"Get active invite","description":"Returns the currently active coaching invite code for the authenticated athlete."},"post":{"tags":["Coaching"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"code":{"type":"string"},"expiresAt":{"type":"string","format":"date-time"},"status":{"type":"string"}}}}}},"401":{"description":"Unauthorized"}},"summary":"Create invite","description":"Generates a new coaching invite code for the authenticated athlete."}},"/api/coaching/overview":{"get":{"tags":["Coaching"],"parameters":[],"responses":{"200":{"description":"Success"},"401":{"description":"Unauthorized"}},"summary":"Get coaching overview","description":"Returns weekly compliance grid data and a combined activity feed for all coached athletes."}},"/api/coaching/teams/{id}":{"get":{"tags":["Coaching","Teams"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Team not found"}},"summary":"Get team details","description":"Returns the details of a specific team if the user has access."}},"/api/coaching/teams/{id}/invites":{"delete":{"tags":["Coaching","Teams"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"}},"summary":"Revoke team invite","description":"Revokes a pending team invite code."},"get":{"tags":["Coaching","Teams"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"}},"summary":"List team invites","description":"Returns the list of pending invites for a team."},"post":{"tags":["Coaching","Teams"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"201":{"description":"Created"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"}},"summary":"Create team invite","description":"Generates a new invite code for the team."}},"/api/coaching/teams/{id}/join-by-code":{"post":{"tags":["Coaching","Teams"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success"},"400":{"description":"Invalid input"},"403":{"description":"Forbidden"},"404":{"description":"Invite not found"}},"summary":"Add athlete by code","description":"Adds an athlete to the team using their personal coaching invite code."}},"/api/coaching/teams/{id}/members/add":{"post":{"tags":["Coaching","Teams"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"201":{"description":"Added"},"400":{"description":"Invalid input"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"}},"summary":"Add connected athlete to team","description":"Directly adds an athlete the coach is already coaching to the team."}},"/api/coaching/teams/{id}/roster":{"get":{"tags":["Coaching","Teams"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"}},"summary":"Get team roster","description":"Returns the list of athletes in a team with their metrics."}},"/api/coaching/teams/accept":{"post":{"tags":["Coaching","Teams"],"parameters":[],"responses":{"200":{"description":"Success"},"400":{"description":"Invalid code"},"401":{"description":"Unauthorized"}},"summary":"Accept team invite","description":"Joins a team using an invite code.","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string"}}}}}}}},"/api/coaching/teams":{"get":{"tags":["Coaching","Teams"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"role":{"type":"string"},"status":{"type":"string"},"team":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"},"description":{"type":"string"}}}}}}}}},"401":{"description":"Unauthorized"}},"summary":"List teams","description":"Returns the list of teams the authenticated user is a member of."},"post":{"tags":["Coaching","Teams"],"parameters":[],"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Unauthorized"}},"summary":"Create team","description":"Creates a new team and assigns the authenticated user as the owner.","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string","minLength":2,"maxLength":100},"description":{"type":"string","maxLength":500}}}}}}}},"/api/debug/config-test":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/debug/sentry":{"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/debug/system":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/debug/workouts":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/developer/apps/{id}":{"delete":{"tags":["Developer"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"No Content"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Not Found"}},"summary":"Delete OAuth Application","description":"Deletes a specific OAuth application and all associated tokens."},"get":{"tags":["Developer"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"sourceName":{"type":"string","nullable":true},"description":{"type":"string","nullable":true},"homepageUrl":{"type":"string","nullable":true},"logoUrl":{"type":"string","nullable":true},"clientId":{"type":"string"},"redirectUris":{"type":"array","items":{"type":"string"}},"isTrusted":{"type":"boolean"},"isPublic":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Not Found"}},"summary":"Get OAuth Application","description":"Returns details for a specific OAuth application."},"patch":{"tags":["Developer"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success"},"400":{"description":"Bad Request"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Not Found"}},"summary":"Update OAuth Application","description":"Updates details for a specific OAuth application.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":3,"maxLength":50},"sourceName":{"type":"string","minLength":1,"maxLength":30,"nullable":true},"description":{"type":"string","maxLength":500},"homepageUrl":{"type":"string","format":"uri"},"redirectUris":{"type":"array","items":{"type":"string","format":"uri"}},"isPublic":{"type":"boolean"}}}}}}}},"/api/developer/apps/{id}/logo":{"post":{"tags":["Developer"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"logoUrl":{"type":"string","format":"uri"}}}}}},"400":{"description":"Bad Request"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Not Found"}},"summary":"Upload App Logo","description":"Uploads a logo for the application. The image will be cropped/resized to a 512x512 square.","requestBody":{"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"logo":{"type":"string","format":"binary"}}}}}}}},"/api/developer/apps/{id}/secret":{"post":{"tags":["Developer"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"clientSecret":{"type":"string"}}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Not Found"}},"summary":"Regenerate Client Secret","description":"Generates a new client secret for the application. The old secret will be invalidated immediately."}},"/api/developer/apps/{id}/webhook-logs":{"get":{"tags":["Developer"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"provider":{"type":"string"},"eventType":{"type":"string"},"payload":{"type":"object"},"headers":{"type":"object"},"query":{"type":"object"},"status":{"type":"string"},"error":{"type":"string"},"processedAt":{"type":"string","format":"date-time"},"createdAt":{"type":"string","format":"date-time"}}}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Not Found"}},"summary":"Get OAuth Application Webhook Logs","description":"Returns recent webhook logs for a specific OAuth application."}},"/api/developer/apps/{id}/webhook-secret":{"post":{"tags":["Developer"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"webhookSecret":{"type":"string"}}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Not Found"}},"summary":"Regenerate Webhook Secret","description":"Generates a new incoming webhook secret for the application. The old secret will be invalidated immediately."}},"/api/developer/apps":{"get":{"tags":["Developer"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"sourceName":{"type":"string","nullable":true},"description":{"type":"string","nullable":true},"homepageUrl":{"type":"string","nullable":true},"logoUrl":{"type":"string","nullable":true},"clientId":{"type":"string"},"redirectUris":{"type":"array","items":{"type":"string"}},"isTrusted":{"type":"boolean"},"isPublic":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"_count":{"type":"object","properties":{"tokens":{"type":"integer"},"consents":{"type":"integer"}}}}}}}}},"401":{"description":"Unauthorized"}},"summary":"List OAuth Applications","description":"Returns a list of OAuth applications owned by the authenticated user."},"post":{"tags":["Developer"],"parameters":[],"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"clientId":{"type":"string"},"clientSecret":{"type":"string"},"name":{"type":"string"}}}}}},"400":{"description":"Bad Request"},"401":{"description":"Unauthorized"}},"summary":"Create OAuth Application","description":"Creates a new OAuth application and returns its credentials. The client secret is only shown once.","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["name","redirectUris"],"properties":{"name":{"type":"string","minLength":3,"maxLength":50},"sourceName":{"type":"string","minLength":1,"maxLength":30},"description":{"type":"string","maxLength":500},"homepageUrl":{"type":"string","format":"uri"},"redirectUris":{"type":"array","items":{"type":"string","format":"uri"},"minItems":1}}}}}}}},"/api/events/{id}":{"delete":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}},"get":{"tags":["Events"],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}},"summary":"Get event details","description":"Returns a single event by ID."},"put":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/events":{"get":{"tags":["Events"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"date":{"type":"string","format":"date-time"},"type":{"type":"string"},"subType":{"type":"string"},"distance":{"type":"number"},"elevation":{"type":"integer"},"expectedDuration":{"type":"number"},"terrain":{"type":"string"},"source":{"type":"string"}}}}}}},"401":{"description":"Unauthorized"}},"summary":"List events","description":"Returns a list of racing events for the authenticated user."},"post":{"tags":["Events"],"parameters":[],"responses":{"200":{"description":"OK"}},"summary":"Create a new racing event","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["title","date"],"properties":{"title":{"type":"string"},"date":{"type":"string","format":"date-time"},"priority":{"type":"string","enum":["A","B","C"]},"isVirtual":{"type":"boolean"},"isPublic":{"type":"boolean"}}}}}}}},"/api/goals/{id}":{"delete":{"tags":["Goals"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}}}}}},"401":{"description":"Unauthorized"},"404":{"description":"Goal not found"}},"summary":"Delete goal","description":"Deletes a specific goal by ID."},"patch":{"tags":["Goals"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"goal":{"type":"object"}}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Goal not found"}},"summary":"Update goal","description":"Updates a specific goal by ID.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string"},"description":{"type":"string"},"currentValue":{"type":"number"},"status":{"type":"string","enum":["ACTIVE","COMPLETED","ARCHIVED"]},"targetDate":{"type":"string","format":"date-time"},"targetValue":{"type":"number"},"aiContext":{"type":"string"},"distance":{"type":"number"},"elevation":{"type":"number"},"duration":{"type":"number"},"terrain":{"type":"string"},"phase":{"type":"string"}}}}}}}},"/api/goals":{"get":{"tags":["Goals"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"goals":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string"},"title":{"type":"string"},"description":{"type":"string","nullable":true},"metric":{"type":"string","nullable":true},"targetValue":{"type":"number","nullable":true},"currentValue":{"type":"number","nullable":true},"targetDate":{"type":"string","format":"date-time","nullable":true},"status":{"type":"string"}}}}}}}}},"401":{"description":"Unauthorized"}},"summary":"List user goals","description":"Returns all goals for the authenticated user."},"post":{"tags":["Goals"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"goal":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"}}}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Unauthorized"}},"summary":"Create goal","description":"Creates a new goal for the authenticated user.","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["type","title"],"properties":{"type":{"type":"string","enum":["BODY_COMPOSITION","EVENT","PERFORMANCE","CONSISTENCY"]},"title":{"type":"string"},"description":{"type":"string"},"targetDate":{"type":"string","format":"date-time"},"eventDate":{"type":"string","format":"date-time"},"eventType":{"type":"string"},"metric":{"type":"string"},"targetValue":{"type":"number"},"startValue":{"type":"number"},"currentValue":{"type":"number"},"priority":{"type":"string","enum":["LOW","MEDIUM","HIGH"],"default":"MEDIUM"},"aiContext":{"type":"string"},"distance":{"type":"number"},"elevation":{"type":"number"},"duration":{"type":"number"},"terrain":{"type":"string"},"phase":{"type":"string"}}}}}}}},"/api/goals/review-result":{"get":{"tags":["Goals"],"parameters":[{"name":"jobId","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string"},"output":{"type":"object","nullable":true},"isCompleted":{"type":"boolean"},"isFailed":{"type":"boolean"}}}}}},"400":{"description":"Job ID required"},"401":{"description":"Unauthorized"}},"summary":"Get goal review result","description":"Retrieves the status and result of a goal review job."}},"/api/goals/review":{"post":{"tags":["Goals"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"jobId":{"type":"string"},"message":{"type":"string"}}}}}},"400":{"description":"No active goals"},"401":{"description":"Unauthorized"}},"summary":"Review goals","description":"Triggers an AI review of all active goals."}},"/api/goals/suggest":{"post":{"tags":["Goals"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"jobId":{"type":"string"},"message":{"type":"string"}}}}}},"401":{"description":"Unauthorized"}},"summary":"Suggest goals","description":"Triggers AI generation of personalized goal suggestions."}},"/api/goals/suggestions":{"get":{"tags":["Goals"],"parameters":[{"name":"jobId","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string"},"output":{"type":"object","nullable":true},"isCompleted":{"type":"boolean"},"isFailed":{"type":"boolean"}}}}}},"400":{"description":"Job ID required"},"401":{"description":"Unauthorized"}},"summary":"Get goal suggestions","description":"Retrieves the status and result of a goal suggestion job."}},"/api/health":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/integrations/fitbit/authorize":{"get":{"tags":["Integrations"],"parameters":[],"responses":{"302":{"description":"Redirect to Fitbit"},"401":{"description":"Unauthorized"}},"summary":"Authorize Fitbit","description":"Initiates the OAuth flow for Fitbit integration. Redirects to Fitbit."}},"/api/integrations/fitbit/callback":{"get":{"tags":["Integrations"],"parameters":[{"name":"code","in":"query","schema":{"type":"string"}},{"name":"state","in":"query","schema":{"type":"string"}},{"name":"error","in":"query","schema":{"type":"string"}}],"responses":{"302":{"description":"Redirect to settings"},"401":{"description":"Unauthorized"}},"summary":"Fitbit callback","description":"Handles the OAuth callback from Fitbit."}},"/api/integrations/fitbit/disconnect":{"delete":{"tags":["Integrations"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"message":{"type":"string"}}}}}},"401":{"description":"Unauthorized"},"404":{"description":"Integration not found"}},"summary":"Disconnect Fitbit","description":"Disconnects the Fitbit integration for the authenticated user."}},"/api/integrations/fitbit/webhook":{"get":{"tags":["Integrations"],"parameters":[{"name":"verify","in":"query","schema":{"type":"string"},"required":true}],"responses":{"204":{"description":"Verified"},"404":{"description":"Not Found"}},"summary":"Fitbit webhook verification","description":"Verifies the Fitbit subscriber endpoint."},"post":{"tags":["Integrations"],"parameters":[],"responses":{"204":{"description":"Received"},"404":{"description":"Not Found"}},"summary":"Fitbit webhook notification","description":"Handles incoming webhook notifications from Fitbit.","requestBody":{"content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"collectionType":{"type":"string"},"date":{"type":"string"},"ownerId":{"type":"string"},"ownerType":{"type":"string"},"subscriptionId":{"type":"string"}}}}}}}}},"/api/integrations/garmin/authorize":{"get":{"tags":["Integrations"],"parameters":[],"responses":{"302":{"description":"Redirect to Garmin"},"401":{"description":"Unauthorized"}},"summary":"Authorize Garmin Connect","description":"Initiates the OAuth2 with PKCE flow for Garmin Connect integration. Redirects to Garmin."}},"/api/integrations/garmin/callback":{"get":{"tags":["Integrations"],"parameters":[],"responses":{"302":{"description":"Redirect to settings"},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"}},"summary":"Garmin Callback","description":"OAuth2 callback handler for Garmin Connect integration."}},"/api/integrations/garmin/disconnect":{"delete":{"tags":["Integrations"],"parameters":[],"responses":{"200":{"description":"Success"},"401":{"description":"Unauthorized"},"404":{"description":"Integration not found"}},"summary":"Disconnect Garmin","description":"Removes the Garmin Connect integration for the current user."}},"/api/integrations/hevy":{"post":{"tags":["Integrations"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}}}}}},"400":{"description":"Invalid API key"},"401":{"description":"Unauthorized"}},"summary":"Connect Hevy","description":"Connects the Hevy integration using an API key.","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["apiKey"],"properties":{"apiKey":{"type":"string"}}}}}}}},"/api/integrations/intervals":{"post":{"tags":["Integrations"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"athlete":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"email":{"type":"string"}}}}}}}},"400":{"description":"Invalid API key or athlete ID"},"401":{"description":"Unauthorized"}},"summary":"Connect Intervals.icu","description":"Connects the Intervals.icu integration using an API key and Athlete ID.","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["apiKey","athleteId"],"properties":{"apiKey":{"type":"string"},"athleteId":{"type":"string"}}}}}}}},"/api/integrations/intervals/disconnect":{"delete":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/integrations/intervals/sync-profile":{"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/integrations/intervals/webhook-async":{"post":{"tags":["Integrations"],"parameters":[],"responses":{"200":{"description":"OK"},"401":{"description":"Unauthorized"}},"summary":"Intervals.icu async webhook","description":"Handles incoming webhook notifications from Intervals.icu asynchronously via Redis queue.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"secret":{"type":"string"},"events":{"type":"array","items":{"type":"object","properties":{"athlete_id":{"type":"string"},"type":{"type":"string"},"timestamp":{"type":"string"}}}}}}}}}}},"/api/integrations/intervals/webhook":{"post":{"tags":["Integrations"],"parameters":[],"responses":{"200":{"description":"OK"},"401":{"description":"Unauthorized"}},"summary":"Intervals.icu webhook","description":"Handles incoming webhook notifications from Intervals.icu for activities, calendar, and wellness updates.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"secret":{"type":"string"},"events":{"type":"array","items":{"type":"object","properties":{"athlete_id":{"type":"string"},"type":{"type":"string"},"timestamp":{"type":"string"}}}}}}}}}}},"/api/integrations/oura/authorize":{"get":{"tags":["Integrations"],"parameters":[],"responses":{"302":{"description":"Redirect to Oura"},"401":{"description":"Unauthorized"}},"summary":"Authorize Oura","description":"Initiates the OAuth flow for Oura integration. Redirects to Oura."}},"/api/integrations/oura/callback":{"get":{"tags":["Integrations"],"parameters":[{"name":"code","in":"query","schema":{"type":"string"}},{"name":"state","in":"query","schema":{"type":"string"}},{"name":"error","in":"query","schema":{"type":"string"}}],"responses":{"302":{"description":"Redirect to settings"},"401":{"description":"Unauthorized"}},"summary":"Oura callback","description":"Handles the OAuth callback from Oura."}},"/api/integrations/oura/disconnect":{"delete":{"tags":["Integrations"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"message":{"type":"string"}}}}}},"401":{"description":"Unauthorized"},"404":{"description":"Integration not found"}},"summary":"Disconnect Oura","description":"Disconnects the Oura integration for the authenticated user."}},"/api/integrations/oura/webhook":{"get":{"tags":["Integrations"],"parameters":[{"name":"verification_token","in":"query","schema":{"type":"string"}},{"name":"challenge","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Challenge accepted"},"401":{"description":"Invalid token"}},"summary":"Oura Webhook Verification","description":"Verifies the Oura webhook subscription."},"post":{"tags":["Integrations"],"parameters":[],"responses":{"200":{"description":"OK"},"401":{"description":"Unauthorized"}},"summary":"Oura webhook","description":"Handles incoming webhook notifications from Oura.","requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}}}},"/api/integrations/polar/authorize":{"get":{"tags":["Integrations"],"parameters":[],"responses":{"302":{"description":"Redirect to Polar"},"401":{"description":"Unauthorized"}},"summary":"Authorize Polar","description":"Initiates the OAuth flow for Polar integration. Redirects to Polar."}},"/api/integrations/polar/callback":{"get":{"tags":["Integrations"],"parameters":[{"name":"code","in":"query","schema":{"type":"string"}},{"name":"state","in":"query","schema":{"type":"string"}},{"name":"error","in":"query","schema":{"type":"string"}}],"responses":{"302":{"description":"Redirect to settings"},"401":{"description":"Unauthorized"}},"summary":"Polar callback","description":"Handles the OAuth callback from Polar."}},"/api/integrations/polar/disconnect":{"delete":{"tags":["Integrations"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"message":{"type":"string"}}}}}},"401":{"description":"Unauthorized"},"404":{"description":"Integration not found"}},"summary":"Disconnect Polar","description":"Disconnects the Polar integration for the authenticated user."}},"/api/integrations/polar/webhook":{"post":{"tags":["Integrations"],"parameters":[],"responses":{"200":{"description":"OK"},"401":{"description":"Unauthorized"}},"summary":"Polar webhook","description":"Handles incoming webhook notifications from Polar.","requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}}}},"/api/integrations/rouvy/authorize":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/integrations/rouvy/callback":{"get":{"tags":["Integrations"],"parameters":[{"name":"code","in":"query","schema":{"type":"string"}},{"name":"state","in":"query","schema":{"type":"string"}},{"name":"error","in":"query","schema":{"type":"string"}}],"responses":{"302":{"description":"Redirect to settings"},"401":{"description":"Unauthorized"}},"summary":"ROUVY callback","description":"Handles the OAuth callback from ROUVY."}},"/api/integrations/rouvy/disconnect":{"delete":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/integrations/status":{"get":{"tags":["Integrations"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"integrations":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"provider":{"type":"string"},"lastSyncAt":{"type":"string","format":"date-time","nullable":true},"syncStatus":{"type":"string","nullable":true},"externalUserId":{"type":"string","nullable":true},"ingestWorkouts":{"type":"boolean"},"errorMessage":{"type":"string","nullable":true}}}}}}}}},"401":{"description":"Unauthorized"}},"summary":"Get integration status","description":"Returns the status of all connected integrations for the user."}},"/api/integrations/strava/authorize":{"get":{"tags":["Integrations"],"parameters":[],"responses":{"302":{"description":"Redirect to Strava"},"401":{"description":"Unauthorized"}},"summary":"Authorize Strava","description":"Initiates the OAuth flow for Strava integration. Redirects to Strava."}},"/api/integrations/strava/callback":{"get":{"tags":["Integrations"],"parameters":[{"name":"code","in":"query","schema":{"type":"string"}},{"name":"state","in":"query","schema":{"type":"string"}},{"name":"error","in":"query","schema":{"type":"string"}}],"responses":{"302":{"description":"Redirect to settings"},"401":{"description":"Unauthorized"}},"summary":"Strava callback","description":"Handles the OAuth callback from Strava."}},"/api/integrations/strava/disconnect":{"delete":{"tags":["Integrations"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"message":{"type":"string"}}}}}},"401":{"description":"Unauthorized"},"404":{"description":"Integration not found"}},"summary":"Disconnect Strava","description":"Disconnects the Strava integration for the authenticated user."}},"/api/integrations/strava/webhook":{"get":{"tags":["Integrations"],"parameters":[],"responses":{"200":{"description":"OK"},"401":{"description":"Unauthorized"}},"summary":"Strava Webhook","description":"Handles Strava webhook validation (GET) and event processing (POST)."}},"/api/integrations/sync":{"post":{"tags":["Integrations"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"jobId":{"type":"string"},"provider":{"type":"string"},"message":{"type":"string"},"dateRange":{"type":"object","properties":{"start":{"type":"string","format":"date-time"},"end":{"type":"string","format":"date-time"}}}}}}}},"400":{"description":"Invalid provider"},"401":{"description":"Unauthorized"},"404":{"description":"Integration not found"}},"summary":"Trigger sync","description":"Triggers a background job to sync data from an integration provider.","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["provider"],"properties":{"provider":{"type":"string","enum":["intervals","whoop","withings","yazio","strava","rouvy","hevy","fitbit","oura","polar","garmin","wahoo","ultrahuman","all"]},"days":{"type":"number","description":"Number of days to sync."}}}}}}}},"/api/integrations/telegram/disconnect":{"delete":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/integrations/telegram/link":{"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/integrations/telegram/webhook":{"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/integrations/ultrahuman/authorize":{"get":{"tags":["Integrations"],"parameters":[],"responses":{"302":{"description":"Redirect to Ultrahuman"},"401":{"description":"Unauthorized"}},"summary":"Ultrahuman authorize","description":"Redirects the user to Ultrahuman for OAuth authorization."}},"/api/integrations/ultrahuman/callback":{"get":{"tags":["Integrations"],"parameters":[{"name":"code","in":"query","schema":{"type":"string"}},{"name":"state","in":"query","schema":{"type":"string"}},{"name":"error","in":"query","schema":{"type":"string"}}],"responses":{"302":{"description":"Redirect to settings"},"401":{"description":"Unauthorized"}},"summary":"Ultrahuman callback","description":"Handles the OAuth callback from Ultrahuman."}},"/api/integrations/ultrahuman/disconnect":{"delete":{"tags":["Integrations"],"parameters":[],"responses":{"200":{"description":"Successfully disconnected"},"401":{"description":"Unauthorized"}},"summary":"Ultrahuman disconnect","description":"Removes the Ultrahuman integration for the current user."}},"/api/integrations/update":{"post":{"tags":["Integrations"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"integration":{"type":"object","properties":{"id":{"type":"string"},"provider":{"type":"string"},"ingestWorkouts":{"type":"boolean"}}}}}}}},"401":{"description":"Unauthorized"},"404":{"description":"Integration not found"}},"summary":"Update integration settings","description":"Updates settings for a specific integration (e.g., toggling workout ingestion).","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["provider"],"properties":{"provider":{"type":"string"},"ingestWorkouts":{"type":"boolean"}}}}}}}},"/api/integrations/wahoo/authorize":{"get":{"tags":["Integrations"],"parameters":[],"responses":{"302":{"description":"Redirect to Wahoo"},"401":{"description":"Unauthorized"}},"summary":"Authorize Wahoo","description":"Initiates the OAuth flow for Wahoo integration. Redirects to Wahoo."}},"/api/integrations/wahoo/callback":{"get":{"tags":["Integrations"],"parameters":[{"name":"code","in":"query","schema":{"type":"string"}},{"name":"state","in":"query","schema":{"type":"string"}},{"name":"error","in":"query","schema":{"type":"string"}}],"responses":{"302":{"description":"Redirect to settings"},"401":{"description":"Unauthorized"}},"summary":"Wahoo callback","description":"Handles the OAuth callback from Wahoo."}},"/api/integrations/wahoo/disconnect":{"delete":{"tags":["Integrations"],"parameters":[],"responses":{"200":{"description":"Success"},"401":{"description":"Unauthorized"},"404":{"description":"Integration not found"}},"summary":"Disconnect Wahoo","description":"Removes the Wahoo integration for the current user."}},"/api/integrations/wahoo/webhook":{"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/integrations/whoop/authorize":{"get":{"tags":["Integrations"],"parameters":[],"responses":{"302":{"description":"Redirect to Whoop"},"401":{"description":"Unauthorized"}},"summary":"Authorize Whoop","description":"Initiates the OAuth flow for Whoop integration. Redirects to Whoop."}},"/api/integrations/whoop/callback":{"get":{"tags":["Integrations"],"parameters":[{"name":"code","in":"query","schema":{"type":"string"}},{"name":"state","in":"query","schema":{"type":"string"}},{"name":"error","in":"query","schema":{"type":"string"}}],"responses":{"302":{"description":"Redirect to settings"},"401":{"description":"Unauthorized"}},"summary":"Whoop callback","description":"Handles the OAuth callback from Whoop."}},"/api/integrations/whoop/disconnect":{"delete":{"tags":["Integrations"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"message":{"type":"string"}}}}}},"401":{"description":"Unauthorized"},"404":{"description":"Integration not found"}},"summary":"Disconnect Whoop","description":"Disconnects the Whoop integration for the authenticated user."}},"/api/integrations/whoop/webhook-async":{"post":{"tags":["Integrations"],"parameters":[],"responses":{"200":{"description":"OK"}},"summary":"Whoop async webhook","description":"Handles incoming webhook notifications from Whoop. Data is stored in SQL and processed asynchronously.","requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}}}},"/api/integrations/whoop/webhook":{"post":{"tags":["Integrations"],"parameters":[],"responses":{"200":{"description":"OK"},"401":{"description":"Unauthorized"}},"summary":"Whoop webhook","description":"Handles incoming webhook notifications from Whoop.","requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}}}},"/api/integrations/withings/authorize":{"get":{"tags":["Integrations"],"parameters":[],"responses":{"302":{"description":"Redirect to Withings"},"401":{"description":"Unauthorized"}},"summary":"Authorize Withings","description":"Initiates the OAuth flow for Withings integration. Redirects to Withings."}},"/api/integrations/withings/callback":{"get":{"tags":["Integrations"],"parameters":[{"name":"code","in":"query","schema":{"type":"string"}},{"name":"state","in":"query","schema":{"type":"string"}},{"name":"error","in":"query","schema":{"type":"string"}}],"responses":{"302":{"description":"Redirect to settings"},"401":{"description":"Unauthorized"}},"summary":"Withings callback","description":"Handles the OAuth callback from Withings."}},"/api/integrations/withings/disconnect":{"delete":{"tags":["Integrations"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}}}}}},"401":{"description":"Unauthorized"},"404":{"description":"Integration not found"}},"summary":"Disconnect Withings","description":"Disconnects the Withings integration for the authenticated user."}},"/api/integrations/withings/webhook":{"post":{"tags":["Integrations"],"parameters":[],"responses":{"200":{"description":"OK"},"400":{"description":"Missing userid"}},"summary":"Withings webhook","description":"Handles incoming webhook notifications from Withings.","requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"userid":{"type":"string"},"appli":{"type":"string"},"startdate":{"type":"string"},"enddate":{"type":"string"}}}},"application/json":{"schema":{"type":"object","properties":{"userid":{"type":"string"},"appli":{"type":"string"},"startdate":{"type":"string"},"enddate":{"type":"string"}}}}}}}},"/api/integrations/yazio/connect":{"post":{"tags":["Integrations"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"integrationId":{"type":"string"}}}}}},"400":{"description":"Missing credentials"},"401":{"description":"Unauthorized or invalid credentials"}},"summary":"Connect Yazio","description":"Connects the Yazio integration using username and password.","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["username","password"],"properties":{"username":{"type":"string"},"password":{"type":"string"}}}}}}}},"/api/internal/render-email":{"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/internal/send-notification":{"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/issues/{id}":{"delete":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}},"get":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}},"patch":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/issues/{id}/comments":{"post":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/issues/{id}/comments/{commentId}":{"delete":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"commentId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}},"patch":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"commentId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/issues/{id}/comments/{commentId}/acknowledge":{"post":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"commentId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/issues/{id}/comments/{commentId}/reaction":{"post":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"commentId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/issues/{id}/reaction":{"post":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/issues":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}},"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/join/{code}":{"get":{"tags":["Coaching","Invites"],"parameters":[{"name":"code","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success"},"404":{"description":"Invite not found"}},"summary":"Get invite details","description":"Returns metadata for a coaching or team invitation code."},"post":{"tags":["Coaching","Invites"],"parameters":[{"name":"code","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success"},"404":{"description":"Invite not found"}},"summary":"Accept invite","description":"Accepts a coaching or team invitation code."}},"/api/library/plan-folders/{id}":{"delete":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}},"patch":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/library/plan-folders":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}},"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/library/plans/{id}/apply":{"post":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/library/plans/{id}/architect":{"get":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}},"patch":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/library/plans/{id}/import":{"post":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/library/plans/{id}/publication":{"patch":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/library/plans/bulk-move":{"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/library/plans/favorite":{"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/library/plans":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}},"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/library/strength-exercises/{id}":{"delete":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}},"patch":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/library/strength-exercises":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}},"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/library/workout-folders/{id}":{"delete":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}},"patch":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/library/workout-folders":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}},"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/library/workouts/{id}":{"delete":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}},"get":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}},"patch":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/library/workouts/{id}/adjust":{"post":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/library/workouts/{id}/generate-structure":{"post":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/library/workouts/{id}/intervals-preview":{"get":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/library/workouts/bulk-move":{"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/library/workouts":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}},"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/library/workouts/save":{"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/llm/feedback":{"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/metrics/today":{"get":{"tags":["Metrics"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"date":{"type":"string","format":"date-time"},"hrv":{"type":"number","nullable":true},"restingHr":{"type":"integer","nullable":true},"sleepScore":{"type":"integer","nullable":true},"readiness":{"type":"integer","nullable":true},"recoveryScore":{"type":"integer","nullable":true}}}}}},"401":{"description":"Unauthorized"}},"summary":"Get today's wellness metrics","description":"Returns the wellness and recovery metrics for the current day."}},"/api/monitoring/trigger":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/notifications":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/notifications/read":{"patch":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/nutrition/{id}":{"get":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/nutrition/{id}/analyze":{"post":{"tags":["Nutrition"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"UUID or Date (YYYY-MM-DD)"}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"nutritionId":{"type":"string"},"jobId":{"type":"string"},"status":{"type":"string"},"message":{"type":"string"}}}}}},"401":{"description":"Unauthorized"},"404":{"description":"Nutrition record not found"}},"summary":"Analyze nutrition","description":"Triggers AI analysis for a specific nutrition record."}},"/api/nutrition/{id}/items":{"patch":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/nutrition/{id}/log":{"post":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/nutrition/{id}/notes":{"patch":{"tags":["Nutrition"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"nutrition":{"type":"object"}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Unauthorized"},"404":{"description":"Nutrition entry not found"}},"summary":"Update nutrition notes","description":"Updates the notes for a specific nutrition entry.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"notes":{"type":"string","nullable":true}}}}}}}},"/api/nutrition/active-feed":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/nutrition/analyze-all":{"post":{"tags":["Nutrition"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"message":{"type":"string"},"total":{"type":"integer"},"triggered":{"type":"integer"},"failed":{"type":"integer"}}}}}},"401":{"description":"Unauthorized"}},"summary":"Analyze all nutrition","description":"Triggers AI analysis for up to 10 pending nutrition records per request."}},"/api/nutrition/extended-wave":{"get":{"tags":["Nutrition"],"parameters":[{"name":"daysAhead","in":"query","schema":{"type":"integer","default":3}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"points":{"type":"array","items":{"type":"object","properties":{"time":{"type":"string"},"timestamp":{"type":"number"},"level":{"type":"number"},"kcalBalance":{"type":"number"},"carbBalance":{"type":"number"},"fluidDeficit":{"type":"number"},"dataType":{"type":"string"},"event":{"type":"string","nullable":true}}}}}}}}},"401":{"description":"Unauthorized"}},"summary":"Get extended metabolic wave","description":"Returns a multi-day predictive energy wave (historical + current + future)."}},"/api/nutrition/generate-plan":{"post":{"tags":["Nutrition"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"message":{"type":"string"},"runId":{"type":"string","nullable":true}}}}}},"401":{"description":"Unauthorized"}},"summary":"Generate fueling plan","description":"Generates fueling plan synchronously for a target date.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"date":{"type":"string","format":"date-time","description":"The date to generate plan for (defaults to today)"}}}}}}}},"/api/nutrition/hydration-quick-add":{"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/nutrition/hydration-reset":{"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/nutrition":{"get":{"tags":["Nutrition"],"parameters":[{"name":"limit","in":"query","schema":{"type":"integer","default":30}},{"name":"startDate","in":"query","schema":{"type":"string","format":"date"}},{"name":"endDate","in":"query","schema":{"type":"string","format":"date"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"count":{"type":"integer"},"nutrition":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"date":{"type":"string","format":"date"},"calories":{"type":"integer","nullable":true},"protein":{"type":"number","nullable":true},"carbs":{"type":"number","nullable":true},"fat":{"type":"number","nullable":true}}}}}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"}},"summary":"List nutrition data","description":"Returns the recent nutrition logs for the authenticated user.","security":[{"bearerAuth":[]}]},"post":{"tags":["Nutrition"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object"}}}}}},"400":{"description":"Invalid data"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"}},"summary":"Upload nutrition data","description":"Logs or updates nutrition data using a flat list of items with timestamps.","security":[{"bearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NutritionUpload"}}}}}},"/api/nutrition/metabolic-wave":{"get":{"tags":["Nutrition"],"parameters":[{"name":"startDate","in":"query","required":true,"schema":{"type":"string","format":"date"}},{"name":"endDate","in":"query","required":true,"schema":{"type":"string","format":"date"}}],"responses":{"200":{"description":"Success"},"401":{"description":"Unauthorized"}},"summary":"Get metabolic wave for range","description":"Returns continuous metabolic points for a specific date range."}},"/api/nutrition/plan":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/nutrition/plan/generate":{"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/nutrition/plan/meal":{"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/nutrition/recommendations/{id}":{"get":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/nutrition/recommendations/meal":{"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/nutrition/simulate-impact":{"post":{"tags":["Nutrition"],"parameters":[],"responses":{"200":{"description":"Success"},"401":{"description":"Unauthorized"}},"summary":"Simulate meal impact","description":"Returns simulated metabolic points for a potential meal.","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["carbs","absorptionType"],"properties":{"date":{"type":"string","format":"date"},"carbs":{"type":"number"},"absorptionType":{"type":"string"},"time":{"type":"string","format":"date-time"}}}}}}}},"/api/nutrition/strategy":{"get":{"tags":["Nutrition"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"hydrationDebt":{"type":"number"},"fuelingMatrix":{"type":"array","items":{"type":"object","properties":{"date":{"type":"string"},"state":{"type":"integer"},"label":{"type":"string"},"carbsTarget":{"type":"number"},"isRest":{"type":"boolean"}}}},"summary":{"type":"string"}}}}}},"401":{"description":"Unauthorized"}},"summary":"Get metabolic strategy summary","description":"Returns weekly fueling states, hydration debt, and strategic fueling insights."}},"/api/nutrition/upcoming-plan":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/oauth/authorize-details":{"get":{"tags":["OAuth"],"parameters":[{"name":"client_id","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"logoUrl":{"type":"string","nullable":true},"description":{"type":"string","nullable":true}}}}}},"404":{"description":"Not Found"}},"summary":"Get Authorization Details","description":"Returns public details for an application to be shown on the consent screen."}},"/api/oauth/authorize":{"get":{"tags":["OAuth"],"parameters":[{"name":"response_type","in":"query","required":true,"schema":{"type":"string","enum":["code"]}},{"name":"client_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"redirect_uri","in":"query","required":true,"schema":{"type":"string","format":"uri"}},{"name":"scope","in":"query","required":false,"schema":{"type":"string"}},{"name":"state","in":"query","required":false,"schema":{"type":"string"}},{"name":"prompt","in":"query","required":false,"schema":{"type":"string"}},{"name":"code_challenge","in":"query","required":false,"schema":{"type":"string"}},{"name":"code_challenge_method","in":"query","required":false,"schema":{"type":"string","enum":["S256","plain"]}}],"responses":{"302":{"description":"Redirect to Consent Screen"},"400":{"description":"Bad Request"}},"summary":"Authorize OAuth Application","description":"Initiates the OAuth 2.0 authorization code flow. Validates parameters and redirects to the consent screen."},"post":{"tags":["OAuth"],"parameters":[],"responses":{"303":{"description":"Redirect to client callback URL"},"400":{"description":"Bad Request"},"401":{"description":"Unauthorized"}},"summary":"Approve Authorization Request","description":"Called by the consent screen to approve or deny an authorization request.","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["client_id","redirect_uri","action"],"properties":{"client_id":{"type":"string"},"redirect_uri":{"type":"string","format":"uri"},"scope":{"type":"string"},"state":{"type":"string"},"code_challenge":{"type":"string"},"code_challenge_method":{"type":"string"},"action":{"type":"string","enum":["approve","deny"]}}}},"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["client_id","redirect_uri","action"],"properties":{"client_id":{"type":"string"},"redirect_uri":{"type":"string","format":"uri"},"scope":{"type":"string"},"state":{"type":"string"},"code_challenge":{"type":"string"},"code_challenge_method":{"type":"string"},"action":{"type":"string","enum":["approve","deny"]}}}}}}}},"/api/oauth/consents":{"get":{"tags":["OAuth"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"app":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"logoUrl":{"type":"string","nullable":true},"description":{"type":"string","nullable":true},"homepageUrl":{"type":"string","nullable":true}}},"scopes":{"type":"array","items":{"type":"string"}},"createdAt":{"type":"string","format":"date-time"}}}}}}},"401":{"description":"Unauthorized"}},"summary":"List Authorized Applications","description":"Returns a list of third-party applications that the user has authorized to access their data."}},"/api/oauth/consents/{appId}":{"delete":{"tags":["OAuth"],"parameters":[{"name":"appId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success"},"401":{"description":"Unauthorized"},"404":{"description":"Not Found"}},"summary":"Revoke Application Access","description":"Revokes a third-party application's access to the user's data."}},"/api/oauth/public-apps":{"get":{"tags":["OAuth"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"sourceName":{"type":"string","nullable":true},"description":{"type":"string","nullable":true},"logoUrl":{"type":"string","nullable":true},"homepageUrl":{"type":"string","nullable":true}}}}}}}},"summary":"List Public OAuth Applications","description":"Returns OAuth applications that are marked public."}},"/api/oauth/revoke":{"post":{"tags":["OAuth"],"parameters":[],"responses":{"200":{"description":"Success"},"400":{"description":"Bad Request"}},"summary":"Revoke Token","description":"Invalidates an access token or refresh token.","requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["token"],"properties":{"token":{"type":"string"},"token_type_hint":{"type":"string","enum":["access_token","refresh_token"]},"client_id":{"type":"string"},"client_secret":{"type":"string"}}}}}}}},"/api/oauth/token":{"post":{"tags":["OAuth"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"access_token":{"type":"string"},"token_type":{"type":"string"},"expires_in":{"type":"integer"},"refresh_token":{"type":"string"},"refresh_token_expires_in":{"type":"integer","nullable":true},"scope":{"type":"string"}}}}}},"400":{"description":"Invalid Request"}},"summary":"Exchange Code for Token","description":"Exchanges an authorization code or refresh token for an access token.","requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["grant_type","client_id"],"properties":{"grant_type":{"type":"string","enum":["authorization_code","refresh_token"]},"client_id":{"type":"string"},"client_secret":{"type":"string"},"code":{"type":"string"},"redirect_uri":{"type":"string","format":"uri"},"refresh_token":{"type":"string"},"code_verifier":{"type":"string"}}}},"application/json":{"schema":{"$ref":"#/components/schemas/TokenRequest"}}}}}},"/api/oauth/userinfo":{"get":{"tags":["OAuth"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"sub":{"type":"string"},"name":{"type":"string"},"email":{"type":"string"},"image":{"type":"string"},"ftp":{"type":"integer"}}}}}},"401":{"description":"Unauthorized"}},"summary":"Get User Information","description":"Returns profile information for the user associated with the provided access token."}},"/api/orchestrate/full-sync":{"post":{"tags":["Orchestration"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"message":{"type":"string"}}}}}},"401":{"description":"Unauthorized"},"409":{"description":"Sync already in progress"}},"summary":"Start full sync","description":"Triggers a full orchestrated sync process, respecting task dependencies."}},"/api/orchestrate/metadata":{"get":{"tags":["Orchestration"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"metadata":{"type":"object","additionalProperties":{"type":"object","properties":{"lastSync":{"type":"string","format":"date-time","nullable":true},"isUpToDate":{"type":"boolean","nullable":true},"pendingCount":{"type":"integer","nullable":true},"totalCount":{"type":"integer","nullable":true},"duplicateCount":{"type":"integer","nullable":true}}}}}}}}},"401":{"description":"Unauthorized"}},"summary":"Get orchestration metadata","description":"Returns status and timestamps for various background tasks and data syncs."}},"/api/orchestrate/progress":{"get":{"tags":["Orchestration"],"parameters":[],"responses":{"200":{"description":"Success","content":{"text/event-stream":{"schema":{"type":"string"}}}},"401":{"description":"Unauthorized"}},"summary":"Get orchestration progress","description":"Streams Server-Sent Events (SSE) for tracking background sync progress."}},"/api/performance/ftp-evolution":{"get":{"tags":["Performance"],"parameters":[{"name":"months","in":"query","schema":{"type":["integer","string"],"default":12}},{"name":"sport","in":"query","schema":{"type":"string"}},{"name":"tags","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"date":{"type":"string","format":"date-time"},"month":{"type":"string"},"ftp":{"type":"integer"},"title":{"type":"string"}}}},"summary":{"type":"object","properties":{"currentFTP":{"type":"integer","nullable":true},"startingFTP":{"type":"integer","nullable":true},"peakFTP":{"type":"integer","nullable":true},"improvement":{"type":"number","nullable":true},"dataPoints":{"type":"integer"}}}}}}}},"401":{"description":"Unauthorized"}},"summary":"Get FTP evolution","description":"Returns the history of Functional Threshold Power changes."}},"/api/performance/pmc":{"get":{"tags":["Performance"],"parameters":[{"name":"days","in":"query","schema":{"type":["integer","string"],"default":90}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"date":{"type":"string","format":"date-time"},"ctl":{"type":"number"},"atl":{"type":"number"},"tsb":{"type":"number"},"tss":{"type":"number"}}}},"summary":{"type":"object","properties":{"currentCTL":{"type":"number"},"currentATL":{"type":"number"},"currentTSB":{"type":"number"},"formStatus":{"type":"string"},"formColor":{"type":"string"},"formDescription":{"type":"string"},"lastUpdated":{"type":"string","format":"date-time"}}}}}}}},"401":{"description":"Unauthorized"}},"summary":"Get Performance Management Chart (PMC)","description":"Returns fitness (CTL), fatigue (ATL), and form (TSB) metrics over time."}},"/api/performance/weight-evolution":{"get":{"tags":["Performance"],"parameters":[{"name":"months","in":"query","schema":{"type":"integer","default":12}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"date":{"type":"string","format":"date-time"},"weight":{"type":"number"}}}},"summary":{"type":"object","properties":{"current":{"type":"number","nullable":true},"starting":{"type":"number","nullable":true},"min":{"type":"number","nullable":true},"max":{"type":"number","nullable":true},"change":{"type":"number"},"unit":{"type":"string"}}}}}}}},"401":{"description":"Unauthorized"}},"summary":"Get weight evolution","description":"Returns the history of weight changes from wellness logs."}},"/api/planned-workouts/{id}":{"delete":{"tags":["Planned Workouts"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"message":{"type":"string"}}}}}},"401":{"description":"Unauthorized"},"404":{"description":"Workout not found"}},"summary":"Delete planned workout","description":"Deletes a specific planned workout and removes it from Intervals.icu."},"get":{"tags":["Planned Workouts"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"date":{"type":"string","format":"date-time"},"type":{"type":"string"},"description":{"type":"string","nullable":true},"durationSec":{"type":"integer","nullable":true},"tss":{"type":"number","nullable":true}}}}}},"401":{"description":"Unauthorized"},"404":{"description":"Workout not found"}},"summary":"Get planned workout","description":"Returns details for a specific planned workout."},"patch":{"tags":["Planned Workouts"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"workout":{"type":"object"},"syncStatus":{"type":"string"},"message":{"type":"string"}}}}}},"401":{"description":"Unauthorized"},"404":{"description":"Workout not found"}},"summary":"Update planned workout","description":"Updates a specific planned workout and syncs changes to Intervals.icu.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"date":{"type":"string","format":"date-time"},"title":{"type":"string"},"description":{"type":"string"},"type":{"type":"string"},"durationSec":{"type":"integer"},"tss":{"type":"number"},"fuelingStrategy":{"type":"string","enum":["STANDARD","TRAIN_LOW","HIGH_CARB"]}}}}}}}},"/api/planned-workouts/{id}/complete":{"post":{"tags":["Planned Workouts"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"plannedWorkout":{"type":"object"},"workout":{"type":"object","nullable":true}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Unauthorized"},"404":{"description":"Workout not found"}},"summary":"Complete planned workout","description":"Marks a planned workout as completed by linking it to an actual workout.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"workoutId":{"type":"string","nullable":true}}}}}}}},"/api/planned-workouts":{"get":{"tags":["Planned Workouts"],"parameters":[{"name":"limit","in":"query","schema":{"type":"integer","default":10}},{"name":"startDate","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"endDate","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"independentOnly","in":"query","schema":{"type":"boolean"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"date":{"type":"string","format":"date-time"},"type":{"type":"string"},"description":{"type":"string","nullable":true},"durationSec":{"type":"integer","nullable":true},"tss":{"type":"number","nullable":true},"trainingWeekId":{"type":"string","nullable":true}}}}}}},"401":{"description":"Unauthorized"}},"summary":"List planned workouts","description":"Returns upcoming planned workouts for the authenticated user."},"post":{"tags":["Planned Workouts"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"workout":{"type":"object"}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Unauthorized"}},"summary":"Create planned workout","description":"Creates a new planned workout and syncs it to Intervals.icu.","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["date","title"],"properties":{"date":{"type":"string","format":"date-time"},"title":{"type":"string"},"description":{"type":"string"},"type":{"type":"string","default":"Ride"},"category":{"type":"string"},"durationSec":{"type":"integer"},"tss":{"type":"number"},"workIntensity":{"type":"number"},"structuredWorkout":{"type":"object"},"fuelingStrategy":{"type":"string","enum":["STANDARD","TRAIN_LOW","HIGH_CARB"]}}}}}}}},"/api/plans/{id}":{"delete":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}},"get":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/plans/{id}/abandon":{"post":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/plans/{id}/activate":{"post":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/plans/{id}/blocks/{blockId}":{"delete":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"blockId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}},"patch":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"blockId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/plans/{id}/blocks":{"post":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/plans/{id}/blocks/reorder":{"put":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/plans/{id}/replan-structure":{"post":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/plans/{id}/save-template":{"post":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/plans/active":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/plans/adapt":{"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/plans/current":{"get":{"tags":["Plans"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"plan":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"status":{"type":"string"},"weekStartDate":{"type":"string","format":"date-time"},"weekEndDate":{"type":"string","format":"date-time"},"planJson":{"type":"object"},"totalTSS":{"type":"number"}}},"weekStart":{"type":"string","format":"date-time"}}}}}},"401":{"description":"Unauthorized"}},"summary":"Get current training plan","description":"Returns the active training plan for the current week."}},"/api/plans/generate-ai-week":{"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/plans/generate-block":{"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/plans/generate":{"post":{"tags":["Plans"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"jobId":{"type":"string"},"message":{"type":"string"}}}}}},"401":{"description":"Unauthorized"}},"summary":"Generate training plan","description":"Triggers a background job to generate a new training plan.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"startDate":{"type":"string","format":"date-time"},"days":{"type":"integer","default":7}}}}}}}},"/api/plans":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/plans/initialize":{"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/plans/status":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/plans/weeks/{id}":{"patch":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/plans/workouts/future":{"delete":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/plans/workouts/orphaned":{"delete":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/plans/workouts/past":{"delete":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/profile/ai-analysis":{"delete":{"tags":["Profile"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"counts":{"type":"object","properties":{"workouts":{"type":"integer"},"recommendations":{"type":"integer"},"planAdherence":{"type":"integer"},"reports":{"type":"integer"}}}}}}}},"401":{"description":"Unauthorized"}},"summary":"Wipe AI Analysis & Recommendations","description":"Removes all AI-generated workout analysis, recommendations, and reports."}},"/api/profile/athlete-profiles":{"delete":{"tags":["Profile"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"count":{"type":"integer"}}}}}},"401":{"description":"Unauthorized"}},"summary":"Delete all athlete profiles","description":"Removes all AI-generated athlete profiles and clears cached scores from the user record."}},"/api/profile/autodetect":{"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/profile/bug-reports":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/profile/bug-reports/{id}/comments":{"get":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}},"post":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/profile/dashboard":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/profile/email-preferences":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}},"put":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/profile/export":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/profile/generate":{"post":{"tags":["Profile"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"reportId":{"type":"string"},"jobId":{"type":"string"},"message":{"type":"string"}}}}}},"401":{"description":"Unauthorized"}},"summary":"Generate athlete profile","description":"Triggers an AI job to analyze data and generate an athlete profile report."}},"/api/profile":{"delete":{"tags":["Profile"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"jobId":{"type":"string"},"message":{"type":"string"}}}}}},"401":{"description":"Unauthorized"}},"summary":"Delete user account","description":"Permanently deletes the user account and all associated data."},"get":{"tags":["Profile"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"connected":{"type":"boolean"},"profile":{"type":"object","properties":{"name":{"type":"string","nullable":true},"nickname":{"type":"string","nullable":true},"email":{"type":"string"},"ftp":{"type":"integer","nullable":true},"maxHr":{"type":"integer","nullable":true},"weight":{"type":"number","nullable":true},"language":{"type":"string"},"uiLanguage":{"type":"string"},"distanceUnits":{"type":"string"},"city":{"type":"string","nullable":true},"country":{"type":"string","nullable":true}}}}}}}},"401":{"description":"Unauthorized"}},"summary":"Get user profile","description":"Returns the full profile and settings for the authenticated user."},"patch":{"tags":["Profile"],"parameters":[],"responses":{"200":{"description":"Success"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"}},"summary":"Update Profile","description":"Updates the authenticated user profile and metrics (Weight, FTP, MaxHR).","security":[{"bearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"weight":{"type":"number","description":"Weight in kilograms"},"ftp":{"type":"integer","description":"Functional Threshold Power in Watts"},"maxHr":{"type":"integer","description":"Maximum Heart Rate in bpm"},"lthr":{"type":"integer","description":"Lactate Threshold Heart Rate in bpm"},"dob":{"type":"string","format":"date","description":"Date of Birth (YYYY-MM-DD)"},"sex":{"type":"string","enum":["Male","Female","M","F"]},"city":{"type":"string"},"country":{"type":"string"},"uiLanguage":{"type":"string"}}}}}}}},"/api/profile/nutrition":{"delete":{"tags":["Profile"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"counts":{"type":"object","properties":{"nutrition":{"type":"integer"},"recommendations":{"type":"integer"},"plans":{"type":"integer"}}}}}}}},"401":{"description":"Unauthorized"}},"summary":"Wipe Nutrition Logs","description":"Removes all imported calorie, macro, and hydration data."},"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}},"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/profile/public":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}},"patch":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/profile/quotas":{"get":{"tags":["Profile"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"tier":{"type":"string"},"quotas":{"type":"array","items":{"type":"object","properties":{"operation":{"type":"string"},"allowed":{"type":"boolean"},"used":{"type":"integer"},"limit":{"type":"integer"},"remaining":{"type":"integer"},"window":{"type":"string"},"resetsAt":{"type":"string","format":"date-time"},"enforcement":{"type":"string"}}}}}}}}},"401":{"description":"Unauthorized"}},"summary":"Get user LLM quotas","description":"Returns the current usage and limits for LLM operations based on the user subscription tier."}},"/api/profile/sport-settings/{id}/detect-from-workouts":{"post":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/profile/status":{"get":{"tags":["Profile"],"parameters":[{"in":"query","name":"jobId","schema":{"type":"string"},"description":"Specific Job ID to check"}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"isRunning":{"type":"boolean"}}}}}},"401":{"description":"Unauthorized"}},"summary":"Get profile generation status","description":"Checks if profile generation tasks are currently running."}},"/api/profile/synced-activities":{"delete":{"tags":["Profile"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"counts":{"type":"object","properties":{"workouts":{"type":"integer"},"fitFiles":{"type":"integer"},"personalBests":{"type":"integer"}}}}}}}},"401":{"description":"Unauthorized"}},"summary":"Wipe Synced Activities","description":"Removes all imported workout data, raw fit files, and related performance metrics."}},"/api/profile/wellness":{"delete":{"tags":["Profile"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"counts":{"type":"object","properties":{"wellness":{"type":"integer"},"dailyMetrics":{"type":"integer"}}}}}}}},"401":{"description":"Unauthorized"}},"summary":"Wipe Wellness Data","description":"Removes all imported HRV, RHR, and Sleep logs."}},"/api/public/authors/{slug}":{"get":{"tags":["API Routes"],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/public/plans/{slug}":{"get":{"tags":["API Routes"],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/public/plans/access/{token}":{"get":{"tags":["API Routes"],"parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/public/plans":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/recommendations/{id}":{"get":{"tags":["Recommendations"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success"},"401":{"description":"Unauthorized"},"404":{"description":"Not found"}},"summary":"Get recommendation details","description":"Get details of a specific recommendation."},"patch":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/recommendations/{id}/accept":{"post":{"tags":["Recommendations"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"message":{"type":"string"}}}}}},"400":{"description":"Invalid recommendation state"},"401":{"description":"Unauthorized"},"404":{"description":"Recommendation not found"}},"summary":"Accept recommendation","description":"Accepts the suggested modifications and updates the planned workout."}},"/api/recommendations/{id}/guide":{"post":{"tags":["Recommendations"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"jobId":{"type":"string"}}}}}},"401":{"description":"Unauthorized"}},"summary":"Generate implementation guide","description":"Triggers AI generation of a structured implementation guide for a recommendation."}},"/api/recommendations/categories":{"get":{"tags":["Recommendations"],"parameters":[],"responses":{"200":{"description":"OK"}},"summary":"List unique recommendation categories"}},"/api/recommendations/clear":{"delete":{"tags":["Recommendations"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"count":{"type":"integer"}}}}}},"401":{"description":"Unauthorized"}},"summary":"Clear all recommendations","description":"Deletes all recommendations for the authenticated user."}},"/api/recommendations/generate":{"post":{"tags":["Recommendations"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"message":{"type":"string"},"jobId":{"type":"string"}}}}}},"401":{"description":"Unauthorized"}},"summary":"Generate recommendations","description":"Triggers a background job to generate recommendations based on existing score trends."}},"/api/recommendations":{"get":{"tags":["Recommendations"],"parameters":[{"name":"status","in":"query","schema":{"type":"string","enum":["ACTIVE","COMPLETED","DISMISSED","ALL"]}},{"name":"isPinned","in":"query","schema":{"type":"boolean"}},{"name":"metric","in":"query","schema":{"type":"string"}},{"name":"category","in":"query","schema":{"type":"string"}},{"name":"sourceType","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","default":50}}],"responses":{"200":{"description":"OK"}},"summary":"List recommendations"}},"/api/recommendations/status":{"get":{"tags":["Recommendations"],"parameters":[{"in":"query","name":"jobId","schema":{"type":"string"},"description":"Specific Job ID to check"}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"isRunning":{"type":"boolean"},"task":{"type":"string","nullable":true}}}}}},"401":{"description":"Unauthorized"}},"summary":"Get recommendation generation status","description":"Checks if recommendation generation tasks are currently running."}},"/api/recommendations/today":{"get":{"tags":["Recommendations"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"date":{"type":"string","format":"date-time"},"recommendation":{"type":"string"},"confidence":{"type":"number"},"reasoning":{"type":"string"},"status":{"type":"string"},"userAccepted":{"type":"boolean"},"analysisJson":{"type":"object"},"plannedWorkout":{"type":"object"}}}}}},"401":{"description":"Unauthorized"}},"summary":"Get today's recommendation","description":"Returns the daily activity recommendation for the current date."},"post":{"tags":["Recommendations"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"jobId":{"type":"string"},"recommendationId":{"type":"string"},"message":{"type":"string"}}}}}},"401":{"description":"Unauthorized"}},"summary":"Generate recommendation","description":"Triggers AI generation of a daily activity recommendation."}},"/api/recovery-context":{"get":{"tags":["Recovery Context"],"parameters":[],"responses":{"200":{"description":"OK"}},"summary":"List unified recovery context items","description":"Returns imported wellness periods, manual journey events, and completed daily check-ins in one normalized response.","security":[{"bearerAuth":[]}]}},"/api/recovery-context/journey":{"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/recovery-context/journey/{id}":{"delete":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}},"patch":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/releases/current":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/releases":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/reports/{id}":{"get":{"tags":["Reports"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string"},"status":{"type":"string"},"markdown":{"type":"string","nullable":true},"analysisJson":{"type":"object","nullable":true},"workouts":{"type":"array","items":{"type":"object"}},"nutrition":{"type":"array","items":{"type":"object"}}}}}}},"401":{"description":"Unauthorized"},"404":{"description":"Report not found"}},"summary":"Get report detail","description":"Returns the full details of a specific analysis report."}},"/api/reports/generate":{"post":{"tags":["Reports"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"reportId":{"type":"string"},"reportType":{"type":"string"},"jobId":{"type":"string"},"message":{"type":"string"}}}}}},"400":{"description":"Invalid report type"},"401":{"description":"Unauthorized"}},"summary":"Generate report","description":"Triggers a background job to generate a new analysis report.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string","enum":["WEEKLY_ANALYSIS","LAST_3_WORKOUTS","LAST_3_NUTRITION","LAST_7_NUTRITION","CUSTOM"],"default":"WEEKLY_ANALYSIS"},"config":{"type":"object","description":"Optional custom configuration for CUSTOM report type"}}}}}}}},"/api/reports":{"get":{"tags":["Reports"],"parameters":[{"name":"limit","in":"query","description":"Maximum number of reports to return","schema":{"type":"integer","default":10}},{"name":"type","in":"query","description":"Filter by report type","schema":{"type":"string"}},{"name":"beforeDate","in":"query","description":"Filter reports created on or before this date","schema":{"type":"string","format":"date-time"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string"},"status":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"dateRangeStart":{"type":"string","format":"date-time"},"dateRangeEnd":{"type":"string","format":"date-time"},"modelVersion":{"type":"string","nullable":true},"analysisJson":{"type":"object","nullable":true}}}}}}},"401":{"description":"Unauthorized"}},"summary":"List reports","description":"Returns a list of reports for the authenticated user."}},"/api/reports/templates":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/runs/{id}":{"delete":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}},"get":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/runs/active":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/scores/athlete-profile":{"get":{"tags":["Scores"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"user":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string","nullable":true},"ftp":{"type":"integer","nullable":true},"weight":{"type":"number","nullable":true},"maxHr":{"type":"integer","nullable":true},"wkg":{"type":"string","nullable":true}}},"scores":{"type":"object","properties":{"currentFitness":{"type":"integer","nullable":true},"recoveryCapacity":{"type":"integer","nullable":true},"nutritionCompliance":{"type":"integer","nullable":true},"trainingConsistency":{"type":"integer","nullable":true},"lastUpdated":{"type":"string","format":"date-time","nullable":true}}}}}}}},"401":{"description":"Unauthorized"},"404":{"description":"User not found"}},"summary":"Get athlete profile scores","description":"Returns the current athlete profile scores and explanations."}},"/api/scores/efficiency-trends":{"get":{"tags":["Scores"],"parameters":[{"name":"days","in":"query","schema":{"type":["integer","string"],"default":90}},{"name":"sport","in":"query","schema":{"type":"string"}},{"name":"tags","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"trends":{"type":"array","items":{"type":"object","properties":{"date":{"type":"string"},"timestamp":{"type":"string","format":"date-time"},"workoutId":{"type":"string","nullable":true},"efficiencyFactor":{"type":"number"},"decoupling":{"type":"number","nullable":true},"normalizedPower":{"type":"number","nullable":true},"averageHr":{"type":"number","nullable":true}}}}}}}}},"401":{"description":"Unauthorized"}},"summary":"Get efficiency trends","description":"Returns efficiency factor (Power/HR) and decoupling trends."}},"/api/scores/explanation":{"get":{"tags":["Scores"],"parameters":[{"name":"type","in":"query","required":true,"schema":{"type":"string","enum":["nutrition","workout"]}},{"name":"period","in":"query","required":true,"schema":{"type":"integer"}},{"name":"metric","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"analysis":{"type":"object","nullable":true},"score":{"type":"number","nullable":true},"period":{"type":"integer","nullable":true},"cached":{"type":"boolean"},"generatedAt":{"type":"string","format":"date-time","nullable":true},"expiresAt":{"type":"string","format":"date-time","nullable":true},"message":{"type":"string","nullable":true},"generating":{"type":"boolean","nullable":true}}}}}},"400":{"description":"Missing required parameters"},"401":{"description":"Unauthorized"}},"summary":"Get score explanation","description":"Returns an AI-generated explanation for a specific score trend."}},"/api/scores/generate-explanations":{"post":{"tags":["Scores"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"message":{"type":"string"},"jobId":{"type":"string"}}}}}},"401":{"description":"Unauthorized"}},"summary":"Generate score explanations","description":"Triggers a background job to generate explanations for all score trends."}},"/api/scores/nutrition-trends-explanation":{"post":{"tags":["Scores"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"analysis":{"type":"object"},"score":{"type":"number"},"period":{"type":"integer"}}}}}},"401":{"description":"Unauthorized"}},"summary":"Generate nutrition trend explanation","description":"Generates an AI explanation for nutrition trends.","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["summary"],"properties":{"days":{"type":"integer","default":14},"summary":{"type":"object","required":["total"],"properties":{"total":{"type":"integer"},"avgOverall":{"type":"number"},"avgMacroBalance":{"type":"number"},"avgQuality":{"type":"number"},"avgAdherence":{"type":"number"},"avgHydration":{"type":"number"}}}}}}}}}},"/api/scores/nutrition-trends":{"get":{"tags":["Scores"],"parameters":[{"name":"days","in":"query","schema":{"type":"integer","default":14}},{"name":"sport","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"nutrition":{"type":"array","items":{"type":"object"}},"summary":{"type":"object","properties":{"total":{"type":"integer"},"avgOverall":{"type":"number"},"avgMacroBalance":{"type":"number"},"avgQuality":{"type":"number"},"avgAdherence":{"type":"number"},"avgHydration":{"type":"number"}}}}}}}},"401":{"description":"Unauthorized"}},"summary":"Get nutrition trends","description":"Returns nutrition scores and averages for a specified period."}},"/api/scores/readiness-correlation":{"get":{"tags":["Scores"],"parameters":[{"name":"days","in":"query","schema":{"type":["integer","string"],"default":30}},{"name":"tags","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"points":{"type":"array","items":{"type":"object","properties":{"x":{"type":"number","description":"Recovery Score"},"y":{"type":"number","description":"Performance (TSS)"},"date":{"type":"string","format":"date-time"},"type":{"type":"string"},"title":{"type":"string"}}}}}}}}},"401":{"description":"Unauthorized"}},"summary":"Get readiness correlation","description":"Returns data points correlating recovery scores with workout performance (TSS)."}},"/api/scores/workout-trends-explanation":{"post":{"tags":["Scores"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"analysis":{"type":"object"},"score":{"type":"number"},"period":{"type":"integer"}}}}}},"401":{"description":"Unauthorized"}},"summary":"Generate workout trend explanation","description":"Generates an AI explanation for workout trends.","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["summary"],"properties":{"days":{"type":"integer","default":30},"summary":{"type":"object","required":["total"],"properties":{"total":{"type":"integer"},"avgOverall":{"type":"number"},"avgTechnical":{"type":"number"},"avgEffort":{"type":"number"},"avgPacing":{"type":"number"},"avgExecution":{"type":"number"}}}}}}}}}},"/api/scores/workout-trends":{"get":{"tags":["Scores"],"parameters":[{"name":"days","in":"query","schema":{"type":"integer","default":30}},{"name":"sport","in":"query","schema":{"type":"string"}},{"name":"tags","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"workouts":{"type":"array","items":{"type":"object","properties":{"date":{"type":"string","format":"date-time"},"overallScore":{"type":"integer"},"technicalScore":{"type":"integer"},"effortScore":{"type":"integer"},"pacingScore":{"type":"integer"},"executionScore":{"type":"integer"},"isGhost":{"type":"boolean"}}}},"summary":{"type":"object","properties":{"total":{"type":"integer"},"avgOverall":{"type":"number"},"avgTechnical":{"type":"number"},"avgEffort":{"type":"number"},"avgPacing":{"type":"number"},"avgExecution":{"type":"number"}}}}}}}},"401":{"description":"Unauthorized"}},"summary":"Get workout trends","description":"Returns daily workout scores and trends for a specified period."}},"/api/settings/ai":{"get":{"tags":["Settings"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"aiPersona":{"type":"string"},"aiModelPreference":{"type":"string"},"aiAutoAnalyzeWorkouts":{"type":"boolean"},"aiAutoAnalyzeNutrition":{"type":"boolean"},"aiAutoAnalyzeReadiness":{"type":"boolean"},"aiRequireToolApproval":{"type":"boolean"},"aiProactivityEnabled":{"type":"boolean"},"aiConversationalEngagement":{"type":"boolean"},"aiMemoryEnabled":{"type":"boolean"},"aiDeepAnalysisEnabled":{"type":"boolean"},"aiContext":{"type":"string","nullable":true},"updateWorkoutNotesEnabled":{"type":"boolean"},"nickname":{"type":"string","nullable":true},"aiTtsStyle":{"type":"string"},"aiTtsVoiceName":{"type":"string"},"aiTtsSpeed":{"type":"string"},"aiTtsAutoReadMessages":{"type":"boolean"}}}}}},"401":{"description":"Unauthorized"},"404":{"description":"User not found"}},"summary":"Get AI settings","description":"Returns the AI preferences for the authenticated user."},"post":{"tags":["Settings"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"settings":{"type":"object","properties":{"aiPersona":{"type":"string"},"aiModelPreference":{"type":"string"},"aiAutoAnalyzeWorkouts":{"type":"boolean"},"aiAutoAnalyzeNutrition":{"type":"boolean"},"aiRequireToolApproval":{"type":"boolean"},"aiMemoryEnabled":{"type":"boolean"},"aiContext":{"type":"string","nullable":true},"nutritionTrackingEnabled":{"type":"boolean"},"updateWorkoutNotesEnabled":{"type":"boolean"},"nickname":{"type":"string","nullable":true},"aiTtsStyle":{"type":"string"},"aiTtsVoiceName":{"type":"string"},"aiTtsSpeed":{"type":"string"},"aiTtsAutoReadMessages":{"type":"boolean"}}}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Unauthorized"}},"summary":"Update AI settings","description":"Updates the AI preferences for the authenticated user.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"aiPersona":{"type":"string","enum":["Analytical","Supportive","Drill Sergeant","Motivational"]},"aiModelPreference":{"type":"string","enum":["flash","pro","experimental"]},"aiAutoAnalyzeWorkouts":{"type":"boolean"},"aiAutoAnalyzeNutrition":{"type":"boolean"},"aiAutoAnalyzeReadiness":{"type":"boolean"},"aiRequireToolApproval":{"type":"boolean"},"aiProactivityEnabled":{"type":"boolean"},"aiConversationalEngagement":{"type":"boolean"},"aiMemoryEnabled":{"type":"boolean"},"aiDeepAnalysisEnabled":{"type":"boolean"},"aiContext":{"type":"string","nullable":true},"nutritionTrackingEnabled":{"type":"boolean"},"updateWorkoutNotesEnabled":{"type":"boolean"},"nickname":{"type":"string","nullable":true},"aiTtsStyle":{"type":"string","enum":["coach","calm","direct","energetic"]},"aiTtsVoiceName":{"type":"string"},"aiTtsSpeed":{"type":"string","enum":["slow","normal","fast"]},"aiTtsAutoReadMessages":{"type":"boolean"}}}}}}}},"/api/settings/api-keys/{id}":{"delete":{"tags":["Settings"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}}}}}},"401":{"description":"Unauthorized"},"404":{"description":"Key not found"}},"summary":"Revoke an API key","description":"Permanently deletes an API key."}},"/api/settings/api-keys":{"get":{"tags":["Settings"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"prefix":{"type":"string"},"lastUsedAt":{"type":"string","nullable":true},"expiresAt":{"type":"string","nullable":true},"createdAt":{"type":"string"}}}}}}},"401":{"description":"Unauthorized"}},"summary":"List API keys","description":"Returns a list of API keys associated with the authenticated user."},"post":{"tags":["Settings"],"parameters":[],"responses":{"200":{"description":"Success - returns the plain API key (only shown once)","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"prefix":{"type":"string"},"key":{"type":"string","description":"The full API key"},"createdAt":{"type":"string"}}}}}},"401":{"description":"Unauthorized"}},"summary":"Create an API key","description":"Generates a new API key for the authenticated user.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Friendly name for the API key"}},"required":["name"]}}}}}},"/api/share/{token}":{"get":{"tags":["Public"],"parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"resourceType":{"type":"string"},"data":{"type":"object"},"user":{"type":"object","properties":{"name":{"type":"string","nullable":true},"image":{"type":"string","nullable":true}}}}}}}},"404":{"description":"Share link not found or expired"}},"summary":"Get shared resource","description":"Returns details of a shared resource via token."}},"/api/share/chat/{token}":{"get":{"tags":["Public"],"parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string","nullable":true},"messages":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"role":{"type":"string"},"content":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}}}},"user":{"type":"object","properties":{"name":{"type":"string","nullable":true},"image":{"type":"string","nullable":true}}}}}}}},"404":{"description":"Chat not found or link invalid"}},"summary":"Get public chat","description":"Returns messages of a publicly shared chat room via token."}},"/api/share/generate":{"post":{"tags":["Share"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string"},"url":{"type":"string"}}}}}},"401":{"description":"Unauthorized"},"404":{"description":"Resource not found"}},"summary":"Generate share token","description":"Generates a share token for a specific resource.","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["resourceType","resourceId"],"properties":{"resourceType":{"type":"string","enum":["WORKOUT","REPORT","NUTRITION","PLANNED_WORKOUT","TRAINING_PLAN","WELLNESS","CHAT_ROOM"]},"resourceId":{"type":"string"},"expiresIn":{"type":["number","null"],"description":"Expiration in seconds. Null creates a non-expiring link."},"forceNew":{"type":"boolean","description":"Force a new token instead of reusing the latest active token."}}}}}}}},"/api/share/workouts/{token}":{"get":{"tags":["Public"],"parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"date":{"type":"string","format":"date-time"},"user":{"type":"object","properties":{"name":{"type":"string","nullable":true},"image":{"type":"string","nullable":true}}}}}}}},"404":{"description":"Workout not found or link invalid"}},"summary":"Get public workout","description":"Returns details of a publicly shared workout via token."}},"/api/share/workouts/{token}/image":{"get":{"tags":["Public"],"parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"image/png":{"schema":{"type":"string","format":"binary"}}}},"404":{"description":"Workout not found"}},"summary":"Get workout share image","description":"Generates and returns a PNG image for a shared workout."}},"/api/share/workouts/{token}/intervals":{"get":{"tags":["Public"],"parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"hasData":{"type":"boolean"},"detectionMetric":{"type":"string","nullable":true},"intervals":{"type":"array"},"peaks":{"type":"object"},"advanced":{"type":"object"}}}}}},"404":{"description":"Workout not found or link invalid"}},"summary":"Get public workout intervals","description":"Detects and analyzes intervals for a publicly shared workout."}},"/api/share/workouts/{token}/power-curve":{"get":{"tags":["Public"],"parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"hasPowerData":{"type":"boolean"},"powerCurve":{"type":"array","items":{"type":"object","properties":{"duration":{"type":"integer"},"power":{"type":"number"}}}},"summary":{"type":"object","properties":{"peak5s":{"type":"number"},"peak20min":{"type":"number"},"estimatedFTP":{"type":"number","nullable":true}}}}}}}},"404":{"description":"Workout not found or link invalid"}},"summary":"Get public power curve","description":"Calculates the power curve for a publicly shared workout."}},"/api/share/workouts/{token}/streams":{"get":{"tags":["Public"],"parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"workoutId":{"type":"string"},"time":{"type":"array"},"watts":{"type":"array"},"heartrate":{"type":"array"},"cadence":{"type":"array"}}}}}},"404":{"description":"Workout not found or link invalid"}},"summary":"Get public workout streams","description":"Returns stream data for a publicly shared workout."}},"/api/stats/monthly-comparison":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/storage/upload":{"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/stripe/change-plan":{"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/stripe/checkout-session":{"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/stripe/portal-session":{"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/stripe/sync":{"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/stripe/webhook":{"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/support/send":{"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/system-messages/dismiss":{"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/system-messages/latest":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/system-messages/share-reward/claim":{"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/user/consent":{"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/user/me":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/user/settings":{"patch":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/webhooks/garmin":{"post":{"tags":["Integrations"],"parameters":[],"responses":{"200":{"description":"OK"}},"summary":"Garmin Webhook","description":"Handles Garmin Push API notifications. Data is stored in SQL and processed asynchronously by the worker."}},"/api/webhooks/oauth/{clientId}":{"post":{"tags":["OAuth"],"parameters":[{"name":"clientId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"},"404":{"description":"Application Not Found"}},"summary":"Generic OAuth Webhook","description":"A generic webhook endpoint for third-party OAuth applications to push data. Captures the raw payload and associates it with the application."}},"/api/webhooks/resend":{"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/websocket-token":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/websocket":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/wellness/{id}":{"patch":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/wellness/{wellnessId}":{"get":{"tags":["Wellness"],"parameters":[{"name":"wellnessParam","in":"path","required":true,"schema":{"type":"string"},"description":"UUID or Date (YYYY-MM-DD)"}],"responses":{"200":{"description":"Success"},"400":{"description":"Invalid format"},"401":{"description":"Unauthorized"},"403":{"description":"Access denied"},"404":{"description":"Not found"}},"summary":"Get wellness by ID or Date","description":"Returns a wellness record by ID or Date."},"patch":{"tags":["Wellness"],"parameters":[{"name":"wellnessId","in":"path","required":true,"schema":{"type":"string"},"description":"Wellness record ID"}],"responses":{"200":{"description":"Success"},"400":{"description":"Invalid input"},"401":{"description":"Unauthorized"},"404":{"description":"Wellness record not found"},"409":{"description":"Date conflict"}},"summary":"Update wellness record","description":"Updates editable fields on a specific wellness record. Fields may be set to null to clear bad data.","security":[{"bearerAuth":[]}]}},"/api/wellness/{wellnessId}/analyze":{"post":{"tags":["API Routes"],"parameters":[{"name":"wellnessId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/wellness/analyze":{"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/wellness/events":{"get":{"tags":["Wellness"],"parameters":[{"name":"days","in":"query","schema":{"type":["integer","string"],"default":30}}],"responses":{"200":{"description":"Success"},"401":{"description":"Unauthorized"}},"summary":"List normalized wellness events","description":"Returns normalized wellness events from synced tags and wellness-related calendar periods for chart overlays and AI context.","security":[{"bearerAuth":[]}]}},"/api/wellness":{"get":{"tags":["Wellness"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"date":{"type":"string","format":"date-time"},"hrv":{"type":"number","nullable":true},"restingHr":{"type":"integer","nullable":true},"sleepScore":{"type":"integer","nullable":true},"readiness":{"type":"integer","nullable":true},"recoveryScore":{"type":"integer","nullable":true},"weight":{"type":"number","nullable":true},"systolic":{"type":"integer","nullable":true},"diastolic":{"type":"integer","nullable":true}}}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"}},"summary":"List wellness data","description":"Returns the last 90 days of wellness data for the authenticated user.","security":[{"bearerAuth":[]}]},"post":{"tags":["Wellness"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object"}}}}}},"400":{"description":"Invalid data"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"}},"summary":"Upload wellness data","description":"Logs or updates wellness metrics for a specific date.","security":[{"bearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WellnessUpload"}}}}}},"/api/wellness/trend":{"get":{"tags":["Wellness"],"parameters":[{"name":"startDate","in":"query","required":true,"schema":{"type":"string","format":"date-time"}},{"name":"endDate","in":"query","required":true,"schema":{"type":"string","format":"date-time"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"date":{"type":"string"},"hrv":{"type":"number","nullable":true},"restingHr":{"type":"integer","nullable":true},"hoursSlept":{"type":"number","nullable":true},"sleepScore":{"type":"integer","nullable":true},"recoveryScore":{"type":"integer","nullable":true}}}}}}},"400":{"description":"Invalid date range"},"401":{"description":"Unauthorized"}},"summary":"Get wellness trends","description":"Returns daily wellness metrics for a specified date range."}},"/api/workouts/{id}":{"delete":{"tags":["Workouts"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}}}}}},"401":{"description":"Unauthorized"},"404":{"description":"Workout not found"}},"summary":"Delete workout","description":"Deletes a specific workout by ID."},"get":{"tags":["Workouts"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Workout"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Workout not found"}},"summary":"Get workout details","description":"Returns the full details for a specific workout."},"patch":{"tags":["Workouts"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"workout":{"$ref":"#/components/schemas/Workout"}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Unauthorized"},"404":{"description":"Workout not found"}},"summary":"Update workout details","description":"Updates a specific workout by ID. Supports renaming, changing types, and overriding metrics.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string"},"type":{"type":"string"},"date":{"type":"string","format":"date-time"},"description":{"type":"string","nullable":true},"durationSec":{"type":"number"},"distanceMeters":{"type":"number","nullable":true},"trainingLoad":{"type":"number","nullable":true},"tss":{"type":"number","nullable":true},"calories":{"type":"integer","nullable":true},"elevationGain":{"type":"integer","nullable":true},"addTags":{"type":"array","items":{"type":"string"}},"removeTags":{"type":"array","items":{"type":"string"}},"setLocalTags":{"type":"array","items":{"type":"string"}}}}}}}}},"/api/workouts/{id}/analyze-adherence":{"post":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/workouts/{id}/analyze":{"post":{"tags":["Workouts"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"workoutId":{"type":"string"},"jobId":{"type":"string"},"status":{"type":"string"},"message":{"type":"string"}}}}}},"401":{"description":"Unauthorized"},"404":{"description":"Workout not found"}},"summary":"Analyze workout","description":"Triggers AI analysis for a specific workout."}},"/api/workouts/{id}/export/gpx":{"get":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/workouts/{id}/intervals":{"get":{"tags":["Workouts"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"debug","in":"query","required":false,"schema":{"type":"boolean"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"hasData":{"type":"boolean"},"detectionMetric":{"type":"string","nullable":true},"intervals":{"type":"array"},"peaks":{"type":"object"},"recovery":{"type":"object","nullable":true},"advanced":{"type":"object"},"chartData":{"type":"object"},"audit":{"type":"object","nullable":true},"message":{"type":"string","nullable":true}}}}}},"401":{"description":"Unauthorized"},"404":{"description":"Workout not found"}},"summary":"Get workout intervals","description":"Detects and analyzes intervals within a workout based on power, pace, or heart rate."}},"/api/workouts/{id}/link":{"post":{"tags":["Workouts"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Unauthorized"},"404":{"description":"Workout or planned workout not found"}},"summary":"Link workout to planned workout","description":"Links an existing completed workout to a planned workout, marking the planned workout as completed.","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["plannedWorkoutId"],"properties":{"plannedWorkoutId":{"type":"string"}}}}}}}},"/api/workouts/{id}/metric-history":{"get":{"tags":["Workouts"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"metricKey","in":"query","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success"},"401":{"description":"Unauthorized"},"404":{"description":"Workout not found"}},"summary":"Get metric history","description":"Returns previous workouts of the same activity type with extracted values for a specific metric."}},"/api/workouts/{id}/notes":{"patch":{"tags":["Workouts"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"workout":{"$ref":"#/components/schemas/Workout"}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Unauthorized"},"404":{"description":"Workout not found"}},"summary":"Update workout notes","description":"Updates the notes for a specific workout.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"notes":{"type":"string","nullable":true}}}}}}}},"/api/workouts/{id}/power-curve":{"get":{"tags":["Workouts"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"hasPowerData":{"type":"boolean"},"powerCurve":{"type":"array","items":{"type":"object","properties":{"duration":{"type":"integer"},"durationLabel":{"type":"string"},"power":{"type":"number"}}}},"summary":{"type":"object","properties":{"peak5s":{"type":"number"},"peak20min":{"type":"number"},"estimatedFTP":{"type":"number","nullable":true}}},"message":{"type":"string","nullable":true}}}}}},"401":{"description":"Unauthorized"},"404":{"description":"Workout not found"}},"summary":"Get workout power curve","description":"Calculates the power curve (peak power over durations) for a specific workout."}},"/api/workouts/{id}/promote":{"post":{"tags":["Workouts"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}}}}}},"400":{"description":"Workout is not a duplicate"},"401":{"description":"Unauthorized"},"404":{"description":"Workout not found"}},"summary":"Promote workout","description":"Promotes a duplicate workout to be the primary version, swapping roles with the current primary."}},"/api/workouts/{id}/publish-summary":{"post":{"tags":["Workouts"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"message":{"type":"string"}}}}}},"400":{"description":"Workout is not eligible for Intervals publish"},"401":{"description":"Unauthorized"},"404":{"description":"Workout not found"}},"summary":"Publish AI workout summary to Intervals.icu","description":"Publishes the workout AI executive summary to the linked Intervals.icu activity description."}},"/api/workouts/{id}/share":{"post":{"tags":["Workouts"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string","nullable":true},"success":{"type":"boolean","nullable":true}}}}}},"400":{"description":"Invalid action"},"401":{"description":"Unauthorized"},"404":{"description":"Workout not found"}},"summary":"Share workout","description":"Generates or revokes a public share token for a workout.","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["action"],"properties":{"action":{"type":"string","enum":["generate","revoke"]}}}}}}}},"/api/workouts/{id}/streams":{"get":{"tags":["Workouts"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"workoutId":{"type":"string"},"time":{"type":"array","items":{"type":"number"}},"watts":{"type":"array","items":{"type":"number"}},"heartrate":{"type":"array","items":{"type":"number"}},"cadence":{"type":"array","items":{"type":"number"}},"hrZoneTimes":{"type":"array","items":{"type":"number"}},"powerZoneTimes":{"type":"array","items":{"type":"number"}},"pacingStrategy":{"type":"object"}}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Workout not found or streams unavailable"}},"summary":"Get workout stream details","description":"Returns detailed stream data (pacing, HR, power) for a specific workout."}},"/api/workouts/{id}/unlink-duplicate":{"post":{"tags":["Workouts"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}}}}}},"401":{"description":"Unauthorized"},"404":{"description":"Workout not found"}},"summary":"Unlink duplicate workout","description":"Removes the duplicate relationship between workouts."}},"/api/workouts/{id}/unlink":{"post":{"tags":["Workouts"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}}}}}},"401":{"description":"Unauthorized"},"404":{"description":"Workout not found"}},"summary":"Unlink workout from planned workout","description":"Removes the link between a completed workout and a planned workout, marking the planned workout as pending."}},"/api/workouts/analyze-all":{"post":{"tags":["Workouts"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"message":{"type":"string"},"total":{"type":"integer"},"triggered":{"type":"integer"},"failed":{"type":"integer"}}}}}},"401":{"description":"Unauthorized"}},"summary":"Analyze all workouts","description":"Triggers AI analysis for up to 10 pending workouts per request."}},"/api/workouts/by-date":{"get":{"tags":["Workouts"],"parameters":[{"name":"date","in":"query","required":true,"schema":{"type":"string","format":"date"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"date":{"type":"string","format":"date-time"},"type":{"type":"string"},"durationSec":{"type":"integer"},"distanceMeters":{"type":"number"}}}}}}},"400":{"description":"Missing date parameter"},"401":{"description":"Unauthorized"}},"summary":"Get workouts by date","description":"Returns all workouts for a specific date."}},"/api/workouts/count":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/workouts/deduplicate":{"post":{"tags":["Workouts"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"taskId":{"type":"string"}}}}}},"401":{"description":"Unauthorized"}},"summary":"Deduplicate workouts","description":"Triggers a background job to identify and merge duplicate workouts."}},"/api/workouts/generate":{"post":{"tags":["Workouts"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"jobId":{"type":"string"},"message":{"type":"string"}}}}}},"401":{"description":"Unauthorized"}},"summary":"Generate ad-hoc workout","description":"Triggers AI generation of a planned workout for today."}},"/api/workouts":{"get":{"tags":["Workouts"],"parameters":[{"name":"limit","in":"query","description":"Maximum number of workouts to return","schema":{"type":"integer"}},{"name":"startDate","in":"query","description":"Filter workouts after this date (ISO 8601)","schema":{"type":"string","format":"date-time"}},{"name":"endDate","in":"query","description":"Filter workouts before this date (ISO 8601)","schema":{"type":"string","format":"date-time"}},{"name":"includeDuplicates","in":"query","description":"Whether to include duplicate workouts in the results","schema":{"type":"boolean"}},{"name":"type","in":"query","description":"Filter workouts by sport type","schema":{"type":"string"}},{"name":"tags","in":"query","description":"Filter workouts by comma-separated tags (ANY match)","schema":{"type":"string"}},{"name":"x-act-as-user","in":"header","description":"Athlete user ID to act as (for coaches)","schema":{"type":"string"}},{"name":"X-API-Key","in":"header","description":"API key for authentication","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Workout"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"}},"summary":"List workouts","description":"Returns a list of workouts for the authenticated user or an athlete they coach.","security":[{"bearerAuth":[]}]}},"/api/workouts/manual":{"post":{"tags":["Workouts"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"workout":{"$ref":"#/components/schemas/Workout"}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Unauthorized"}},"summary":"Create manual workout","description":"Creates a manual workout entry for the user.","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["title","date","durationSec"],"properties":{"title":{"type":"string"},"description":{"type":"string"},"type":{"type":"string"},"date":{"type":"string","format":"date-time"},"durationSec":{"type":"integer"},"distanceMeters":{"type":"number"},"tss":{"type":"number"},"rpe":{"type":"integer"},"plannedWorkoutId":{"type":"string"}}}}}}}},"/api/workouts/merge":{"post":{"tags":["Workouts"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Unauthorized"},"404":{"description":"Workouts not found"}},"summary":"Merge workouts","description":"Manually merges two workouts, marking one as a duplicate of the other.","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["primaryWorkoutId","secondaryWorkoutId"],"properties":{"primaryWorkoutId":{"type":"string"},"secondaryWorkoutId":{"type":"string"}}}}}}}},"/api/workouts/planned/{id}":{"get":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/workouts/planned/{id}/adjust":{"post":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/workouts/planned/{id}/download/{format}":{"get":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"format","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/workouts/planned/{id}/fueling":{"get":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/workouts/planned/{id}/generate-structure":{"post":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/workouts/planned/{id}/intervals-preview":{"get":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/workouts/planned/{id}/link":{"post":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/workouts/planned/{id}/messages":{"post":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/workouts/planned/{id}/move":{"post":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/workouts/planned/{id}/neighbors":{"get":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/workouts/planned/{id}/publish-garmin":{"post":{"tags":["Planned Workouts"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Published successfully"},"400":{"description":"Invalid request or missing permissions"},"401":{"description":"Unauthorized"},"404":{"description":"Workout not found"}},"summary":"Publish planned workout to Garmin","description":"Publishes a planned workout to Garmin Training API or Courses API."}},"/api/workouts/planned/{id}/publish":{"post":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/workouts/planned/{id}/structure":{"patch":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/workouts/planned/{id}/unlink":{"post":{"tags":["API Routes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/workouts/planned/bulk-delete":{"post":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/workouts/planned/range":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/workouts/planned/today":{"get":{"tags":["Workouts"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"durationSec":{"type":"number"},"tss":{"type":"number"},"type":{"type":"string"},"structuredWorkout":{"type":"object"}}}}}},"401":{"description":"Unauthorized"}},"summary":"Get today's planned workout","description":"Returns the planned workout for the current date."}},"/api/workouts/planned/upcoming":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/workouts/power-curve":{"get":{"tags":["Workouts"],"parameters":[{"name":"days","in":"query","schema":{"type":["integer","string"],"default":90}},{"name":"sport","in":"query","schema":{"type":"string"}},{"name":"tags","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"current":{"type":"array","items":{"type":"object","properties":{"duration":{"type":"integer"},"watts":{"type":"number"}}}},"allTime":{"type":"array","items":{"type":"object","properties":{"duration":{"type":"integer"},"watts":{"type":"number"}}}}}}}}},"401":{"description":"Unauthorized"}},"summary":"Get aggregate power curve","description":"Returns the power curve (current period vs all-time) for the athlete."}},"/api/workouts/sports":{"get":{"tags":["API Routes"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/api/workouts/streams":{"post":{"tags":["Workouts"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"workoutId":{"type":"string"},"time":{"type":"array"},"watts":{"type":"array"},"heartrate":{"type":"array"},"cadence":{"type":"array"},"hrZoneTimes":{"type":"array"},"powerZoneTimes":{"type":"array"}}}}}}},"401":{"description":"Unauthorized"}},"summary":"Get workout streams","description":"Returns stream data (HR, power, cadence, etc.) for a list of workout IDs.","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["workoutIds"],"properties":{"workoutIds":{"type":"array","items":{"type":"string"}},"points":{"type":"number","description":"Target number of points for downsampling (default 2000)"},"keys":{"type":"array","items":{"type":"string"},"description":"Specific stream keys to return"}}}}}}}},"/api/workouts/tags":{"get":{"tags":["Workouts"],"parameters":[{"name":"q","in":"query","schema":{"type":"string"}},{"name":"includeIcu","in":"query","schema":{"type":"boolean","default":true}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string"},"count":{"type":"integer"}}}}}}},"401":{"description":"Unauthorized"}},"summary":"Get workout tags","description":"Returns distinct workout tags and counts for the authenticated user."}},"/api/workouts/upload-fit":{"post":{"tags":["Workouts"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"message":{"type":"string"},"results":{"type":"object","properties":{"total":{"type":"integer"},"processed":{"type":"integer"},"duplicates":{"type":"integer"},"failed":{"type":"integer"},"errors":{"type":"array","items":{"type":"string"}}}}}}}}},"400":{"description":"Invalid file or missing upload"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"}},"summary":"Upload FIT file","description":"Uploads a .fit file for processing and ingestion.","security":[{"bearerAuth":[]}],"requestBody":{"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary","description":"The .fit file to upload"},"name":{"type":"string","description":"Optional activity name to use for the imported workout title. Falls back to the uploaded filename."},"metadata":{"type":"string","description":"Optional JSON string containing raw development data (rawJson)"}}}}}}}},"/__nuxt_error":{"get":{"tags":["Internal"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/__nuxt_island/{*param1}":{"get":{"tags":["Internal"],"parameters":[{"name":"*param1","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/_nuxt_icon/{collection}":{"get":{"tags":["API Routes"],"parameters":[{"name":"collection","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/__nuxt_content/content/sql_dump.txt":{"get":{"tags":["Internal"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/__nuxt_content/info/sql_dump.txt":{"get":{"tags":["Internal"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/__nuxt_content/content/query":{"get":{"tags":["Internal"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/__nuxt_content/info/query":{"get":{"tags":["Internal"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/_openapi.json":{"get":{"tags":["Internal"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/_docs/scalar":{"get":{"tags":["Internal"],"parameters":[],"responses":{"200":{"description":"OK"}}}},"/_docs/swagger":{"get":{"tags":["Internal"],"parameters":[],"responses":{"200":{"description":"OK"}}}}},"components":{"schemas":{"FoodItem":{"type":"object","required":["logged_at"],"properties":{"name":{"type":"string","description":"Optional item name. Defaults to \"Unknown item\"."},"calories":{"type":"number"},"carbs":{"type":"number"},"protein":{"type":"number"},"fat":{"type":"number"},"fiber":{"type":"number"},"sugar":{"type":"number"},"logged_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp"},"absorptionType":{"type":"string","enum":["RAPID","FAST","BALANCED","DENSE","HYPER_LOAD"],"default":"BALANCED"},"quantity":{"type":"string"}}},"NutritionUpload":{"type":"object","required":["date"],"properties":{"date":{"type":"string","format":"date","description":"YYYY-MM-DD or ISO string"},"items":{"type":"array","items":{"$ref":"#/components/schemas/FoodItem"}},"calories":{"type":"integer","description":"Optional override for daily total"},"carbs":{"type":"number","description":"Optional override for daily total"},"protein":{"type":"number","description":"Optional override for daily total"},"fat":{"type":"number","description":"Optional override for daily total"},"waterMl":{"type":"integer"},"rawJson":{"type":"object","description":"Raw developer data for historical reference"}}},"WellnessUpload":{"type":"object","required":["date"],"properties":{"date":{"type":"string","format":"date","description":"YYYY-MM-DD or ISO string"},"hrv":{"type":"number","description":"Heart Rate Variability (ms)"},"hrvSdnn":{"type":"number","description":"Standard deviation of NN intervals (ms)"},"restingHr":{"type":"integer","description":"Resting Heart Rate (bpm)"},"avgSleepingHr":{"type":"integer","description":"Average HR during sleep (bpm)"},"sleepScore":{"type":"integer","description":"Sleep quality score (1-100)"},"sleepHours":{"type":"number","description":"Total sleep duration in hours"},"sleepSecs":{"type":"integer","description":"Total sleep duration in seconds"},"sleepQuality":{"type":"integer","description":"Subjective sleep quality (1-10)"},"sleepDeepSecs":{"type":"integer","description":"Deep sleep duration in seconds"},"sleepRemSecs":{"type":"integer","description":"REM sleep duration in seconds"},"sleepLightSecs":{"type":"integer","description":"Light sleep duration in seconds"},"sleepAwakeSecs":{"type":"integer","description":"Awake duration during sleep session in seconds"},"readiness":{"type":"integer","description":"Overall readiness score (1-100)"},"recoveryScore":{"type":"integer","description":"Recovery score (1-100)"},"weight":{"type":"number","description":"Body weight (kg)"},"bodyFat":{"type":"number","description":"Body fat percentage (%)"},"bloodGlucose":{"type":"number","description":"Blood glucose levels"},"skinTemp":{"type":"number","description":"Skin temperature deviation (Celsius)"},"respiration":{"type":"number","description":"Respiratory rate (breaths per min)"},"spO2":{"type":"number","description":"Blood oxygen saturation (%)"},"vo2max":{"type":"number","description":"Estimated VO2 Max"},"restingCaloriesBurned":{"type":"integer","description":"Resting calories burned for the day (kcal)"},"activeCaloriesBurned":{"type":"integer","description":"Active calories burned for the day (kcal)"},"totalCaloriesBurned":{"type":"integer","description":"Total calories burned for the day (kcal)"},"systolic":{"type":"integer","description":"Systolic blood pressure"},"diastolic":{"type":"integer","description":"Diastolic blood pressure"},"ctl":{"type":"number","description":"Chronic Training Load (Fitness)"},"atl":{"type":"number","description":"Acute Training Load (Fatigue)"},"stress":{"type":"integer","description":"Subjective stress level (1-10)"},"mood":{"type":"integer","description":"Subjective mood level (1-10)"},"motivation":{"type":"integer","description":"Subjective motivation (1-10)"},"fatigue":{"type":"integer","description":"Subjective fatigue (1-10)"},"soreness":{"type":"integer","description":"Subjective soreness (1-10)"},"comments":{"type":"string","description":"User notes or journal entry"},"rawJson":{"type":"object","description":"Raw developer data for historical reference"}}},"Workout":{"type":"object","properties":{"id":{"type":"string"},"userId":{"type":"string"},"externalId":{"type":"string"},"source":{"type":"string"},"oauthApp":{"type":"object","nullable":true,"properties":{"name":{"type":"string","nullable":true},"sourceName":{"type":"string","nullable":true}}},"date":{"type":"string","format":"date-time"},"title":{"type":"string"},"description":{"type":"string","nullable":true},"tags":{"type":"array","items":{"type":"string"}},"type":{"type":"string","nullable":true},"durationSec":{"type":"integer"},"distanceMeters":{"type":"number","nullable":true},"elevationGain":{"type":"integer","nullable":true},"averageWatts":{"type":"integer","nullable":true},"maxWatts":{"type":"integer","nullable":true},"normalizedPower":{"type":"integer","nullable":true},"averageHr":{"type":"integer","nullable":true},"maxHr":{"type":"integer","nullable":true},"tss":{"type":"number","nullable":true},"intensity":{"type":"number","nullable":true},"kilojoules":{"type":"integer","nullable":true},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}}}}}