{"openapi":"3.1.0","info":{"title":"SweatStack API","description":"API for SweatStack application","version":"0.113.2"},"paths":{"/api/v1/users/":{"get":{"tags":["users"],"summary":"List Users","description":"List all users accessible to the current user.\n\nReturns a list of users including:\n- The current user (self) with default scopes\n- Users managed by the current user (if include_managed=True) with default scopes\n- Users who have shared access with the current user (if include_shared=True) with their granted scopes\n\nUse the is_managed property on each user to determine if they are managed.","operationId":"list_users_api_v1_users__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"include_managed","in":"query","required":false,"schema":{"type":"boolean","default":true,"title":"Include Managed"}},{"name":"include_shared","in":"query","required":false,"schema":{"type":"boolean","default":true,"title":"Include Shared"}},{"name":"refreshed-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refreshed-Token"}},{"name":"token","in":"cookie","required":false,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/UserSummary"},"title":"Response List Users Api V1 Users  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["users"],"summary":"Create Managed User","description":"Create a new managed user.\n\nManaged users are users created by another user (the manager).\nThey cannot login themselves and their data is managed by the manager.","operationId":"create_managed_user_api_v1_users__post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"refreshed-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refreshed-Token"}},{"name":"token","in":"cookie","required":false,"schema":{"type":"string","title":"Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ManagedUserCreate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/users/{user_id}":{"get":{"tags":["users"],"summary":"Get Managed User","description":"Get details of a managed user.\n\nOnly the manager of the user can access this endpoint.","operationId":"get_managed_user_api_v1_users__user_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","title":"User Id"}},{"name":"refreshed-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refreshed-Token"}},{"name":"token","in":"cookie","required":false,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["users"],"summary":"Update Managed User","description":"Update a managed user's details.\n\nOnly the manager of the user can update their details.","operationId":"update_managed_user_api_v1_users__user_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","title":"User Id"}},{"name":"refreshed-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refreshed-Token"}},{"name":"token","in":"cookie","required":false,"schema":{"type":"string","title":"Token"}}],"requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/Body_update_managed_user_api_v1_users__user_id__put"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["users"],"summary":"Delete Managed User","description":"Delete a managed user and all their data.\n\nOnly the manager of the user can delete them.\nThis is irreversible and deletes all activities, traces, and other data.","operationId":"delete_managed_user_api_v1_users__user_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","title":"User Id"}},{"name":"refreshed-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refreshed-Token"}},{"name":"token","in":"cookie","required":false,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/teams/":{"get":{"tags":["teams"],"summary":"List Teams","description":"List all teams the current user owns or is a member of.","operationId":"list_teams_api_v1_teams__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"refreshed-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refreshed-Token"}},{"name":"token","in":"cookie","required":false,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TeamResponse"},"title":"Response List Teams Api V1 Teams  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/teams/authorized":{"get":{"tags":["teams"],"summary":"List Authorized Teams","description":"List all teams the current user has authorized to access their data.","operationId":"list_authorized_teams_api_v1_teams_authorized_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"refreshed-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refreshed-Token"}},{"name":"token","in":"cookie","required":false,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AuthorizedTeamResponse"},"title":"Response List Authorized Teams Api V1 Teams Authorized Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/teams/{team_id}/authorize":{"post":{"tags":["teams"],"summary":"Authorize Team","description":"Authorize a team to access a managed user's data.\n\nRequires a delegated token — the subject (sub) must be a managed user\nof the authorized party (azp). Regular users authorize teams through\nthe browser-based OAuth flow.","operationId":"authorize_team_api_v1_teams__team_id__authorize_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"team_id","in":"path","required":true,"schema":{"type":"string","title":"Team Id"}},{"name":"refreshed-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refreshed-Token"}},{"name":"token","in":"cookie","required":false,"schema":{"type":"string","title":"Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthorizeTeamRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["teams"],"summary":"Revoke Team Authorization","description":"Revoke a team's authorization to access a managed user's data.\n\nRequires a delegated token — the subject (sub) must be a managed user\nof the authorized party (azp). Regular users manage team authorizations\nthrough the browser.","operationId":"revoke_team_authorization_api_v1_teams__team_id__authorize_delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"team_id","in":"path","required":true,"schema":{"type":"string","title":"Team Id"}},{"name":"refreshed-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refreshed-Token"}},{"name":"token","in":"cookie","required":false,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/teams/{team_id}/users":{"get":{"tags":["teams"],"summary":"List Team Users","description":"List all users who have authorized a team to access their data.\nOnly accessible by team members.","operationId":"list_team_users_api_v1_teams__team_id__users_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"team_id","in":"path","required":true,"schema":{"type":"string","title":"Team Id"}},{"name":"refreshed-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refreshed-Token"}},{"name":"token","in":"cookie","required":false,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/UserSummary"},"title":"Response List Team Users Api V1 Teams  Team Id  Users Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/activities/":{"get":{"tags":["activities"],"summary":"List Activities","operationId":"list_activities_api_v1_activities__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"start","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Start"}},{"name":"end","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"End"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Offset"}},{"name":"sport","in":"query","required":false,"schema":{"type":"array","items":{"type":"string"},"title":"Sport"}},{"name":"tags","in":"query","required":false,"schema":{"type":"array","items":{"type":"string"},"title":"Tags"}},{"name":"refreshed-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refreshed-Token"}},{"name":"token","in":"cookie","required":false,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ActivitySummary"},"title":"Response List Activities Api V1 Activities  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/activities/latest":{"get":{"tags":["activities"],"summary":"Latest Activity","operationId":"latest_activity_api_v1_activities_latest_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"sport","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sport"}},{"name":"refreshed-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refreshed-Token"}},{"name":"token","in":"cookie","required":false,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivityDetails"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/activities/backfill-status":{"get":{"tags":["activities"],"summary":"Get Backfill Status","description":"Get the backfill status as a streaming newline-delimited JSON (NDJSON) response.\n\nThis endpoint is intended for newly connected users who your application needs to wait for historical\nactivity data to be backfilled. It provides real-time progress updates as the backfill\nprocesses.\n\nStreaming behavior:\n- Updates are sent periodically, approximately every few seconds.\n- Each line contains a complete JSON object followed by a newline character\n- Streaming automatically stops after 60 seconds\n\nThe `backfill_loaded_until` timestamp indicates the earliest activity date that has been\nsuccessfully loaded. As activities are backfilled from newest to oldest, this timestamp\nmoves backward in time toward the user's historical data.","operationId":"get_backfill_status_api_v1_activities_backfill_status_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"refreshed-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refreshed-Token"}},{"name":"token","in":"cookie","required":false,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"anyOf":[{"$ref":"#/components/schemas/BackfillStatus"},{"$ref":"#/components/schemas/BackfillError"}]},"title":"Response Get Backfill Status Api V1 Activities Backfill Status Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/activities/longitudinal-data":{"get":{"tags":["activities"],"summary":"Get Longitudinal Data","operationId":"get_longitudinal_data_api_v1_activities_longitudinal_data_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"sport","in":"query","required":false,"schema":{"type":"array","items":{"type":"string"},"title":"Sport"}},{"name":"metrics","in":"query","required":false,"schema":{"type":"array","items":{"$ref":"#/components/schemas/Metric"},"description":"Metrics to include in the longitudinal data. Duration is always included.","default":["duration","power","speed","heart_rate"],"title":"Metrics"},"description":"Metrics to include in the longitudinal data. Duration is always included."},{"name":"start","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"Start of the local-date range (each activity's own local date).","title":"Start"},"description":"Start of the local-date range (each activity's own local date)."},{"name":"end","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"End of the local-date range (inclusive).","title":"End"},"description":"End of the local-date range (inclusive)."},{"name":"segmentation_on","in":"query","required":false,"schema":{"anyOf":[{"enum":["power","speed"],"type":"string"},{"type":"null"}],"title":"Segmentation On"}},{"name":"refreshed-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refreshed-Token"}},{"name":"token","in":"cookie","required":false,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/activities/longitudinal-mean-max":{"get":{"tags":["activities"],"summary":"Get Longitudinal Mean Max","description":"Longitudinal mean-max (power-duration) curve enveloped across activities.\n\nFor a sport and metric over a date range, returns the best sustained mean-max curve\nacross all matching activities, as Parquet.\n\n**Without `after`** the curve is value-indexed (one row per intensity level), with the\nmetric value as the index. `by=intensity` is the default here today; this is unchanged for\nnow, but `by=duration` will become the default and eventually the only option in a future\nrelease (it currently requires `after`).\n\n**With `after`** (fatigue states) the mean-max is computed on the fly over the portion of\neach ride after the given accumulated work (kJ for power; metres for speed, experimental).\nThe response is index-free (the indexed axis becomes a regular column) with an extra\n`after` column, the date range is capped at 1 year, and at most 5 `after` values are\nallowed. The `by` parameter selects the orientation:\n\n- **`by=duration`** is the default for `after` with metric=power: a duration-indexed curve\n  via the segment kernel, exact on the AISC segments and substantially faster. Sampled\n  at `durations` if given, else a default grid. Columns: `duration`, `<metric>`,\n  `activity_id`, `sport`, `after`.\n- **`by=intensity`** is the legacy value-indexed orientation and is **deprecated**. For the\n  `after` case `by=duration` will become the only supported orientation, and more generally\n  `by=duration` is set to become the default and only option for this endpoint. We recommend\n  passing `by=duration` explicitly. (`by=intensity` currently remains the only orientation\n  for metric=speed.)\n\n`by=duration` requires `after` and metric=power.","operationId":"get_longitudinal_mean_max_api_v1_activities_longitudinal_mean_max_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"sport","in":"query","required":false,"schema":{"type":"array","items":{"type":"string"},"title":"Sport"}},{"name":"metric","in":"query","required":true,"schema":{"enum":["power","speed"],"type":"string","title":"Metric"}},{"name":"start","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"Start of date range. Preferred over 'date'/'window_days'.","title":"Start"},"description":"Start of date range. Preferred over 'date'/'window_days'."},{"name":"end","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"End of date range (defaults to today). Used with 'start'.","title":"End"},"description":"End of date range (defaults to today). Used with 'start'."},{"name":"date","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"Deprecated: use 'start' and 'end' instead.","title":"Date"},"description":"Deprecated: use 'start' and 'end' instead."},{"name":"window_days","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Deprecated: use 'start' and 'end' instead.","title":"Window Days"},"description":"Deprecated: use 'start' and 'end' instead."},{"name":"durations","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated durations in seconds (e.g., '5,60,300,1200')","title":"Durations"},"description":"Comma-separated durations in seconds (e.g., '5,60,300,1200')"},{"name":"after","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"number"}},{"type":"null"}],"description":"Optional, repeatable fatigue state(s). Compute mean-max on the fly over the portion of each ride after this much accumulated work (kJ, for power) or distance (metres, for speed; experimental). Repeat for multiple states (max 5). With 'after' the date range is capped at 1 year and the response is index-free with an 'after' column.","title":"After"},"description":"Optional, repeatable fatigue state(s). Compute mean-max on the fly over the portion of each ride after this much accumulated work (kJ, for power) or distance (metres, for speed; experimental). Repeat for multiple states (max 5). With 'after' the date range is capped at 1 year and the response is index-free with an 'after' column."},{"name":"by","in":"query","required":false,"schema":{"anyOf":[{"enum":["intensity","duration"],"type":"string"},{"type":"null"}],"description":"Axis to index the mean-max on, only meaningful together with 'after'. 'duration' returns a duration-indexed curve via the fast segment kernel (exact on the AISC segments, ~8x faster), sampled at 'durations' if given else a default grid. 'intensity' is the legacy value-indexed orientation and is DEPRECATED: for the 'after' case 'duration' will become the only supported orientation, and 'duration' is set to become the default and only option for this endpoint generally. We recommend passing 'duration' explicitly. When omitted, 'after' with metric=power defaults to 'duration', every other case to 'intensity'. 'duration' requires 'after' and metric=power.","title":"By"},"description":"Axis to index the mean-max on, only meaningful together with 'after'. 'duration' returns a duration-indexed curve via the fast segment kernel (exact on the AISC segments, ~8x faster), sampled at 'durations' if given else a default grid. 'intensity' is the legacy value-indexed orientation and is DEPRECATED: for the 'after' case 'duration' will become the only supported orientation, and 'duration' is set to become the default and only option for this endpoint generally. We recommend passing 'duration' explicitly. When omitted, 'after' with metric=power defaults to 'duration', every other case to 'intensity'. 'duration' requires 'after' and metric=power."},{"name":"refreshed-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refreshed-Token"}},{"name":"token","in":"cookie","required":false,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/activities/longitudinal-accumulated-work-duration":{"get":{"tags":["activities"],"summary":"Get Longitudinal Accumulated Work Duration","description":"**Warning: This endpoint is in development and subject to change.**\n\nGet longitudinal accumulated work duration (AWD) data for a given sport and metric.\n\nReturns AWD values for each intensity level:\n- max: The highest daily AWD\n- hard: Sustainable AWD for hard workouts\n- medium: Sustainable AWD for medium workouts\n- easy: Sustainable AWD for easy workouts\n\nArgs:\n    format: Response format - \"parquet\" (default) or \"json\"","operationId":"get_longitudinal_accumulated_work_duration_api_v1_activities_longitudinal_accumulated_work_duration_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"sport","in":"query","required":false,"schema":{"type":"array","items":{"type":"string"},"title":"Sport"}},{"name":"metric","in":"query","required":true,"schema":{"$ref":"#/components/schemas/Metric"}},{"name":"start","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"Start of date range. Preferred over 'date'/'window_days'.","title":"Start"},"description":"Start of date range. Preferred over 'date'/'window_days'."},{"name":"end","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"End of date range (defaults to today). Used with 'start'.","title":"End"},"description":"End of date range (defaults to today). Used with 'start'."},{"name":"date","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"Deprecated: use 'start' and 'end' instead.","title":"Date"},"description":"Deprecated: use 'start' and 'end' instead."},{"name":"window_days","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Deprecated: use 'start' and 'end' instead.","title":"Window Days"},"description":"Deprecated: use 'start' and 'end' instead."},{"name":"format","in":"query","required":false,"schema":{"enum":["parquet","json"],"type":"string","default":"parquet","title":"Format"}},{"name":"refreshed-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refreshed-Token"}},{"name":"token","in":"cookie","required":false,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/activities/{activity_id}/data":{"get":{"tags":["activities"],"summary":"Get Activity Data","operationId":"get_activity_data_api_v1_activities__activity_id__data_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"activity_id","in":"path","required":true,"schema":{"type":"string","title":"Activity Id"}},{"name":"metrics","in":"query","required":false,"schema":{"type":"array","items":{"$ref":"#/components/schemas/Metric"},"default":["duration","power","speed","heart_rate"],"title":"Metrics"}},{"name":"segmentation_on","in":"query","required":false,"schema":{"anyOf":[{"enum":["power","speed"],"type":"string"},{"type":"null"}],"title":"Segmentation On"}},{"name":"refreshed-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refreshed-Token"}},{"name":"token","in":"cookie","required":false,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/activities/{activity_id}/mean-max":{"get":{"tags":["activities"],"summary":"Get Activity Mean Max","description":"Get mean-max values for a specific metric of an activity.\nFor all sports, the default metric is `power` if available, else `speed`.","operationId":"get_activity_mean_max_api_v1_activities__activity_id__mean_max_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"activity_id","in":"path","required":true,"schema":{"type":"string","title":"Activity Id"}},{"name":"metric","in":"query","required":true,"schema":{"enum":["power","speed"],"type":"string","title":"Metric"}},{"name":"segmentation","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Segmentation"}},{"name":"durations","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated durations in seconds (e.g., '5,60,300,1200')","title":"Durations"},"description":"Comma-separated durations in seconds (e.g., '5,60,300,1200')"},{"name":"refreshed-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refreshed-Token"}},{"name":"token","in":"cookie","required":false,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/activities/{activity_id}/accumulated-work-duration":{"get":{"tags":["activities"],"summary":"Get Activity Accumulated Work Duration","description":"Get accumulated work duration (AWD) for an activity.\n\nAWD represents the total duration spent at each intensity level, calculated by sorting\nthe activity data by intensity and accumulating the time spent at or above each level.\n\nIf no metric is specified, the default metric is determined by the activity's sport:\n- Cycling: power\n- Other sports: speed","operationId":"get_activity_accumulated_work_duration_api_v1_activities__activity_id__accumulated_work_duration_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"activity_id","in":"path","required":true,"schema":{"type":"string","title":"Activity Id"}},{"name":"metric","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/Metric"},{"type":"null"}],"title":"Metric"}},{"name":"refreshed-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refreshed-Token"}},{"name":"token","in":"cookie","required":false,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/activities/{activity_id}":{"get":{"tags":["activities"],"summary":"Get Activity","operationId":"get_activity_api_v1_activities__activity_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"activity_id","in":"path","required":true,"schema":{"type":"string","title":"Activity Id"}},{"name":"refreshed-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refreshed-Token"}},{"name":"token","in":"cookie","required":false,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivityDetails"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/activities/{activity_id}/download":{"get":{"tags":["activities"],"summary":"Download Activity","operationId":"download_activity_api_v1_activities__activity_id__download_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"activity_id","in":"path","required":true,"schema":{"type":"string","title":"Activity Id"}},{"name":"refreshed-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refreshed-Token"}},{"name":"token","in":"cookie","required":false,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/activities/upload":{"post":{"tags":["activities"],"summary":"Upload Activity File","description":"Upload up to 10 activity files at once. Supported formats: .fit, .csv.\n\nA FIT file carries its own sport; a CSV must include a `sport` column with an Open Sport\nTaxonomy code (e.g. `cycling.road`) — there is no `sport` parameter. The CSV must also have a\n`timestamp` column with offset-aware ISO 8601 datetimes (e.g. `...+02:00` or `...Z`).\n\nReturns `202` with one source per file (plan 041): `{\"sources\": [SourceResponse, …]}`. Each is\n`processing` (accepted, ingest continues asynchronously) or `failed` (a per-file problem caught\nat the door). Poll `GET /api/v1/sources/{id}` or listen for `source_processed`/`source_failed`\nwebhooks for the outcome. Request-shape problems (no files, too many) are an RFC 7807 `4xx`.","operationId":"upload_activity_file_api_v1_activities_upload_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"refreshed-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refreshed-Token"}},{"name":"token","in":"cookie","required":false,"schema":{"type":"string","title":"Token"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_activity_file_api_v1_activities_upload_post"}}}},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/activities/{activity_id}/app-metadata":{"put":{"tags":["activities"],"summary":"Put Activity Metadata","operationId":"put_activity_metadata_api_v1_activities__activity_id__app_metadata_put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"activity_id","in":"path","required":true,"schema":{"type":"string","title":"Activity Id"}},{"name":"refreshed-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refreshed-Token"}},{"name":"token","in":"cookie","required":false,"schema":{"type":"string","title":"Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Data"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["activities"],"summary":"Delete Activity Metadata","operationId":"delete_activity_metadata_api_v1_activities__activity_id__app_metadata_delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"activity_id","in":"path","required":true,"schema":{"type":"string","title":"Activity Id"}},{"name":"refreshed-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refreshed-Token"}},{"name":"token","in":"cookie","required":false,"schema":{"type":"string","title":"Token"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/sources/{source_id}":{"get":{"tags":["sources"],"summary":"Get Source","description":"The observable resource behind an upload (plan 041): status, named error, and the resulting\n`activity_ids`. Also resolves the `source_id` an activity carries.","operationId":"get_source_api_v1_sources__source_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"source_id","in":"path","required":true,"schema":{"type":"string","title":"Source Id"}},{"name":"refreshed-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refreshed-Token"}},{"name":"token","in":"cookie","required":false,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SourceResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/sources":{"get":{"tags":["sources"],"summary":"List Sources","description":"List the user's sources, newest first. Filter by `status` / `origin` / created range for\nreconciliation (e.g. `?status=processing&created_after=…` to sweep for stragglers). The filter\nis on the stored status; the read-time `processing_timeout` override is presentational. The\ntotal matching count (ignoring limit/offset) is returned in the `X-Total-Count` header, so a\npaginating client knows whether it has seen everything.","operationId":"list_sources_api_v1_sources_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/SourceStatus"},{"type":"null"}],"title":"Status"}},{"name":"origin","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/SourceOrigin"},{"type":"null"}],"title":"Origin"}},{"name":"created_after","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created After"}},{"name":"created_before","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created Before"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Offset"}},{"name":"refreshed-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refreshed-Token"}},{"name":"token","in":"cookie","required":false,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/SourceResponse"},"title":"Response List Sources Api V1 Sources Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/traces/":{"get":{"tags":["traces"],"summary":"List Traces","operationId":"list_traces_api_v1_traces__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tags","in":"query","required":false,"schema":{"type":"array","items":{"type":"string"},"title":"Tags"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":100,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Offset"}},{"name":"start","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Start"}},{"name":"end","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"End"}},{"name":"sport","in":"query","required":false,"schema":{"type":"array","items":{"type":"string"},"title":"Sport"}},{"name":"refreshed-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refreshed-Token"}},{"name":"token","in":"cookie","required":false,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TraceDetails"},"title":"Response List Traces Api V1 Traces  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["traces"],"summary":"Create Trace","operationId":"create_trace_api_v1_traces__post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"refreshed-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refreshed-Token"}},{"name":"token","in":"cookie","required":false,"schema":{"type":"string","title":"Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TraceCreateOrUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/traces/{trace_id}":{"get":{"tags":["traces"],"summary":"Get Trace","operationId":"get_trace_api_v1_traces__trace_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"trace_id","in":"path","required":true,"schema":{"type":"string","title":"Trace Id"}},{"name":"refreshed-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refreshed-Token"}},{"name":"token","in":"cookie","required":false,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TraceDetails"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["traces"],"summary":"Update Trace","operationId":"update_trace_api_v1_traces__trace_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"trace_id","in":"path","required":true,"schema":{"type":"string","title":"Trace Id"}},{"name":"refreshed-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refreshed-Token"}},{"name":"token","in":"cookie","required":false,"schema":{"type":"string","title":"Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TraceCreateOrUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["traces"],"summary":"Delete Trace","operationId":"delete_trace_api_v1_traces__trace_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"trace_id","in":"path","required":true,"schema":{"type":"string","title":"Trace Id"}},{"name":"refreshed-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refreshed-Token"}},{"name":"token","in":"cookie","required":false,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/traces/{trace_id}/app-metadata":{"put":{"tags":["traces"],"summary":"Put Trace Metadata","operationId":"put_trace_metadata_api_v1_traces__trace_id__app_metadata_put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"trace_id","in":"path","required":true,"schema":{"type":"string","title":"Trace Id"}},{"name":"refreshed-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refreshed-Token"}},{"name":"token","in":"cookie","required":false,"schema":{"type":"string","title":"Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Data"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["traces"],"summary":"Delete Trace Metadata","operationId":"delete_trace_metadata_api_v1_traces__trace_id__app_metadata_delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"trace_id","in":"path","required":true,"schema":{"type":"string","title":"Trace Id"}},{"name":"refreshed-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refreshed-Token"}},{"name":"token","in":"cookie","required":false,"schema":{"type":"string","title":"Token"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/tests/":{"post":{"tags":["tests"],"summary":"Create Test","operationId":"create_test_api_v1_tests__post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"refreshed-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refreshed-Token"}},{"name":"token","in":"cookie","required":false,"schema":{"type":"string","title":"Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestCreate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestSummary"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["tests"],"summary":"List Tests","operationId":"list_tests_api_v1_tests__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"start","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Start"}},{"name":"end","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"End"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Offset"}},{"name":"sport","in":"query","required":false,"schema":{"type":"array","items":{"type":"string"},"title":"Sport"}},{"name":"tags","in":"query","required":false,"schema":{"type":"array","items":{"type":"string"},"title":"Tags"}},{"name":"created_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Created By"}},{"name":"refreshed-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refreshed-Token"}},{"name":"token","in":"cookie","required":false,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TestSummary"},"title":"Response List Tests Api V1 Tests  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/tests/{test_id}":{"get":{"tags":["tests"],"summary":"Get Test","operationId":"get_test_api_v1_tests__test_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"test_id","in":"path","required":true,"schema":{"type":"string","title":"Test Id"}},{"name":"traces","in":"query","required":false,"schema":{"$ref":"#/components/schemas/TraceResolution","description":"How traces are matched to this test. `auto` (default): traces whose timestamp falls in the test's time range, plus any traces explicitly linked to this test, minus any traces explicitly linked to a different test. `linked`: only traces explicitly linked to this test via `test_id`, regardless of timestamp. Affects only the `traces` list; `activities` is always time-overlap matched.","default":"auto"},"description":"How traces are matched to this test. `auto` (default): traces whose timestamp falls in the test's time range, plus any traces explicitly linked to this test, minus any traces explicitly linked to a different test. `linked`: only traces explicitly linked to this test via `test_id`, regardless of timestamp. Affects only the `traces` list; `activities` is always time-overlap matched."},{"name":"refreshed-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refreshed-Token"}},{"name":"token","in":"cookie","required":false,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestDetails"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["tests"],"summary":"Update Test","operationId":"update_test_api_v1_tests__test_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"test_id","in":"path","required":true,"schema":{"type":"string","title":"Test Id"}},{"name":"refreshed-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refreshed-Token"}},{"name":"token","in":"cookie","required":false,"schema":{"type":"string","title":"Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["tests"],"summary":"Delete Test","operationId":"delete_test_api_v1_tests__test_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"test_id","in":"path","required":true,"schema":{"type":"string","title":"Test Id"}},{"name":"refreshed-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refreshed-Token"}},{"name":"token","in":"cookie","required":false,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/tests/{test_id}/app-metadata":{"put":{"tags":["tests"],"summary":"Put Test Metadata","operationId":"put_test_metadata_api_v1_tests__test_id__app_metadata_put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"test_id","in":"path","required":true,"schema":{"type":"string","title":"Test Id"}},{"name":"refreshed-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refreshed-Token"}},{"name":"token","in":"cookie","required":false,"schema":{"type":"string","title":"Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Data"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["tests"],"summary":"Delete Test Metadata","operationId":"delete_test_metadata_api_v1_tests__test_id__app_metadata_delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"test_id","in":"path","required":true,"schema":{"type":"string","title":"Test Id"}},{"name":"refreshed-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refreshed-Token"}},{"name":"token","in":"cookie","required":false,"schema":{"type":"string","title":"Token"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/workouts/schedule":{"post":{"tags":["workouts"],"summary":"Create Scheduled Workout","description":"BETA: Workout functionality in SweatStack is experimental and subject to breaking changes.\nSome functionality may be incomplete or behave unexpectedly. Not recommended for production use.","operationId":"create_scheduled_workout_api_v1_workouts_schedule_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"refreshed-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refreshed-Token"}},{"name":"token","in":"cookie","required":false,"schema":{"type":"string","title":"Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScheduledWorkoutCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScheduledWorkoutCreateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/workouts/schedule/":{"get":{"tags":["workouts"],"summary":"List Scheduled Workouts","description":"BETA: Workout functionality in SweatStack is experimental and subject to breaking changes.","operationId":"list_scheduled_workouts_api_v1_workouts_schedule__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Offset"}},{"name":"application_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter to workouts created by a specific application. Pass the application's id to scope the list to that app's workouts only.","title":"Application Id"},"description":"Filter to workouts created by a specific application. Pass the application's id to scope the list to that app's workouts only."},{"name":"refreshed-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refreshed-Token"}},{"name":"token","in":"cookie","required":false,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ScheduledWorkoutResponse"},"title":"Response List Scheduled Workouts Api V1 Workouts Schedule  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/workouts/schedule/{workout_id}":{"put":{"tags":["workouts"],"summary":"Update Scheduled Workout","description":"BETA: Workout functionality in SweatStack is experimental and subject to breaking changes.\n\nReplaces the workout's plan (swf/start/parameters) and re-delivers to connected integrations\nin place, preserving the integration-side identity (e.g. the Garmin workout is updated, not\nrecreated). Best-effort and asynchronous, like create; read `deliveries` for the outcome.","operationId":"update_scheduled_workout_api_v1_workouts_schedule__workout_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"workout_id","in":"path","required":true,"schema":{"type":"string","title":"Workout Id"}},{"name":"refreshed-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refreshed-Token"}},{"name":"token","in":"cookie","required":false,"schema":{"type":"string","title":"Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScheduledWorkoutCreate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScheduledWorkoutCreateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["workouts"],"summary":"Get Scheduled Workout","description":"BETA: Workout functionality in SweatStack is experimental and subject to breaking changes.","operationId":"get_scheduled_workout_api_v1_workouts_schedule__workout_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"workout_id","in":"path","required":true,"schema":{"type":"string","title":"Workout Id"}},{"name":"refreshed-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refreshed-Token"}},{"name":"token","in":"cookie","required":false,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScheduledWorkoutResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["workouts"],"summary":"Delete Scheduled Workout","description":"BETA: Workout functionality in SweatStack is experimental and subject to breaking changes.\n\nDeleting a scheduled workout also removes it from connected integrations (e.g. it is\nunscheduled from the user's Garmin calendar). That cleanup is best-effort and asynchronous:\nthe delete succeeds immediately, and a device-side failure leaves at most a stale entry.","operationId":"delete_scheduled_workout_api_v1_workouts_schedule__workout_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"workout_id","in":"path","required":true,"schema":{"type":"string","title":"Workout Id"}},{"name":"refreshed-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refreshed-Token"}},{"name":"token","in":"cookie","required":false,"schema":{"type":"string","title":"Token"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/profile/tags/":{"get":{"tags":["profile"],"summary":"List Profile Tags","operationId":"list_profile_tags_api_v1_profile_tags__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"refreshed-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refreshed-Token"}},{"name":"token","in":"cookie","required":false,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/profile/sports/":{"get":{"tags":["profile"],"summary":"List Profile Sports","operationId":"list_profile_sports_api_v1_profile_sports__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"only_root","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Only Root"}},{"name":"refreshed-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refreshed-Token"}},{"name":"token","in":"cookie","required":false,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/profile/template-week":{"get":{"tags":["profile"],"summary":"Get Profile Template Week","description":"Get a template week for the user based on their training history.\nThe template week is a list of days, each with a name, a list of sports, and a typical and average training duration for that day.","operationId":"get_profile_template_week_api_v1_profile_template_week_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"refreshed-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refreshed-Token"}},{"name":"token","in":"cookie","required":false,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateWeekResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/profile/intensity-duration-model":{"get":{"tags":["profile"],"summary":"Get Intensity Duration Model","description":"**Warning: This endpoint is in development and subject to change.**","operationId":"get_intensity_duration_model_api_v1_profile_intensity_duration_model_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"sport","in":"query","required":true,"schema":{"type":"string","title":"Sport"}},{"name":"metric","in":"query","required":true,"schema":{"enum":["power","speed"],"type":"string","description":"The metric to use for the model. Only `power` and `speed` are supported at this time.","title":"Metric"},"description":"The metric to use for the model. Only `power` and `speed` are supported at this time."},{"name":"by","in":"query","required":false,"schema":{"const":"intensity","type":"string","description":"The axis to index on. Only `intensity` is supported at this time.","default":"intensity","title":"By"},"description":"The axis to index on. Only `intensity` is supported at this time."},{"name":"index","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"anyOf":[{"type":"integer"},{"type":"number"}]}},{"type":"null"}],"description":"The index values to use for the model. Defaults to the full range of values for `duration`.","title":"Index"},"description":"The index values to use for the model. Defaults to the full range of values for `duration`."},{"name":"date","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"The date to use for the model. Defaults to the current date and is inclusive for the passed date.","title":"Date"},"description":"The date to use for the model. Defaults to the current date and is inclusive for the passed date."},{"name":"refreshed-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refreshed-Token"}},{"name":"token","in":"cookie","required":false,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/profile/app-metadata":{"put":{"tags":["profile"],"summary":"Put Profile Metadata","operationId":"put_profile_metadata_api_v1_profile_app_metadata_put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"refreshed-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refreshed-Token"}},{"name":"token","in":"cookie","required":false,"schema":{"type":"string","title":"Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Data"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["profile"],"summary":"Delete Profile Metadata","operationId":"delete_profile_metadata_api_v1_profile_app_metadata_delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"refreshed-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refreshed-Token"}},{"name":"token","in":"cookie","required":false,"schema":{"type":"string","title":"Token"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/oauth/token":{"post":{"tags":["oauth"],"summary":"Token Endpoint","operationId":"token_endpoint_api_v1_oauth_token_post","requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/TokenRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBasic":[]}]}},"/api/v1/oauth/userinfo":{"get":{"tags":["oauth"],"summary":"Userinfo","operationId":"userinfo_api_v1_oauth_userinfo_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"refreshed-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refreshed-Token"}},{"name":"token","in":"cookie","required":false,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserInfoResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/oauth/delegated-token":{"post":{"tags":["oauth"],"summary":"Delegated Token","operationId":"delegated_token_api_v1_oauth_delegated_token_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"refreshed-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refreshed-Token"}},{"name":"token","in":"cookie","required":false,"schema":{"type":"string","title":"Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DelegatedTokenRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/oauth/principal-token":{"get":{"tags":["oauth"],"summary":"Principal Token","operationId":"principal_token_api_v1_oauth_principal_token_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"refreshed-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refreshed-Token"}},{"name":"token","in":"cookie","required":false,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/portal/sessions":{"post":{"tags":["portal"],"summary":"Create Portal Session","description":"Mint a portal deep-link URL for a 3rd-party app (plan 016). The app\nauthenticates with its own client credentials in the body; SweatStack\nstamps the authenticated app id into the returned URL as the brand\ncontext. Server-to-server (no user token); the user is identified at\nopen time when they land on the portal page and sign in.\n\nThis is the construction boundary: integrators only ever see the\nreturned `url`, so the portal URL shape stays an internal detail we\ncan evolve (e.g. to opaque tokens) without changing this contract.","operationId":"create_portal_session_api_v1_portal_sessions_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PortalSessionRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PortalSessionResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/applications":{"post":{"tags":["applications"],"summary":"Create Application","description":"Create a private application for devevelopment purposes.\n\nThis endpoint creates private applications suitable for development and testing.\nPrivate apps cannot be published to the marketplace. To create a public application,\nuse the web interface where additional metadata (description, image, privacy policy)\ncan be provided.\n\nWhen a page slug is provided, the page URL is automatically added to the redirect URIs.\nIf no explicit redirect URIs are provided, localhost is also added to allow local development.","operationId":"create_application_api_v1_applications_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"refreshed-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refreshed-Token"}},{"name":"token","in":"cookie","required":false,"schema":{"type":"string","title":"Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApplicationCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApplicationCreateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["applications"],"summary":"List Applications","description":"List all applications owned by the authenticated user.\n\nReturns a list of applications with minimal information (id, name, page_slug).\nApplications are sorted by creation date descending (newest first).","operationId":"list_applications_api_v1_applications_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"refreshed-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refreshed-Token"}},{"name":"token","in":"cookie","required":false,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ApplicationListItem"},"title":"Response List Applications Api V1 Applications Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/applications/{application_id}/page":{"put":{"tags":["applications"],"summary":"Ensure Application Page","description":"Idempotently ensure this Application has a Page at ``slug``.\n\nUnlike ``POST /pages`` (create-only), this is safe to call repeatedly: the same slug\nis a no-op, a different slug is rejected (we never silently rename a live URL), and a\nslug owned by another application is rejected. Conflicts return ``409`` here (this\nendpoint is new, so there is no client to break), while validation errors return ``400``.","operationId":"ensure_application_page_api_v1_applications__application_id__page_put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"application_id","in":"path","required":true,"schema":{"type":"string","title":"Application Id"}},{"name":"refreshed-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refreshed-Token"}},{"name":"token","in":"cookie","required":false,"schema":{"type":"string","title":"Token"}}],"requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/Body_ensure_application_page_api_v1_applications__application_id__page_put"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PageResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/pages/{slug}":{"get":{"tags":["pages"],"summary":"Get Page","description":"Get a Page by its slug.","operationId":"get_page_api_v1_pages__slug__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"refreshed-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refreshed-Token"}},{"name":"token","in":"cookie","required":false,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PageResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["pages"],"summary":"Delete Page","description":"Delete a Page and its assets.","operationId":"delete_page_api_v1_pages__slug__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"refreshed-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refreshed-Token"}},{"name":"token","in":"cookie","required":false,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/pages":{"post":{"tags":["pages"],"summary":"Create Page","description":"Create a new Page for an Application.","operationId":"create_page_api_v1_pages_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"refreshed-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refreshed-Token"}},{"name":"token","in":"cookie","required":false,"schema":{"type":"string","title":"Token"}}],"requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/Body_create_page_api_v1_pages_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PageResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/pages/{slug}/deploy":{"put":{"tags":["pages"],"summary":"Deploy Page","description":"Deploy files to a Page. This replaces all existing files.","operationId":"deploy_page_api_v1_pages__slug__deploy_put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"refreshed-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refreshed-Token"}},{"name":"token","in":"cookie","required":false,"schema":{"type":"string","title":"Token"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_deploy_page_api_v1_pages__slug__deploy_put"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PageResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/dailies/{measure}":{"post":{"tags":["dailies"],"summary":"Upsert Daily","operationId":"upsert_daily_api_v1_dailies__measure__post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"measure","in":"path","required":true,"schema":{"$ref":"#/components/schemas/DailyMeasure"}},{"name":"refreshed-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refreshed-Token"}},{"name":"token","in":"cookie","required":false,"schema":{"type":"string","title":"Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DailyCreate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DailyResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["dailies"],"summary":"List Dailies","operationId":"list_dailies_api_v1_dailies__measure__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"measure","in":"path","required":true,"schema":{"$ref":"#/components/schemas/DailyMeasure"}},{"name":"start","in":"query","required":true,"schema":{"type":"string","format":"date","title":"Start"}},{"name":"end","in":"query","required":true,"schema":{"type":"string","format":"date","title":"End"}},{"name":"interpolate","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Interpolate"}},{"name":"refreshed-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refreshed-Token"}},{"name":"token","in":"cookie","required":false,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/DailyResponse"},"title":"Response List Dailies Api V1 Dailies  Measure  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["dailies"],"summary":"Delete Daily","operationId":"delete_daily_api_v1_dailies__measure__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"measure","in":"path","required":true,"schema":{"$ref":"#/components/schemas/DailyMeasure"}},{"name":"date","in":"query","required":true,"schema":{"type":"string","format":"date","title":"Date"}},{"name":"refreshed-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refreshed-Token"}},{"name":"token","in":"cookie","required":false,"schema":{"type":"string","title":"Token"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"webhooks":{"webhook-event":{"post":{"summary":"Webhook Event","description":"Handle webhook events from applications.\n\nEvents are signed with HMAC-SHA256 for verification. The signature is sent in the\n`X-Sweatstack-Signature` header with format: `t={timestamp},v1={signature}`\n\nTo verify:\n1. Extract timestamp and signature from header\n2. Construct signed payload: `\"{timestamp}.{json_body}\"`\n3. Compute HMAC-SHA256 of signed payload using your webhook secret\n4. Compare computed signature with received signature (constant-time comparison)\n5. Optionally check timestamp to prevent replay attacks\n\nResponse requirements:\n- Your endpoint must return a 2xx status code within 2 seconds\n- Failed deliveries are retried with exponential backoff\n- Retries stop when delay would exceed 24 hours or a 2xx response is received.","operationId":"webhook_eventwebhook_event_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEventBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"ActivityDetails":{"properties":{"tags":{"items":{"type":"string"},"type":"array","title":"Tags"},"id":{"type":"string","title":"Id"},"sport":{"type":"string","description":"Sport string in OpenSportTaxonomy format (e.g., 'cycling.road+stationary')"},"start":{"type":"string","format":"date-time","title":"Start","description":"Absolute instant in UTC (ISO 8601 with `Z`, e.g. `2026-05-18T15:32:00Z`). Sort, compare and merge on this; for the local wall-clock use the matching `*_local` field."},"end":{"type":"string","format":"date-time","title":"End","description":"Absolute instant in UTC (ISO 8601 with `Z`, e.g. `2026-05-18T15:32:00Z`). Sort, compare and merge on this; for the local wall-clock use the matching `*_local` field."},"metrics":{"items":{"$ref":"#/components/schemas/Metric"},"type":"array","title":"Metrics"},"source_id":{"type":"string","title":"Source Id"},"summary":{"anyOf":[{"$ref":"#/components/schemas/ActivitySummarySummary"},{"type":"null"}]},"laps":{"anyOf":[{"items":{"$ref":"#/components/schemas/Lap"},"type":"array"},{"type":"null"}],"title":"Laps"},"traces":{"anyOf":[{"items":{"$ref":"#/components/schemas/TraceDetails"},"type":"array"},{"type":"null"}],"title":"Traces"},"app_metadata":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"App Metadata"},"distance":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Distance"},"devices":{"items":{"type":"string"},"type":"array","title":"Devices"},"duration":{"type":"string","format":"duration","title":"Duration","readOnly":true},"start_local":{"type":"string","format":"date-time","title":"Start Local","description":"Naive local wall-clock at the record's own place/time (ISO 8601 without an offset, e.g. `2026-05-18T17:32:00`). Use for display and for grouping by local calendar date.","readOnly":true},"end_local":{"type":"string","format":"date-time","title":"End Local","description":"Naive local wall-clock at the record's own place/time (ISO 8601 without an offset, e.g. `2026-05-18T17:32:00`). Use for display and for grouping by local calendar date.","readOnly":true}},"type":"object","required":["id","sport","start","end","metrics","source_id","duration","start_local","end_local"],"title":"ActivityDetails"},"ActivitySummary":{"properties":{"tags":{"items":{"type":"string"},"type":"array","title":"Tags"},"id":{"type":"string","title":"Id"},"sport":{"type":"string","description":"Sport string in OpenSportTaxonomy format (e.g., 'cycling.road+stationary')"},"start":{"type":"string","format":"date-time","title":"Start","description":"Absolute instant in UTC (ISO 8601 with `Z`, e.g. `2026-05-18T15:32:00Z`). Sort, compare and merge on this; for the local wall-clock use the matching `*_local` field."},"end":{"type":"string","format":"date-time","title":"End","description":"Absolute instant in UTC (ISO 8601 with `Z`, e.g. `2026-05-18T15:32:00Z`). Sort, compare and merge on this; for the local wall-clock use the matching `*_local` field."},"metrics":{"items":{"$ref":"#/components/schemas/Metric"},"type":"array","title":"Metrics"},"source_id":{"type":"string","title":"Source Id"},"summary":{"anyOf":[{"$ref":"#/components/schemas/ActivitySummarySummary"},{"type":"null"}]},"laps":{"anyOf":[{"items":{"$ref":"#/components/schemas/Lap"},"type":"array"},{"type":"null"}],"title":"Laps"},"traces":{"anyOf":[{"items":{"$ref":"#/components/schemas/TraceDetails"},"type":"array"},{"type":"null"}],"title":"Traces"},"app_metadata":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"App Metadata"},"duration":{"type":"string","format":"duration","title":"Duration","readOnly":true},"start_local":{"type":"string","format":"date-time","title":"Start Local","description":"Naive local wall-clock at the record's own place/time (ISO 8601 without an offset, e.g. `2026-05-18T17:32:00`). Use for display and for grouping by local calendar date.","readOnly":true},"end_local":{"type":"string","format":"date-time","title":"End Local","description":"Naive local wall-clock at the record's own place/time (ISO 8601 without an offset, e.g. `2026-05-18T17:32:00`). Use for display and for grouping by local calendar date.","readOnly":true}},"type":"object","required":["id","sport","start","end","metrics","source_id","duration","start_local","end_local"],"title":"ActivitySummary"},"ActivitySummarySummary":{"properties":{"power":{"anyOf":[{"$ref":"#/components/schemas/PowerSummary"},{"type":"null"}]},"speed":{"anyOf":[{"$ref":"#/components/schemas/SpeedSummary"},{"type":"null"}]},"distance":{"anyOf":[{"$ref":"#/components/schemas/DistanceSummary"},{"type":"null"}]},"altitude":{"anyOf":[{"$ref":"#/components/schemas/AltitudeSummary"},{"type":"null"}]},"heart_rate":{"anyOf":[{"$ref":"#/components/schemas/HeartRateSummary"},{"type":"null"}]},"cadence":{"anyOf":[{"$ref":"#/components/schemas/CadenceSummary"},{"type":"null"}]},"temperature":{"anyOf":[{"$ref":"#/components/schemas/TemperatureSummary"},{"type":"null"}]},"core_temperature":{"anyOf":[{"$ref":"#/components/schemas/CoreTemperatureSummary"},{"type":"null"}]},"smo2":{"anyOf":[{"$ref":"#/components/schemas/Smo2Summary"},{"type":"null"}]}},"type":"object","title":"ActivitySummarySummary","description":"Summary statistics for an activity or lap.\n\nEach metric summary contains aggregated values calculated from timeseries data:\n\n- power: mean, max (watts)\n- speed: mean, max (m/s)\n- heart_rate: mean, min, max, start, end (bpm)\n- distance: sum (meters)\n- altitude: mean, gain, loss, min, max (meters)\n- cadence: mean, max (excluding zeros for stopped periods)\n- temperature: mean, min, max, start, end (°C, ambient)\n- core_temperature: mean, min, max, start, end (°C, body core)\n- smo2: mean, min, max, start, end (%, muscle oxygen saturation)"},"AltitudeSummary":{"properties":{"mean":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Mean"},"gain":{"anyOf":[{"type":"integer"},{"type":"number"},{"type":"null"}],"title":"Gain"},"loss":{"anyOf":[{"type":"integer"},{"type":"number"},{"type":"null"}],"title":"Loss"},"min":{"anyOf":[{"type":"integer"},{"type":"number"},{"type":"null"}],"title":"Min"},"max":{"anyOf":[{"type":"integer"},{"type":"number"},{"type":"null"}],"title":"Max"}},"type":"object","title":"AltitudeSummary"},"ApplicationCreate":{"properties":{"name":{"type":"string","maxLength":100,"minLength":1,"title":"Name"},"description":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Description"},"redirect_uris":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Redirect Uris"},"page":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Page"},"generate_secret":{"type":"boolean","title":"Generate Secret","default":false}},"type":"object","required":["name"],"title":"ApplicationCreate","description":"Create a private application.\n\nThis endpoint creates private applications suitable for development and testing.\nPrivate apps cannot be published to the marketplace. To create a public application,\nuse the web interface where additional metadata (description, image, privacy policy)\ncan be provided."},"ApplicationCreateResponse":{"properties":{"id":{"type":"string","title":"Id"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"image":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"Image"},"url":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"Url"},"redirect_uris":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Redirect Uris"},"privacy_statement":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"Privacy Statement"},"published":{"type":"boolean","title":"Published"},"webhook_endpoints":{"anyOf":[{"items":{"type":"string","minLength":1,"format":"uri"},"type":"array"},{"type":"null"}],"title":"Webhook Endpoints"},"webhook_secret":{"anyOf":[{"type":"string","format":"password","writeOnly":true},{"type":"null"}],"title":"Webhook Secret"},"client_secret":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Secret"},"page":{"anyOf":[{"$ref":"#/components/schemas/PageResponse"},{"type":"null"}]},"is_private":{"type":"boolean","title":"Is Private","description":"An application is private if it is missing any of: description, URL, image, or privacy statement.","readOnly":true},"is_clientside_app":{"type":"boolean","title":"Is Clientside App","description":"Check if this is a client-side app based on privacy policy URL.\n\nApps published via fast-track have privacy_statement set to the standard\nclient-side privacy policy URL, indicating they attested to being client-side.","readOnly":true}},"type":"object","required":["id","name","published","is_private","is_clientside_app"],"title":"ApplicationCreateResponse","description":"Response for created application."},"ApplicationListItem":{"properties":{"id":{"type":"string","title":"Id"},"name":{"type":"string","title":"Name"},"page_slug":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Page Slug"}},"type":"object","required":["id","name"],"title":"ApplicationListItem","description":"Minimal application info for list endpoint."},"ApplicationMemberRole":{"type":"string","enum":["owner","member"],"title":"ApplicationMemberRole"},"AuthorizeTeamRequest":{"properties":{"scopes":{"items":{"$ref":"#/components/schemas/Scope"},"type":"array","title":"Scopes"}},"type":"object","required":["scopes"],"title":"AuthorizeTeamRequest","description":"Request body for authorizing a team to access user data."},"AuthorizedTeamResponse":{"properties":{"id":{"type":"string","title":"Id"},"name":{"type":"string","title":"Name"},"description":{"type":"string","title":"Description"},"url":{"type":"string","minLength":1,"format":"uri","title":"Url"},"image":{"type":"string","minLength":1,"format":"uri","title":"Image"},"privacy_statement":{"type":"string","minLength":1,"format":"uri","title":"Privacy Statement"},"scopes":{"items":{"$ref":"#/components/schemas/Scope"},"type":"array","title":"Scopes"}},"type":"object","required":["id","name","description","url","image","privacy_statement","scopes"],"title":"AuthorizedTeamResponse"},"BackfillError":{"properties":{"error":{"type":"string","title":"Error"}},"type":"object","required":["error"],"title":"BackfillError"},"BackfillStatus":{"properties":{"backfill_loaded_until":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Backfill Loaded Until"}},"type":"object","required":["backfill_loaded_until"],"title":"BackfillStatus"},"Body_create_page_api_v1_pages_post":{"properties":{"application_id":{"type":"string","title":"Application Id"},"slug":{"type":"string","title":"Slug"}},"type":"object","required":["application_id","slug"],"title":"Body_create_page_api_v1_pages_post"},"Body_deploy_page_api_v1_pages__slug__deploy_put":{"properties":{"files":{"items":{"type":"string","format":"binary"},"type":"array","title":"Files"}},"type":"object","required":["files"],"title":"Body_deploy_page_api_v1_pages__slug__deploy_put"},"Body_ensure_application_page_api_v1_applications__application_id__page_put":{"properties":{"slug":{"type":"string","title":"Slug"}},"type":"object","required":["slug"],"title":"Body_ensure_application_page_api_v1_applications__application_id__page_put"},"Body_update_managed_user_api_v1_users__user_id__put":{"properties":{"first_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"First Name"},"last_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Name"}},"type":"object","title":"Body_update_managed_user_api_v1_users__user_id__put"},"Body_upload_activity_file_api_v1_activities_upload_post":{"properties":{"files":{"items":{"type":"string","format":"binary"},"type":"array","title":"Files"}},"type":"object","required":["files"],"title":"Body_upload_activity_file_api_v1_activities_upload_post"},"CadenceSummary":{"properties":{"mean":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Mean"},"max":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Max"}},"type":"object","title":"CadenceSummary"},"ConstantValue":{"properties":{"type":{"type":"string","const":"constant","title":"Type","default":"constant"},"quantity":{"anyOf":[{"$ref":"#/components/schemas/VolumeQuantity"},{"$ref":"#/components/schemas/IntensityQuantity"}],"title":"Quantity"},"value":{"anyOf":[{"type":"integer"},{"type":"number"},{"$ref":"#/components/schemas/ParameterRef"},{"$ref":"#/components/schemas/TTERef"}],"title":"Value"}},"type":"object","required":["quantity","value"],"title":"ConstantValue"},"CoreTemperatureSummary":{"properties":{"mean":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Mean"},"min":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Min"},"max":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Max"},"start":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Start"},"end":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"End"}},"type":"object","title":"CoreTemperatureSummary"},"DailyCreate":{"properties":{"date":{"type":"string","format":"date","title":"Date"},"value":{"type":"number","title":"Value"}},"type":"object","required":["date","value"],"title":"DailyCreate"},"DailyMeasure":{"type":"string","enum":["body_mass","body_fat_pct","resting_hr","hrv","sleep_duration","sleep_altitude","menstrual_cycle_day"],"title":"DailyMeasure"},"DailyResponse":{"properties":{"date":{"type":"string","format":"date","title":"Date"},"value":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Value"},"status":{"$ref":"#/components/schemas/DailyStatus"},"source":{"anyOf":[{"$ref":"#/components/schemas/DailySource"},{"type":"null"}]}},"type":"object","required":["date","value","status"],"title":"DailyResponse"},"DailySource":{"type":"string","enum":["manual","garmin_connect","intervals_icu","wahoo"],"title":"DailySource","description":"Provenance of a stored daily value. Distinct from read-time status."},"DailyStatus":{"type":"string","enum":["stored","estimated","missing"],"title":"DailyStatus","description":"Read-time state of a day in a dailies series. Never persisted."},"DelegatedTokenRequest":{"properties":{"sub":{"type":"string","title":"Sub"},"scopes":{"anyOf":[{"items":{"$ref":"#/components/schemas/Scope"},"type":"array"},{"type":"null"}],"title":"Scopes"},"team_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Team Id"}},"type":"object","required":["sub"],"title":"DelegatedTokenRequest"},"DeliveryView":{"properties":{"integration":{"type":"string","title":"Integration"},"status":{"type":"string","title":"Status"},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason"},"detail":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Detail"},"updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Updated At"}},"type":"object","required":["integration","status"],"title":"DeliveryView","description":"Curated, stable view of a workout's delivery to one integration.\n\n`status` is the durable three-value contract (`pending` | `delivered` | `not_delivered`);\n`reason` explains a `not_delivered` (e.g. `missing_permission`, `incompatible`, `not_scheduled`)\nand may gain values without breaking consumers; `detail` is human-readable and never parsed.\nThe internal, higher-fidelity outcome is not exposed (see app/workouts/delivery.py)."},"DistanceSummary":{"properties":{"sum":{"anyOf":[{"type":"integer"},{"type":"number"},{"type":"null"}],"title":"Sum"}},"type":"object","title":"DistanceSummary"},"Effort":{"type":"string","enum":["work","rest"],"title":"Effort"},"GrantType":{"type":"string","enum":["authorization_code","refresh_token"],"title":"GrantType"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"HeartRateSummary":{"properties":{"mean":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Mean"},"min":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Min"},"max":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Max"},"start":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Start"},"end":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"End"}},"type":"object","title":"HeartRateSummary"},"IntensityQuantity":{"type":"string","enum":["speed","power","heart_rate","rpe_cr10","rpe_borg"],"title":"IntensityQuantity"},"Lap":{"properties":{"power":{"anyOf":[{"$ref":"#/components/schemas/PowerSummary"},{"type":"null"}]},"speed":{"anyOf":[{"$ref":"#/components/schemas/SpeedSummary"},{"type":"null"}]},"distance":{"anyOf":[{"$ref":"#/components/schemas/DistanceSummary"},{"type":"null"}]},"altitude":{"anyOf":[{"$ref":"#/components/schemas/AltitudeSummary"},{"type":"null"}]},"heart_rate":{"anyOf":[{"$ref":"#/components/schemas/HeartRateSummary"},{"type":"null"}]},"cadence":{"anyOf":[{"$ref":"#/components/schemas/CadenceSummary"},{"type":"null"}]},"temperature":{"anyOf":[{"$ref":"#/components/schemas/TemperatureSummary"},{"type":"null"}]},"core_temperature":{"anyOf":[{"$ref":"#/components/schemas/CoreTemperatureSummary"},{"type":"null"}]},"smo2":{"anyOf":[{"$ref":"#/components/schemas/Smo2Summary"},{"type":"null"}]},"start":{"type":"string","format":"date-time","title":"Start","description":"Absolute instant in UTC (ISO 8601 with `Z`, e.g. `2026-05-18T15:32:00Z`). Sort, compare and merge on this; for the local wall-clock use the matching `*_local` field."},"end":{"type":"string","format":"date-time","title":"End","description":"Absolute instant in UTC (ISO 8601 with `Z`, e.g. `2026-05-18T15:32:00Z`). Sort, compare and merge on this; for the local wall-clock use the matching `*_local` field."},"duration":{"type":"string","format":"duration","title":"Duration","readOnly":true},"start_local":{"type":"string","format":"date-time","title":"Start Local","description":"Naive local wall-clock at the record's own place/time (ISO 8601 without an offset, e.g. `2026-05-18T17:32:00`). Use for display and for grouping by local calendar date.","readOnly":true},"end_local":{"type":"string","format":"date-time","title":"End Local","description":"Naive local wall-clock at the record's own place/time (ISO 8601 without an offset, e.g. `2026-05-18T17:32:00`). Use for display and for grouping by local calendar date.","readOnly":true}},"type":"object","required":["start","end","duration","start_local","end_local"],"title":"Lap"},"ManagedUserCreate":{"properties":{"first_name":{"type":"string","title":"First Name"},"last_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Name"}},"type":"object","required":["first_name","last_name"],"title":"ManagedUserCreate"},"Marker":{"properties":{"power":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Power"},"speed":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Speed"},"heart_rate":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Heart Rate"},"lactate":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Lactate"},"vo2":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Vo2"}},"type":"object","title":"Marker","description":"A physiological snapshot at an intensity point — co-occurring values at that intensity."},"Metric":{"type":"string","enum":["duration","lap","power","speed","heart_rate","respiration_rate","smo2","core_temperature","elevation","altitude","cadence","temperature","distance","longitude","latitude","lactate","rpe","notes"],"title":"Metric"},"Note":{"properties":{"type":{"type":"string","const":"note","title":"Type","default":"note"},"text":{"type":"string","title":"Text"}},"type":"object","required":["text"],"title":"Note"},"PageApplicationInfo":{"properties":{"id":{"type":"string","title":"Id"},"name":{"type":"string","title":"Name"},"is_private":{"type":"boolean","title":"Is Private"}},"type":"object","required":["id","name","is_private"],"title":"PageApplicationInfo","description":"Nested application info for PageResponse."},"PageResponse":{"properties":{"slug":{"type":"string","title":"Slug"},"published":{"type":"boolean","title":"Published"},"application":{"$ref":"#/components/schemas/PageApplicationInfo"},"url":{"type":"string","title":"Url","description":"The public URL where this page is served.","readOnly":true}},"type":"object","required":["slug","published","application","url"],"title":"PageResponse","description":"Response body for Page details."},"ParameterRef":{"properties":{"percent":{"anyOf":[{"type":"integer"},{"type":"number"}],"title":"Percent"},"of":{"type":"string","title":"Of"}},"type":"object","required":["percent","of"],"title":"ParameterRef","description":"Reference to a named parameter, e.g. 75% of FTP."},"PortalDestination":{"type":"string","enum":["manage-teams"],"title":"PortalDestination"},"PortalSessionRequest":{"properties":{"client_id":{"type":"string","title":"Client Id"},"client_secret":{"type":"string","format":"password","title":"Client Secret","writeOnly":true},"destination":{"$ref":"#/components/schemas/PortalDestination"},"return_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Return Url"}},"type":"object","required":["client_id","client_secret","destination"],"title":"PortalSessionRequest","description":"Request body for POST /api/v1/portal/sessions. A 3rd-party app\nauthenticates with its own client credentials and asks SweatStack to\nmint a portal deep-link for a given destination. SweatStack stamps the\nauthenticated app id into the returned URL, so the brand context is\nestablished by authentication, not by a client-supplied parameter.\nSee plan 016."},"PortalSessionResponse":{"properties":{"url":{"type":"string","title":"Url"}},"type":"object","required":["url"],"title":"PortalSessionResponse"},"PowerSummary":{"properties":{"mean":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Mean"},"max":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Max"}},"type":"object","title":"PowerSummary"},"RampValue":{"properties":{"type":{"type":"string","const":"ramp","title":"Type","default":"ramp"},"quantity":{"anyOf":[{"$ref":"#/components/schemas/VolumeQuantity"},{"$ref":"#/components/schemas/IntensityQuantity"}],"title":"Quantity"},"start":{"anyOf":[{"type":"integer"},{"type":"number"},{"$ref":"#/components/schemas/ParameterRef"},{"$ref":"#/components/schemas/TTERef"}],"title":"Start"},"end":{"anyOf":[{"type":"integer"},{"type":"number"},{"$ref":"#/components/schemas/ParameterRef"},{"$ref":"#/components/schemas/TTERef"}],"title":"End"}},"type":"object","required":["quantity","start","end"],"title":"RampValue"},"RangeValue":{"properties":{"type":{"type":"string","const":"range","title":"Type","default":"range"},"quantity":{"anyOf":[{"$ref":"#/components/schemas/VolumeQuantity"},{"$ref":"#/components/schemas/IntensityQuantity"}],"title":"Quantity"},"min":{"anyOf":[{"type":"integer"},{"type":"number"},{"$ref":"#/components/schemas/ParameterRef"},{"$ref":"#/components/schemas/TTERef"},{"type":"null"}],"title":"Min"},"max":{"anyOf":[{"type":"integer"},{"type":"number"},{"$ref":"#/components/schemas/ParameterRef"},{"$ref":"#/components/schemas/TTERef"},{"type":"null"}],"title":"Max"}},"type":"object","required":["quantity"],"title":"RangeValue"},"Repeat-Input":{"properties":{"type":{"type":"string","const":"repeat","title":"Type","default":"repeat"},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"},"count":{"anyOf":[{"type":"integer"},{"$ref":"#/components/schemas/ParameterRef"},{"$ref":"#/components/schemas/RepeatCount"}],"title":"Count"},"content":{"items":{"oneOf":[{"$ref":"#/components/schemas/Step-Input"},{"$ref":"#/components/schemas/Repeat-Input"},{"$ref":"#/components/schemas/Note"}],"discriminator":{"propertyName":"type","mapping":{"note":"#/components/schemas/Note","repeat":"#/components/schemas/Repeat-Input","step":"#/components/schemas/Step-Input"}}},"type":"array","title":"Content"}},"type":"object","required":["count","content"],"title":"Repeat"},"Repeat-Output":{"properties":{"type":{"type":"string","const":"repeat","title":"Type","default":"repeat"},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"},"count":{"anyOf":[{"type":"integer"},{"$ref":"#/components/schemas/ParameterRef"},{"$ref":"#/components/schemas/RepeatCount"}],"title":"Count"},"content":{"items":{"oneOf":[{"$ref":"#/components/schemas/Step-Output"},{"$ref":"#/components/schemas/Repeat-Output"},{"$ref":"#/components/schemas/Note"}],"discriminator":{"propertyName":"type","mapping":{"note":"#/components/schemas/Note","repeat":"#/components/schemas/Repeat-Output","step":"#/components/schemas/Step-Output"}}},"type":"array","title":"Content"}},"type":"object","required":["count","content"],"title":"Repeat"},"RepeatCount":{"properties":{"min":{"type":"integer","title":"Min"},"max":{"type":"integer","title":"Max"}},"type":"object","required":["min","max"],"title":"RepeatCount"},"ScheduledWorkoutCreate":{"properties":{"swf":{"$ref":"#/components/schemas/Workout-Input"},"start":{"type":"string","format":"date-time","title":"Start","description":"Naive local datetime (ISO 8601 without an offset, e.g. `2026-05-25T07:00:00`). A scheduled workout is a plan in the athlete's local wall-clock, so this carries no timezone."},"parameters":{"anyOf":[{"additionalProperties":{"type":"number"},"type":"object"},{"type":"null"}],"title":"Parameters"}},"type":"object","required":["swf","start"],"title":"ScheduledWorkoutCreate"},"ScheduledWorkoutCreateResponse":{"properties":{"id":{"type":"string","title":"Id"},"sport":{"type":"string","description":"Sport string in OpenSportTaxonomy format (e.g., 'cycling.road+stationary')"},"start":{"type":"string","format":"date-time","title":"Start","description":"Naive local datetime (ISO 8601 without an offset, e.g. `2026-05-25T07:00:00`). A scheduled workout is a plan in the athlete's local wall-clock, so this carries no timezone."},"swf":{"$ref":"#/components/schemas/Workout-Output"},"parameters":{"anyOf":[{"additionalProperties":{"type":"number"},"type":"object"},{"type":"null"}],"title":"Parameters"},"application_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Application Id"},"application_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Application Name"},"deliveries":{"items":{"$ref":"#/components/schemas/DeliveryView"},"type":"array","title":"Deliveries"},"warnings":{"items":{"$ref":"#/components/schemas/WorkoutWarning"},"type":"array","title":"Warnings"}},"type":"object","required":["id","sport","start","swf"],"title":"ScheduledWorkoutCreateResponse","description":"Create/update response. Adds `warnings`: a create-time, per-integration compatibility\nheads-up that a plain read (`GET`) cannot recompute, so it lives only here. Empty when every\nconnected integration will consume the workout as-is."},"ScheduledWorkoutResponse":{"properties":{"id":{"type":"string","title":"Id"},"sport":{"type":"string","description":"Sport string in OpenSportTaxonomy format (e.g., 'cycling.road+stationary')"},"start":{"type":"string","format":"date-time","title":"Start","description":"Naive local datetime (ISO 8601 without an offset, e.g. `2026-05-25T07:00:00`). A scheduled workout is a plan in the athlete's local wall-clock, so this carries no timezone."},"swf":{"$ref":"#/components/schemas/Workout-Output"},"parameters":{"anyOf":[{"additionalProperties":{"type":"number"},"type":"object"},{"type":"null"}],"title":"Parameters"},"application_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Application Id"},"application_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Application Name"},"deliveries":{"items":{"$ref":"#/components/schemas/DeliveryView"},"type":"array","title":"Deliveries"}},"type":"object","required":["id","sport","start","swf"],"title":"ScheduledWorkoutResponse"},"Scope":{"type":"string","enum":["data:read","data:write","admin","openid","profile","offline_access"],"title":"Scope"},"Section-Input":{"properties":{"type":{"type":"string","const":"section","title":"Type","default":"section"},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"},"phase":{"$ref":"#/components/schemas/SectionPhase"},"content":{"items":{"oneOf":[{"$ref":"#/components/schemas/Step-Input"},{"$ref":"#/components/schemas/Repeat-Input"},{"$ref":"#/components/schemas/Note"}],"discriminator":{"propertyName":"type","mapping":{"note":"#/components/schemas/Note","repeat":"#/components/schemas/Repeat-Input","step":"#/components/schemas/Step-Input"}}},"type":"array","title":"Content"}},"type":"object","required":["phase","content"],"title":"Section"},"Section-Output":{"properties":{"type":{"type":"string","const":"section","title":"Type","default":"section"},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"},"phase":{"$ref":"#/components/schemas/SectionPhase"},"content":{"items":{"oneOf":[{"$ref":"#/components/schemas/Step-Output"},{"$ref":"#/components/schemas/Repeat-Output"},{"$ref":"#/components/schemas/Note"}],"discriminator":{"propertyName":"type","mapping":{"note":"#/components/schemas/Note","repeat":"#/components/schemas/Repeat-Output","step":"#/components/schemas/Step-Output"}}},"type":"array","title":"Content"}},"type":"object","required":["phase","content"],"title":"Section"},"SectionPhase":{"type":"string","enum":["warmup","main","cooldown"],"title":"SectionPhase"},"Smo2Summary":{"properties":{"mean":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Mean"},"min":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Min"},"max":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Max"},"start":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Start"},"end":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"End"}},"type":"object","title":"Smo2Summary"},"SourceError":{"properties":{"code":{"type":"string","title":"Code"},"message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Message"}},"type":"object","required":["code"],"title":"SourceError"},"SourceOrigin":{"type":"string","enum":["manual_upload","garmin_connect","intervals_icu","wahoo"],"title":"SourceOrigin"},"SourceResponse":{"properties":{"id":{"type":"string","title":"Id"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Type"},"origin":{"type":"string","title":"Origin"},"filename":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Filename"},"status":{"type":"string","title":"Status"},"error":{"anyOf":[{"$ref":"#/components/schemas/SourceError"},{"type":"null"}]},"activity_ids":{"items":{"type":"string"},"type":"array","title":"Activity Ids"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","type","origin","filename","status","activity_ids","created_at"],"title":"SourceResponse","description":"Developer-facing view of a `Source` (plan 041). Curated (no `external_id` / internals);\n`origin` is an OPEN set (tolerate values added later). Built via `from_source`, which applies\nthe read-time `processing_timeout` override."},"SourceStatus":{"type":"string","enum":["processing","processed","failed"],"title":"SourceStatus"},"SpeedSummary":{"properties":{"mean":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Mean"},"max":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Max"}},"type":"object","title":"SpeedSummary"},"Sport":{"properties":{"code":{"type":"string","title":"Code"},"modifiers":{"items":{"type":"string"},"type":"array","uniqueItems":true,"title":"Modifiers"}},"type":"object","required":["code","modifiers"],"title":"Sport"},"Step-Input":{"properties":{"type":{"type":"string","const":"step","title":"Type","default":"step"},"effort":{"$ref":"#/components/schemas/Effort","default":"work"},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"},"volume":{"anyOf":[{"oneOf":[{"$ref":"#/components/schemas/ConstantValue"},{"$ref":"#/components/schemas/RangeValue"},{"$ref":"#/components/schemas/RampValue"},{"$ref":"#/components/schemas/ZoneValue"}],"discriminator":{"propertyName":"type","mapping":{"constant":"#/components/schemas/ConstantValue","ramp":"#/components/schemas/RampValue","range":"#/components/schemas/RangeValue","zone":"#/components/schemas/ZoneValue"}}},{"type":"null"}],"title":"Volume"},"intensity":{"anyOf":[{"oneOf":[{"$ref":"#/components/schemas/ConstantValue"},{"$ref":"#/components/schemas/RangeValue"},{"$ref":"#/components/schemas/RampValue"},{"$ref":"#/components/schemas/ZoneValue"}],"discriminator":{"propertyName":"type","mapping":{"constant":"#/components/schemas/ConstantValue","ramp":"#/components/schemas/RampValue","range":"#/components/schemas/RangeValue","zone":"#/components/schemas/ZoneValue"}}},{"type":"null"}],"title":"Intensity"}},"type":"object","title":"Step"},"Step-Output":{"properties":{"type":{"type":"string","const":"step","title":"Type","default":"step"},"effort":{"$ref":"#/components/schemas/Effort","default":"work"},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"},"volume":{"anyOf":[{"oneOf":[{"$ref":"#/components/schemas/ConstantValue"},{"$ref":"#/components/schemas/RangeValue"},{"$ref":"#/components/schemas/RampValue"},{"$ref":"#/components/schemas/ZoneValue"}],"discriminator":{"propertyName":"type","mapping":{"constant":"#/components/schemas/ConstantValue","ramp":"#/components/schemas/RampValue","range":"#/components/schemas/RangeValue","zone":"#/components/schemas/ZoneValue"}}},{"type":"null"}],"title":"Volume"},"intensity":{"anyOf":[{"oneOf":[{"$ref":"#/components/schemas/ConstantValue"},{"$ref":"#/components/schemas/RangeValue"},{"$ref":"#/components/schemas/RampValue"},{"$ref":"#/components/schemas/ZoneValue"}],"discriminator":{"propertyName":"type","mapping":{"constant":"#/components/schemas/ConstantValue","ramp":"#/components/schemas/RampValue","range":"#/components/schemas/RangeValue","zone":"#/components/schemas/ZoneValue"}}},{"type":"null"}],"title":"Intensity"}},"type":"object","title":"Step"},"TTERef":{"properties":{"tte":{"anyOf":[{"type":"integer"},{"type":"number"}],"title":"Tte"}},"type":"object","required":["tte"],"title":"TTERef","description":"Time-to-exhaustion reference, e.g. power at 5-minute TTE."},"TeamResponse":{"properties":{"id":{"type":"string","title":"Id"},"name":{"type":"string","title":"Name"},"description":{"type":"string","title":"Description"},"url":{"type":"string","minLength":1,"format":"uri","title":"Url"},"image":{"type":"string","minLength":1,"format":"uri","title":"Image"},"privacy_statement":{"type":"string","minLength":1,"format":"uri","title":"Privacy Statement"},"role":{"anyOf":[{"$ref":"#/components/schemas/ApplicationMemberRole"},{"type":"null"}]}},"type":"object","required":["id","name","description","url","image","privacy_statement","role"],"title":"TeamResponse"},"TemperatureSummary":{"properties":{"mean":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Mean"},"min":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Min"},"max":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Max"},"start":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Start"},"end":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"End"}},"type":"object","title":"TemperatureSummary"},"TemplateDay":{"properties":{"sports":{"items":{"type":"string","description":"Sport string in OpenSportTaxonomy format (e.g., 'cycling.road+stationary')"},"type":"array","title":"Sports"},"avg_training_duration":{"type":"string","format":"duration","title":"Avg Training Duration"},"typical_training_duration":{"type":"string","format":"duration","title":"Typical Training Duration"}},"type":"object","required":["sports","avg_training_duration","typical_training_duration"],"title":"TemplateDay"},"TemplateWeekResponse":{"properties":{"monday":{"$ref":"#/components/schemas/TemplateDay"},"tuesday":{"$ref":"#/components/schemas/TemplateDay"},"wednesday":{"$ref":"#/components/schemas/TemplateDay"},"thursday":{"$ref":"#/components/schemas/TemplateDay"},"friday":{"$ref":"#/components/schemas/TemplateDay"},"saturday":{"$ref":"#/components/schemas/TemplateDay"},"sunday":{"$ref":"#/components/schemas/TemplateDay"}},"type":"object","required":["monday","tuesday","wednesday","thursday","friday","saturday","sunday"],"title":"TemplateWeekResponse"},"TestCreate":{"properties":{"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"sport":{"type":"string","description":"Sport string in OpenSportTaxonomy format (e.g., 'cycling.road+stationary')"},"start":{"type":"string","format":"date-time","title":"Start","description":"Offset-aware ISO 8601 (e.g. `2026-05-18T17:32:00+02:00` or `...Z`). A naive timestamp is rejected; the offset is stored so the local time round-trips."},"end":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"End","description":"Offset-aware ISO 8601 (e.g. `2026-05-18T17:32:00+02:00` or `...Z`). A naive timestamp is rejected; the offset is stored so the local time round-trips."},"results":{"anyOf":[{"$ref":"#/components/schemas/TestResults"},{"type":"null"}]},"tags":{"items":{"type":"string"},"type":"array","title":"Tags"}},"type":"object","required":["sport","start"],"title":"TestCreate"},"TestDetails":{"properties":{"tags":{"items":{"type":"string"},"type":"array","title":"Tags"},"id":{"type":"string","title":"Id"},"created_by":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Created By"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"sport":{"type":"string","description":"Sport string in OpenSportTaxonomy format (e.g., 'cycling.road+stationary')"},"start":{"type":"string","format":"date-time","title":"Start","description":"Absolute instant in UTC (ISO 8601 with `Z`, e.g. `2026-05-18T15:32:00Z`). Sort, compare and merge on this; for the local wall-clock use the matching `*_local` field."},"end":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"End","description":"Absolute instant in UTC (ISO 8601 with `Z`, e.g. `2026-05-18T15:32:00Z`). Sort, compare and merge on this; for the local wall-clock use the matching `*_local` field."},"results":{"anyOf":[{"$ref":"#/components/schemas/TestResults"},{"type":"null"}]},"app_metadata":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"App Metadata"},"traces":{"anyOf":[{"items":{"$ref":"#/components/schemas/TraceDetails"},"type":"array"},{"type":"null"}],"title":"Traces"},"activities":{"anyOf":[{"items":{"$ref":"#/components/schemas/ActivitySummary"},"type":"array"},{"type":"null"}],"title":"Activities"},"start_local":{"type":"string","format":"date-time","title":"Start Local","description":"Naive local wall-clock at the record's own place/time (ISO 8601 without an offset, e.g. `2026-05-18T17:32:00`). Use for display and for grouping by local calendar date.","readOnly":true},"end_local":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"End Local","description":"Naive local wall-clock at the record's own place/time (ISO 8601 without an offset, e.g. `2026-05-18T17:32:00`). Use for display and for grouping by local calendar date.","readOnly":true}},"type":"object","required":["id","sport","start","start_local","end_local"],"title":"TestDetails"},"TestResults":{"properties":{"first_threshold":{"anyOf":[{"$ref":"#/components/schemas/Marker"},{"type":"null"}]},"second_threshold":{"anyOf":[{"$ref":"#/components/schemas/Marker"},{"type":"null"}]},"fatmax":{"anyOf":[{"$ref":"#/components/schemas/Marker"},{"type":"null"}]},"lt1":{"anyOf":[{"$ref":"#/components/schemas/Marker"},{"type":"null"}]},"lt2":{"anyOf":[{"$ref":"#/components/schemas/Marker"},{"type":"null"}]},"vt1":{"anyOf":[{"$ref":"#/components/schemas/Marker"},{"type":"null"}]},"vt2":{"anyOf":[{"$ref":"#/components/schemas/Marker"},{"type":"null"}]},"mlss":{"anyOf":[{"$ref":"#/components/schemas/Marker"},{"type":"null"}]},"vo2max":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Vo2Max"},"vo2peak":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Vo2Peak"},"vlamax":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Vlamax"},"heart_rate_max":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Heart Rate Max"},"critical_power":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Critical Power"},"critical_speed":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Critical Speed"},"w_prime":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"W Prime"},"d_prime":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"D Prime"},"economy":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Economy"},"efficiency":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Efficiency"}},"type":"object","title":"TestResults","description":"Structured test results stored as JSON on the Test model."},"TestSummary":{"properties":{"tags":{"items":{"type":"string"},"type":"array","title":"Tags"},"id":{"type":"string","title":"Id"},"created_by":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Created By"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"sport":{"type":"string","description":"Sport string in OpenSportTaxonomy format (e.g., 'cycling.road+stationary')"},"start":{"type":"string","format":"date-time","title":"Start","description":"Absolute instant in UTC (ISO 8601 with `Z`, e.g. `2026-05-18T15:32:00Z`). Sort, compare and merge on this; for the local wall-clock use the matching `*_local` field."},"end":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"End","description":"Absolute instant in UTC (ISO 8601 with `Z`, e.g. `2026-05-18T15:32:00Z`). Sort, compare and merge on this; for the local wall-clock use the matching `*_local` field."},"results":{"anyOf":[{"$ref":"#/components/schemas/TestResults"},{"type":"null"}]},"app_metadata":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"App Metadata"},"start_local":{"type":"string","format":"date-time","title":"Start Local","description":"Naive local wall-clock at the record's own place/time (ISO 8601 without an offset, e.g. `2026-05-18T17:32:00`). Use for display and for grouping by local calendar date.","readOnly":true},"end_local":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"End Local","description":"Naive local wall-clock at the record's own place/time (ISO 8601 without an offset, e.g. `2026-05-18T17:32:00`). Use for display and for grouping by local calendar date.","readOnly":true}},"type":"object","required":["id","sport","start","start_local","end_local"],"title":"TestSummary"},"TestUpdate":{"properties":{"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"sport":{"type":"string","description":"Sport string in OpenSportTaxonomy format (e.g., 'cycling.road+stationary')"},"start":{"type":"string","format":"date-time","title":"Start","description":"Offset-aware ISO 8601 (e.g. `2026-05-18T17:32:00+02:00` or `...Z`). A naive timestamp is rejected; the offset is stored so the local time round-trips."},"end":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"End","description":"Offset-aware ISO 8601 (e.g. `2026-05-18T17:32:00+02:00` or `...Z`). A naive timestamp is rejected; the offset is stored so the local time round-trips."},"results":{"anyOf":[{"$ref":"#/components/schemas/TestResults"},{"type":"null"}]},"tags":{"items":{"type":"string"},"type":"array","title":"Tags"}},"type":"object","required":["sport","start"],"title":"TestUpdate","description":"PUT semantics: full replace. Omitted optional fields are set to null."},"TokenRequest":{"properties":{"grant_type":{"$ref":"#/components/schemas/GrantType"},"client_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Id"},"code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Code"},"client_secret":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Secret"},"code_verifier":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Code Verifier"},"refresh_token":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refresh Token"}},"type":"object","required":["grant_type"],"title":"TokenRequest"},"TokenResponse":{"properties":{"access_token":{"type":"string","title":"Access Token"},"token_type":{"type":"string","const":"Bearer","title":"Token Type","default":"Bearer"},"expires_in":{"type":"integer","title":"Expires In"},"refresh_token":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refresh Token"},"scope":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Scope"},"id_token":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Id Token"}},"type":"object","required":["access_token","expires_in"],"title":"TokenResponse"},"TraceCreateOrUpdate":{"properties":{"timestamp":{"type":"string","format":"date-time","title":"Timestamp","description":"Offset-aware ISO 8601 (e.g. `2026-05-18T17:32:00+02:00` or `...Z`). A naive timestamp is rejected; the offset is stored so the local time round-trips."},"test_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Test Id"},"lactate":{"anyOf":[{"type":"null"},{"type":"number"}],"title":"Lactate"},"rpe":{"anyOf":[{"type":"null"},{"type":"integer"}],"title":"Rpe"},"notes":{"anyOf":[{"type":"null"},{"type":"string"}],"title":"Notes"},"power":{"anyOf":[{"type":"null"},{"type":"integer","minimum":0.0}],"title":"Power"},"speed":{"anyOf":[{"type":"null"},{"type":"number","minimum":0.0}],"title":"Speed"},"heart_rate":{"anyOf":[{"type":"null"},{"type":"integer","minimum":0.0}],"title":"Heart Rate"},"vo2":{"anyOf":[{"type":"null"},{"type":"number","minimum":0.0}],"title":"Vo2"},"tags":{"items":{"type":"string"},"type":"array","title":"Tags"},"sport":{"anyOf":[{"type":"string","description":"Sport string in OpenSportTaxonomy format (e.g., 'cycling.road+stationary')"},{"type":"null"}]}},"type":"object","required":["timestamp"],"title":"TraceCreateOrUpdate"},"TraceDetails":{"properties":{"tags":{"items":{"type":"string"},"type":"array","title":"Tags"},"id":{"type":"string","title":"Id"},"test_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Test Id"},"timestamp":{"type":"string","format":"date-time","title":"Timestamp","description":"Absolute instant in UTC (ISO 8601 with `Z`, e.g. `2026-05-18T15:32:00Z`). Sort, compare and merge on this; for the local wall-clock use the matching `*_local` field."},"lactate":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Lactate"},"rpe":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Rpe"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes"},"power":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Power"},"speed":{"anyOf":[{"type":"number","minimum":0.0},{"type":"null"}],"title":"Speed"},"heart_rate":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Heart Rate"},"vo2":{"anyOf":[{"type":"number","minimum":0.0},{"type":"null"}],"title":"Vo2"},"lap":{"anyOf":[{"$ref":"#/components/schemas/Lap"},{"type":"null"}]},"activity":{"anyOf":[{"$ref":"#/components/schemas/ActivitySummary"},{"type":"null"}]},"test":{"anyOf":[{"$ref":"#/components/schemas/TestSummary"},{"type":"null"}]},"test_match":{"anyOf":[{"type":"string","enum":["explicit","window"]},{"type":"null"}],"title":"Test Match"},"sport":{"anyOf":[{"type":"string","description":"Sport string in OpenSportTaxonomy format (e.g., 'cycling.road+stationary')"},{"type":"null"}]},"app_metadata":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"App Metadata"},"timestamp_local":{"type":"string","format":"date-time","title":"Timestamp Local","description":"Naive local wall-clock at the record's own place/time (ISO 8601 without an offset, e.g. `2026-05-18T17:32:00`). Use for display and for grouping by local calendar date.","readOnly":true}},"type":"object","required":["id","timestamp","timestamp_local"],"title":"TraceDetails"},"TraceResolution":{"type":"string","enum":["auto","linked"],"title":"TraceResolution","description":"How traces are matched to a test on GET /tests/{id}."},"UserInfoResponse":{"properties":{"sub":{"type":"string","title":"Sub"},"given_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Given Name"},"family_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Family Name"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"},"registered_at":{"type":"string","format":"date-time","title":"Registered At"},"name":{"type":"string","title":"Name","readOnly":true}},"type":"object","required":["sub","registered_at","name"],"title":"UserInfoResponse"},"UserResponse":{"properties":{"id":{"type":"string","title":"Id"},"first_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"First Name"},"last_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Name"},"admin":{"type":"boolean","title":"Admin"},"registered_at":{"type":"string","format":"date-time","title":"Registered At"},"display_name":{"type":"string","title":"Display Name","readOnly":true},"is_managed":{"type":"boolean","title":"Is Managed","readOnly":true}},"type":"object","required":["id","first_name","last_name","admin","registered_at","display_name","is_managed"],"title":"UserResponse"},"UserSummary":{"properties":{"id":{"type":"string","title":"Id"},"first_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"First Name"},"last_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Name"},"scopes":{"items":{"$ref":"#/components/schemas/Scope"},"type":"array","title":"Scopes"},"display_name":{"type":"string","title":"Display Name","readOnly":true},"is_managed":{"type":"boolean","title":"Is Managed","readOnly":true}},"type":"object","required":["id","first_name","last_name","scopes","display_name","is_managed"],"title":"UserSummary"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"VolumeQuantity":{"type":"string","enum":["duration","distance"],"title":"VolumeQuantity"},"WebhookEventBody":{"properties":{"user_id":{"type":"string","title":"User Id"},"event_type":{"$ref":"#/components/schemas/WebhookEventType"},"resource_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Resource Id"},"timestamp":{"type":"string","format":"date-time","title":"Timestamp"}},"type":"object","required":["user_id","event_type","resource_id","timestamp"],"title":"WebhookEventBody","description":"The webhook payload sent to application endpoints"},"WebhookEventType":{"type":"string","enum":["activity_created","activity_updated","activity_deleted","test_created","test_updated","test_deleted","source_processed","source_failed"],"title":"WebhookEventType"},"Workout-Input":{"properties":{"$schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"$Schema"},"version":{"type":"string","title":"Version","default":"0.4.0"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"sport":{"type":"string","description":"Sport string in OpenSportTaxonomy format (e.g., 'cycling.road+stationary')"},"pool_length":{"anyOf":[{"type":"integer"},{"type":"number"},{"type":"null"}],"title":"Pool Length"},"content":{"items":{"oneOf":[{"$ref":"#/components/schemas/Step-Input"},{"$ref":"#/components/schemas/Repeat-Input"},{"$ref":"#/components/schemas/Section-Input"},{"$ref":"#/components/schemas/Note"}],"discriminator":{"propertyName":"type","mapping":{"note":"#/components/schemas/Note","repeat":"#/components/schemas/Repeat-Input","section":"#/components/schemas/Section-Input","step":"#/components/schemas/Step-Input"}}},"type":"array","title":"Content"}},"type":"object","required":["sport","content"],"title":"Workout"},"Workout-Output":{"properties":{"$schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"$Schema"},"version":{"type":"string","title":"Version","default":"0.4.0"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"sport":{"type":"string","description":"Sport string in OpenSportTaxonomy format (e.g., 'cycling.road+stationary')"},"pool_length":{"anyOf":[{"type":"integer"},{"type":"number"},{"type":"null"}],"title":"Pool Length"},"content":{"items":{"oneOf":[{"$ref":"#/components/schemas/Step-Output"},{"$ref":"#/components/schemas/Repeat-Output"},{"$ref":"#/components/schemas/Section-Output"},{"$ref":"#/components/schemas/Note"}],"discriminator":{"propertyName":"type","mapping":{"note":"#/components/schemas/Note","repeat":"#/components/schemas/Repeat-Output","section":"#/components/schemas/Section-Output","step":"#/components/schemas/Step-Output"}}},"type":"array","title":"Content"}},"type":"object","required":["sport","content"],"title":"Workout"},"WorkoutWarning":{"properties":{"integration":{"type":"string","title":"Integration"},"issues":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Issues"},"adjustments":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Adjustments"}},"type":"object","required":["integration"],"title":"WorkoutWarning","description":"A per-integration compatibility heads-up computed at create time via `check_fanout`.\n\n`issues` are structural incompatibilities the target cannot represent; `adjustments` are\nlossy-but-accepted transforms the target will apply (e.g. nesting flattened, RPE to note,\nzone-model translated). Each entry is the library's `{path, code, message}` shape."},"ZoneValue":{"properties":{"type":{"type":"string","const":"zone","title":"Type","default":"zone"},"quantity":{"$ref":"#/components/schemas/IntensityQuantity"},"zone":{"type":"integer","title":"Zone"},"of":{"type":"integer","title":"Of"}},"type":"object","required":["quantity","zone","of"],"title":"ZoneValue","description":"Zone-based intensity: references the athlete's configured zone on their device."}},"securitySchemes":{"HTTPBearer":{"type":"http","scheme":"bearer"},"HTTPBasic":{"type":"http","scheme":"basic"}}}}