Videos
A video moves through four stages: create (credits charged), generate (poll status), render (free, produces the MP4) and publish (free). This guide walks the whole lifecycle; publishing and scheduling covers the last stage in depth.
Models and cost
Pick the model in POST /videos. Credits are charged at creation, not at render:
| Model | Credits | What you get |
|---|---|---|
storyboard | 20 | Static AI scenes with motion effects |
motion_lite | 50 | Animated transitions between scenes |
motion_pro | 100 | Cinematic AI motion video |
GET /options?kind=models returns the same catalog with costs, so an agent can decide programmatically.
1. Create (POST /videos, scope videos:write)
Send a finished narration script and a voice id (from GET /voices). Optional fields: style, language, name, enableBackgroundMusic, masterStyle, globalNegativePrompt.
curl -s -X POST https://faceless.so/api/v1/videos \
-H "Authorization: Bearer $FACELESS_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"script": "Did you know the ocean has lakes and rivers of its own? ...", "voiceId": "EXAVITQu4vr4xnSDxMaL", "model": "storyboard"}'
Response (201):
{
"success": true,
"data": {
"id": "665f1b2a9c31a2b3c4d5e801",
"name": "Did you kn...",
"model": "storyboard",
"status": "processing",
"creditsUsed": 20,
"statusUrl": "/api/v1/videos/665f1b2a9c31a2b3c4d5e801/status"
}
}
Common errors: 402 insufficient_credits (top up before retrying), 403 usage_limit_reached (plan project limit, upgrade to create more), 429 rate_limited (10 creations per 60s per key; wait for Retry-After).
2. Poll generation (GET /videos/{id}/status, scope videos:read)
Generation is asynchronous and typically takes a few minutes. Poll every 10 to 30 seconds until status is completed or failed:
curl -s https://faceless.so/api/v1/videos/665f1b2a9c31a2b3c4d5e801/status \
-H "Authorization: Bearer $FACELESS_API_KEY"
{
"success": true,
"data": { "id": "665f1b2a9c31a2b3c4d5e801", "status": "processing", "percentCompleted": 62, "readyForEditing": false, "errorMessages": [], "renderedVideoUrl": null }
}
On failed, read errorMessages for the reason. With the CLI, faceless videos create --wait and faceless videos status <id> handle the polling.
3. Render (POST /videos/{id}/render, scope videos:write)
Rendering assembles the final MP4 in the cloud. It is free (credits were charged at creation) and requires generation to be completed first.
curl -s -X POST https://faceless.so/api/v1/videos/665f1b2a9c31a2b3c4d5e801/render \
-H "Authorization: Bearer $FACELESS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"codec": "h264"}'
The 202 response contains a renderId. Poll GET /renders/{renderId} (scope videos:read) every 5 to 15 seconds; renders typically finish in under two minutes:
curl -s https://faceless.so/api/v1/renders/abcd1234efgh \
-H "Authorization: Bearer $FACELESS_API_KEY"
{
"success": true,
"data": { "renderId": "abcd1234efgh", "status": "done", "overallProgress": 1, "url": "https://exports.faceless.so/renders/665f1b2a9c31a2b3c4d5e801/1722333444555.mp4" }
}
status is in-progress (with overallProgress 0 to 1), done (with the MP4 url) or error. The MP4 url is a direct download; it also appears as renderedVideoUrl on the video.
4. Publish
Publish immediately with POST /posts, or set per-platform metadata with PATCH /videos/{id} and schedule with POST /posts/schedule. Both are free; see publishing and scheduling.
Captioning existing footage (POST /videos/captions)
To caption a video or audio file you already have (no AI visuals, no credit cost), send its public URL. Processing is asynchronous; poll GET /videos/{id}/status like any other video.
curl -s -X POST https://faceless.so/api/v1/videos/captions \
-H "Authorization: Bearer $FACELESS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"videoUrl": "https://example.com/clip.mp4", "language": "English"}'
Provide videoUrl or audioUrl (an audio file becomes a captioned video). Rate limit: 10 per 300s.
Managing videos
GET /videos(scope videos:read): paginated list, newest first, withrenderedVideoUrlwhen available.?archived=truefor archived only.GET /videos/{id}: one video with script, voice, model, status and post metadata.PATCH /videos/{id}(scope videos:write): rename, or set per-platform post metadata before scheduling.DELETE /videos/{id}(scope videos:write): permanent, no credit refund.
A 404 not_found on any of these means the id does not exist or belongs to another team.