Skip to content

Guides

Animate

Fifteen presets fitted to any rig for free, custom motions described in words, and motions copied from a reference video.

All animation goes through one endpoint, POST /mascots/{id}/animations, with four body shapes: a preset, a prompt, a reference_upload_id, or a hand-authored clip. Whatever you create is saved on the mascot under its name and travels in the player bundle.

Presets#

15 motions, fitted to each rig without a model call. They answer at once with 201, cost nothing, and work on every character, whatever its shape. Presets are always usable by id (in exports, embeds, canvases) even if you never save them; saving one lets you give it your own intensity, duration and name.

presetDefault lengthMotion
idle4sBreathing, blinking, a little life
wave2sFriendly hello
nod1.2sYes!
shake1.2sNope
bounce1sSpringy squash and stretch
celebrate1.6sArms up, big joy
jump1.4sA big hop
talk2sChatty mouth for assistants
sad3sDroopy and blue
surprised1.6sWhoa!
dance2sGroove on the beat
think3sHmm… pondering
working1.2sBusy, focused hustle
listen2.4sAttentive, leaning in
sleep4sSnoozing
curl -X POST https://lumorig.com/api/v1/mascots/msc_…/animations -H "Authorization: Bearer $LUMORIG_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "preset": "celebrate", "intensity": 1.4, "duration": 2, "name": "big-win" }'
# 201 → { "animation": { "id": "anm_…", "name": "big-win", "source": "preset", "preset": "celebrate", "duration": 2, "loop": true, … } }
NameTypeDescription
presetrequiredstringOne of the ids above. GET /presets lists them without a key.
intensitynumber0.25–2. About 0.5 is subtle, 1 normal, 1.5 big.
durationnumberSeconds, 0.3–20. Defaults to the preset's length.
namestringMax 60 characters. Defaults to the preset's label (e.g. Celebrate).

Motions from words#

Describe anything else and the Animator agent choreographs it for this rig: keyframes with anticipation and overshoot, expression changes, and spring follow-through on dangling parts. It costs 20 credits, runs as a job, and usually finishes in under a minute.

curl -X POST https://lumorig.com/api/v1/mascots/msc_…/animations -H "Authorization: Bearer $LUMORIG_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "prompt": "hops twice, then does a tiny bow", "duration": 2.5, "name": "bow" }'
# 202 → { "job": { "id": "job_…", "type": "animate", "status": "queued", … } }
NameTypeDescription
promptrequiredstringThe motion, 3–1,000 characters. Describe beats and timing, not camera moves.
durationnumberSeconds, 0.3–20. Omit it to let the Animator choose.
namestringMax 60 characters. Defaults to the name the Animator gives the clip.
max_cost_usdnumberStop the job if its model spend passes this.

The finished job's result has animation_id, the animation itself and a one-line summary. While it works, the event stream carries draft_clip events with each draft clip.

Motions from a reference video#

Film someone (or something) doing the motion, upload the clip, and the Animator watches frames sampled from it and performs the same motion on your rig. Same price as a motion from words: 20 credits.

# 1. upload the reference (MP4, MOV or WebM, up to 15 MB)
curl -X POST https://lumorig.com/api/v1/uploads -H "Authorization: Bearer $LUMORIG_API_KEY" -F "file=@./wave.mp4"
# 201 → { "id": "file_…", "kind": "video", "mime": "video/mp4", … }

# 2. perform it
curl -X POST https://lumorig.com/api/v1/mascots/msc_…/animations -H "Authorization: Bearer $LUMORIG_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "reference_upload_id": "file_…", "prompt": "only the right arm; keep the body still" }'
NameTypeDescription
reference_upload_idrequiredstringAn uploaded video (kind: "video"). An image upload returns 400.
promptstringOptional guidance, max 1,000 characters.
durationnumberSeconds, 0.3–12.
namestringMax 60 characters.
max_cost_usdnumberStop the job if its model spend passes this.

Batches and suggestions#

Several motions at once#

POST/mascots/{id}/animations/batch takes up to 8 prompts (and an optional shared duration) and starts one job each. The whole batch is checked against your balance up front (20 credits per prompt), so it either starts completely or returns 402.

curl
curl -X POST https://lumorig.com/api/v1/mascots/msc_…/animations/batch -H "Authorization: Bearer $LUMORIG_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "prompts": ["peeks out from the left", "typing furiously", "shrugs, then smiles"] }'
# 202 → { "object": "list", "data": [{ "id": "job_…", "type": "animate", … }, …] }

Signature-motion ideas#

POST/mascots/{id}/suggestions proposes motions that fit this character and where it will appear. Pass an optional use_case (max 500 characters). Unlike other jobs, this request waits (up to about 90 seconds) and returns the finished job, whose result.suggestions is a list of { name, prompt, moment }. It costs 5 credits. Feed any prompt back into a motion from words.

curl -X POST https://lumorig.com/api/v1/mascots/msc_…/suggestions -H "Authorization: Bearer $LUMORIG_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "use_case": "onboarding guide in a budgeting app" }'

Managing animations#

EndpointDoes
GET/mascots/{id}/animationsList saved animations (without their clips).
GET/mascots/{id}/animations/{animationId}One animation, including its clip.
DELETE/mascots/{id}/animations/{animationId}Remove it from the mascot and future bundles.

Anywhere the API asks for an animation you can pass an animation id, a saved name (the newest wins if two share a name), or a preset id. Names are what the player uses: <lumorig-player animation="bow">.

Hand-authored clips#

Send { "clip": { … }, "name": "…" } to save an AnimationClip you wrote or edited yourself. It is validated against the rig (known parts and states, rotation within joint limits, looping tracks that start and end on the same value) and saved with source: "custom", free and instantly. Problems come back as a 400 with a list in error.details.