Browse the docs
Developers / Docs / AI tools
Generate a video clip
Generates a short AI video clip with an AI Studio model: Seedance and Veo from text or images, Clippie Recast and Genjutsu from a source video (referenceVideoUrl or motionTemplateId) plus photos. Spends credits, from tens to hundreds a clip depending on model, length and resolution (list_models has the prices). Run with dryRun: true (or estimate_cost) first and confirm the cost. Returns a job; clips take 1-10 minutes, so use get_job with waitSeconds.
Paste it into any AI assistant. The shortcuts open with the prompt typed in; nothing is sent until you press enter.
At a glance
- REST
POST https://api.clippie.ai/v1/ai/videos
- MCP tool
generate_video
- Scope
create
- Cost
- Spends credits or minutes, at the same prices as the app. Send
"dryRun": true(or call estimate_cost) first to see the exact cost without spending anything.
- Spends credits or minutes, at the same prices as the app. Send
- Limit bucket
ai_video(see Rate limits)
Parameters
model- In:
- body
- Type:
- string
- Required:
- Yes
- Description:
- Video model id from list_models (type video). One of
seedance-2-5,seedance-2-0,seedance-2-0-fast,seedance-2-0-mini,seedance-1-5-pro-251215,seedance-1-0-pro-250528,seedance-1-0-pro-fast-251015,veo-3.1-generate-preview,veo-3.1-fast-generate-preview,veo-3.0-generate-001,veo-3.0-fast-generate-001,clippie-recast,genjutsu-motion-transfer,genjutsu-object-swap,genjutsu-restyle.
prompt- In:
- body
- Type:
- string
- Required:
- No
- Default:
""- Description:
- What happens in the clip. Optional for the source-video models. Up to 5000 chars.
imageUrl- In:
- body
- Type:
- string
- Required:
- No
- Description:
- First frame, or the character photo for Recast and Genjutsu: a file id from POST /v1/files (file_…) or a public https URL (copied into Clippie first, up to 100 MB). 1-2048 chars.
lastFrameUrl- In:
- body
- Type:
- string
- Required:
- No
- Description:
- Last frame (needs imageUrl): a file id from POST /v1/files (file_…) or a public https URL (copied into Clippie first, up to 100 MB). 1-2048 chars.
referenceImages- In:
- body
- Type:
- array of string
- Required:
- No
- Description:
- Reference images (Seedance 2, Veo 3.1), or more people and objects for Recast and Genjutsu. Up to 30 items.
referenceVideos- In:
- body
- Type:
- array of string
- Required:
- No
- Description:
- Seedance 2 reference videos. Up to 10 items.
referenceAudios- In:
- body
- Type:
- array of string
- Required:
- No
- Description:
- Seedance 2 reference audio. Up to 10 items.
referenceVideoUrl- In:
- body
- Type:
- string
- Required:
- No
- Description:
- Source video for Recast and Genjutsu: a file id from POST /v1/files (file_…) or a public https URL (copied into Clippie first, up to 100 MB). 1-2048 chars.
motionTemplateId- In:
- body
- Type:
- string
- Required:
- No
- Description:
- A motion template id from list_motion_templates, used as the source video instead of referenceVideoUrl. 1-120 chars.
duration- In:
- body
- Type:
- integer
- Required:
- No
- Description:
- Seconds, within the model's range (list_models). Source-video models take the source's length. 1-30.
resolution- In:
- body
- Type:
- string
- Required:
- No
- Description:
- Default: 720p when the model has it, else its first. One of
480p,720p,1080p.
aspectRatio- In:
- body
- Type:
- string
- Required:
- No
- Description:
- Default 9:16 when the model has it. One of
auto,21:9,16:9,4:3,1:1,3:4,9:16.
withAudio- In:
- body
- Type:
- boolean
- Required:
- No
- Description:
- Generate sound, for the models that can (Veo always does).
presetId- In:
- body
- Type:
- string (UUID)
- Required:
- No
- Description:
- Genjutsu Restyle look.
seed- In:
- body
- Type:
- integer
- Required:
- No
cameraFixed- In:
- body
- Type:
- boolean
- Required:
- No
- Description:
- Seedance 1.x: keep the camera still.
dryRun- In:
- body
- Type:
- boolean
- Required:
- No
- Description:
- Check the request and return { estimate } (credits and minutes) without spending anything.
webhookUrl- In:
- body
- Type:
- string (URL)
- Required:
- No
- Description:
- https URL that receives job.completed / job.failed, signed with your webhook secret. Up to 2048 chars.
Idempotency-Key- In:
- header
- Type:
- string
- Required:
- No
- Description:
- Retry-safe key: a retry with the same key and body within 24 hours returns the first job instead of starting (and charging) again. The same key with a different body is a 409. MCP clients pass it as the idempotencyKey argument. 1-255 chars. MCP:
idempotencyKey.
Example
# 1. Dry run: the exact cost, nothing is spent.
curl https://api.clippie.ai/v1/ai/videos \
-H "Authorization: Bearer $CLIPPIE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "seedance-2-0-fast",
"prompt": "A slow dolly shot down a neon-lit Tokyo street at night, light rain",
"duration": 5,
"aspectRatio": "9:16",
"dryRun": true
}'
# => { "dryRun": true, "estimate": { "credits": ..., "minutes": { ... }, "wouldSucceed": true } }
# 2. The real call. Keep the key and send the same one if you retry, so it is never charged twice.
KEY=$(uuidgen)
curl https://api.clippie.ai/v1/ai/videos \
-H "Authorization: Bearer $CLIPPIE_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $KEY" \
-d '{
"model": "seedance-2-0-fast",
"prompt": "A slow dolly shot down a neon-lit Tokyo street at night, light rain",
"duration": 5,
"aspectRatio": "9:16"
}'
# => 202 { "job": { "id": "job_...", "status": "queued", ... } }import { randomUUID } from 'node:crypto';
const auth = { Authorization: `Bearer ${process.env.CLIPPIE_API_KEY}` };
const input = {
"model": "seedance-2-0-fast",
"prompt": "A slow dolly shot down a neon-lit Tokyo street at night, light rain",
"duration": 5,
"aspectRatio": "9:16"
};
async function call(body, headers = {}) {
const res = await fetch('https://api.clippie.ai/v1/ai/videos', {
method: 'POST',
headers: { ...auth, 'Content-Type': 'application/json', ...headers },
body: JSON.stringify(body),
});
const json = await res.json();
if (!res.ok) throw new Error(`${json.error.type}: ${json.error.message}`);
return json;
}
// 1. Dry run: the exact cost, nothing is spent. Confirm it before going on.
const { estimate } = await call({ ...input, dryRun: true });
console.log(estimate); // { credits, minutes, wouldSucceed, reason }
// 2. Create. Keep the key and reuse it on retries, so a retry never charges twice.
let { job } = await call(input, { 'Idempotency-Key': randomUUID() });
// 3. Wait. Each call holds for up to 30 seconds until the job changes.
while (!['completed', 'failed', 'canceled'].includes(job.status)) {
const res = await fetch(`https://api.clippie.ai/v1/jobs/${job.id}?wait=30`, { headers: auth });
({ job } = await res.json());
}
console.log(job.status, job.output);Response
202 { job }: the job, straight away. Wait for it with Get job (?wait=30) or a webhookUrl; see Jobs and waiting. With "dryRun": true the answer is 200 { dryRun: true, estimate } and nothing is started.
{
"job": {
"id": "job_abc123",
"object": "job",
"kind": "generate_video",
"status": "queued",
"step": null,
"progress": null,
"input": {
"prompt": "The lost library of Alexandria"
},
"output": null,
"cost": {
"credits": 0,
"minutes": {
"voiceover": 1,
"captions": 1,
"export": 1
}
},
"error": null,
"source": "api",
"webhookUrl": null,
"createdAt": "2026-10-24T12:00:00.000Z",
"startedAt": null,
"completedAt": null
}
}{
"dryRun": true,
"estimate": {
"credits": 0,
"minutes": {
"voiceover": 0,
"captions": 0,
"export": 0
},
"wouldSucceed": true
}
}From an MCP client
Your AI calls generate_video with the same fields as JSON arguments, plus idempotencyKey instead of the header. See MCP server to connect one.
{
"name": "generate_video",
"arguments": {
"model": "seedance-2-0-fast",
"prompt": "A slow dolly shot down a neon-lit Tokyo street at night, light rain",
"duration": 5,
"aspectRatio": "9:16",
"idempotencyKey": "a-unique-key-per-thing-you-make"
}
}