Workout Events
Events for workout lifecycle and statistics.
| Event | Data Fields | Description |
| workout_started | id: string, date: string | Workout session started |
| workout_started (alt) | workoutId: string | Alternative workout start format |
| workout_progress | data: object | Live progress, sent after every completed exercise and on request (see below) |
| workout_completed | data: { workout: string, date: string } | Workout finished, user exits overview |
| workout_ended | id: string, exit_type: string, date: string | Workout session ended (see exit_type values below) |
| workout_overview | data: object | Complete workout summary statistics |
| workout_restart | data: { workout: string, date: string } | User tapped Restart on the results screen. No completion or exit event follows |
| statistic_sheet_opened | - | The motion replay sheet opened on the results screen |
| statistic_subpage_opened | - | The detailed per-exercise breakdown opened on the results screen |
| statistic_subpage_closed | - | The detailed breakdown closed |
Motion tracking off: in workouts, plans, custom workouts and the AI Trainer, users log their sets in the Gym Log when AI motion tracking is off (unless you pass selfModeEnabled: false). It sends the same workout_started, exercise_completed, workout_progress and workout_ended events with the same shapes. See Motion Tracking Settings.
workout_progress Data Structure:
1{
2 completion_percentage: number, // 0-100, same formula as workout_overview
3 completed_reps_count: number,
4 target_reps_count: number,
5 calories_burned: number, // 2 decimal places
6 exercise_index: number, // 1-based, rest periods not counted
7 total_exercises: number, // rest periods not counted
8 workout_id?: string, // omitted when unknown
9 workout_title?: string, // omitted when unknown
10 date: string // "DD MM YYYY HH:MM:SS", device-local
11}To get fresh numbers at any moment (for example, right before your app goes to the background), send { workout_activity_action: "log" }. The SDK replies with a new workout_progress, or with error_occurred (severity: "warning", message: "log: no active workout") when no workout is loaded. A workout counts as loaded from its detail page until the user leaves the results screen.
workout_ended exit_type values:
| Value | Meaning |
| complete | User finished the entire workout including outro (in the Gym Log: every set was logged or skipped) |
| exit | User abandoned the workout mid-session |
| outro | User exited from the outro/cooldown screen after completing all exercises. Not sent by the Gym Log |
workout_overview Data Structure:
1{
2 workout_title: string, // Workout name
3 workout_id: string, // Unique workout ID
4 target_duration_seconds: number, // Target workout duration (seconds)
5 workout_duration_seconds: number, // Total wall-clock session time
6 // (includes rest, transitions, pauses).
7 // For challenges/assessments this equals
8 // total_time_spent (no wall-clock concept)
9 total_time_spent: number, // Active exercise time only (seconds)
10 completed_reps_count: number, // Total completed reps
11 target_reps_count: number, // Total target reps
12 calories_burned: number, // Calories (2 decimal places)
13 completion_percentage: number, // Completion % (2 decimals)
14 total_mistakes: number, // Total mistake count
15 accuracy_score: number, // Overall accuracy (0-100)
16 efficiency_score: number, // Efficiency metric (0-100)
17 total_exercise: number, // Number of exercises
18 actual_hold_time_seconds: number, // Time in correct position
19 target_hold_time_seconds: number // Target hold time
20}Note: Use workout_duration_seconds to display or log the full session time (including rest periods). Use total_time_spent if you only need active exercise time.
1case .workout_overview(let data):
2 if let calories = data["calories_burned"] as? Double,
3 let completion = data["completion_percentage"] as? Double {
4 print("Burned \(calories) cal, \(completion)% complete")
5 }