{"openapi":"3.1.0","info":{"title":"Daptly Exercise API","version":"1.0.0","description":"The Daptly exercise library: 100 curated strength and fitness exercises with original coaching instructions, muscles by role and a consistent infographic per exercise.\n\n**Reading the catalog**\n- `GET /v1/exercises` lists summaries: filter, search (`q`), page, or batch-fetch by `ids` for a workout plan.\n- `GET /v1/exercises/{idOrSlug}` returns the full record.\n- `GET /v1/muscles` and `GET /v1/taxonomy` hold the filter values with counts.\n\n**Caching**: every catalog response carries `catalogVersion`, an `ETag` and `Cache-Control: private, max-age=300`. Send the ETag back as `If-None-Match` and the answer is `304 Not Modified` until the catalog or the deployment changes. Image URLs are content-addressed and immutable; cache the images indefinitely.\n\n**Images** are private and served by this API behind the same sign-in: `image.url` (1200 x 1440 WebP), `image.thumbnailUrl` (480 x 576 WebP) and `image.pngUrl` (the authored PNG) point at `GET /v1/images/{sha256}/{variant}`. Send the bearer token with them.\n\n**Errors** are RFC 9457 problem details (`application/problem+json`) with a stable `code`.\n\n**Content status**: instructions are editorial drafts (`provenance.contentReviewStatus`), images are visually reviewed; neither is a professional coaching certification."},"servers":[{"url":"/","description":"This deployment"}],"security":[{"clerkSession":[]},{"clerkMachine":[]}],"tags":[{"name":"Exercises","description":"The exercise catalog"},{"name":"Reference","description":"Muscles and filter vocabularies"},{"name":"Images","description":"Exercise infographics (private)"},{"name":"Operations","description":"Probes"}],"components":{"securitySchemes":{"clerkSession":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Clerk session token of the signed-in app user (`getToken()` in the Clerk SDK)."},"clerkMachine":{"type":"http","scheme":"bearer","description":"Clerk machine-to-machine token of an internal service (narrowed by ALLOWED_MACHINE_IDS when set)."}},"schemas":{"Problem":{"type":"object","properties":{"type":{"type":"string","example":"urn:daptly:exercise:problem:exercise-not-found"},"title":{"type":"string","example":"Not found"},"status":{"type":"integer","example":404},"code":{"type":"string","description":"Stable machine-readable error code","example":"EXERCISE_NOT_FOUND"},"detail":{"type":"string"},"instance":{"type":"string","example":"/v1/exercises/unknown-exercise"},"requestId":{"type":"string"},"errors":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]},"description":"Field-level issues for VALIDATION_FAILED"}},"required":["type","title","status","code"],"description":"RFC 9457 problem details"},"ExerciseList":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/ExerciseSummary"}},"total":{"type":"integer","description":"Matches before paging","example":100},"limit":{"type":"integer","example":20},"offset":{"type":"integer","example":0},"catalogVersion":{"type":"string","pattern":"^[a-f0-9]{16}$","description":"Content hash of the catalog being served. Changes whenever any exercise or muscle changes; compare it to know whether an offline copy is current.","example":"4c1f0e9a7b2d6c35"}},"required":["items","total","limit","offset","catalogVersion"]},"ExerciseSummary":{"type":"object","properties":{"id":{"type":"string","example":"daptly-ex-001"},"slug":{"type":"string","example":"barbell-bench-press"},"name":{"type":"string","example":"Barbell Bench Press"},"category":{"type":"string","enum":["chest","back","shoulders","arms","lower-body","core","full-body"],"example":"chest"},"equipment":{"type":"array","items":{"type":"string"},"description":"Required equipment ids, including supports and attachments","example":["barbell","weight-plates","flat-bench","rack"]},"primaryMuscles":{"type":"array","items":{"$ref":"#/components/schemas/MuscleRef"}},"difficulty":{"type":"string","enum":["beginner","intermediate","advanced"],"description":"Editorial estimate, not an individual recommendation","example":"intermediate"},"coreTen":{"type":"boolean","description":"One of the ten core movements (priorities 1-10)","example":true},"priority":{"type":"integer","minimum":1,"description":"Editorial order of the library (1 first); not a popularity ranking","example":1},"summary":{"type":"string","example":"Barbell Bench Press is a horizontal push exercise targeting pectoralis major."},"image":{"anyOf":[{"$ref":"#/components/schemas/ExerciseImage"},{"type":"null"}]}},"required":["id","slug","name","category","equipment","primaryMuscles","difficulty","coreTen","priority","summary","image"],"description":"List entry; fetch the full record by id or slug"},"MuscleRef":{"type":"object","properties":{"id":{"type":"string","enum":["pectoralis-major","anterior-deltoids","lateral-deltoids","posterior-deltoids","triceps","biceps","brachialis","brachioradialis","latissimus-dorsi","rhomboids","upper-trapezius","middle-trapezius","lower-trapezius","erector-spinae","quadriceps","gluteus-maximus","gluteus-medius","gluteus-minimus","hamstrings","adductors","gastrocnemius","soleus","rectus-abdominis","obliques","hip-flexors","forearms","forearm-extensors","teres-major","teres-minor","infraspinatus","supraspinatus","rotator-cuff"],"example":"pectoralis-major"},"label":{"type":"string","example":"Pectoralis Major"},"view":{"type":"string","enum":["front","back","deep"],"description":"Anatomy view the muscle is drawn on; `deep` muscles have no surface region in the illustration.","example":"front"}},"required":["id","label","view"],"description":"A muscle from GET /v1/muscles, resolved"},"ExerciseImage":{"type":"object","properties":{"url":{"type":"string","format":"uri","description":"Full-size 1200 x 1440 WebP: use this one. Like every image URL it needs the bearer token.","example":"https://exercise.daptly.ai/v1/images/d30e45c969b07a05c6a5b265e88da7884f19100c37984eaac6f90fe490cc7482/1200.webp"},"thumbnailUrl":{"type":"string","format":"uri","description":"480 x 576 WebP for lists and cards","example":"https://exercise.daptly.ai/v1/images/d30e45c969b07a05c6a5b265e88da7884f19100c37984eaac6f90fe490cc7482/480.webp"},"pngUrl":{"type":"string","format":"uri","description":"The authored 1200 x 1440 PNG (larger; for clients without WebP)","example":"https://exercise.daptly.ai/v1/images/d30e45c969b07a05c6a5b265e88da7884f19100c37984eaac6f90fe490cc7482/infographic.png"},"width":{"type":"integer","example":1200},"height":{"type":"integer","example":1440},"altText":{"type":"string","example":"Two positions of barbell bench press above front and back anatomy views highlighting Pectoralis Major, Anterior Deltoids, Triceps Brachii."},"sha256":{"type":"string","pattern":"^[a-f0-9]{64}$","description":"SHA-256 of the PNG. Image URLs are content-addressed by it and never change content, so the images can be cached indefinitely.","example":"d30e45c969b07a05c6a5b265e88da7884f19100c37984eaac6f90fe490cc7482"}},"required":["url","thumbnailUrl","pngUrl","width","height","altText","sha256"],"description":"Exercise infographic: two movement positions above front and back anatomy views with the worked muscles highlighted. The URLs point at GET /v1/images/{sha256}/{variant} on this API and need the same bearer token."},"Exercise":{"type":"object","properties":{"id":{"type":"string","example":"daptly-ex-001"},"slug":{"type":"string","example":"barbell-bench-press"},"name":{"type":"string","example":"Barbell Bench Press"},"aliases":{"type":"array","items":{"type":"string"},"example":["bench press","flat bench press"]},"language":{"type":"string","example":"en"},"priority":{"type":"integer","minimum":1,"description":"Editorial order of the library (1 first); not a popularity ranking","example":1},"coreTen":{"type":"boolean","description":"One of the ten core movements (priorities 1-10)","example":true},"category":{"type":"string","enum":["chest","back","shoulders","arms","lower-body","core","full-body"],"example":"chest"},"equipment":{"type":"array","items":{"type":"string"},"description":"Required equipment ids, including supports and attachments","example":["barbell","weight-plates","flat-bench","rack"]},"movementPattern":{"type":"string","example":"horizontal-push"},"mechanics":{"type":"string","enum":["compound","isolation","isometric"],"example":"compound"},"difficulty":{"type":"string","enum":["beginner","intermediate","advanced"],"description":"Editorial estimate, not an individual recommendation","example":"intermediate"},"laterality":{"type":"string","enum":["bilateral","unilateral","alternating"],"example":"bilateral"},"summary":{"type":"string","example":"Barbell Bench Press is a horizontal push exercise targeting pectoralis major."},"tracking":{"$ref":"#/components/schemas/ExerciseTracking"},"muscles":{"$ref":"#/components/schemas/ExerciseMuscles"},"instructions":{"$ref":"#/components/schemas/ExerciseInstructions"},"variations":{"$ref":"#/components/schemas/ExerciseVariations"},"illustration":{"$ref":"#/components/schemas/ExerciseIllustration"},"image":{"anyOf":[{"$ref":"#/components/schemas/ExerciseImage"},{"type":"null"}]},"provenance":{"$ref":"#/components/schemas/ExerciseProvenance"},"references":{"type":"array","items":{"$ref":"#/components/schemas/ExerciseReference"}},"catalogVersion":{"type":"string","pattern":"^[a-f0-9]{16}$","description":"Content hash of the catalog being served. Changes whenever any exercise or muscle changes; compare it to know whether an offline copy is current.","example":"4c1f0e9a7b2d6c35"}},"required":["id","slug","name","aliases","language","priority","coreTen","category","equipment","movementPattern","mechanics","difficulty","laterality","summary","tracking","muscles","instructions","variations","illustration","image","provenance","references","catalogVersion"],"description":"The full exercise record"},"ExerciseTracking":{"type":"object","properties":{"metric":{"type":"string","enum":["repetitions","duration","distance"],"example":"repetitions"},"unit":{"type":"string","enum":["reps","seconds","meters"],"example":"reps"},"loadUnit":{"type":["string","null"],"enum":["kg",null],"description":"Unit of external load; null for bodyweight-only exercises","example":"kg"},"repetitionConvention":{"type":"string","description":"What counts as one repetition (or how to log sides)","example":"one complete controlled cycle"}},"required":["metric","unit","loadUnit","repetitionConvention"],"description":"How a set of this exercise is logged"},"ExerciseMuscles":{"type":"object","properties":{"primary":{"type":"array","items":{"$ref":"#/components/schemas/MuscleRef"},"description":"Main intended targets"},"secondary":{"type":"array","items":{"$ref":"#/components/schemas/MuscleRef"},"description":"Additional active contributors"},"stabilizers":{"type":"array","items":{"$ref":"#/components/schemas/MuscleRef"},"description":"Stabilizing contributors"}},"required":["primary","secondary","stabilizers"],"description":"Muscles by role. None of the lists is an exhaustive activation map."},"ExerciseInstructions":{"type":"object","properties":{"setup":{"type":"string"},"steps":{"type":"array","items":{"type":"string"},"description":"Ordered movement steps"},"breathing":{"type":"string"},"cues":{"type":"array","items":{"type":"string"}},"commonMistakes":{"type":"array","items":{"type":"string"}},"safetyNotes":{"type":"array","items":{"type":"string"}}},"required":["setup","steps","breathing","cues","commonMistakes","safetyNotes"]},"ExerciseVariations":{"type":"object","properties":{"regression":{"type":"string","description":"Easier option","example":"Incline Push-Up"},"progression":{"type":"string","description":"Alternative or harder option; may name an exercise outside this library","example":"Dumbbell Bench Press"}},"required":["regression","progression"]},"ExerciseIllustration":{"type":"object","properties":{"positions":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string"},"description":{"type":"string"}},"required":["label","description"]},"description":"The two positions shown in the top panels, left to right","example":[{"label":"START","description":"Lower the bar under control toward the mid chest."},{"label":"PRESS","description":"Press the bar upward until it is above the shoulders."}]},"muscleLabels":{"type":"array","items":{"type":"object","properties":{"muscleId":{"type":"string","enum":["pectoralis-major","anterior-deltoids","lateral-deltoids","posterior-deltoids","triceps","biceps","brachialis","brachioradialis","latissimus-dorsi","rhomboids","upper-trapezius","middle-trapezius","lower-trapezius","erector-spinae","quadriceps","gluteus-maximus","gluteus-medius","gluteus-minimus","hamstrings","adductors","gastrocnemius","soleus","rectus-abdominis","obliques","hip-flexors","forearms","forearm-extensors","teres-major","teres-minor","infraspinatus","supraspinatus","rotator-cuff"]},"text":{"type":"string","description":"Exact label printed on the image"},"view":{"type":"string","enum":["front","back"]},"region":{"type":"string","description":"Highlighted surface region"}},"required":["muscleId","text","view","region"]},"description":"Up to five labelled, highlighted muscles"},"subtitle":{"type":"string","example":"MUSCLES WORKED"}},"required":["positions","muscleLabels","subtitle"],"description":"What the infographic shows"},"ExerciseProvenance":{"type":"object","properties":{"contentAuthor":{"type":"string","example":"Original AI-assisted editorial draft"},"contentReviewStatus":{"type":"string","enum":["draft","reviewed"],"description":"`draft` until a substantive instruction review is recorded","example":"draft"},"exerciseSpecificSourceChecked":{"type":"boolean","description":"Whether an exercise-specific reference was checked (see references)"},"checkedOn":{"type":["string","null"],"format":"date","example":"2026-10-11"},"createdOn":{"type":"string","format":"date","example":"2026-10-11"},"imageGenerator":{"type":"string","example":"built-in image_gen"},"imageGenerationStatus":{"type":"string","enum":["pending","complete","failed"],"example":"complete"},"imageReviewStatus":{"type":"string","enum":["pending","reviewed","needs_revision"],"description":"Visual inspection of the image. `reviewed` is not a certification of coaching accuracy.","example":"reviewed"},"imageStyleVersion":{"type":"string","example":"1.0.0"}},"required":["contentAuthor","contentReviewStatus","exerciseSpecificSourceChecked","checkedOn","createdOn","imageGenerator","imageGenerationStatus","imageReviewStatus","imageStyleVersion"],"description":"Authorship and review state"},"ExerciseReference":{"type":"object","properties":{"id":{"type":"string","example":"nasm-bench"},"title":{"type":"string","example":"NASM: Barbell Bench Press"},"url":{"type":"string","format":"uri","example":"https://www.nasm.org/resource-center/exercise-library/barbell-bench-press"},"scope":{"type":"string","description":"What this source was used to verify","example":"Bench press reference resource."}},"required":["id","title","url","scope"]},"MuscleList":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/Muscle"}},"catalogVersion":{"type":"string","pattern":"^[a-f0-9]{16}$","description":"Content hash of the catalog being served. Changes whenever any exercise or muscle changes; compare it to know whether an offline copy is current.","example":"4c1f0e9a7b2d6c35"}},"required":["items","catalogVersion"]},"Muscle":{"type":"object","properties":{"id":{"type":"string","enum":["pectoralis-major","anterior-deltoids","lateral-deltoids","posterior-deltoids","triceps","biceps","brachialis","brachioradialis","latissimus-dorsi","rhomboids","upper-trapezius","middle-trapezius","lower-trapezius","erector-spinae","quadriceps","gluteus-maximus","gluteus-medius","gluteus-minimus","hamstrings","adductors","gastrocnemius","soleus","rectus-abdominis","obliques","hip-flexors","forearms","forearm-extensors","teres-major","teres-minor","infraspinatus","supraspinatus","rotator-cuff"],"example":"gluteus-maximus"},"label":{"type":"string","example":"Glutes"},"view":{"type":"string","enum":["front","back","deep"],"description":"Anatomy view the muscle is drawn on; `deep` muscles have no surface region in the illustration.","example":"back"},"region":{"type":"string","description":"Region highlighted on the illustration","example":"both buttocks"},"exerciseCount":{"type":"object","properties":{"primary":{"type":"integer","description":"Exercises that target it (what `muscle=<id>` returns)","example":20},"any":{"type":"integer","description":"Exercises that work it in any role (`muscle=<id>&role=any`)","example":33}},"required":["primary","any"],"description":"Matches for the muscle filter of GET /v1/exercises"}},"required":["id","label","view","region","exerciseCount"]},"Taxonomy":{"type":"object","properties":{"categories":{"type":"array","items":{"$ref":"#/components/schemas/FacetValue"},"description":"Values of `category`, in canonical order"},"equipment":{"type":"array","items":{"$ref":"#/components/schemas/FacetValue"},"description":"Values of `equipment`, most used first"},"movementPatterns":{"type":"array","items":{"$ref":"#/components/schemas/FacetValue"},"description":"Values of `movementPattern`, most used first"},"mechanics":{"type":"array","items":{"$ref":"#/components/schemas/FacetValue"},"description":"Values of `mechanics`, in canonical order"},"difficulties":{"type":"array","items":{"$ref":"#/components/schemas/FacetValue"},"description":"Values of `difficulty`, easiest first"},"lateralities":{"type":"array","items":{"$ref":"#/components/schemas/FacetValue"},"description":"Values of `laterality`, in canonical order"},"catalogVersion":{"type":"string","pattern":"^[a-f0-9]{16}$","description":"Content hash of the catalog being served. Changes whenever any exercise or muscle changes; compare it to know whether an offline copy is current.","example":"4c1f0e9a7b2d6c35"}},"required":["categories","equipment","movementPatterns","mechanics","difficulties","lateralities","catalogVersion"],"description":"Every filter value with its exercise count, for filter chips. Closed vocabularies list every value (count may be 0); equipment and movement patterns list the values in use."},"FacetValue":{"type":"object","properties":{"value":{"type":"string","description":"Filter value","example":"lower-body"},"label":{"type":"string","description":"Display label","example":"Lower body"},"count":{"type":"integer","description":"Exercises with this value","example":34}},"required":["value","label","count"]},"Health":{"type":"object","properties":{"status":{"type":"string","example":"ok"}},"required":["status"]},"Readiness":{"type":"object","properties":{"status":{"type":"string","example":"ok"},"checks":{"type":"object","additionalProperties":{"type":"string","enum":["ok","fail"]},"example":{"catalog":"ok"}}},"required":["status","checks"]}},"parameters":{}},"paths":{"/v1/exercises":{"get":{"operationId":"listExercises","tags":["Exercises"],"summary":"List, filter, search and batch-fetch exercises","description":"Without `q` results are in editorial priority order (with `ids`, in the requested order); with `q` they are ranked by relevance. All filters combine with AND; `equipment` matches any of its values.","security":[{"clerkSession":[]},{"clerkMachine":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":100,"example":"bench press"},"required":false,"description":"Search over names, aliases, muscle labels and equipment. Ranked exact name, then exact alias, then name or alias prefix, then words of the name, then words anywhere (words match as prefixes, plurals fold); ties in editorial order.","name":"q","in":"query"},{"schema":{"type":"string","enum":["chest","back","shoulders","arms","lower-body","core","full-body"]},"required":false,"name":"category","in":"query"},{"schema":{"type":"array","items":{"type":"string"},"example":["dumbbells","kettlebell"]},"required":false,"description":"Any of these equipment ids (repeat the parameter or separate with commas). See GET /v1/taxonomy.","style":"form","explode":false,"name":"equipment","in":"query"},{"schema":{"type":"string","enum":["pectoralis-major","anterior-deltoids","lateral-deltoids","posterior-deltoids","triceps","biceps","brachialis","brachioradialis","latissimus-dorsi","rhomboids","upper-trapezius","middle-trapezius","lower-trapezius","erector-spinae","quadriceps","gluteus-maximus","gluteus-medius","gluteus-minimus","hamstrings","adductors","gastrocnemius","soleus","rectus-abdominis","obliques","hip-flexors","forearms","forearm-extensors","teres-major","teres-minor","infraspinatus","supraspinatus","rotator-cuff"],"example":"gluteus-maximus"},"required":false,"description":"Muscle id; see `role`","name":"muscle","in":"query"},{"schema":{"type":"string","enum":["primary","any"],"default":"primary"},"required":false,"description":"With `muscle`: `primary` matches exercises that target it, `any` also those where it is a secondary contributor or stabilizer.","name":"role","in":"query"},{"schema":{"type":"string","maxLength":64,"pattern":"^[a-z0-9]+(?:-[a-z0-9]+)*$","example":"hip-hinge"},"required":false,"name":"movementPattern","in":"query"},{"schema":{"type":"string","enum":["compound","isolation","isometric"]},"required":false,"name":"mechanics","in":"query"},{"schema":{"type":"string","enum":["beginner","intermediate","advanced"]},"required":false,"name":"difficulty","in":"query"},{"schema":{"type":"string","enum":["bilateral","unilateral","alternating"]},"required":false,"name":"laterality","in":"query"},{"schema":{"type":"string","enum":["true","false"]},"required":false,"description":"Only (true) or no (false) core-ten movements","name":"coreTen","in":"query"},{"schema":{"type":"array","items":{"type":"string","pattern":"^daptly-ex-\\d{3}$"},"example":["daptly-ex-001","daptly-ex-002"]},"required":false,"description":"Batch fetch by exercise id (at most 100; repeat or comma-separate). Results keep the requested order, unknown ids are left out, and `limit` defaults to 100.","style":"form","explode":false,"name":"ids","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"example":20},"required":false,"description":"Page size, default 20 (100 with `ids`)","name":"limit","in":"query"},{"schema":{"type":"integer","minimum":0,"maximum":10000,"default":0},"required":false,"name":"offset","in":"query"},{"schema":{"type":"string","description":"ETag of a cached response; answered with 304 while it is current","example":"\"4c1f0e9a7b2d6c35.9a8b7c6d\""},"required":false,"description":"ETag of a cached response; answered with 304 while it is current","name":"If-None-Match","in":"header"}],"responses":{"200":{"description":"One page of exercise summaries","headers":{"ETag":{"schema":{"type":"string","description":"Catalog version plus a deployment fingerprint. Send it back as If-None-Match to get 304 while nothing changed.","example":"\"4c1f0e9a7b2d6c35.9a8b7c6d\""},"required":true,"description":"Catalog version plus a deployment fingerprint. Send it back as If-None-Match to get 304 while nothing changed."},"Cache-Control":{"schema":{"type":"string","example":"private, max-age=300"},"required":true}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExerciseList"}}}},"304":{"description":"Not modified: the If-None-Match ETag is current. No body.","headers":{"ETag":{"schema":{"type":"string","description":"Catalog version plus a deployment fingerprint. Send it back as If-None-Match to get 304 while nothing changed.","example":"\"4c1f0e9a7b2d6c35.9a8b7c6d\""},"required":true,"description":"Catalog version plus a deployment fingerprint. Send it back as If-None-Match to get 304 while nothing changed."},"Cache-Control":{"schema":{"type":"string","example":"private, max-age=300"},"required":true}}},"400":{"description":"Invalid request. `code`: `VALIDATION_FAILED`","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing, invalid or expired token. `code`: `UNAUTHENTICATED`","headers":{"WWW-Authenticate":{"schema":{"type":"string","example":"Bearer"},"required":true}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Machine token from a machine that is not allowed. `code`: `FORBIDDEN`","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Token verification is temporarily unavailable. `code`: `SERVICE_UNAVAILABLE`","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/exercises/{idOrSlug}":{"get":{"operationId":"getExercise","tags":["Exercises"],"summary":"Get the full record of one exercise","description":"Instructions, tracking, variations, muscles by role, illustration labels, image, provenance and references.","security":[{"clerkSession":[]},{"clerkMachine":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":100,"example":"barbell-bench-press"},"required":true,"description":"Exercise id (`daptly-ex-001`) or slug (`barbell-bench-press`)","name":"idOrSlug","in":"path"},{"schema":{"type":"string","description":"ETag of a cached response; answered with 304 while it is current","example":"\"4c1f0e9a7b2d6c35.9a8b7c6d\""},"required":false,"description":"ETag of a cached response; answered with 304 while it is current","name":"If-None-Match","in":"header"}],"responses":{"200":{"description":"The exercise","headers":{"ETag":{"schema":{"type":"string","description":"Catalog version plus a deployment fingerprint. Send it back as If-None-Match to get 304 while nothing changed.","example":"\"4c1f0e9a7b2d6c35.9a8b7c6d\""},"required":true,"description":"Catalog version plus a deployment fingerprint. Send it back as If-None-Match to get 304 while nothing changed."},"Cache-Control":{"schema":{"type":"string","example":"private, max-age=300"},"required":true}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Exercise"}}}},"304":{"description":"Not modified: the If-None-Match ETag is current. No body.","headers":{"ETag":{"schema":{"type":"string","description":"Catalog version plus a deployment fingerprint. Send it back as If-None-Match to get 304 while nothing changed.","example":"\"4c1f0e9a7b2d6c35.9a8b7c6d\""},"required":true,"description":"Catalog version plus a deployment fingerprint. Send it back as If-None-Match to get 304 while nothing changed."},"Cache-Control":{"schema":{"type":"string","example":"private, max-age=300"},"required":true}}},"400":{"description":"Invalid request. `code`: `VALIDATION_FAILED`","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing, invalid or expired token. `code`: `UNAUTHENTICATED`","headers":{"WWW-Authenticate":{"schema":{"type":"string","example":"Bearer"},"required":true}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Machine token from a machine that is not allowed. `code`: `FORBIDDEN`","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"No exercise has this id or slug. `code`: `EXERCISE_NOT_FOUND`","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Token verification is temporarily unavailable. `code`: `SERVICE_UNAVAILABLE`","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/muscles":{"get":{"operationId":"listMuscles","tags":["Reference"],"summary":"Muscles with exercise counts","description":"Every muscle the catalog uses, in anatomical order, with how many exercises work it.","security":[{"clerkSession":[]},{"clerkMachine":[]}],"parameters":[{"schema":{"type":"string","description":"ETag of a cached response; answered with 304 while it is current","example":"\"4c1f0e9a7b2d6c35.9a8b7c6d\""},"required":false,"description":"ETag of a cached response; answered with 304 while it is current","name":"If-None-Match","in":"header"}],"responses":{"200":{"description":"All muscles","headers":{"ETag":{"schema":{"type":"string","description":"Catalog version plus a deployment fingerprint. Send it back as If-None-Match to get 304 while nothing changed.","example":"\"4c1f0e9a7b2d6c35.9a8b7c6d\""},"required":true,"description":"Catalog version plus a deployment fingerprint. Send it back as If-None-Match to get 304 while nothing changed."},"Cache-Control":{"schema":{"type":"string","example":"private, max-age=300"},"required":true}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MuscleList"}}}},"304":{"description":"Not modified: the If-None-Match ETag is current. No body.","headers":{"ETag":{"schema":{"type":"string","description":"Catalog version plus a deployment fingerprint. Send it back as If-None-Match to get 304 while nothing changed.","example":"\"4c1f0e9a7b2d6c35.9a8b7c6d\""},"required":true,"description":"Catalog version plus a deployment fingerprint. Send it back as If-None-Match to get 304 while nothing changed."},"Cache-Control":{"schema":{"type":"string","example":"private, max-age=300"},"required":true}}},"401":{"description":"Missing, invalid or expired token. `code`: `UNAUTHENTICATED`","headers":{"WWW-Authenticate":{"schema":{"type":"string","example":"Bearer"},"required":true}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Machine token from a machine that is not allowed. `code`: `FORBIDDEN`","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Token verification is temporarily unavailable. `code`: `SERVICE_UNAVAILABLE`","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/taxonomy":{"get":{"operationId":"getTaxonomy","tags":["Reference"],"summary":"Filter values with counts","description":"Categories, equipment, movement patterns, mechanics, difficulties and lateralities with exercise counts, for the filter chips of GET /v1/exercises.","security":[{"clerkSession":[]},{"clerkMachine":[]}],"parameters":[{"schema":{"type":"string","description":"ETag of a cached response; answered with 304 while it is current","example":"\"4c1f0e9a7b2d6c35.9a8b7c6d\""},"required":false,"description":"ETag of a cached response; answered with 304 while it is current","name":"If-None-Match","in":"header"}],"responses":{"200":{"description":"All filter values","headers":{"ETag":{"schema":{"type":"string","description":"Catalog version plus a deployment fingerprint. Send it back as If-None-Match to get 304 while nothing changed.","example":"\"4c1f0e9a7b2d6c35.9a8b7c6d\""},"required":true,"description":"Catalog version plus a deployment fingerprint. Send it back as If-None-Match to get 304 while nothing changed."},"Cache-Control":{"schema":{"type":"string","example":"private, max-age=300"},"required":true}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Taxonomy"}}}},"304":{"description":"Not modified: the If-None-Match ETag is current. No body.","headers":{"ETag":{"schema":{"type":"string","description":"Catalog version plus a deployment fingerprint. Send it back as If-None-Match to get 304 while nothing changed.","example":"\"4c1f0e9a7b2d6c35.9a8b7c6d\""},"required":true,"description":"Catalog version plus a deployment fingerprint. Send it back as If-None-Match to get 304 while nothing changed."},"Cache-Control":{"schema":{"type":"string","example":"private, max-age=300"},"required":true}}},"401":{"description":"Missing, invalid or expired token. `code`: `UNAUTHENTICATED`","headers":{"WWW-Authenticate":{"schema":{"type":"string","example":"Bearer"},"required":true}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Machine token from a machine that is not allowed. `code`: `FORBIDDEN`","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Token verification is temporarily unavailable. `code`: `SERVICE_UNAVAILABLE`","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/images/{sha256}/{variant}":{"get":{"operationId":"getExerciseImage","tags":["Images"],"summary":"Download an exercise image","description":"The URLs in `image.url`, `image.thumbnailUrl` and `image.pngUrl` point here. Images are private: send the same bearer token as for the catalog. Only images of the current catalog are served.","security":[{"clerkSession":[]},{"clerkMachine":[]}],"parameters":[{"schema":{"type":"string","pattern":"^[a-f0-9]{64}$","example":"d30e45c969b07a05c6a5b265e88da7884f19100c37984eaac6f90fe490cc7482"},"required":true,"description":"Digest from `image.sha256`","name":"sha256","in":"path"},{"schema":{"type":"string","enum":["1200.webp","480.webp","infographic.png"],"example":"480.webp"},"required":true,"description":"`1200.webp` (1200 x 1440), `480.webp` (480 x 576 thumbnail) or `infographic.png` (the authored PNG)","name":"variant","in":"path"},{"schema":{"type":"string","description":"ETag of a cached response; answered with 304 while it is current","example":"\"4c1f0e9a7b2d6c35.9a8b7c6d\""},"required":false,"description":"ETag of a cached response; answered with 304 while it is current","name":"If-None-Match","in":"header"}],"responses":{"200":{"description":"The image. Its content never changes for a given URL: keep it in the cache for good.","headers":{"ETag":{"schema":{"type":"string","example":"\"d30e45c969b07a05c6a5b265e88da7884f19100c37984eaac6f90fe490cc7482-480.webp\""},"required":true},"Cache-Control":{"schema":{"type":"string","example":"private, max-age=31536000, immutable"},"required":true},"Content-Length":{"schema":{"type":"string","example":"19456"},"required":true}},"content":{"image/webp":{"schema":{"type":"string","format":"binary"}},"image/png":{"schema":{"type":"string","format":"binary"}}}},"304":{"description":"Not modified (answered without touching storage). No body.","headers":{"ETag":{"schema":{"type":"string","example":"\"d30e45c969b07a05c6a5b265e88da7884f19100c37984eaac6f90fe490cc7482-480.webp\""},"required":true},"Cache-Control":{"schema":{"type":"string","example":"private, max-age=31536000, immutable"},"required":true}}},"401":{"description":"Missing, invalid or expired token. `code`: `UNAUTHENTICATED`","headers":{"WWW-Authenticate":{"schema":{"type":"string","example":"Bearer"},"required":true}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Machine token from a machine that is not allowed. `code`: `FORBIDDEN`","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not an image of the current catalog. `code`: `IMAGE_NOT_FOUND`","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"502":{"description":"The catalog names an image that storage does not hold. `code`: `IMAGE_UNAVAILABLE`","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Image storage or token verification is temporarily unavailable. `code`: `STORAGE_UNAVAILABLE`, `SERVICE_UNAVAILABLE`","headers":{"Retry-After":{"schema":{"type":"string"},"required":false}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/healthz":{"get":{"operationId":"liveness","tags":["Operations"],"summary":"Liveness probe","security":[],"responses":{"200":{"description":"Process is alive","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Health"}}}}}}},"/readyz":{"get":{"operationId":"readiness","tags":["Operations"],"summary":"Readiness probe (catalog loaded, not draining)","security":[],"responses":{"200":{"description":"Ready","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Readiness"}}}},"503":{"description":"Not ready","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Readiness"}}}}}}}},"webhooks":{}}