Easymotion API

Make motion graphics videos from your own code. Send a prompt, and Easymotion writes the motion and renders the video.

Last updated: October 8, 2026 · Use Easymotion in Claude and ChatGPT

Overview

The Easymotion API makes motion graphics videos from a prompt. You send a prompt, Easymotion writes the motion, then renders it as a video file. This takes a few minutes, so you start a generation, check on it, and download the video when it is ready.

Everything you make with the API also appears in Easymotion Studio, where you can watch it, change it, and keep working on it.

  • Base URL: https://studio-be.easymotion.io/v1
  • Requests and responses are JSON.
  • Generations use your Easymotion credits, the same as in Studio. Rendering the video costs no extra credits.

Get an API key

The API is part of the paid plans. Anyone can read these docs.

  1. Open Easymotion Studio.
  2. Click your profile picture, then Claude, ChatGPT & API.
  3. Open the API tab and click Create key. Give it a name you will recognise, like the app that will use it.
  4. Copy the key. It is shown only once.

Keep your key secret, like a password: anyone who has it can use your credits. Call the API from your server, never from a website or app that runs in the browser. You can have up to 5 keys. Delete a key in the same place; it stops working within a minute.

Authentication

Send your key in the Authorization header with every request:

http
Authorization: Bearer em_live_…

If your tool can't set that header, send X-API-Key: em_live_… instead. You can also send X-EM-Email with your account email. When you do, a request whose email does not match the key's account is refused.

Quick start

1. Create a generation. It answers in a few seconds with an id.

curl
curl -X POST https://studio-be.easymotion.io/v1/generations \
  -H "Authorization: Bearer $EASYMOTION_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"prompt": "Bar chart of Q3 revenue: EU 40, US 35, APAC 25", "aspect_ratio": "16:9"}'

2. Check it every 10–15 seconds until status is completed. Writing the motion takes 2–4 minutes, then the video renders for 1–3 minutes.

curl
curl https://studio-be.easymotion.io/v1/generations/gen_… \
  -H "Authorization: Bearer $EASYMOTION_API_KEY"

3. Download the video. video.url in the response works for one hour. This link always works with your key:

curl
curl -L -o motion.mp4 https://studio-be.easymotion.io/v1/generations/gen_…/video \
  -H "Authorization: Bearer $EASYMOTION_API_KEY"

The same in JavaScript (Node.js 18 or newer)

javascript
const API = "https://studio-be.easymotion.io/v1";
const headers = {
  Authorization: `Bearer ${process.env.EASYMOTION_API_KEY}`,
  "Content-Type": "application/json",
};

// 1. Start a generation
let generation = await fetch(`${API}/generations`, {
  method: "POST",
  headers,
  body: JSON.stringify({ prompt: "Bar chart of Q3 revenue: EU 40, US 35, APAC 25" }),
}).then((res) => res.json());
if (!generation.id) throw new Error(generation.error.message);

// 2. Check every 15 seconds until it is done
while (["generating", "rendering"].includes(generation.status)) {
  await new Promise((resolve) => setTimeout(resolve, 15000));
  generation = await fetch(`${API}/generations/${generation.id}`, { headers }).then((res) => res.json());
}

// 3. Use the result
if (generation.status === "completed") console.log(generation.video.url);
else console.log(generation.status, generation.question || generation.error);

Statuses

Every generation has one of these statuses:

StatusMeaning
generatingEasymotion is writing the motion. progress shows how far it is.
needs_inputEasymotion asked a question (question). No credits were used. See Change a motion or answer a question.
renderingThe motion is ready and the video file is rendering.
completedThe video is ready in video. With "export": false, the motion is ready in Studio and there is no file.
failedSee error.code and error.message. Credits held for a failed generation are returned.

Create a generation

POST /generations

FieldTypeWhat it does
promptstring, requiredWhat to make, or what to change. Up to 2,000 characters. Put data in attachments, not in the prompt.
session_idstringContinue an earlier motion, or answer its question. Leave it out for a new motion.
aspect_ratio16:9 9:16 1:1 4:5Default 16:9 for new motions. Follow-ups keep the motion's shape unless you set it.
exportobject or falseThe video file to render. Default {"format": "mp4", "fps": 30, "resolution": "fhd"}. Formats mp4 mov gif, fps 30 60, resolution fhd 4k (4K and 60 fps need Plus or Pro). false makes the motion without a video file.
attachmentsarrayUp to 6 files: images, logos, data, PDFs, video references. See Attachments.
metadataobjectUp to 20 of your own text values, for example your order ID. Returned as they are.

Example request

json
{
  "prompt": "Bar chart of Q3 revenue: EU 40, US 35, APAC 25",
  "aspect_ratio": "9:16",
  "export": { "format": "mp4", "fps": 30, "resolution": "fhd" },
  "metadata": { "order_id": "A-1042" }
}

Example response

