# Tredict API - Comprehensive LLM System Description ## Overview This document provides a comprehensive description of the Tredict API for Large Language Models (LLMs) to understand and interact with the Tredict OAuth2 system and endpoints. ## Authentication Flow Tredict supports two authentication methods: ### 1. OAuth2 Authorization (for applications) - **Authorization URL**: `https://www.tredict.com/authorization/` - **Token URL**: `https://www.tredict.com/user/oauth/v2/token` - **Supported Flows**: Standard OAuth2 and OAuth2.1 with PKCE - **Use Case**: Applications accessing data for multiple users ### 2. Personal API (for individual users) - **Access**: Generate personal tokens via Tredict web interface (Settings -> Personal API) - **Authentication**: Bearer token in Authorization header - **Use Case**: Individual users accessing their own data ## OAuth2 Authorization ### Required Parameters for Authorization Request - `client_id`: Your client ID (required) - `state`: Optional URL-encoded state for CSRF protection - `redirect_uri`: Optional override for default callback URL - `code_challenge`: Optional for PKCE flow - `code_challenge_method`: Must be "S256" for PKCE ### PKCE (Proof Key for Code Exchange) Flow PKCE is recommended for public clients and provides enhanced security: 1. **Code Verifier Generation**: - Generate a random code verifier (32-96 characters) - Example: `code_verifier = base64url_encode(random_bytes(32))` 2. **Code Challenge Creation**: - Transform code verifier using SHA-256 - Example: `code_challenge = base64url_encode(sha256(code_verifier))` 3. **Authorization Request**: - Include `code_challenge` and `code_challenge_method="S256"` 4. **Token Request**: - Include `code_verifier` when exchanging authorization code for tokens 5. **Refresh Token Rotation**: - Each refresh token request with PKCE invalidates the old refresh token - A new refresh token is returned with each access token refresh ### Token Request Examples **Standard Flow (without PKCE):** ``` POST /user/oauth/v2/token Authorization: Basic base64(client_id:client_secret) Content-Type: application/x-www-form-urlencoded grant_type=authorization_code&code=AUTH_CODE ``` **PKCE Flow:** ``` POST /user/oauth/v2/token Content-Type: application/x-www-form-urlencoded grant_type=authorization_code&code=AUTH_CODE&code_verifier=CODE_VERIFIER&client_id=CLIENT_ID ``` **Refresh Token Flow:** ``` POST /user/oauth/v2/token Authorization: Basic base64(client_id:client_secret) Content-Type: application/x-www-form-urlencoded grant_type=refresh_token&refresh_token=REFRESH_TOKEN ``` **PKCE Refresh Token Flow (with token rotation):** ``` POST /user/oauth/v2/token Content-Type: application/x-www-form-urlencoded grant_type=refresh_token&refresh_token=REFRESH_TOKEN&client_id=CLIENT_ID ``` ### Token Request - **Method**: POST - **Headers**: - `Authorization`: Basic auth with client_id:client_secret (or omit for PKCE) - `Content-Type`: application/x-www-form-urlencoded - `Accept`: application/json;charset=UTF-8 - **Parameters**: - `grant_type`: "authorization_code" or "refresh_token" - `code`: Authorization code (for authorization_code grant) - `refresh_token`: Refresh token (for refresh_token grant) - `code_verifier`: Required for PKCE (only with authorization_code grant) - `client_id`: Required for PKCE (only with authorization_code grant) ### Refresh Token Behavior - **Initial Refresh Token**: Returned when `grant_type` is "authorization_code" - **PKCE Refresh Behavior**: When using PKCE, each refresh token request invalidates the old refresh token and returns a new one - **Non-PKCE Behavior**: Refresh token remains the same across multiple uses - **Security**: PKCE provides enhanced security by rotating refresh tokens ### Token Response - **access_token**: Bearer token (valid for 2 days) - **expires_at**: Token lifetime in seconds (not Unix timestamp) - **refresh_token**: Long-lived token (returned with initial authorization_code grant or PKCE refresh) - `client_id`: Required for PKCE ## Personal API The Tredict Personal API provides an alternative authentication method for individual users to access their own data without requiring full OAuth2 application registration. ### Personal API Overview - **Purpose**: Designed for individual users to access their personal Tredict data - **Authentication**: Uses personal access tokens generated via Tredict web interface - **Endpoints**: Same endpoints as OAuth2 API - **Use Cases**: Personal scripts, custom integrations, personal applications ### Personal API Authentication Personal access tokens are used as bearer tokens: ``` Authorization: Bearer YOUR_PERSONAL_ACCESS_TOKEN ``` ### Personal API vs OAuth2 API | Feature | Personal API | OAuth2 API | |---------|-------------|-----------| | Target Users | Individual users for personal use | Developers building applications for multiple users | | Registration Required | No (generate via settings in the Tredict app) | Yes (apply to Tredict) | | Token Management | Automatic (web interface) | Manual (application flow) | | Multi-User Support | No (personal data only) | Yes (multiple users) | | Scopes | Configurable per personal token | Configurable per application | ### When to Use Personal API - **Personal projects**: Scripts for your own data analysis - **Custom integrations**: Personal workout uploaders or data processors - **Testing**: Quick API testing without full OAuth2 setup - **Single-user tools**: Applications only you will use ### When to Use OAuth2 API - **Multi-user applications**: Apps used by multiple Tredict users - **Production applications**: Publicly available services - **Commercial integrations**: Platforms connecting to Tredict - **Enhanced security**: Applications requiring configurable scopes ## API Endpoints ### Activity Endpoints #### Activity List - **URL**: `GET https://www.tredict.com/api/oauth/v2/activityList` - **Scope**: activityRead - **Parameters**: - `startDate`: Optional start date (ISO format). If omitted, the first list entry will be the newest activity. - `pageSize`: Optional page size (50-1000, default 500) - `extendedSummary`: Optional (set to 1 for extended activity metrics) - **Response**: Paginated list of activities with self and next links - **Extended Summary**: When `extendedSummary=1`, includes additional metrics like pace, speed, heartrate, power, cadence, etc. #### Activity Details - **URL**: `GET https://www.tredict.com/api/oauth/v2/activity/${activityId}` - **Scope**: activityRead - **Response**: Complete activity data including summary, equipment and time series Possible keys in the summary: durationTotal, duration, distance, altitude, positionLat, positionLong, walkingDuration, calories, speed, speedMax, heartrate, heartrateMax, respirationRate, respirationRateMax, power, powerMax, pace, paceMax, cadence, cadenceMax, temperature, strokes, poolLength Possible keys in seriesSampled: positionLat, positionLong, speed, distance, altitude, heartrate, cadence, power, respirationRate, temperature Equipment array contains objects with: id, type (shoes, bikes, swimming, misc), name, usageRange, count, duration, distance #### Activity Update - **URL**: `POST https://www.tredict.com/api/oauth/v2/activity/update/${activityId}` - **Scope**: activityWrite - **Body**: `{ "training": { "title": "...", "notes": "..." } }` #### Activity File Download - **URL**: `GET https://www.tredict.com/api/oauth/v2/activity/file/${activityId}` - **Scope**: activityRead - **Response**: Binary download of the activity as a raw .fit or .tcx file - **Content-Type**: application/octet-stream - **Note**: The filename is included in the content-disposition header. The file extension depends on the original source. #### Activity File Upload - **URL**: `POST https://www.tredict.com/api/oauth/v2/activity/upload` - **Scope**: activityWrite - **Content-Type**: multipart/form-data - **Supported Formats**: .fit, .tcx **Request Form Data Fields:** - `file`: The activity file (required) - `Content-Disposition`: `form-data; name="file"; filename="activity.fit"` - `name`: Optional workout name (e.g., "Morning Run") - `Content-Disposition`: `form-data; name="name"` - `notes`: Optional workout description (max 1024 characters) - `Content-Disposition`: `form-data; name="notes"` **Response Formats:** - **Success (200)**: `{ "success": [{ "date": "ISO_DATE", "trainingId": "ID" }] }` - **Error**: `{ "error": "ERROR_TYPE", "meta": [...] }` - Possible errors: FILE_EXISTS, FILE_EXTENSION_UNSUPPORTED, SPORT_TYPE_UNSUPPORTED ### Planned Training Endpoints #### Planned Training List - **URL**: `GET https://www.tredict.com/api/oauth/v2/plannedTrainingList` - **Scope**: activityRead - **Parameters**: - `startDate`: Optional start date (defaults to "today", max 2 years in the past) - `endDate`: Optional end date - `sportType`: Optional filter (running, cycling, swimming, misc) - **Response fields**: id, date, updatedAt, timezone, sportType, title (optional), notes (optional), distance (optional, meters), duration (optional, seconds), executedTrainingId (optional) #### Planned Training Details - **URL**: `GET https://www.tredict.com/api/oauth/v2/plannedTraining/file/json/${trainingId}` - **Scope**: activityRead - **Parameters**: - `language`: Optional (en, de) - `extraValues`: Optional (1 to include Tredict-specific values like targetProgressionType, extraValueCadence, extraValueHeartrate, extraValueSpeed, extraValuePower) #### Planned Training File Download - **URL**: `GET https://www.tredict.com/api/oauth/v2/plannedTraining/file/fit/${trainingId}` - **Scope**: activityRead - **Parameters**: - `language`: Optional (en, de) - **Response**: Binary download of the planned training as a Garmin workout .fit file - **Content-Type**: application/octet-stream - **Note**: The filename is included in the content-disposition header. This file can be used on the user's device for a planned training session. #### Planned Training Change Date - **URL**: `POST https://www.tredict.com/api/oauth/v2/plannedTraining/changeDate` - **Scope**: activityWrite - **Body**: `{ "trainingId": "...", "date": "ISO-8601 datetime string" }` - **Note**: Reschedules an existing planned training to a new date. The date must be in the future. Only the date/time is changed; all other fields (title, notes, structure) stay intact. ### Health and Body Data Endpoints #### Body Values - **URL**: `GET https://www.tredict.com/api/oauth/v2/bodyvalues` - **Scope**: bodyvaluesRead - **Response**: Array of body value revisions with timestamps - **Fields**: timestamp, timezoneOffsetInSeconds, restingHeartrate, weightInKilograms, bodyHeightInCentimeter, bodyFatInPercent, bodyWaterInPercent, muscleMassInPercent #### Body Values Upload - **URL**: `POST https://www.tredict.com/api/oauth/v2/bodyvalues` - **Scope**: bodyvaluesWrite - **Body**: `{ "bodyvalues": [...] }` - **Mandatory fields**: timestamp, timezoneOffsetInSeconds - **Optional fields**: restingHeartrate, weightInKilograms, bodyHeightInCentimeter, bodyFatInPercent, bodyWaterInPercent, muscleMassInPercent #### Capacity Values - **URL**: `GET https://www.tredict.com/api/oauth/v2/capacity` - **Scope**: bodyvaluesRead - **Parameters**: `sportType` (optional filter) - **Response**: Capacity values per sport type with fields: timestamp, timezoneOffset, hrMax, hrLth, ftp, ftpa #### HRV Data - **URL**: `GET https://www.tredict.com/api/oauth/v2/hrv` - **Scope**: bodyvaluesRead - **Parameters**: `startDate` (optional, defaults to "now"), `endDate` (optional, defaults to "1 year back") - **Response**: Records in a `hrv` object with YYYYMMDD as date key and tuple [RMSSD night, Baseline] as value #### HRV Data Upload - **URL**: `POST https://www.tredict.com/api/oauth/v2/hrv` - **Scope**: bodyvaluesWrite - **Body**: `{ "hrv": [...] }` - **Mandatory fields**: timestamp, timezoneOffsetInSeconds, rmssd (RMSSD value in milliseconds, 1-500) - **Note**: If an entry with the same timestamp already exists, it will be updated. #### Sleep Data - **URL**: `GET https://www.tredict.com/api/oauth/v2/sleep` - **Scope**: bodyvaluesRead - **Parameters**: `startDate` (optional, defaults to "now"), `endDate` (optional, defaults to "1 year back") - **Response**: Records in a `sleep` object with YYYYMMDD as date key and tuple [total sleep in seconds, Baseline] as value #### Sleep Data Upload - **URL**: `POST https://www.tredict.com/api/oauth/v2/sleep` - **Scope**: bodyvaluesWrite - **Body**: `{ "sleep": [...] }` - **Mandatory fields**: startTimestamp, endTimestamp, timezoneOffsetInSeconds, sleepDurationInSeconds (1-86400) - **Note**: sleepDurationInSeconds is the actual time spent sleeping (excluding awake time). If an entry with the same startTimestamp already exists, it will be updated. ### Training Plan Endpoints #### Plan Creation - **URL**: `POST https://www.tredict.com/api/oauth/v2/plan` - **Scope**: activityWrite - **Body Structure**: ```json { "plan": { "title": "string (5-255 chars)", "description": "string (10-10240 chars)", "categories": ["general", "base", "building", "intensity", "race_specific", "race_phase", "recovery", "special"], "targetgroups": ["general", "beginner", "intermediate", "profi"], "zonetypes": ["heartrate", "power", "pace"], "language": "de" or "en" }, "planTrainings": [ { "day": 1-1024, "time": 0-1449, // minutes from midnight "structuredWorkout": { // Either note workout or planned workout } } ] } ``` #### Add Plan Training - **URL**: `POST https://www.tredict.com/api/oauth/v2/plan/training` - **Scope**: activityWrite - **Body**: `{ "planId": "...", "planTraining": { ... } }` - **planTraining structure**: Same as in Plan Creation ### Other Endpoints #### Training Efforts - **URL**: `GET https://www.tredict.com/api/oauth/v2/efforts` - **Scope**: activityRead - **Parameters**: `startDate` (optional, defaults to "now"), `endDate` (optional, defaults to "1 year back from startDate") - **Response**: Records in a `trainingEfforts` object with YYYYMMDD as date key, an array with tuples [single activity effort, optional isRace indicator] #### Zones - **URL**: `GET https://www.tredict.com/api/oauth/v2/zones` - **Scope**: bodyvaluesRead - **Parameters**: `sportType` (optional filter) - **Response**: Zone definitions per sport type (running, cycling, swimming, misc), each with heartrate, pace, power and cadence zones. Zones have name, from, to and intensity fields. Zone timestamps serve as revision keys. #### Equipment List - **URL**: `GET https://www.tredict.com/api/oauth/v2/equipmentList` - **Scope**: activityRead - **Response**: Array of equipment objects - **Equipment types**: bikes, shoes, swimming, misc - **Fields**: id, type, name, usageRange (start, end), weight, notes, previousDistance, trainingIds, count, duration, distance, distanceAvg, distanceMax, paceAvg, paceMax, cadenceAvg, cadenceMax, heartrateAvg, heartrateMax, powerAvg, powerMax, effortAvg - **Note**: Additional fields may be present depending on type (e.g., size, drop for shoes, itemtype for swimming and misc). Aggregated stats are computed from assigned trainings. #### Deregistration - **URL**: `DELETE https://www.tredict.com/user/oauth/v2/token` - **Scope**: Any valid token - **Purpose**: Revoke access token and refresh token ## Data Structures ### Workout Types #### Note Workout ```json { "title": "string", "notes": "string (optional)", "trainingType": "note", "sportType": "misc", "subSportType": "note" or "rest_day" } ``` #### Planned Workout ```json { "title": "string", "notes": "string (optional)", "trainingType": "planned", "sportType": "running", "cycling", "swimming", or "misc", "subSportType": "...", // See sport-specific sub types "poolLength": number, // For swimming only "steps": [...] // Array of workout steps } ``` ### Workout Steps #### Base Step ```json { "note": "string (optional)", "intensityType": "warmup", "active", "recover", "rest", "cooldown", or "misc", "duration": number, // seconds (optional) "distance": number, // meters (optional) "durationType": "time", "distance", or "open", "progressionType": "steady" or "ramp" (default: "steady"), "targetMode": "range" or "padding" (default: "range"), "targetZoneType": "cadence", "heartrate", "pace", or "power", "targets": { ... } // Target zone definitions } ``` #### Repetition Step ```json { "repetitions": number, // 1 or more "steps": [...] // Array of base steps to repeat } ``` ### Target Modes #### Range Target (for targetMode "range") ```json { "ftp": {"from": 0.5, "to": 1.0}, // FTP percentage "ftpa": {"from": 0.5, "to": 1.0}, // FTPa percentage "hrMax": {"from": 0.5, "to": 1.0} // HRMax percentage } ``` #### Padding Target (for targetMode "padding") ```json { "pace": {"value": 300, "padding": 10}, // seconds per km "heartrate": {"value": 140, "padding": 10}, // bpm "power": {"value": 200, "padding": 10}, // watts "cadence": {"value": 90, "padding": 5} // spm or rpm } ``` ## Sport Types and Sub Types ### Running - generic, treadmill, street, trail, orienteering, track, obstacle, running_abc, transition, virtual_activity ### Cycling - generic, virtual_activity, spin, indoor_cycling, road, mountain, gravel_cycling, downhill, bmx, recumbent, hand_cycling, track_cycling, commuting ### Swimming - generic, open_water, lap_swimming, virtual_activity ### Misc - generic, virtual_activity, walking, speed_walking, hiking, strength_training, core_training, pilates, flexibility_training, yoga, cardio_training, jump_rope, elliptical, backcountry, cross_country_skiing, alpine_skiing, snowboarding, mountaineering, rock_climbing, ice_climbing, indoor_rowing, rowing, kayaking, paddling, stand_up_paddleboarding, surfing, windsurfing, kitesurfing, inline_skating, ice_skating, stair_climbing, sailing, golf, horseback_riding, volleyball, basketball, handball, soccer, american_football, tennis, badminton, squash ## Error Handling ### Common Status Codes - 200: Success - 400: Bad request/invalid data - 401: Invalid authorization - 402: Payment required - 403: Forbidden/expired token - 404: Not found - 429: Rate limited - 500: Server error - 503: Service unavailable ### Rate Limits - Activity upload: 8 requests/second - Activity download: 10 requests/second - Token endpoint: 20 requests/second ## Best Practices 1. **Token Management**: Store refresh tokens securely and use them to obtain new access tokens 2. **PKCE**: Use PKCE for public clients (mobile, SPAs) for enhanced security 3. **State Parameter**: Always use state parameter to prevent CSRF attacks 4. **Error Handling**: Implement proper retry logic for rate limits 5. **Data Validation**: Validate all input data before sending to API ## Scopes - `activityWrite`: Upload activity files and create/update plans - `activityRead`: Download the activity list and activity files from Tredict - `bodyvaluesWrite`: Upload health data, capacity values and body values to Tredict - `bodyvaluesRead`: Download health data, capacity values and body values from Tredict ## Localization - Use `https://www.tredict.de/` for German authorization dialog - Use `https://www.tredict.com/` for English authorization dialog - API responses use language specified in user profile or request parameters ## Implementation Notes for LLMs 1. **Authentication First**: Always ensure proper OAuth2 authentication before making API calls 2. **Scope Checking**: Verify required scopes before attempting operations 3. **Data Structure Validation**: Use the documented schemas to validate input/output 4. **Error Recovery**: Implement robust error handling and retry logic 5. **User Context**: Maintain user context and preferences across interactions 6. **Rate Limit Awareness**: Be mindful of rate limits when making multiple requests 7. **Security**: Never expose client secrets or tokens in logs or responses This comprehensive description provides LLMs with all necessary information to understand and interact with the Tredict API effectively.