Integrate in one afternoon
44 exercises, each with a multi-frame demonstration in male and female variants. One exercise image API for the metadata, one URL pattern for the images. New here? Start with what the exercise database API returns.
Quickstart
Three steps to an image on screen.
First, get a key
Free, no card. Either sign up in the portal, or straight from your terminal:
curl -X POST https://api.moveindex.dev/v1/signup \
-H "content-type: application/json" \
-d '{"email":"you@example.com"}' 1. Fetch the catalogue
curl https://api.moveindex.dev/v1/exercises \
-H "Authorization: Bearer $MOVEINDEX_KEY" 2. Read an image URL from the response
{
"slug": "farmer-carry",
"name": "Farmer Carry",
"frame_count": 2,
"images": {
"male": "https://cdn.moveindex.dev/$MOVEINDEX_KEY/exercises/farmer-carry-male.png",
"female": "https://cdn.moveindex.dev/$MOVEINDEX_KEY/exercises/farmer-carry-female.png"
},
"watermarked": false
} 3. Render it
<img src="https://cdn.moveindex.dev/$MOVEINDEX_KEY/exercises/farmer-carry-male.png"
alt="Farmer Carry demonstration" /> You can also build the URL yourself from a slug rather than storing ours — the pattern is stable and documented below.
Authentication
The API takes a bearer token. The image CDN takes the key in the path, because an
<img> tag cannot send headers.
# API
curl https://api.moveindex.dev/v1/exercises -H "Authorization: Bearer xdb_…"
# Images
https://cdn.moveindex.dev/xdb_…/exercises/farmer-carry-male.png Your CDN key is not a secret
It ships in your web bundle and inside your app binary, so treat it as a public identifier rather than a credential. It is read-only and cannot change anything, and you can restrict it to your own domains in the portal so a copied key is useless elsewhere. Rotating is instant, but if your framework inlines public variables at build time — Next, Vite, Expo all do — the key is compiled into your bundle, so a rotation needs a rebuild and deploy rather than a config change. If you would rather it never reach the client, proxy image requests through your own server.
Images
Two canvases, two variants, one URL pattern.
https://cdn.moveindex.dev/{key}/exercises/{slug}-{male|female}.png
Each image is a single tall picture containing the phases of the movement stacked
vertically. frame_count tells you how many.
| frame_count | Canvas | Typical |
|---|---|---|
| 3 | 768 × 1376 | most exercises |
| 2 | 896 × 1200 | holds and carries |
Images are dark-gym photographs, which sit well on dark interfaces and poorly on light ones. They are scenes, not cutouts, so they cannot be composited onto another background. Check one against your design before you commit.
Endpoints
/v1/exercises Search and filter the catalogue.
params: muscle, equipment, category, q, limit, offset
/v1/exercises/:slug One exercise. Aliases resolve to their canonical entry.
/v1/meta Every filter value with live counts.
/v1/usage What this key has requested.
/health Unauthenticated liveness check.
curl https://api.moveindex.dev/v1/exercises \
-H "Authorization: Bearer $MOVEINDEX_KEY" \
-G -d muscle=quads -d equipment=barbell -d limit=20 Filter values
Live counts from the catalogue. Nothing to guess.
muscle
- core (9)
- quads (9)
- back (7)
- glutes (5)
- hamstrings (4)
- chest (3)
- full_body (3)
- shoulders (2)
- forearms (1)
- calves (1)
equipment
- bodyweight (13)
- dumbbell (10)
- barbell (8)
- sled (3)
- cable (2)
- sandbag (2)
- pull_up_bar (2)
- kettlebell (1)
- medicine_ball (1)
- band (1)
- machine (1)
category
- strength (30)
- core (7)
- hyrox (6)
- mobility (1)
Errors
Every failure returns JSON with a stable error code.
missing_key No Authorization header, or it does not start with xdb_. invalid_key The key is unknown or has been revoked. inactive_key Billing has lapsed. The key exists but is not active. upgrade_required This key cannot fetch originals. Subscribe. trial_expired The trial ran out. Subscribe to carry on. origin_not_allowed The key is restricted to domains this request did not come from. not_found No such exercise. We log these — they become the generation queue.
Image responses also carry an x-moveindex-error
header, so a lapsed key is distinguishable from a missing file rather than looking like
a broken image.
Trial
Seven days, everything, no card.
A trial key gets what a paid key gets: clean, full-resolution images, the full catalogue and every field. After seven days its images stop until you subscribe.
Licence
Every image is generated by us. There is no stock-photo chain, no model releases to chase and no unclear attribution — which is why we can license them cleanly for commercial use in your app.
Full terms are being drafted. Ask if you need them before then.