{"openapi":"3.1.0","info":{"title":"Garmin Analytics coach API","version":"1.0.0","description":"Personal Garmin training data: current state, load, recovery, activities and trends; create and delete workouts in Garmin Connect."},"servers":[{"url":"https://garmin.srv894922.hstgr.cloud"}],"components":{"securitySchemes":{"oauth":{"type":"oauth2","flows":{"authorizationCode":{"authorizationUrl":"https://garmin.srv894922.hstgr.cloud/oauth/authorize","tokenUrl":"https://garmin.srv894922.hstgr.cloud/api/oauth/token","scopes":{"training":"Read training data and manage Garmin workouts"}}}}},"schemas":{"WorkoutStep":{"type":"object","required":["name","intensity","durationType","durationValue"],"properties":{"name":{"type":"string","maxLength":16,"description":"Short step name, max 16 characters"},"notes":{"type":"string","maxLength":254},"intensity":{"type":"string","enum":["warmup","active","cooldown","recovery","interval","rest"]},"durationType":{"type":"string","enum":["time","distance","open","reps"],"description":"time = seconds, distance = metres, reps = repetitions (strength), open = until the athlete presses Lap"},"durationValue":{"type":"number","minimum":0,"description":"Seconds, metres or repetitions; 0 when durationType is open"},"exerciseCategory":{"type":"string","description":"Strength only: Garmin category from getStrengthExercises, e.g. SQUAT"},"exerciseName":{"type":"string","description":"Strength only: Garmin exercise from getStrengthExercises, e.g. DUMBBELL_SQUAT. Must belong to exerciseCategory."},"weightKg":{"type":"number","minimum":0,"maximum":300,"description":"Strength only: dumbbell load in kg; omit for bodyweight or bands"},"targetType":{"type":"string","enum":["open","pace","heartRate","cadence","power"],"description":"pace = targetLow/targetHigh in seconds per km; heartRate = bpm; cadence = spm; power = watts"},"targetLow":{"type":"number","description":"Fastest pace in s/km (e.g. 3:42/km = 222), or lowest bpm/spm/W. Omit when targetType is open."},"targetHigh":{"type":"number","description":"Slowest pace in s/km (e.g. 3:51/km = 231), or highest bpm/spm/W. Omit when targetType is open."}}},"WorkoutItem":{"type":"object","description":"Either a single step (set name, intensity, durationType, durationValue and optionally a target) OR a repeat block (set only repeatCount and steps, e.g. 6 x [800 m at pace, 2 min recovery]).","properties":{"name":{"type":"string","maxLength":16,"description":"Short step name, max 16 characters"},"notes":{"type":"string","maxLength":254},"intensity":{"type":"string","enum":["warmup","active","cooldown","recovery","interval","rest"]},"durationType":{"type":"string","enum":["time","distance","open","reps"],"description":"time = seconds, distance = metres, reps = repetitions (strength), open = until the athlete presses Lap"},"durationValue":{"type":"number","minimum":0,"description":"Seconds, metres or repetitions; 0 when durationType is open"},"exerciseCategory":{"type":"string","description":"Strength only: Garmin category from getStrengthExercises, e.g. SQUAT"},"exerciseName":{"type":"string","description":"Strength only: Garmin exercise from getStrengthExercises, e.g. DUMBBELL_SQUAT. Must belong to exerciseCategory."},"weightKg":{"type":"number","minimum":0,"maximum":300,"description":"Strength only: dumbbell load in kg; omit for bodyweight or bands"},"targetType":{"type":"string","enum":["open","pace","heartRate","cadence","power"],"description":"pace = targetLow/targetHigh in seconds per km; heartRate = bpm; cadence = spm; power = watts"},"targetLow":{"type":"number","description":"Fastest pace in s/km (e.g. 3:42/km = 222), or lowest bpm/spm/W. Omit when targetType is open."},"targetHigh":{"type":"number","description":"Slowest pace in s/km (e.g. 3:51/km = 231), or highest bpm/spm/W. Omit when targetType is open."},"repeatCount":{"type":"integer","minimum":1,"maximum":30,"description":"Repeat block only: how many times to repeat steps"},"steps":{"type":"array","minItems":1,"maxItems":8,"items":{"type":"object","required":["name","intensity","durationType","durationValue"],"properties":{"name":{"type":"string","maxLength":16,"description":"Short step name, max 16 characters"},"notes":{"type":"string","maxLength":254},"intensity":{"type":"string","enum":["warmup","active","cooldown","recovery","interval","rest"]},"durationType":{"type":"string","enum":["time","distance","open","reps"],"description":"time = seconds, distance = metres, reps = repetitions (strength), open = until the athlete presses Lap"},"durationValue":{"type":"number","minimum":0,"description":"Seconds, metres or repetitions; 0 when durationType is open"},"exerciseCategory":{"type":"string","description":"Strength only: Garmin category from getStrengthExercises, e.g. SQUAT"},"exerciseName":{"type":"string","description":"Strength only: Garmin exercise from getStrengthExercises, e.g. DUMBBELL_SQUAT. Must belong to exerciseCategory."},"weightKg":{"type":"number","minimum":0,"maximum":300,"description":"Strength only: dumbbell load in kg; omit for bodyweight or bands"},"targetType":{"type":"string","enum":["open","pace","heartRate","cadence","power"],"description":"pace = targetLow/targetHigh in seconds per km; heartRate = bpm; cadence = spm; power = watts"},"targetLow":{"type":"number","description":"Fastest pace in s/km (e.g. 3:42/km = 222), or lowest bpm/spm/W. Omit when targetType is open."},"targetHigh":{"type":"number","description":"Slowest pace in s/km (e.g. 3:51/km = 231), or highest bpm/spm/W. Omit when targetType is open."}}},"description":"Repeat block only: the steps inside the block"}}},"WorkoutDefinition":{"type":"object","required":["name","sport","items"],"properties":{"name":{"type":"string","maxLength":16,"description":"Workout name, max 16 characters, e.g. \"6x800 z4 r2'\""},"sport":{"type":"string","enum":["running","cycling","swimming","walking","strength","generic"],"description":"Use strength for gym sessions so Garmin creates a real strength workout with named exercises"},"description":{"type":"string","maxLength":254},"items":{"type":"array","minItems":1,"maxItems":12,"items":{"type":"object","description":"Either a single step (set name, intensity, durationType, durationValue and optionally a target) OR a repeat block (set only repeatCount and steps, e.g. 6 x [800 m at pace, 2 min recovery]).","properties":{"name":{"type":"string","maxLength":16,"description":"Short step name, max 16 characters"},"notes":{"type":"string","maxLength":254},"intensity":{"type":"string","enum":["warmup","active","cooldown","recovery","interval","rest"]},"durationType":{"type":"string","enum":["time","distance","open","reps"],"description":"time = seconds, distance = metres, reps = repetitions (strength), open = until the athlete presses Lap"},"durationValue":{"type":"number","minimum":0,"description":"Seconds, metres or repetitions; 0 when durationType is open"},"exerciseCategory":{"type":"string","description":"Strength only: Garmin category from getStrengthExercises, e.g. SQUAT"},"exerciseName":{"type":"string","description":"Strength only: Garmin exercise from getStrengthExercises, e.g. DUMBBELL_SQUAT. Must belong to exerciseCategory."},"weightKg":{"type":"number","minimum":0,"maximum":300,"description":"Strength only: dumbbell load in kg; omit for bodyweight or bands"},"targetType":{"type":"string","enum":["open","pace","heartRate","cadence","power"],"description":"pace = targetLow/targetHigh in seconds per km; heartRate = bpm; cadence = spm; power = watts"},"targetLow":{"type":"number","description":"Fastest pace in s/km (e.g. 3:42/km = 222), or lowest bpm/spm/W. Omit when targetType is open."},"targetHigh":{"type":"number","description":"Slowest pace in s/km (e.g. 3:51/km = 231), or highest bpm/spm/W. Omit when targetType is open."},"repeatCount":{"type":"integer","minimum":1,"maximum":30,"description":"Repeat block only: how many times to repeat steps"},"steps":{"type":"array","minItems":1,"maxItems":8,"items":{"type":"object","required":["name","intensity","durationType","durationValue"],"properties":{"name":{"type":"string","maxLength":16,"description":"Short step name, max 16 characters"},"notes":{"type":"string","maxLength":254},"intensity":{"type":"string","enum":["warmup","active","cooldown","recovery","interval","rest"]},"durationType":{"type":"string","enum":["time","distance","open","reps"],"description":"time = seconds, distance = metres, reps = repetitions (strength), open = until the athlete presses Lap"},"durationValue":{"type":"number","minimum":0,"description":"Seconds, metres or repetitions; 0 when durationType is open"},"exerciseCategory":{"type":"string","description":"Strength only: Garmin category from getStrengthExercises, e.g. SQUAT"},"exerciseName":{"type":"string","description":"Strength only: Garmin exercise from getStrengthExercises, e.g. DUMBBELL_SQUAT. Must belong to exerciseCategory."},"weightKg":{"type":"number","minimum":0,"maximum":300,"description":"Strength only: dumbbell load in kg; omit for bodyweight or bands"},"targetType":{"type":"string","enum":["open","pace","heartRate","cadence","power"],"description":"pace = targetLow/targetHigh in seconds per km; heartRate = bpm; cadence = spm; power = watts"},"targetLow":{"type":"number","description":"Fastest pace in s/km (e.g. 3:42/km = 222), or lowest bpm/spm/W. Omit when targetType is open."},"targetHigh":{"type":"number","description":"Slowest pace in s/km (e.g. 3:51/km = 231), or highest bpm/spm/W. Omit when targetType is open."}}},"description":"Repeat block only: the steps inside the block"}}},"description":"Ordered steps: warm-up, optional open rest, repeat blocks, cool-down"}}},"ScheduledWorkout":{"type":"object","required":["name","sport","items"],"properties":{"name":{"type":"string","maxLength":16,"description":"Workout name, max 16 characters, e.g. \"6x800 z4 r2'\""},"sport":{"type":"string","enum":["running","cycling","swimming","walking","strength","generic"],"description":"Use strength for gym sessions so Garmin creates a real strength workout with named exercises"},"description":{"type":"string","maxLength":254},"items":{"type":"array","minItems":1,"maxItems":12,"items":{"type":"object","description":"Either a single step (set name, intensity, durationType, durationValue and optionally a target) OR a repeat block (set only repeatCount and steps, e.g. 6 x [800 m at pace, 2 min recovery]).","properties":{"name":{"type":"string","maxLength":16,"description":"Short step name, max 16 characters"},"notes":{"type":"string","maxLength":254},"intensity":{"type":"string","enum":["warmup","active","cooldown","recovery","interval","rest"]},"durationType":{"type":"string","enum":["time","distance","open","reps"],"description":"time = seconds, distance = metres, reps = repetitions (strength), open = until the athlete presses Lap"},"durationValue":{"type":"number","minimum":0,"description":"Seconds, metres or repetitions; 0 when durationType is open"},"exerciseCategory":{"type":"string","description":"Strength only: Garmin category from getStrengthExercises, e.g. SQUAT"},"exerciseName":{"type":"string","description":"Strength only: Garmin exercise from getStrengthExercises, e.g. DUMBBELL_SQUAT. Must belong to exerciseCategory."},"weightKg":{"type":"number","minimum":0,"maximum":300,"description":"Strength only: dumbbell load in kg; omit for bodyweight or bands"},"targetType":{"type":"string","enum":["open","pace","heartRate","cadence","power"],"description":"pace = targetLow/targetHigh in seconds per km; heartRate = bpm; cadence = spm; power = watts"},"targetLow":{"type":"number","description":"Fastest pace in s/km (e.g. 3:42/km = 222), or lowest bpm/spm/W. Omit when targetType is open."},"targetHigh":{"type":"number","description":"Slowest pace in s/km (e.g. 3:51/km = 231), or highest bpm/spm/W. Omit when targetType is open."},"repeatCount":{"type":"integer","minimum":1,"maximum":30,"description":"Repeat block only: how many times to repeat steps"},"steps":{"type":"array","minItems":1,"maxItems":8,"items":{"type":"object","required":["name","intensity","durationType","durationValue"],"properties":{"name":{"type":"string","maxLength":16,"description":"Short step name, max 16 characters"},"notes":{"type":"string","maxLength":254},"intensity":{"type":"string","enum":["warmup","active","cooldown","recovery","interval","rest"]},"durationType":{"type":"string","enum":["time","distance","open","reps"],"description":"time = seconds, distance = metres, reps = repetitions (strength), open = until the athlete presses Lap"},"durationValue":{"type":"number","minimum":0,"description":"Seconds, metres or repetitions; 0 when durationType is open"},"exerciseCategory":{"type":"string","description":"Strength only: Garmin category from getStrengthExercises, e.g. SQUAT"},"exerciseName":{"type":"string","description":"Strength only: Garmin exercise from getStrengthExercises, e.g. DUMBBELL_SQUAT. Must belong to exerciseCategory."},"weightKg":{"type":"number","minimum":0,"maximum":300,"description":"Strength only: dumbbell load in kg; omit for bodyweight or bands"},"targetType":{"type":"string","enum":["open","pace","heartRate","cadence","power"],"description":"pace = targetLow/targetHigh in seconds per km; heartRate = bpm; cadence = spm; power = watts"},"targetLow":{"type":"number","description":"Fastest pace in s/km (e.g. 3:42/km = 222), or lowest bpm/spm/W. Omit when targetType is open."},"targetHigh":{"type":"number","description":"Slowest pace in s/km (e.g. 3:51/km = 231), or highest bpm/spm/W. Omit when targetType is open."}}},"description":"Repeat block only: the steps inside the block"}}},"description":"Ordered steps: warm-up, optional open rest, repeat blocks, cool-down"},"calendarDate":{"type":"string","format":"date","description":"Day to schedule this workout on, YYYY-MM-DD"}}}}},"security":[{"oauth":["training"]}],"paths":{"/api/gpt/today-state":{"get":{"operationId":"getTodayState","summary":"Current training state","description":"Call at the start of every reply. Returns how fresh the data is, a plain-language summary, readiness, ACWR, HRV vs baseline, sleep, body battery, the last 7 days vs the athlete's norm, recent weeks and activities, thresholds, HR zones and personal records.","responses":{"200":{"description":"Today's state","content":{"application/json":{"schema":{"type":"object","properties":{"date":{"type":"string","format":"date"},"weekday":{"type":"string"},"dataFreshness":{"type":"object","additionalProperties":true,"description":"now, timezone, lastWatchSync {at, minutesAgo} and per-signal {at, minutesAgo}"},"summary":{"type":"string","description":"Authoritative plain-language digest of the decisive numbers"},"currentLoad":{"type":"object","additionalProperties":true},"recovery":{"type":"object","additionalProperties":true},"latestSignals":{"type":"object","additionalProperties":true},"recentWeeks":{"type":"array","items":{"type":"object","additionalProperties":true}},"recentActivities":{"type":"array","items":{"type":"object","additionalProperties":true}},"thresholds":{"type":"object","additionalProperties":true},"heartRateZones":{"type":"object","additionalProperties":true},"personalRecords":{"type":"array","items":{"type":"object","additionalProperties":true}}}}}}}}}},"/api/gpt/context":{"get":{"operationId":"getTrainingContext","summary":"Full coaching context for long-term planning","description":"Totals, sport mix, thresholds, zones, latest signals, current load, recovery, recent activities, personal records and insights. Use before building a multi-week plan.","responses":{"200":{"description":"Context","content":{"application/json":{"schema":{"type":"object","properties":{"date":{"type":"string","format":"date"},"dataFreshness":{"type":"object","additionalProperties":true},"summary":{"type":"string"},"period":{"type":"object","additionalProperties":true},"totals":{"type":"object","additionalProperties":true},"distribution":{"type":"array","items":{"type":"object","additionalProperties":true}},"thresholds":{"type":"object","additionalProperties":true},"heartRateZones":{"type":"object","additionalProperties":true},"powerZones":{"type":"array","items":{"type":"object","additionalProperties":true}},"latestSignals":{"type":"object","additionalProperties":true},"currentLoad":{"type":"object","additionalProperties":true},"recovery":{"type":"object","additionalProperties":true},"recentActivities":{"type":"array","items":{"type":"object","additionalProperties":true}},"personalRecords":{"type":"array","items":{"type":"object","additionalProperties":true}},"keyInsights":{"type":"array","items":{"type":"string"}}}}}}}}}},"/api/gpt/activities":{"get":{"operationId":"listActivities","summary":"Recent activities","description":"Newest first, with distance, duration, pace, HR, power and training load.","parameters":[{"name":"days","in":"query","schema":{"type":"integer","default":28,"maximum":365}},{"name":"sport","in":"query","schema":{"type":"string"},"description":"Substring of the Garmin sport key: running, trail_running, strength_training"},{"name":"limit","in":"query","schema":{"type":"integer","default":100,"maximum":100}}],"responses":{"200":{"description":"Activities","content":{"application/json":{"schema":{"type":"object","properties":{"days":{"type":"integer"},"sport":{"type":"string"},"count":{"type":"integer"},"activities":{"type":"array","items":{"type":"object","additionalProperties":true}}}}}}}}}},"/api/gpt/activities/{id}":{"get":{"operationId":"getActivity","summary":"One activity with per-lap splits","description":"Full detail of a single activity, including every lap with its pace, heart rate and power.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Activity","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"},"sport":{"type":"string"},"startTime":{"type":"string"},"distanceKm":{"type":"number"},"durationHours":{"type":"number"},"paceMinPerKm":{"type":"number"},"avgHr":{"type":"number"},"maxHr":{"type":"number"},"avgPower":{"type":"number"},"trainingLoad":{"type":"number"},"steps":{"type":"number"},"splits":{"type":"array","items":{"type":"object","additionalProperties":true}}}}}}},"404":{"description":"Not found"}}}},"/api/gpt/trends":{"get":{"operationId":"getTrend","summary":"Time series of one metric","description":"Daily or weekly history of one metric over the requested window.","parameters":[{"name":"metric","in":"query","required":true,"schema":{"type":"string","enum":["readiness","acwr","sleep","hrv","vo2","race","status","weekly","monthly"]}},{"name":"days","in":"query","schema":{"type":"integer","default":90,"maximum":730}}],"responses":{"200":{"description":"Series","content":{"application/json":{"schema":{"type":"object","properties":{"metric":{"type":"string"},"days":{"type":"integer"},"count":{"type":"integer"},"points":{"type":"array","items":{"type":"object","additionalProperties":true}}}}}}}}}},"/api/gpt/activities/{id}/analysis":{"get":{"operationId":"getActivityAnalysis","summary":"Deep analysis of one session, second by second","description":"Computed from the per-second recording: aerobic decoupling, cardiac drift, real minutes in each HR zone, pace and HR per gradient band, cadence and running-dynamics drift, aerobic efficiency, and the best effort over every duration and distance inside the session.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"Activity id from listActivities"},{"name":"refresh","in":"query","schema":{"type":"string"},"description":"Set to true to recompute instead of reading the stored analysis"}],"responses":{"200":{"description":"Session analysis","content":{"application/json":{"schema":{"type":"object","properties":{"activityId":{"type":"integer"},"name":{"type":"string"},"startTime":{"type":"string"},"movingSec":{"type":"integer"},"available":{"type":"object","additionalProperties":true},"heartRate":{"type":"object","additionalProperties":true},"decoupling":{"type":"object","additionalProperties":true},"cardiacDrift":{"type":"object","additionalProperties":true},"efficiency":{"type":"object","additionalProperties":true},"cadence":{"type":"object","additionalProperties":true},"dynamics":{"type":"object","additionalProperties":true},"elevation":{"type":"object","additionalProperties":true},"pace":{"type":"object","additionalProperties":true},"temperature":{"type":"object","additionalProperties":true},"bests":{"type":"object","additionalProperties":true}}}}}},"404":{"description":"No such activity, or it has no per-second recording"}}}},"/api/gpt/records":{"get":{"operationId":"getRecordsCurve","summary":"Best pace and power over every duration","description":"The mean-maximal curve: fastest pace and highest power the athlete has held for 10 s up to 90 min, all-time and in a recent window, plus the critical speed and critical power fitted from the 5 to 30 minute efforts. Use it to judge form and set realistic targets.","parameters":[{"name":"days","in":"query","schema":{"type":"integer"},"description":"Recent window in days, default 90"},{"name":"sport","in":"query","schema":{"type":"string"},"description":"Sport to restrict to, default running"}],"responses":{"200":{"description":"Records curve","content":{"application/json":{"schema":{"type":"object","properties":{"recentWindowDays":{"type":"integer"},"points":{"type":"array","items":{"type":"object","additionalProperties":true}},"criticalSpeed":{"type":"object","additionalProperties":true},"criticalPower":{"type":"object","additionalProperties":true}}}}}}}}},"/api/gpt/intensity":{"get":{"operationId":"getIntensityDistribution","summary":"Real minutes per heart-rate zone, week by week","description":"Counted second by second, not from session averages. Splits each week into easy (zones 1-2), moderate (zone 3) and hard (zones 4-5) so you can see whether training is polarised or stuck in the grey zone.","parameters":[{"name":"weeks","in":"query","schema":{"type":"integer"},"description":"How many weeks back, default 12"}],"responses":{"200":{"description":"Intensity distribution","content":{"application/json":{"schema":{"type":"object","properties":{"weeks":{"type":"array","items":{"type":"object","additionalProperties":true}},"summary":{"type":"object","additionalProperties":true}}}}}}}}},"/api/gpt/fitness-trends":{"get":{"operationId":"getFitnessTrends","summary":"Aerobic markers session by session","description":"Decoupling, aerobic efficiency, cadence, cadence drift and ground contact time for every session over a window, plus monthly means. Efficiency rising while decoupling falls at the same heart rate is direct evidence the aerobic base is growing.","parameters":[{"name":"days","in":"query","schema":{"type":"integer"},"description":"Window in days, default 180"}],"responses":{"200":{"description":"Fitness trends","content":{"application/json":{"schema":{"type":"object","properties":{"sessions":{"type":"array","items":{"type":"object","additionalProperties":true}},"monthly":{"type":"array","items":{"type":"object","additionalProperties":true}}}}}}}}}},"/api/gpt/durability":{"get":{"operationId":"getDurability","summary":"How well form holds late in long sessions","description":"For sessions past a minimum duration: their decoupling, cadence slope and ground-contact drift, with the averages. Holding form at 90 minutes is a different quality from being fast at 20, and it decides how a long race ends.","parameters":[{"name":"days","in":"query","schema":{"type":"integer"},"description":"Window in days, default 365"},{"name":"minMinutes","in":"query","schema":{"type":"integer"},"description":"Only sessions at least this long, default 60"}],"responses":{"200":{"description":"Durability","content":{"application/json":{"schema":{"type":"object","properties":{"minMinutes":{"type":"integer"},"sessions":{"type":"array","items":{"type":"object","additionalProperties":true}},"averages":{"type":"object","additionalProperties":true}}}}}}}}},"/api/gpt/dose-response":{"get":{"operationId":"getDoseResponse","summary":"What each size of training day costs in recovery","description":"Pairs every training day with the next morning readiness, HRV and sleep score, grouped by how hard the day was. Tells you what a hard session costs this athlete rather than what it costs on average.","parameters":[{"name":"days","in":"query","schema":{"type":"integer"},"description":"Window in days, default 120"}],"responses":{"200":{"description":"Dose response","content":{"application/json":{"schema":{"type":"object","properties":{"windowDays":{"type":"integer"},"buckets":{"type":"array","items":{"type":"object","additionalProperties":true}},"recentDays":{"type":"array","items":{"type":"object","additionalProperties":true}}}}}}}}}},"/api/gpt/gear":{"get":{"operationId":"getGearUsage","summary":"Kilometres on each pair of shoes","description":"Distance and activity count per item of gear against the limit set for it, so worn-out shoes can be retired before they cause trouble.","responses":{"200":{"description":"Gear","content":{"application/json":{"schema":{"type":"object","properties":{"gear":{"type":"array","items":{"type":"object","additionalProperties":true}}}}}}}}}},"/api/gpt/strength-progression":{"get":{"operationId":"getStrengthProgression","summary":"Strength work per exercise over time","description":"Sets, reps and load for each strength exercise by month, so the next block can be progressed on what was actually lifted.","parameters":[{"name":"days","in":"query","schema":{"type":"integer"},"description":"Window in days, default 180"}],"responses":{"200":{"description":"Strength progression","content":{"application/json":{"schema":{"type":"object","properties":{"exercises":{"type":"array","items":{"type":"object","additionalProperties":true}}}}}}}}}},"/api/gpt/strength-exercises":{"get":{"operationId":"getStrengthExercises","summary":"Garmin exercises usable with dumbbells, bands or bodyweight","description":"The only category and exerciseName values Garmin accepts for this athlete's strength sessions. Call before building one and copy the values verbatim; anything else is rejected on upload.","parameters":[{"name":"category","in":"query","schema":{"type":"string"},"description":"Return only this category, e.g. SQUAT"},{"name":"search","in":"query","schema":{"type":"string"},"description":"Substring of an exercise name, e.g. DUMBBELL"}],"responses":{"200":{"description":"Exercise catalogue","content":{"application/json":{"schema":{"type":"object","properties":{"categories":{"type":"array","items":{"type":"string"}},"exercises":{"type":"object","additionalProperties":true},"matches":{"type":"array","items":{"type":"object","additionalProperties":true}},"category":{"type":"string"},"count":{"type":"integer"}}}}}}}}},"/api/gpt/workouts":{"get":{"operationId":"listGarminWorkouts","summary":"Workouts already in Garmin Connect","description":"The athlete's workout library plus what is scheduled in a month. Call before creating or changing workouts so you know what exists and can reuse its exact name and id.","parameters":[{"name":"month","in":"query","schema":{"type":"string"},"description":"YYYY-MM; returns the workouts scheduled that month"}],"responses":{"200":{"description":"Workouts","content":{"application/json":{"schema":{"type":"object","properties":{"workouts":{"type":"array","items":{"type":"object","additionalProperties":true}},"scheduled":{"type":"array","items":{"type":"object","additionalProperties":true}},"month":{"type":"string"}}}}}}}}},"/api/gpt/workouts/{id}":{"delete":{"operationId":"deleteGarminWorkout","summary":"Delete one workout from Garmin Connect","description":"Removes the workout template and any calendar entry for it. Only call after the athlete agrees.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"workoutId from listGarminWorkouts"}],"responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"type":"object","properties":{"deleted":{"type":"integer"}}}}}},"400":{"description":"Invalid id"}}}},"/api/gpt/workouts/upload":{"post":{"operationId":"uploadWorkoutsToGarmin","summary":"Create structured workouts in Garmin Connect","description":"Creates each workout with its guided steps and schedules it on its calendarDate. A workout with the same name already on that day is replaced, not duplicated. To change one session, send only that one. Only call after the athlete agrees.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["workouts"],"properties":{"workouts":{"type":"array","minItems":1,"maxItems":20,"items":{"type":"object","required":["name","sport","items"],"properties":{"name":{"type":"string","maxLength":16,"description":"Workout name, max 16 characters, e.g. \"6x800 z4 r2'\""},"sport":{"type":"string","enum":["running","cycling","swimming","walking","strength","generic"],"description":"Use strength for gym sessions so Garmin creates a real strength workout with named exercises"},"description":{"type":"string","maxLength":254},"items":{"type":"array","minItems":1,"maxItems":12,"items":{"type":"object","description":"Either a single step (set name, intensity, durationType, durationValue and optionally a target) OR a repeat block (set only repeatCount and steps, e.g. 6 x [800 m at pace, 2 min recovery]).","properties":{"name":{"type":"string","maxLength":16,"description":"Short step name, max 16 characters"},"notes":{"type":"string","maxLength":254},"intensity":{"type":"string","enum":["warmup","active","cooldown","recovery","interval","rest"]},"durationType":{"type":"string","enum":["time","distance","open","reps"],"description":"time = seconds, distance = metres, reps = repetitions (strength), open = until the athlete presses Lap"},"durationValue":{"type":"number","minimum":0,"description":"Seconds, metres or repetitions; 0 when durationType is open"},"exerciseCategory":{"type":"string","description":"Strength only: Garmin category from getStrengthExercises, e.g. SQUAT"},"exerciseName":{"type":"string","description":"Strength only: Garmin exercise from getStrengthExercises, e.g. DUMBBELL_SQUAT. Must belong to exerciseCategory."},"weightKg":{"type":"number","minimum":0,"maximum":300,"description":"Strength only: dumbbell load in kg; omit for bodyweight or bands"},"targetType":{"type":"string","enum":["open","pace","heartRate","cadence","power"],"description":"pace = targetLow/targetHigh in seconds per km; heartRate = bpm; cadence = spm; power = watts"},"targetLow":{"type":"number","description":"Fastest pace in s/km (e.g. 3:42/km = 222), or lowest bpm/spm/W. Omit when targetType is open."},"targetHigh":{"type":"number","description":"Slowest pace in s/km (e.g. 3:51/km = 231), or highest bpm/spm/W. Omit when targetType is open."},"repeatCount":{"type":"integer","minimum":1,"maximum":30,"description":"Repeat block only: how many times to repeat steps"},"steps":{"type":"array","minItems":1,"maxItems":8,"items":{"type":"object","required":["name","intensity","durationType","durationValue"],"properties":{"name":{"type":"string","maxLength":16,"description":"Short step name, max 16 characters"},"notes":{"type":"string","maxLength":254},"intensity":{"type":"string","enum":["warmup","active","cooldown","recovery","interval","rest"]},"durationType":{"type":"string","enum":["time","distance","open","reps"],"description":"time = seconds, distance = metres, reps = repetitions (strength), open = until the athlete presses Lap"},"durationValue":{"type":"number","minimum":0,"description":"Seconds, metres or repetitions; 0 when durationType is open"},"exerciseCategory":{"type":"string","description":"Strength only: Garmin category from getStrengthExercises, e.g. SQUAT"},"exerciseName":{"type":"string","description":"Strength only: Garmin exercise from getStrengthExercises, e.g. DUMBBELL_SQUAT. Must belong to exerciseCategory."},"weightKg":{"type":"number","minimum":0,"maximum":300,"description":"Strength only: dumbbell load in kg; omit for bodyweight or bands"},"targetType":{"type":"string","enum":["open","pace","heartRate","cadence","power"],"description":"pace = targetLow/targetHigh in seconds per km; heartRate = bpm; cadence = spm; power = watts"},"targetLow":{"type":"number","description":"Fastest pace in s/km (e.g. 3:42/km = 222), or lowest bpm/spm/W. Omit when targetType is open."},"targetHigh":{"type":"number","description":"Slowest pace in s/km (e.g. 3:51/km = 231), or highest bpm/spm/W. Omit when targetType is open."}}},"description":"Repeat block only: the steps inside the block"}}},"description":"Ordered steps: warm-up, optional open rest, repeat blocks, cool-down"},"calendarDate":{"type":"string","format":"date","description":"Day to schedule this workout on, YYYY-MM-DD"}}}},"calendarDate":{"type":"string","format":"date","description":"Default date for workouts without their own calendarDate"},"pushToDevice":{"type":"boolean","default":false,"description":"Also send the workouts to the athlete's watch"},"replaceExisting":{"type":"boolean","default":true,"description":"Replace a same-named workout already scheduled that day. Leave true to avoid duplicates."}}}}}},"responses":{"200":{"description":"Upload results","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"allSuccess":{"type":"boolean"},"uploaded":{"type":"integer"},"total":{"type":"integer"},"results":{"type":"array","items":{"type":"object","additionalProperties":true,"description":"name, success, workoutId, scheduled, replaced (ids removed), detail"}}}}}}},"400":{"description":"Validation errors"}}}}}}