Workout Analytics API
The Workout Analytics API provides comprehensive performance insights, personal record tracking, and program-aware analytics for user workout data. This system analyzes workout history to deliver meaningful metrics, trends, and comparisons across different time periods and programs.
⚠️ CRITICAL: THIN CLIENT IMPLEMENTATION ONLY
What Flutter SHOULD do:
- ✅ Display analytics dashboards and performance charts
- ✅ Show personal records and strength progression
- ✅ Present program comparisons and timeline visualizations
- ✅ Handle analytics query parameters and filtering
- ✅ Cache analytics data for offline viewing
What Flutter MUST NOT do:
- ❌ Calculate personal records or strength gains
- ❌ Process volume trends or statistical analysis
- ❌ Implement 1RM estimation algorithms
- ❌ Generate program comparison metrics
- ❌ Calculate workout consistency streaks
Core Concepts
Analytics Periods
The system supports various time periods for analysis:
- Fixed Periods:
last_7d,last_30d,last_90d,last_180d,last_360d,all_time - Program-Aware:
current_programanalyzes data from the active program enrollment - Comparison: Each period includes current vs previous period comparison data
Volume Analytics
Volume refers to the total weight lifted (weight × reps × sets) and is a key metric for:
- Trend Analysis: Track volume progression over time
- Program Effectiveness: Compare volume across different programs
- Muscle Group Balance: Analyze volume distribution across muscle groups
- Recovery Assessment: Identify volume spikes and recovery patterns
Personal Records (PRs)
The system tracks multiple types of personal records:
- Estimated 1RM: Calculated using proven strength formulas (Epley, Brzycki, etc.)
- Best Weight for Reps: Maximum weight lifted for specific rep ranges (1-15 reps)
- Max Volume Session: Highest total volume achieved in a single workout for an exercise
Program-Aware Analytics
Advanced analytics that understand program context:
- Program Boundaries: Identifies where one program ends and another begins
- Cross-Program Comparison: Compares performance across different training programs
- Program Effectiveness: Analyzes strength gains and volume progression within programs
- Timeline Analysis: Shows exercise progression with program transition markers
Muscle Group Categorization
Analytics organize muscle groups into broad categories:
- Back: Latissimus Dorsi, Trapezius, Rhomboids, Erector Spinae
- Chest: Pectoralis Major, Serratus Anterior
- Shoulders: All Deltoids, Rotator Cuff muscles
- Arms: Biceps, Triceps, Forearms
- Legs: Quadriceps, Hamstrings, Glutes, Calves
- Core: Abdominals, Obliques
GraphQL Schema
Types
type AnalyticsSummary {
period: String!
current: PeriodAnalytics!
previous: PeriodAnalytics!
}
type PeriodAnalytics {
startDate: DateTime
endDate: DateTime
workoutCount: Int!
suppressedWorkoutCount: Int!
totalDuration: Int!
totalVolume: Float!
totalSets: Int!
muscleDistribution: [MuscleDistributionItem!]!
detailedMuscleSetCounts: [DetailedMuscleSetCountItem!]!
topExercises: [TopExerciseItem!]!
}
type MuscleDistributionItem {
categoryName: String!
setCount: Int!
}
type DetailedMuscleSetCountItem {
muscleGroupId: ID!
muscleName: String!
setCount: Int!
}
type TopExerciseItem {
exerciseId: ID!
exerciseName: String!
workoutCount: Int!
exercise: Exercise!
}
type VolumeTrend {
filter: JSON!
trend: [VolumeTrendDataPoint!]!
}
type VolumeTrendDataPoint {
timeUnitStart: DateTime!
totalVolume: Float!
}
type PersonalRecordsResponse {
exerciseId: ID!
exerciseName: String!
records: JSON!
exercise: Exercise!
}
type ShortSummary {
workoutCount: JSON!
totalVolume: JSON!
consistencyStreakWeeks: Int!
strengthImprovement: JSON
}
type ProgramMetadata {
programUserInstanceId: ID!
programName: String!
startDate: DateTime!
expectedEndDate: DateTime!
actualEndDate: DateTime
status: String!
weekNumber: Int!
durationWeeks: Int!
}
type ProgramComparison {
programUserInstanceId: ID!
programName: String!
startDate: DateTime!
endDate: DateTime
totalWorkouts: Int!
totalVolume: Float!
totalSets: Int!
averageWorkoutsPerWeek: Float!
strengthGains: [ExerciseProgression!]!
muscleDistribution: [MuscleDistributionItem!]!
}
type ExerciseProgression {
exerciseId: ID!
exerciseName: String!
startingBest: PRSourceSet
endingBest: PRSourceSet
percentageGain: Float
exercise: Exercise!
}
type PRSourceSet {
weight: Float!
reps: Int!
setId: ID
}
type CrossProgramTimelineItem {
date: DateTime!
programUserInstanceId: ID!
programName: String!
exerciseId: ID!
exerciseName: String!
bestSetOfDay: PRSourceSet!
volume: Float!
isProgramBoundary: Boolean
exercise: Exercise!
}
enum AnalyticsPeriod {
last_7d
last_30d
last_90d
last_180d
last_360d
all_time
current_program
}
enum Granularity {
daily
weekly
monthly
}
enum BroadCategory {
Back
Chest
Core
Shoulders
Arms
Legs
}
Input Types
input VolumeTrendQueryInput {
period: AnalyticsPeriod!
granularity: Granularity
category: BroadCategory
muscleGroupId: ID
exerciseId: ID
programUserInstanceId: ID
}
input ProgramAnalyticsQueryInput {
programUserInstanceId: ID
includeCurrentOnly: Boolean
comparePrograms: Boolean
}