Creates a video from a brief and immediately queues the generation
pipeline, so this call is asynchronous: it returns as soon as the job
is enqueued, with process.status: QUEUED. Poll GET /videos/{id} or
subscribe to video.generation_completed.
The brief may be sent flat or nested under brief; the nested form
wins, so a serialized video can be posted straight back. Unknown keys
are ignored, a known key with a malformed value is a 400.
Generation charges credits and counts against the monthly generation
limit, so it can be refused with warning-no-credits,
warning-plan-generations, warning-plan-storage or
warning-plan-duration. Pass process.render: true to chain the
render as soon as generation finishes.
isAutomation is refused here: create a blueprint with
POST /automations instead.
Authorization
bearerAuth An API key created under Settings > API & Webhooks. Keys start with sf_live_.
In: header
Header Parameters
Unique key per action (a UUID works well). Reusing it replays the first response instead of running the action again, so a retry after a timeout can never generate, render, publish or charge twice.
length <= 255Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
application/json
application/json
curl -X POST "https://example.com/videos" \ -H "Content-Type: application/json" \ -d '{ "type": "faceless", "subType": "generic", "prompt": "Why founders burn out and what to do about it", "videoDuration": "short", "aspectRatio": "9:16", "inputMode": "idea", "language": "en", "imageStyle": "mixed", "voiceId": "Enceladus", "voiceProvider": "gemini", "mood": "inspiring", "showSubtitles": true, "process": { "transcribe": true, "addBRolls": true, "render": true } }'{ "data": { "id": "7bQxL2mF9dR4tK1sv", "title": "Why founders burn out", "type": "faceless", "subType": "generic", "isAutomation": false, "parentVideoId": null, "isClip": false, "brief": { "prompt": "Why founders burn out and what to do about it", "text": null, "scriptPrompt": null, "description": null, "descriptionPrompt": null, "inputMode": "idea", "videoDuration": "short", "language": "en", "aspectRatio": "9:16", "imageStyle": "mixed", "customStyleText": null, "voiceId": "Enceladus", "voiceProvider": "gemini", "showSubtitles": true, "presentationTone": null, "presentationAssets": [], "targetDuration": null, "characterImageUrl": null, "characterDescription": null }, "config": {}, "mood": "inspiring", "presentationMood": null, "durationSeconds": null, "media": { "sourceUrl": null, "audioUrl": null, "captionsUrl": null, "thumbnailUrl": null, "renderUrl": null, "bytes": null }, "process": { "status": "QUEUED", "progress": 0, "statusText": null, "queuedAt": "2026-08-06T09:12:44.000Z", "startedAt": null, "error": null }, "render": null, "publish": null, "createdAt": "2026-08-06T09:12:44.000Z", "updatedAt": "2026-08-06T09:12:44.000Z" }}Convert an AI video to an editable one POST
Turns a finished AI video (`type: ai`) into the editable pipeline, so its stitched output becomes a source video with a transcript, caption pages and b-roll segments you can edit through the Editor endpoints. One-way: a video that already runs the editable pipeline is refused with `422`.
Make a clip or variation POST
Creates a new video from this one, pointing back at it through `parentVideoId`. `regenerate: true` rewrites the script and visuals (charging credits) instead of reusing them; `render: true` queues the render as soon as the clip is ready. The editor's pipeline guards (nothing failed, nothing already waiting to publish) are deliberately off here: an integration builds its own flow and is not looking at the publishing pipeline view.