Magic Motion
Movimento de personagem que acerta o alvo. Animação 3D de personagem direcionável para agentes de IA. Prompt mais marcas no chão, caminhos e poses, com exportação FBX/GLB/BVH. Login via OAuth, sem necessidade de chave de API.
Servidor MCP hospedado
npx add-mcp 'https://www.magicmotion.ai/api/mcp'Instala no Claude Code, Codex, Cursor e outros
Documentação
Welcome to MMAI
MMAI turns ideas into usable 3D character motion — for creators in the browser and for agents on the same stack. Describe the performance, direct pose and path when the shot has to land, then preview and export. This guide covers the first motion through full API integration.
AI-Powered Generation
Seconds, Not Hours
Constrained Motion
FBX / GLB / BVH Export
REST API
Custom Characters
Timeline Editor
Overview
MMAI uses a state-of-the-art motion diffusion model to generate full-body 3D animations from a single text prompt. Describe any human movement — from a subtle wave to a complex martial arts combo — and the AI produces a ready-to-use animation file within seconds.
01
Write a prompt
Describe the motion in plain language. Be specific for best results.
02
Add constraints (optional)
Place waypoints, draw a path, or keyframe poses when you need spatial control.
03
Adjust parameters
Set duration (2–10s), guidance scale (3–20), and an optional seed.
04
Download & use
Export as FBX and drop straight into Unreal, Unity, Blender, or Maya.
Your First Motion
Recommended first generation: a directed shot — pose from a photo or the rig, plus a short prompt. Describe-only sketches are cheaper and easier to burn through a trial without seeing the product.
- 1 Open the Dashboard Navigate to magicmotion.ai/dashboard. Constraint tools sit above the timeline. The Pose tool reveals Pose from image.
- 2 Lock a pose Drop a photo, or pose the rig and add a pose key. Optional: draw a path or drop a mark so travel is directed too.
- 3 Describe the action Prompt still drives style. Example: "person walks to the mark, then holds this pose with confidence". Keep the first clip around 3 seconds.
- 4 Generate the shot Any pose, path, or mark directs generation. Directed and describe-only clips both cost 1 credit per second.
- 5 Download your file Export FBX from the panel. From My Motions you can re-download any previous generation, including saved constraints.
Prompt tip: Start with an action verb and subject. "person waving hello with both hands enthusiastically" or "someone jumping with joy". Adding adverbs like "slowly", "quickly", "gracefully" significantly affects the output style.
Constrained Motion
Constrained motion lets you combine a text prompt with spatial control on the 3D stage. Your prompt still drives style and action — constraints tell the system where the character should be and how specific body parts should move at key moments.
You never pick an engine manually. If your scene has any waypoint, path sample, or pose key, generation automatically uses constrained motion. Prompt-only jobs use standard text-to-motion.
Three authoring tools
Tool 1 — Waypoints
Click the studio floor to pin the character root at a specific frame. Use the timeline to scrub and add more stops — great for turns, staging marks, and hold positions.
Waypoints appear as glowing markers on the ground and timeline.
Tool 2 — Root path
Draw a spline on the floor to define how the character travels through the scene. Combine with your prompt — e.g. "walks confidently" along the path you sketched.
Switch back to waypoints anytime; both share the same root track.
Tool 3 — Pose keys
Keyframe full-body poses or individual hands and feet. Pose the character with the on-screen controls, then add a key at the current frame. Ghost previews show saved poses on the timeline.
Full-body keys lock the entire posture; end-effector keys target left/right hand or foot independently.
Quick workflow
- 1 Open the Create tab In the dashboard, make sure you are on Create. The 3D stage loads with constraint tools in the toolbar above the timeline.
- 2 Write your prompt Describe the action as you normally would — constrained motion still needs a clear prompt for style and intent.
- 3 Author constraints Select a tool (waypoint, path, or pose key), click or pose on the stage, and place keys on the timeline. Scrub playback to preview ghost overlays.
- 4 Generate Click Generate. The credit estimate updates automatically when constraints are present. Results preview in the stage like any other motion.
- 5 Save or export Download FBX from the panel or find the generation later in My Motions. Constraint data is stored with the generation for reload.
Start simple: Try a single waypoint mid-clip before building complex paths. Add one hand target if you need a precise grab or reach — you do not need every constraint type on every shot.
Understanding Credits
Credits are consumed at 1 credit per second of animation, including directed clips. A 5-second clip costs 5 credits; a 10-second clip costs 10. The REST API uses this same pool. You do not need a subscription — sign up, add credits (or start a plan for a monthly allotment), and generate a key.
| Plan | Monthly Credits | API + agents |
|---|---|---|
| Starter Magic | 300 | Credits |
| Creator MagicPopular | 1,000 | Credits |
| Pro Magic | 10,000 | Credits |
One-time credit bundles work without a plan. Agents meter the same credits as the studio.
Timeline Editor
Available on Creator Magic and Pro Magic plans, the Timeline Editor lets you sequence and blend multiple motion clips into a single animation.
Multi-clip sequencing
Chain any number of generated clips with configurable transitions.
Blend transitions
Smooth cross-fades between motions prevent jarring cuts.
Real-time preview
Changes apply instantly to the 3D stage — no re-generation required.
Export combined clip
The full sequence exports as a single FBX file ready for your engine.
Exporting Animations
Generated animations are delivered as FBX files. The animation_url in every API response is a signed URL to download the FBX directly.
FBX
Unreal Engine, Unity, Blender, Maya, 3ds Max
Primary output format. Signed URL expires after 1 hour.
GLB
Web (Three.js, Babylon.js), AR/VR, Sketchfab
Available as an additional export from the dashboard.
BVH
Blender, MotionBuilder, iClone, Cascadeur
Raw motion capture format. Available as an additional export from the dashboard.
Custom Characters
Bring Your Own Character (BYOC) is available on Creator Magic and above. Import any humanoid character and MMAI's smart retargeting applies generated animations to your skeleton automatically.
BYOC supports characters from Meshy, Tripo, Blender, Maya, and any tool that outputs a standard humanoid rig in FBX or GLB format. Best results come from characters in a T-pose or A-pose bind pose.
Video Tutorials
Learn by Watching
Step-by-step video guides for every skill level.
Getting Started
5:12
MMAI in 5 Minutes
A rapid tour of the dashboard — prompts, parameters, generation, and your first download.
8:30
Understanding the Dashboard
Deep-dive into every control: the 3D stage, control panel, credit counter, and more.
Timeline Walkthrough
6:45
Timeline Editor Basics
Add clips, set transitions, and preview a blended multi-motion sequence in real time.
11:20
Complex Motion Sequences
Build a 30-second showcase by chaining idle, walk, jump, and land animations.
Character Import
7:55
Importing from Meshy & Tripo
Export a character from Meshy AI or Tripo, import into MMAI, and apply a motion in minutes.
9:10
Blender to MMAI Workflow
Prepare a Blender character for BYOC — correct T-pose, clean armature, and export settings.
API Integration
6:00
API Quick Start in JavaScript
Call the generate-motion endpoint, handle the response, and save the animation URL in Node.js.
8:40
Async Polling Pattern
Use async_mode to kick off long generations and poll job-status until completion.
Connect an agent
Magic Motion MCP
Any agent that speaks MCP can generate, find, and play motions on your Magic Motion account. You give it one URL. It signs you in. A headless agent can send its Magic Motion API key as a bearer token instead.
Any agent
Add a remote MCP server with Streamable HTTP. This is the only address:
https://www.magicmotion.ai/api/mcp
Most clients take that URL in a config file. Use the name magic-motion:
{
"mcpServers": {
"magic-motion": {
"url": "https://www.magicmotion.ai/api/mcp"
}
}
}
If the client has no config file, paste the URL into its remote server or custom connector field.
- 1Save the server and start the connection. Desktop agents such as Claude Code, Codex, VS Code, and Cursor return through http://localhost or http://127.0.0.1 on the port they open. You do not register that address.
- 2A browser opens magicmotion.ai. The agent registers itself. You do not create an OAuth app.
- 3Sign in with the account that should own the motions. New users can create an account on that screen.
- 4Choose Allow access. That grants reading your library and generating new motions.
- 5Go back to the agent and ask “How many Magic Motion credits do I have?” A balance means the link works.
Generation uses the same credit pool as the studio. A clip costs 1 credit per second, including directed motion. Remove the server in the agent to stop new access.
ChatGPT
Install Magic Motion from the plugin directory and connect your account. Before it is listed, add a custom connector in developer mode and paste the server URL.
Cursor
Put the config above in Cursor Settings → MCP, or in ~/.cursor/mcp.json, then choose Connect. The desktop login returns through localhost:8787, so leave that port free. Cloud agents return through cursor.com. You do not register those addresses.
Codex
codex mcp add magic-motion --url https://www.magicmotion.ai/api/mcp
codex mcp login magic-motion
Approve the Magic Motion page when it opens. If it does not, run codex mcp login magic-motion. The published plugin uses this same server.
Claude
claude mcp add --transport http magic-motion https://www.magicmotion.ai/api/mcp
In the Claude app, add a custom connector with the same URL. Hosted Claude returns through claude.ai. Claude Code uses a localhost port.
VS Code
{
"servers": {
"magic-motion": {
"type": "http",
"url": "https://www.magicmotion.ai/api/mcp"
}
}
}
VS Code signs in through https://vscode.dev/redirect and a localhost port. If that port is already in use, it picks another one. You do not register either address.
Vercel Connect
If your agent runs on Vercel, create a connector against the Magic Motion server instead of storing a refresh token in the project:
vercel connect create www.magicmotion.ai --name magic-motion
vercel connect attach oauth/magic-motion
Finish the consent popup. Your app then asks Vercel Connect for a short-lived token when it calls the MCP server. The connector name in the second command is the one create prints. Confirm it before attaching.
Scopes and tokens
| Scope | Allows |
|---|---|
| motion:read | Account, credits, library, and job status |
| motion:write | Start a generation or read a pose from an image, which spends credits |
Sign-in offers both scopes. A token that only has motion:read can still list and play motions. Generating asks you to reconnect and allow write. Access tokens last 1 hour. Refresh tokens last 30 days and keep the scopes from the original approval, so a read-only connection stays read-only until you disconnect and connect again.
What the agent can do
| Tool | Use it for |
|---|---|
| get_account | Plan name, remaining credits, and the auto top-up setting |
| generate_motion | Start a clip from a prompt or from pose constraints. Returns a job id immediately |
| get_job | Poll until the clip is ready and get a fresh FBX link |
| list_motions | Search saved motions by id. Download links come from get_motion |
| get_motion | Open one saved motion by id |
| pose_from_image | Read a person in a photo into pose constraints. Costs 1 credit |
| buy_credits | Stripe Checkout link for a credit pack. Minimum $5 |
| set_auto_topup | Off immediately, or a confirmation link the account holder must open to turn it on |
| validate_constraints | Check a path or pose constraint before generating |
| render_motion | Play a finished clip in ChatGPT |
Ask for a length between 2 and 10 seconds. The agent should poll get_job until the status is COMPLETED, then play or download the file. The full timeline, IK, and custom-character tools stay in the studio.
API Quick Start
Integrate in Minutes
The MMAI REST API lets you generate animations programmatically. No subscription required — an account, credits, and an API key. Agents spend the same credit pool as the studio.
Get Your API Key
- 1Sign up at magicmotion.ai
- 2Go to your Account page → API tab
- 3Generate and copy your API key
Keep your API key secure and never expose it in client-side code. Use environment variables and never commit keys to version control.
Authentication
All API requests require a Bearer token in the Authorization header.
Authorization: Bearer your_api_key_here
You can also send X-API-Key: your_api_key_here. Use base URL https://www.magicmotion.ai so Bearer auth is not dropped on redirects.
Verify your key at any time without using credits:
curl -X GET https://www.magicmotion.ai/api/test-api-key \
-H "Authorization: Bearer your_api_key_here"
First Request
curl -X POST https://www.magicmotion.ai/api/generate-motion \
-H "Authorization: Bearer your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"prompt": "dancing with excitement",
"length": 8,
"guidance_scale": 12
}'
const generateAnimation = async (prompt, options = {}) => {
const response = await fetch('https://www.magicmotion.ai/api/generate-motion', {
method: 'POST',
headers: {
'Authorization': \`Bearer ${process.env.MAGIC_MOTION_API_KEY}\`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
prompt,
length: options.length ?? 5,
guidance_scale: options.guidance_scale ?? 4,
...options,
}),
});
if (!response.ok) {
const error = await response.json();
throw new Error(\`MMAI API Error: ${error.message}\`);
}
return response.json();
};
const result = await generateAnimation('jumping with joy', {
length: 6,
guidance_scale: 10,
});
console.log('Animation URL:', result.animation_url);
console.log('Credits remaining:', result.metadata.credits_remaining);
import requests
import os
def generate_animation(prompt, length=5, guidance_scale=4, seed=None):
headers = {
'Authorization': f'Bearer {os.getenv("MAGIC_MOTION_API_KEY")}',
'Content-Type': 'application/json',
}
data = {'prompt': prompt, 'length': length, 'guidance_scale': guidance_scale}
if seed:
data['seed'] = seed
response = requests.post(
'https://www.magicmotion.ai/api/generate-motion',
headers=headers,
json=data,
)
response.raise_for_status()
return response.json()
result = generate_animation('running in place', length=7, guidance_scale=8)
print(f"Animation URL: {result['animation_url']}")
print(f"Credits remaining: {result['metadata']['credits_remaining']}")
Handling Responses
A successful synchronous response (200 OK):
{
"success": true,
"job_id": "run_abc123def456",
"animation_url": "https://storage.supabase.co/...",
"metadata": {
"prompt": "A Person dancing with excitement",
"original_prompt": "dancing with excitement",
"length": 8,
"guidance_scale": 12,
"seed": "1234567",
"credits_used": 8,
"credits_remaining": 492
}
}
The animation_url is a signed URL that expires after 1 hour. Download the file promptly and store it on your own infrastructure.
Advanced API
Advanced Usage
Scale your integration with constrained motion, async generation, and intelligent polling.
Constrained Motion API
Send a constraints array with your generation request to enable spatial control. You do not need to set engine manually — non-empty constraints automatically route to constrained motion.
| Request | Engine | Credits |
|---|---|---|
| No constraints (or empty array) | Standard text-to-motion | length × 1 |
| Non-empty constraints array | Constrained motion | 1 credit per second |
Constraint object types
| type | Purpose |
|---|---|
root2d | Ground-plane waypoints or paths — smooth_root_2d, frame_indices, optional global_root_heading. |
fullbody | Full-body pose keyframes — local_joints_rot, root_positions, frame_indices. |
end-effector | Hand or foot targets — joint_names, local_joints_rot, frame_indices. |
curl -X POST https://www.magicmotion.ai/api/generate-motion \
-H "Authorization: Bearer your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"prompt": "A person walks forward confidently",
"length": 5,
"async_mode": true,
"constraints": [{
"type": "root2d",
"frame_indices": [0, 60],
"smooth_root_2d": [[0, 0], [1.5, 0]],
"global_root_heading": [[1, 0], [1, 0]]
}]
}'
Async responses include generation_engine and metadata.poll_url. When polling constrained jobs, prefer the returned poll_url — it includes the correct engine routing before generation metadata is written.
Validate constraints (no GPU, no credits)
bash
curl -X POST https://www.magicmotion.ai/api/kimodo/validate-constraints \
-H "Authorization: Bearer your_api_key_here" \
-H "Content-Type: application/json" \
-d '{"constraints":[{"type":"root2d","frame_indices":[0],"smooth_root_2d":[[0,0]]}]}'
Pose from Image
POST /api/pose-from-image estimates one full-body pose from a photo (SAM 3D Body → SMPL-H → Kimodo SOMA77). The call is synchronous: the server polls the pose worker and returns when the pose is ready. Do not send async_mode.
| Detail | Value |
|---|---|
| Credits | 1 per successful pose |
| Auth | API key or signed-in session |
| Client timeout | Allow up to 3 minutes (cold start + inference) |
Pose from a public image URL
bash
curl -X POST https://www.magicmotion.ai/api/pose-from-image \
-H "Authorization: Bearer your_api_key_here" \
-H "Content-Type: application/json" \
-d '{"image_url":"https://example.com/person.jpg","frame":0}'
Pass image_b64 instead of image_url for a raw or data-URL base64 image (body limit 12 MB). Optional person_index picks a person when several are detected (default 0). Optional bboxes is an array of [x1, y1, x2, y2] boxes.
constraints in the response is a Kimodo fullbody array. Pass it straight into POST /api/generate-motion to animate from that pose.pose_key.stageRootFlipX is a Studio display flag — the constraint already includes the upright root correction.
Chain the pose into constrained motion
bash
POSE=$(curl -s -X POST https://www.magicmotion.ai/api/pose-from-image \
-H "Authorization: Bearer your_api_key_here" \
-H "Content-Type: application/json" \
-d '{"image_url":"https://example.com/person.jpg","frame":0}')
curl -X POST https://www.magicmotion.ai/api/generate-motion \
-H "Authorization: Bearer your_api_key_here" \
-H "Content-Type: application/json" \
-d "$(jq -n --argjson c "$(echo "$POSE" | jq '.constraints')" \
'{prompt:"A person holds the pose then walks", length:5, async_mode:true, constraints:$c}')"
Async Mode
By default the API waits for generation to complete before responding. For longer clips or batch pipelines, pass async_mode: true to receive a job_id immediately (202 Accepted) without holding the connection open.
Use async_mode to avoid HTTP timeout errors on longer generations. The maximum generation time is 10 minutes.
# Start generation — returns immediately
curl -X POST https://www.magicmotion.ai/api/generate-motion \
-H "Authorization: Bearer your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"prompt": "dancing with excitement",
"length": 8,
"guidance_scale": 12,
"async_mode": true
}'
# Response (202 Accepted)
# {
# "success": true,
# "job_id": "e8f184eb-c082-43de-8963-2ae33eb6006c-u2",
# "status": "IN_PROGRESS",
# "message": "Generation started. Poll /api/job-status/{job_id} for updates.",
# "metadata": { ..., "estimated_time_seconds": 48 }
# }
Polling for Status
Poll GET /api/job-status/{job_id} until the status is COMPLETED or FAILED.
async function waitForAnimation(jobId, apiKey) {
const POLL_MS = 3000;
const MAX_MS = 10 * 60 * 1000; // 10 minutes
const start = Date.now();
while (Date.now() - start < MAX_MS) {
await new Promise((r) => setTimeout(r, POLL_MS));
const res = await fetch(
\`https://www.magicmotion.ai/api/job-status/${jobId}\`,
{ headers: { Authorization: \`Bearer ${apiKey}\` } }
);
const data = await res.json();
if (data.status === 'COMPLETED') return data.animation_url;
if (data.status === 'FAILED')
throw new Error(\`Generation failed: ${data.message}\`);
// IN_QUEUE or IN_PROGRESS — keep polling
}
throw new Error('Timed out waiting for animation');
}
Rate Limits & Best Practices
| Limit | Value |
|---|---|
| Credit cost | 1 credit per second of animation |
| Max animation length | 10 seconds |
| Max generation time | 10 minutes |
| Credits only | 60 requests/min, 2 generations/min, 1 at a time |
| Starter Magic | 120 requests/min, 4 generations/min, 2 at a time |
| Creator Magic | 300 requests/min, 12 generations/min, 4 at a time |
| Pro Magic | 600 requests/min, 30 generations/min, 10 at a time |
- Use async_mode for all production jobs to avoid holding HTTP connections.
- Poll job status about every 3 seconds. A 429 includes Retry-After and your plan limit.
- Download and cache animation URLs immediately — signed URLs expire after 1 hour.
- Pin the seed parameter when you need reproducible outputs across runs.
- Check credits_remaining in every response to avoid failed generations.
- On a 408 timeout, retry with async_mode: true and poll the returned job_id.
API Reference
API Reference
Full parameter reference for every endpoint. Base URL: https://magicmotion.ai
POST /api/generate-motion
Generate a 3D character animation from a text prompt. Optionally include spatial constraints for waypoints, paths, or pose keys. Returns the completed animation URL (sync) or a job ID to poll (async).
Request body
| Parameter | Type | Description | Default |
|---|---|---|---|
prompt required | string | Text description of the animation, e.g. "dancing", "waving hello". | |
length | integer | Duration in seconds. Range: 2–10. Prompt and constrained jobs cost 1 credit per second. | 5 |
guidance_scale | integer | How closely the model follows the prompt. Range: 3–20. | 4 |
seed | string | Optional seed for reproducible results. Omit for a random result. | |
async_mode | boolean | If true, returns job_id immediately (202 Accepted) without waiting for generation. | false |
constraints | array | Spatial constraint objects (root2d, fullbody, end-effector). Non-empty array enables constrained motion automatically. | |
engine | string | Optional. "kimodo" for constrained motion; "hymotion" for standard. Usually omitted — routing is automatic from constraints. |
Response — sync (200 OK)
{
"success": true,
"job_id": "run_abc123def456",
"generation_id": 1234,
"generation_engine": "hymotion",
"animation_url": "https://storage.supabase.co/...",
"metadata": {
"prompt": "A Person dancing with excitement",
"original_prompt": "dancing with excitement",
"length": 8,
"guidance_scale": 12,
"seed": "1234567",
"credits_used": 8,
"credits_remaining": 492,
"constraints_count": 0
}
}
Response — async (202 Accepted)
{
"success": true,
"job_id": "e8f184eb-c082-43de-8963-2ae33eb6006c-u2",
"generation_id": null,
"generation_engine": "kimodo",
"status": "IN_PROGRESS",
"message": "Generation started. Use the job_id to check status via GET /api/job-status/{job_id}",
"request_id": "abc123",
"metadata": {
"prompt": "A person walks forward confidently",
"original_prompt": "walks forward confidently",
"length": 5,
"guidance_scale": 12,
"seed": "1234567",
"estimated_time_seconds": 48,
"constraints_count": 1,
"poll_url": "/api/job-status/e8f184eb-c082-43de-8963-2ae33eb6006c-u2?engine=kimodo&seed=1234567&length=5&guidance_scale=12&started_at=2026-02-19T10:00:00.000Z"
}
}
POST /api/pose-from-image
Estimate a full-body pose from one image. Synchronous only — the request stays open until the pose worker finishes (up to about 3 minutes). Costs 1 credit on success. Failed calls (no person, worker error, timeout) are not charged. Auth: API key or signed-in session.
Request body
| Parameter | Type | Description | Default |
|---|---|---|---|
image_b64 | string | Raw or data-URL base64 image. Provide this or image_url. Aliases: imageBase64. | |
image_url | string | Publicly reachable image URL. Provide this or image_b64. Aliases: imageUrl. | |
frame | integer | Constraint frame index written onto pose_key and the fullbody constraint. | 0 |
person_index | integer | Which detected person to convert when the image contains several. Aliases: personIndex. | 0 |
bboxes | array | Optional detection boxes as [x1, y1, x2, y2] or an Nx4 array. Alias: bbox. |
Response (200 OK)
{
"success": true,
"pose_key": {
"frame": 0,
"limbIds": [],
"localJointsRot": [[[0, 0, 0]]],
"rootPosition": [0, 0.9, 0],
"stageRootFlipX": true
},
"constraints": [{
"type": "fullbody",
"frame_indices": [0],
"local_joints_rot": [[[0, 0, 0]]],
"root_positions": [[0, 0.9, 0]],
"smooth_root_2d": [[0, 0]]
}],
"smplh": {
"poses": [[[0, 0, 0]]],
"trans": [[0, 0, 0]],
"num_joints": 52,
"layout": "smplh_axis_angle_52"
},
"meta": {
"num_people": 1,
"person_index": 0,
"bbox": [10, 20, 400, 800],
"fit_error": 0.012,
"conversion_method": "pytorch",
"job_id": "sam-job-id"
},
"credits_charged": 1,
"credits_remaining": 449
}
pose_key.localJointsRot is SOMA77 axis-angle for Studio. constraints[0] is the Kimodo fullbody key (root already corrected for Stage Y-up). smplh.poses is the raw worker pack, shape (1, 52, 3).
Errors
| Status | When |
|---|---|
| 400 | Missing image, or async_mode is set |
| 401 | Missing or invalid API key / session |
| 402 | Fewer than 1 credit |
| 422 | No person detected |
| 500 | Pose service not configured |
| 502 | Worker request failed or returned no pose |
| 504 | Pose estimation timed out |
POST /api/kimodo/validate-constraints
Validate constraint JSON schema before submitting a generation job. Does not consume credits or run GPU inference. Accepts API key or signed-in session auth.
| Parameter | Type | Description | |
|---|---|---|---|
constraints required | array | Array of constraint objects to validate. |
{
"success": true,
"valid": true,
"constraints_count": 1
}
GET /api/job-status/{job_id}
Check the status of an async generation job. Poll after calling /generate-motion with async_mode: true. The response keeps job_id as the canonical polling identifier.
| Parameter | Type | Description | Default |
|---|---|---|---|
job_id required | string | The job_id returned by a previous call to /generate-motion with async_mode: true. |
{
"success": true,
"job_id": "e8f184eb-c082-43de-8963-2ae33eb6006c-u2",
"generation_id": null,
"status": "IN_PROGRESS",
"message": "Job is currently being processed",
"request_id": "def456",
"checked_at": "2024-12-30T18:57:14.005Z"
}
{
"success": true,
"job_id": "e8f184eb-c082-43de-8963-2ae33eb6006c-u2",
"generation_id": 1234,
"generation_engine": "kimodo",
"status": "COMPLETED",
"animation_url": "https://storage.supabase.co/...",
"request_id": "def456",
"completed_at": "2024-12-30T18:57:14.005Z"
}
{
"success": false,
"job_id": "e8f184eb-c082-43de-8963-2ae33eb6006c-u2",
"status": "FAILED",
"message": "Motion generation failed. Please try again with different parameters.",
"request_id": "def456",
"failed_at": "2024-12-30T18:57:14.005Z"
}
GET /api/test-api-key
Validate an API key and retrieve account information without consuming credits.
{
"success": true,
"message": "API key is valid",
"account": {
"user_id": "uuid-here",
"plan": "Creator Magic",
"credits_available": 450,
"features": {
"api_access": true,
"priority_support": true,
"advanced_models": true,
"batch_processing": false
},
"subscription_active": true
},
"endpoints": {
"motion_generation": "/api/generate-motion",
"pose_from_image": "/api/pose-from-image",
"job_status": "/api/job-status/{job_id}",
"list_generations": "/api/generations",
"get_generation_by_id": "/api/generations/{id}"
}
}
GET /api/generations
Retrieve a paginated, searchable list of all your previous generations.
Query parameters
| Parameter | Type | Description | Default |
|---|---|---|---|
page | integer | 1-based page number. | 1 |
pageSize | integer | Items per page. Range: 1–100. | 24 |
sort | string | newest · oldest · name_asc · name_desc · length_asc · length_desc | newest |
query | string | Searches generation folder name and prompt text. | |
include_download_urls | boolean | If true, each item includes animation_url when available. | false |
curl -X GET "https://www.magicmotion.ai/api/generations?page=1&pageSize=20&sort=newest&query=dance&include_download_urls=false" \
-H "Authorization: Bearer your_api_key_here"
{
"success": true,
"page": 1,
"pageSize": 20,
"sort": "newest",
"total": 128,
"totalPages": 7,
"include_download_urls": false,
"items": [
{
"id": 1234,
"prompts_id": 4567,
"created_at": "2026-02-19T14:32:55.901Z",
"files_parent_folder": "dance_loop_energy",
"seed": 1234567,
"guidance_scale": 8,
"anim_length": 6,
"generation_engine": "kimodo",
"prompt_texts": ["A Person dancing with high energy"]
}
]
}
GET /api/generations/{id}
Retrieve a single generation by numeric ID, or by Runpod job UUID when mapped.
| Parameter | Type | Description | Default |
|---|---|---|---|
id required | string | Numeric generation id or job UUID when mapping exists. |
curl -X GET https://www.magicmotion.ai/api/generations/1234 \
-H "Authorization: Bearer your_api_key_here"
{
"success": true,
"generation": {
"id": 1234,
"prompts_id": 4567,
"created_at": "2026-02-19T14:32:55.901Z",
"files_parent_folder": "dance_loop_energy",
"seed": 1234567,
"guidance_scale": 8,
"anim_length": 6,
"prompt_texts": ["A Person dancing with high energy"],
"animation_url": "https://storage.supabase.co/...",
"download_available": true
}
}
Error Codes
| Status | Meaning | Resolution |
|---|---|---|
| 400 | Invalid parameters | Check parameter ranges (length 2–10, guidance_scale 3–20). |
| 401 | Invalid or missing API key | Verify your Authorization header. |
| 402 | Insufficient credits | Top up credits or upgrade your plan. |
| 408 | Generation timed out | Retry with async_mode: true and poll the returned job_id. |
| 429 | Plan rate or concurrency limit | Wait for Retry-After. Higher plans allow more requests and simultaneous generations. |
| 500 | Internal server error | Retry the request. Contact support if persistent. |
Ready to build?
Jump into the dashboard to generate your first motion, or grab an API key and start integrating — credits only, no subscription.
MMAI Platform Docs · v1.4 · Updated October 2026