Magic Motion

Character motion that hits the mark. Directable 3D character animation for AI agents. Prompt plus floor marks, paths, and poses, with FBX/GLB/BVH export. OAuth sign-in, no API key needed.

เซิร์ฟเวอร์ MCP แบบโฮสต์

npx add-mcp 'https://www.magicmotion.ai/api/mcp'

ติดตั้งลง Claude Code, Codex, Cursor และอื่นๆ

เอกสาร

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. 1 Open the Dashboard Navigate to magicmotion.ai/dashboard. Constraint tools sit above the timeline. The Pose tool reveals Pose from image.
  2. 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. 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. 4 Generate the shot Any pose, path, or mark directs generation. Directed and describe-only clips both cost 1 credit per second.
  5. 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. 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. 2 Write your prompt Describe the action as you normally would — constrained motion still needs a clear prompt for style and intent.
  3. 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. 4 Generate Click Generate. The credit estimate updates automatically when constraints are present. Results preview in the stage like any other motion.
  5. 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.

PlanMonthly CreditsAPI + agents
Starter Magic300Credits
Creator MagicPopular1,000Credits
Pro Magic10,000Credits

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.

  1. 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.
  2. 2A browser opens magicmotion.ai. The agent registers itself. You do not create an OAuth app.
  3. 3Sign in with the account that should own the motions. New users can create an account on that screen.
  4. 4Choose Allow access. That grants reading your library and generating new motions.
  5. 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

ScopeAllows
motion:readAccount, credits, library, and job status
motion:writeStart 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

ToolUse it for
get_accountPlan name, remaining credits, and the auto top-up setting
generate_motionStart a clip from a prompt or from pose constraints. Returns a job id immediately
get_jobPoll until the clip is ready and get a fresh FBX link
list_motionsSearch saved motions by id. Download links come from get_motion
get_motionOpen one saved motion by id
pose_from_imageRead a person in a photo into pose constraints. Costs 1 credit
buy_creditsStripe Checkout link for a credit pack. Minimum $5
set_auto_topupOff immediately, or a confirmation link the account holder must open to turn it on
validate_constraintsCheck a path or pose constraint before generating
render_motionPlay 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

  1. 1Sign up at magicmotion.ai
  2. 2Go to your Account page → API tab
  3. 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.

RequestEngineCredits
No constraints (or empty array)Standard text-to-motionlength × 1
Non-empty constraints arrayConstrained motion1 credit per second

Constraint object types

typePurpose
root2dGround-plane waypoints or paths — smooth_root_2d, frame_indices, optional global_root_heading.
fullbodyFull-body pose keyframes — local_joints_rot, root_positions, frame_indices.
end-effectorHand 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.

DetailValue
Credits1 per successful pose
AuthAPI key or signed-in session
Client timeoutAllow 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

LimitValue
Credit cost1 credit per second of animation
Max animation length10 seconds
Max generation time10 minutes
Credits only60 requests/min, 2 generations/min, 1 at a time
Starter Magic120 requests/min, 4 generations/min, 2 at a time
Creator Magic300 requests/min, 12 generations/min, 4 at a time
Pro Magic600 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

ParameterTypeDescriptionDefault
prompt requiredstringText description of the animation, e.g. "dancing", "waving hello".
lengthintegerDuration in seconds. Range: 2–10. Prompt and constrained jobs cost 1 credit per second.5
guidance_scaleintegerHow closely the model follows the prompt. Range: 3–20.4
seedstringOptional seed for reproducible results. Omit for a random result.
async_modebooleanIf true, returns job_id immediately (202 Accepted) without waiting for generation.false
constraintsarraySpatial constraint objects (root2d, fullbody, end-effector). Non-empty array enables constrained motion automatically.
enginestringOptional. "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

ParameterTypeDescriptionDefault
image_b64stringRaw or data-URL base64 image. Provide this or image_url. Aliases: imageBase64.
image_urlstringPublicly reachable image URL. Provide this or image_b64. Aliases: imageUrl.
frameintegerConstraint frame index written onto pose_key and the fullbody constraint.0
person_indexintegerWhich detected person to convert when the image contains several. Aliases: personIndex.0
bboxesarrayOptional 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

StatusWhen
400Missing image, or async_mode is set
401Missing or invalid API key / session
402Fewer than 1 credit
422No person detected
500Pose service not configured
502Worker request failed or returned no pose
504Pose 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.

ParameterTypeDescription
constraints requiredarrayArray 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.

ParameterTypeDescriptionDefault
job_id requiredstringThe 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

ParameterTypeDescriptionDefault
pageinteger1-based page number.1
pageSizeintegerItems per page. Range: 1–100.24
sortstringnewest · oldest · name_asc · name_desc · length_asc · length_descnewest
querystringSearches generation folder name and prompt text.
include_download_urlsbooleanIf 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.

ParameterTypeDescriptionDefault
id requiredstringNumeric 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

StatusMeaningResolution
400Invalid parametersCheck parameter ranges (length 2–10, guidance_scale 3–20).
401Invalid or missing API keyVerify your Authorization header.
402Insufficient creditsTop up credits or upgrade your plan.
408Generation timed outRetry with async_mode: true and poll the returned job_id.
429Plan rate or concurrency limitWait for Retry-After. Higher plans allow more requests and simultaneous generations.
500Internal server errorRetry 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