{"openapi":"3.0.3","info":{"title":"YMove Exercise Video API","version":"2.2.0","description":"Access 636+ professional exercise videos with rate limiting, monthly exercise caps, and video access protection. Video URLs are pre-signed and expire after 48 hours. Always fetch fresh exercise data before displaying videos. Use demo key `demo_ymove_2026` for instant access (video URLs hidden). Sign up at https://ymove.app/exercise-api/signup for full access.","contact":{"email":"contact@ymove.app","url":"https://ymove.app/exercise-api"}},"servers":[{"url":"https://exercise-api.ymove.app/api/v2","description":"Production"}],"security":[{"ApiKeyHeader":[]},{"ApiKeyQuery":[]}],"components":{"securitySchemes":{"ApiKeyHeader":{"type":"apiKey","in":"header","name":"X-API-Key"},"ApiKeyQuery":{"type":"apiKey","in":"query","name":"api_key"}},"schemas":{"Video":{"type":"object","required":["tag","isPrimary"],"description":"Video URLs are pre-signed and expire after 48 hours. Do not cache these URLs. Always fetch fresh exercise data before displaying videos.","properties":{"videoUrl":{"type":"string","format":"uri","description":"Pre-signed CDN URL for MP4 video. Expires after 48 hours."},"videoHlsUrl":{"type":"string","format":"uri","description":"Pre-signed CDN URL for HLS playlist. Expires after 48 hours."},"thumbnailUrl":{"type":"string","format":"uri","description":"Pre-signed CDN URL for thumbnail image. Expires after 48 hours."},"tag":{"type":"string","enum":["white-background","gym-shot"]},"orientation":{"type":"string","enum":["landscape","portrait"]},"isPrimary":{"type":"boolean"}}},"Exercise":{"type":"object","required":["id","title","slug","muscleGroup","equipment","hasVideo","hasVideoWhite","hasVideoGym","videos"],"properties":{"id":{"type":"string","format":"uuid"},"title":{"type":"string"},"slug":{"type":"string"},"description":{"type":"string","nullable":true},"instructions":{"type":"array","items":{"type":"string"},"nullable":true},"importantPoints":{"type":"array","items":{"type":"string"},"nullable":true},"muscleGroup":{"type":"string"},"secondaryMuscles":{"type":"array","items":{"type":"string"},"nullable":true},"equipment":{"type":"string"},"category":{"type":"string","nullable":true},"difficulty":{"type":"string","nullable":true},"videoUrl":{"type":"string","format":"uri","nullable":true,"description":"Pre-signed CDN URL for primary video. Expires after 48 hours."},"videoHlsUrl":{"type":"string","format":"uri","nullable":true,"description":"Pre-signed CDN URL for HLS playlist. Expires after 48 hours."},"thumbnailUrl":{"type":"string","format":"uri","nullable":true,"description":"Pre-signed CDN URL for thumbnail. Expires after 48 hours."},"videoDurationSecs":{"type":"integer","nullable":true},"exerciseType":{"type":"array","items":{"type":"string"},"nullable":true},"hasVideo":{"type":"boolean"},"hasVideoWhite":{"type":"boolean"},"hasVideoGym":{"type":"boolean"},"videos":{"type":"array","items":{"$ref":"#/components/schemas/Video"}}},"example":{"id":"a1b2c3d4-e5f6-7890-abcd-ef1234567890","title":"Barbell Bench Press","slug":"barbell-bench-press","description":"A compound chest exercise performed lying on a flat bench.","instructions":["Lie on a flat bench with feet flat on the floor","Grip the barbell slightly wider than shoulder width","Lower the bar to mid-chest","Press the bar back up to full arm extension"],"importantPoints":["Keep your back flat on the bench","Do not bounce the bar off your chest"],"muscleGroup":"chest","secondaryMuscles":["triceps","shoulders"],"equipment":"barbell","category":"compound","difficulty":"intermediate","videoUrl":"https://vz-xxx.b-cdn.net/video-id/play_720p.mp4?token=...","videoHlsUrl":"https://vz-xxx.b-cdn.net/video-id/playlist.m3u8?token=...","thumbnailUrl":"https://vz-xxx.b-cdn.net/video-id/thumbnail.jpg?token=...","videoDurationSecs":12,"exerciseType":["strength"],"hasVideo":true,"hasVideoWhite":true,"hasVideoGym":false,"videos":[{"videoUrl":"https://vz-xxx.b-cdn.net/video-id/play_720p.mp4?token=...","videoHlsUrl":"https://vz-xxx.b-cdn.net/video-id/playlist.m3u8?token=...","thumbnailUrl":"https://vz-xxx.b-cdn.net/video-id/thumbnail.jpg?token=...","tag":"white-background","orientation":"landscape","isPrimary":true}]}},"Pagination":{"type":"object","required":["page","pageSize","total","totalPages"],"properties":{"page":{"type":"integer"},"pageSize":{"type":"integer"},"total":{"type":"integer"},"totalPages":{"type":"integer"}}},"MuscleGroup":{"type":"object","properties":{"slug":{"type":"string"},"name":{"type":"string"},"exerciseCount":{"type":"integer"}}},"WorkoutExercise":{"type":"object","properties":{"exercise":{"$ref":"#/components/schemas/Exercise"},"sets":{"type":"integer"},"reps":{"type":"string"},"restSeconds":{"type":"integer"},"order":{"type":"integer"}}},"Workout":{"type":"object","properties":{"name":{"type":"string"},"muscleGroup":{"type":"string"},"difficulty":{"type":"string"},"estimatedMinutes":{"type":"integer"},"exerciseCount":{"type":"integer"},"exercises":{"type":"array","items":{"$ref":"#/components/schemas/WorkoutExercise"}}}},"ProgramDay":{"type":"object","properties":{"day":{"type":"integer"},"name":{"type":"string"},"muscleGroups":{"type":"array","items":{"type":"string"}},"exercises":{"type":"array","items":{"$ref":"#/components/schemas/WorkoutExercise"}}}},"Program":{"type":"object","properties":{"name":{"type":"string"},"goal":{"type":"string"},"daysPerWeek":{"type":"integer"},"weeks":{"type":"integer"},"split":{"type":"string"},"weeklySchedule":{"type":"array","items":{"$ref":"#/components/schemas/ProgramDay"}},"notes":{"type":"string"}}},"PostureIssue":{"type":"object","properties":{"name":{"type":"string","description":"Issue identifier (e.g. \"forward_head\", \"rounded_shoulders\", \"knee_valgus\")."},"severity":{"type":"string","enum":["mild","moderate","severe"]},"description":{"type":"string","description":"Human-readable description of the issue detected."},"how_to_fix":{"type":"string","description":"Plain-language instructions on how to correct the issue."},"exercises":{"type":"array","description":"Corrective exercises with video URLs.","items":{"$ref":"#/components/schemas/CorrectiveExercise"}}}},"CorrectiveExercise":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"slug":{"type":"string"},"video_url":{"type":"string","format":"uri","nullable":true},"thumbnail_url":{"type":"string","format":"uri","nullable":true},"duration":{"type":"string","description":"Recommended sets/reps (e.g. \"30s hold x 3 sets each side\")."}}},"PostureAnalysisResult":{"type":"object","properties":{"data":{"type":"object","properties":{"score":{"type":"integer","description":"Form score from 0 (poor) to 100 (perfect)."},"issues":{"type":"array","items":{"$ref":"#/components/schemas/PostureIssue"}},"summary":{"type":"string","description":"Overall summary of the analysis."},"frames_analyzed":{"type":"integer","description":"Number of video frames analyzed."},"analysis_type":{"type":"string","enum":["standing","seated","walking","exercise","general"]},"exercise_name":{"type":"string"},"llm_used":{"type":"string"},"disclaimer":{"type":"string"}}},"usage":{"type":"object","properties":{"posture_analyses_used":{"type":"integer"},"posture_analyses_included":{"type":"integer"},"is_overage":{"type":"boolean"},"overage_charge":{"type":"number"}}}}},"Usage":{"type":"object","properties":{"plan":{"type":"string"},"status":{"type":"string","description":"Account status (e.g. \"active\", \"trial\")"},"minutesUsed":{"type":"integer"},"minutesLimit":{"type":"integer"},"minutesRemaining":{"type":"integer"},"percentUsed":{"type":"integer"},"rateLimit":{"type":"integer","description":"Requests per minute allowed for your plan"},"monthlyExercisesUsed":{"type":"integer","description":"Distinct exercises accessed in last 30 days"},"monthlyExerciseLimit":{"oneOf":[{"type":"integer"},{"type":"string","enum":["unlimited"]}],"description":"Max unique exercises per month for your plan. Returns \"unlimited\" for yearly plans."},"postureAnalyses":{"type":"object","properties":{"used":{"type":"integer"},"included":{"type":"integer"},"remaining_free":{"type":"integer"},"overage_count":{"type":"integer"},"overage_charge":{"type":"number"},"price_per_extra":{"type":"number"}}},"whiteVideoAccess":{"type":"boolean"},"premiumVideoAccess":{"type":"boolean"},"trialEndsAt":{"type":"string","format":"date-time","nullable":true,"description":"ISO 8601 timestamp when trial expires (null for non-trial accounts)"}}},"ExerciseType":{"type":"object","properties":{"slug":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"exerciseCount":{"type":"integer"}}},"RateLimitError":{"type":"object","required":["error","retryAfterMs"],"properties":{"error":{"type":"string"},"retryAfterMs":{"type":"integer","description":"Milliseconds until the rate limit resets"},"upgradeUrl":{"type":"string","description":"URL to upgrade your plan"},"availablePlans":{"type":"array","items":{"type":"string"}}}},"MonthlyCapWarning":{"type":"object","description":"Included as `_warning` in the response body when the monthly exercise cap is exceeded. Exercises not previously accessed will have their video properties (videoUrl, videoHlsUrl, thumbnailUrl, videoDurationSecs, videos) removed entirely from the response. Previously accessed exercises keep their video URLs.","properties":{"message":{"type":"string"},"reason":{"type":"string","enum":["monthly_exercise_cap"]},"monthlyExercisesUsed":{"type":"integer"},"monthlyExerciseLimit":{"type":"integer"},"upgradeUrl":{"type":"string"}}},"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"string"},"message":{"type":"string"}}},"Plan":{"type":"object","required":["plan","minutesLimit","postureLimit","brandLimit"],"properties":{"plan":{"type":"string","enum":["basic","pro","scale","enterprise"]},"minutesLimit":{"type":"integer"},"postureLimit":{"type":"integer"},"brandLimit":{"type":"integer"}}}}},"paths":{"/exercises":{"get":{"summary":"List and search exercises","operationId":"listExercises","tags":["Exercises"],"parameters":[{"name":"muscleGroup","in":"query","example":"chest","schema":{"type":"string","enum":["chest","back","shoulders","biceps","triceps","forearms","quads","hamstrings","glutes","calves","core","full_body"]},"description":"Filter by muscle group"},{"name":"exerciseType","in":"query","schema":{"type":"string","enum":["strength","yoga","stretching","cardio","plyometric","calisthenics","warmup","cooldown","balance","mobility","isometric","rehabilitation","functional","core","hiit"]},"description":"Filter by exercise type"},{"name":"equipment","in":"query","schema":{"type":"string","enum":["machine","barbell","dumbbell","kettlebell","bodyweight","cable"]},"description":"Filter by equipment"},{"name":"difficulty","in":"query","schema":{"type":"string","enum":["beginner","intermediate","advanced"]},"description":"Filter by difficulty"},{"name":"hasVideo","in":"query","example":true,"schema":{"type":"boolean"},"description":"Only return exercises with video"},{"name":"hasVideoWhite","in":"query","schema":{"type":"boolean"},"description":"Only exercises with white-background video"},{"name":"hasVideoGym","in":"query","schema":{"type":"boolean"},"description":"Only exercises with gym-shot video"},{"name":"videoTag","in":"query","schema":{"type":"string","enum":["white-background","gym-shot"]},"description":"Filter video array by tag"},{"name":"search","in":"query","schema":{"type":"string"},"description":"Search by exercise title"},{"name":"page","in":"query","example":1,"schema":{"type":"integer","default":1,"minimum":1},"description":"Page number"},{"name":"pageSize","in":"query","example":3,"schema":{"type":"integer","default":20,"minimum":1,"maximum":50},"description":"Results per page"}],"responses":{"200":{"description":"Paginated list of exercises. When the monthly exercise cap is exceeded, exercises not previously accessed will have video properties (videoUrl, videoHlsUrl, thumbnailUrl, videoDurationSecs, videos) removed entirely. A `_warning` object is included with details. Previously accessed exercises keep their video URLs.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Exercise"}},"pagination":{"$ref":"#/components/schemas/Pagination"},"_warning":{"$ref":"#/components/schemas/MonthlyCapWarning"}}}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/exercises/exercise-types":{"get":{"summary":"List all exercise types with counts","operationId":"listExerciseTypes","tags":["Exercises"],"responses":{"200":{"description":"List of exercise types","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ExerciseType"}}}}}}}}}},"/exercises/muscle-groups":{"get":{"summary":"List all muscle groups with exercise counts","operationId":"listMuscleGroups","tags":["Exercises"],"responses":{"200":{"description":"List of muscle groups","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/MuscleGroup"}}}}}}}}}},"/exercises/{id}":{"get":{"summary":"Get a single exercise by ID or slug","operationId":"getExercise","tags":["Exercises"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Exercise UUID or slug"}],"responses":{"200":{"description":"Exercise details. When the monthly exercise cap is exceeded and this exercise was not previously accessed, video properties are removed entirely and a `_warning` is included.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Exercise"},"_warning":{"$ref":"#/components/schemas/MonthlyCapWarning"}}}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Exercise not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/workouts/generate":{"get":{"summary":"Generate a structured workout","operationId":"generateWorkout","tags":["Workouts"],"parameters":[{"name":"muscleGroup","in":"query","required":true,"schema":{"type":"string","enum":["chest","back","shoulders","biceps","triceps","quads","hamstrings","glutes","core"]},"description":"Target muscle group"},{"name":"equipment","in":"query","schema":{"type":"string","enum":["machine","barbell","dumbbell","kettlebell","bodyweight","cable"]},"description":"Limit to specific equipment"},{"name":"difficulty","in":"query","schema":{"type":"string","enum":["beginner","intermediate","advanced"],"default":"intermediate"},"description":"Difficulty level"},{"name":"exerciseCount","in":"query","schema":{"type":"integer","default":6,"minimum":3,"maximum":12},"description":"Number of exercises"}],"responses":{"200":{"description":"Generated workout. When the monthly exercise cap is exceeded, exercises not previously accessed will have video properties removed entirely. A `_warning` object is included with details.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Workout"},"_warning":{"$ref":"#/components/schemas/MonthlyCapWarning"}}}}}},"400":{"description":"Missing required parameter","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/programs/generate":{"get":{"summary":"Generate a multi-week training program","operationId":"generateProgram","tags":["Programs"],"parameters":[{"name":"goal","in":"query","schema":{"type":"string","enum":["muscle_building","weight_loss","strength","endurance"],"default":"muscle_building"},"description":"Training goal"},{"name":"daysPerWeek","in":"query","schema":{"type":"integer","minimum":3,"maximum":6,"default":4},"description":"Training days per week"},{"name":"weeks","in":"query","schema":{"type":"integer","enum":[4,8,12],"default":4},"description":"Program duration in weeks"},{"name":"equipment","in":"query","schema":{"type":"string","enum":["machine","barbell","dumbbell","kettlebell","bodyweight","cable"]},"description":"Limit to specific equipment"}],"responses":{"200":{"description":"Generated training program. When the monthly exercise cap is exceeded, exercises not previously accessed will have video properties removed entirely. A `_warning` object is included with details.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Program"},"_warning":{"$ref":"#/components/schemas/MonthlyCapWarning"}}}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/posture/analyze":{"post":{"summary":"Analyze exercise form from video (max 100MB)","operationId":"analyzePosture","tags":["Form Analysis"],"description":"Upload an exercise video and get AI-powered form analysis. Returns a form score (0-100), detected issues with plain-language fixes, and corrective exercise recommendations.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["video","exercise_name"],"properties":{"video":{"type":"object","required":["type","data"],"description":"The exercise video to analyze.","properties":{"type":{"type":"string","enum":["base64","url"],"description":"How the video is provided: base64-encoded data or a public URL."},"data":{"type":"string","description":"Base64-encoded video data, or a public URL to the video file."},"media_type":{"type":"string","enum":["video/mp4","video/webm","video/mov","video/quicktime"],"default":"video/mp4"}}},"exercise_name":{"type":"string","description":"Name of the exercise being performed (e.g. \"barbell squat\", \"deadlift\").","minLength":1,"maxLength":200},"analysis_type":{"type":"string","enum":["standing","seated","walking","exercise","general"],"default":"exercise","description":"Type of analysis to perform."},"custom_instructions":{"type":"string","maxLength":500,"description":"Optional extra instructions for the analysis (e.g. \"focus on knee alignment\")."},"num_frames":{"type":"integer","minimum":4,"maximum":20,"default":16,"description":"Number of frames to extract from the video for analysis."}}}}}},"responses":{"200":{"description":"Form analysis result with score, issues, and corrective exercises","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostureAnalysisResult"}}}},"400":{"description":"Validation error or analysis failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/usage":{"get":{"summary":"Check API usage and limits (includes monthly exercise cap)","operationId":"getUsage","tags":["Account"],"responses":{"200":{"description":"Current usage data including monthly exercise cap","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Usage"}}}}}}}}},"/upgrade":{"get":{"summary":"Get available plans and billing portal URL","operationId":"getUpgradeInfo","tags":["Account"],"responses":{"200":{"description":"Available plans and current subscription info","content":{"application/json":{"schema":{"type":"object","required":["currentPlan","availablePlans","message"],"properties":{"currentPlan":{"type":"string","description":"Your current plan (e.g. \"demo\", \"basic\", \"pro\")"},"availablePlans":{"type":"array","items":{"$ref":"#/components/schemas/Plan"}},"billingPortalUrl":{"type":"string","format":"uri","description":"Stripe billing portal URL (only for paid keys with a Stripe customer)"},"message":{"type":"string"}}}}}}}},"post":{"summary":"Start or upgrade a subscription","operationId":"upgradeSubscription","tags":["Account"],"description":"Creates a Stripe checkout session for new subscriptions or returns a billing portal URL for existing subscribers to upgrade.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["plan"],"properties":{"plan":{"type":"string","enum":["basic","pro","scale","enterprise"],"description":"The plan to subscribe to"},"email":{"type":"string","format":"email","description":"Required for demo keys. Paid keys use the email on file."}}}}}},"responses":{"200":{"description":"Checkout or billing portal URL","content":{"application/json":{"schema":{"type":"object","required":["url","message"],"properties":{"url":{"type":"string","format":"uri","description":"Stripe checkout or billing portal URL. Open in a browser to complete."},"message":{"type":"string"}}}}}},"400":{"description":"Invalid plan or missing email","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"tags":[{"name":"Exercises","description":"Browse and search exercise videos. Video URLs are pre-signed and expire after 48 hours."},{"name":"Workouts","description":"Generate structured workouts"},{"name":"Programs","description":"Generate multi-week training programs"},{"name":"Form Analysis","description":"AI-powered exercise form analysis from video"},{"name":"Account","description":"Usage and account management"}]}