json
{
  "id": "gen_6f1c2a9b8e7d4c3b2a1f0e9d",
  "object": "generation",
  "status": "generating",
  "session_id": "6702f1c2a9b8e7d4c3b2a1f0",
  "version": null,
  "title": "Q3 revenue by region",
  "prompt": "Bar chart of Q3 revenue: EU 40, US 35, APAC 25",
  "aspect_ratio": "9:16",
  "export": { "format": "mp4", "fps": 30, "resolution": "fhd" },
  "studio_url": "https://studio.easymotion.io/s/6702f1c2a9b8e7d4c3b2a1f0",
  "progress": { "phase": "generating", "percent": 35, "message": "Generating motion...", "estimated_seconds": 180 },
  "metadata": { "order_id": "A-1042" },
  "created_at": "2026-10-08T10:00:00.000Z",
  "updated_at": "2026-10-08T10:00:04.000Z",
  "completed_at": null
}

Attachments

Add up to 6 files to a generation. Each attachment has one of these:

FieldWhat it is
urlA public link to the file.
data_base64The file itself, base64-encoded. Also send filename and content_type. Up to 25 MB.
csvCSV text for a chart or table, up to 200 KB.
svgSVG markup of a logo or icon, up to 512 KB.

Tell Easymotion how to use a file with use_as:

use_asMeaning
style_referenceCopy the look of this image.
image_assetPlace this image in the motion. Add a description, like "our logo, top-left".
logo_svgAnimate this SVG logo.
dataUse this sheet (CSV or XLSX) as chart data.
documentUse this PDF as a brief.
video_referenceCopy the motion style of this clip. Needs duration_seconds (60 or less).

PNG, JPG and WebP images need use_as. For other files it is worked out from the file type. Your plan's file limits are the same as in Studio.

json
{
  "prompt": "Animated sales report in our brand style, our logo top-left",
  "attachments": [
    { "url": "https://example.com/brand-style.png", "use_as": "style_reference" },
    { "url": "https://example.com/logo.png", "use_as": "image_asset", "description": "our logo" },
    { "csv": "month,sales\nJan,120\nFeb,180\nMar,240" }
  ]
}

Change a motion or answer a question

Each generation is one message in a motion's conversation, like a chat message in Studio. To change a motion, create a new generation with its session_id and the change as the prompt. You get a new version and a new video. Earlier versions stay in Studio.

json
{
  "session_id": "6702f1c2a9b8e7d4c3b2a1f0",
  "prompt": "Make the bars blue and the animation slower"
}

When the status is needs_input, Easymotion asked a question instead of making the motion — for example, which years a chart should show. No credits were used. Answer the same way: a new generation with the same session_id and your answer as the prompt.

Get a generation

GET /generations/{id} returns the generation. When status is completed, it has a video:

json
"video": {
  "format": "mp4",
  "fps": 30,
  "resolution": "fhd",
  "url": "https://…",
  "url_expires_at": "2026-10-08T11:05:00.000Z",
  "download_url": "https://studio-be.easymotion.io/v1/generations/gen_6f1c2a9b8e7d4c3b2a1f0e9d/video",
  "file_size_bytes": 4823910,
  "duration_seconds": 12.5
}
FieldMeaning
urlDownload link for the file. Works for one hour (url_expires_at).
download_urlA permanent link. With your key it always redirects to a fresh download link, so you can store it.
deleted_afterMOV files only: when the file is deleted. MP4 and GIF files are kept.

GET /generations/{id}/video is the same as download_url: it redirects to the file. Use curl -L or follow redirects in your HTTP client.

Other endpoints

EndpointWhat it does
GET /generationsYour generations, newest first. limit (up to 100), before, session_id.
GET /accountYour plan, credits left, generations running, and plan limits.

For the next page of a list, pass the created_at of the last item as before. Lists don't include download links; get one generation for those.

Errors

Errors use normal HTTP status codes and this shape:

json
{ "error": { "code": "INSUFFICIENT_CREDITS", "message": "Not enough credits for this motion." } }
StatusCodeWhat to do
400INVALID_REQUEST, INVALID_JSONFix the request. error.details lists each field.
401INVALID_API_KEYCheck the key. It may have been deleted.
402INSUFFICIENT_CREDITSAdd credits or upgrade your plan.
403PAID_PLAN_REQUIRED, PLAN_EXPORT_UPGRADE_REQUIREDYour plan doesn't include this. Upgrade on the pricing page.
404NOT_FOUNDThe generation or session_id is not in your account.
409ALREADY_GENERATING, NOT_READYWait for the motion's current generation, or for the video to finish.
422ATTACHMENT_FAILEDA file could not be used. error.details says why. Nothing was generated.
429TOO_MANY_IN_FLIGHT, RATE_LIMITEDWait and try again. Retry-After says how many seconds.

Limits and retries

  • Up to 3 generations running at once.
  • Up to 30 generations and 1,200 other requests per hour. These limits are shared with Claude and ChatGPT.
  • Prompts up to 2,000 characters, up to 6 attachments, files up to 25 MB.

Safe retries: send an Idempotency-Key header with a unique value, like your order ID. If the same key comes again, you get the first generation back instead of a new one, so a retry after a timeout never charges you twice.

OpenAPI

A machine-readable description of the API is at https://studio-be.easymotion.io/v1/openapi.json. Import it into Postman or Insomnia, or give it to an AI coding assistant.

Prefer chatting? You can also make motions from Claude and ChatGPT.