Archived docs Get your API Key
Get started
Tutorials
Guides
Reference
Help for AI agents
🤖 AI Assistant

Create movie

POST https://api.json2video.com/v2/movies

Submits a Movie JSON payload for rendering. The endpoint returns immediately with a project ID. The render runs asynchronously; clients poll GET /v2/movies for completion.

Request

Headers

Header Required Value
x-api-key yes API key issued from the dashboard.
Content-Type yes application/json

Query parameters

None.

Body

A JSON object that follows the Movie JSON syntax. The minimum valid body has a single scenes array; everything else has defaults.

{
    "resolution": "full-hd",
    "scenes": [
        {
            "elements": [
                { "type": "video", "src": "https://example.com/video.mp4" }
            ]
        }
    ]
}

The body may also reference a saved template:

{
    "template": "your-template-id",
    "variables": { "headline": "Hello" }
}

Idempotency

POST /v2/movies is not idempotent. Each call creates a new project, even with the same body. To deduplicate at the asset layer, set cache: true (default) on elements and on the movie — identical assets and identical movies are served from cache without re-rendering.

Response

200 OK

{
    "success": true,
    "project": "JkGxEoPRF9EgRb32",
    "timestamp": "2026-05-12T10:49:52.924Z"
}
Field Type Description
success boolean Always true on 200.
project string 16-character project identifier. Use it to poll status.
timestamp string ISO-8601 timestamp of the submission.

Errors

Status Message Cause
400 No movie JSON received Empty request body.
400 Error parsing movie JSON or the movie was empty Body is not valid JSON.
400 No valid movie JSON received Body parsed to null or non-object.
401 You exceeded the quota of movies in your plan. Please upgrade your plan to continue. Render quota exhausted.
401 Movie is larger ({w}x{h}) than your plan allowance ({w}x{h}) Resolution exceeds account plan.
404 Template not found Body references a template ID that does not exist or belongs to another account.
500 Error creating movie: … Server error. Retry with exponential backoff.
500 Error starting subprocess The render could not be started. Retry with exponential backoff.

Examples

cURL

curl --location --request POST 'https://api.json2video.com/v2/movies' \
  --header 'x-api-key: YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data-raw '{
    "resolution": "full-hd",
    "scenes": [
      {
        "elements": [
          { "type": "text", "text": "Hello", "duration": 5 }
        ]
      }
    ]
  }'

Node.js

const res = await fetch("https://api.json2video.com/v2/movies", {
    method: "POST",
    headers: {
        "x-api-key": process.env.J2V_API_KEY,
        "Content-Type": "application/json"
    },
    body: JSON.stringify({
        resolution: "full-hd",
        scenes: [{ elements: [{ type: "text", text: "Hello", duration: 5 }] }]
    })
});
const { project } = await res.json();

Polling pattern

After submission, poll GET /v2/movies?project={id} every 5–10 seconds until status is done, error, or timeout.

async function waitForRender(projectId) {
    while (true) {
        const r = await fetch(`https://api.json2video.com/v2/movies?project=${projectId}`, {
            headers: { "x-api-key": process.env.J2V_API_KEY }
        });
        const { movie } = await r.json();
        if (["done", "error", "timeout"].includes(movie.status)) return movie;
        await new Promise(r => setTimeout(r, 5000));
    }
}

For production workflows, prefer a webhook destination over polling. See Webhooks.