curl --request POST \
--url https://apis.viggle.ai/api/render \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: multipart/form-data' \
--form ref_image='@example-file' \
--form ref_image_url=https://example.com/character.png \
--form driving_video='@example-file' \
--form driving_video_url=https://example.com/dance.mp4 \
--form character_id=char_550e8400e29b41d4 \
--form scene_id=scene_660e8400e29b41d4 \
--form model=V3_Preview \
--form background_mode=original \
--form 'bg_color=0,255,0'import requests
url = "https://apis.viggle.ai/api/render"
files = {
"ref_image": ("example-file", open("example-file", "rb")),
"driving_video": ("example-file", open("example-file", "rb"))
}
payload = {
"ref_image_url": "https://example.com/character.png",
"driving_video_url": "https://example.com/dance.mp4",
"character_id": "char_550e8400e29b41d4",
"scene_id": "scene_660e8400e29b41d4",
"model": "V3_Preview",
"background_mode": "original",
"bg_color": "0,255,0"
}
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, data=payload, files=files, headers=headers)
print(response.text)const form = new FormData();
form.append('ref_image', '<string>');
form.append('ref_image_url', 'https://example.com/character.png');
form.append('driving_video', '<string>');
form.append('driving_video_url', 'https://example.com/dance.mp4');
form.append('character_id', 'char_550e8400e29b41d4');
form.append('scene_id', 'scene_660e8400e29b41d4');
form.append('model', 'V3_Preview');
form.append('background_mode', 'original');
form.append('bg_color', '0,255,0');
const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
options.body = form;
fetch('https://apis.viggle.ai/api/render', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://apis.viggle.ai/api/render",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"ref_image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"ref_image_url\"\r\n\r\nhttps://example.com/character.png\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"driving_video\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"driving_video_url\"\r\n\r\nhttps://example.com/dance.mp4\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"character_id\"\r\n\r\nchar_550e8400e29b41d4\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"scene_id\"\r\n\r\nscene_660e8400e29b41d4\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"model\"\r\n\r\nV3_Preview\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"background_mode\"\r\n\r\noriginal\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"bg_color\"\r\n\r\n0,255,0\r\n-----011000010111000001101001--",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: multipart/form-data"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://apis.viggle.ai/api/render"
payload := strings.NewReader("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"ref_image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"ref_image_url\"\r\n\r\nhttps://example.com/character.png\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"driving_video\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"driving_video_url\"\r\n\r\nhttps://example.com/dance.mp4\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"character_id\"\r\n\r\nchar_550e8400e29b41d4\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"scene_id\"\r\n\r\nscene_660e8400e29b41d4\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"model\"\r\n\r\nV3_Preview\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"background_mode\"\r\n\r\noriginal\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"bg_color\"\r\n\r\n0,255,0\r\n-----011000010111000001101001--")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://apis.viggle.ai/api/render")
.header("Authorization", "Bearer <token>")
.body("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"ref_image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"ref_image_url\"\r\n\r\nhttps://example.com/character.png\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"driving_video\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"driving_video_url\"\r\n\r\nhttps://example.com/dance.mp4\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"character_id\"\r\n\r\nchar_550e8400e29b41d4\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"scene_id\"\r\n\r\nscene_660e8400e29b41d4\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"model\"\r\n\r\nV3_Preview\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"background_mode\"\r\n\r\noriginal\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"bg_color\"\r\n\r\n0,255,0\r\n-----011000010111000001101001--")
.asString();require 'uri'
require 'net/http'
url = URI("https://apis.viggle.ai/api/render")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request.body = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"ref_image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"ref_image_url\"\r\n\r\nhttps://example.com/character.png\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"driving_video\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"driving_video_url\"\r\n\r\nhttps://example.com/dance.mp4\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"character_id\"\r\n\r\nchar_550e8400e29b41d4\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"scene_id\"\r\n\r\nscene_660e8400e29b41d4\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"model\"\r\n\r\nV3_Preview\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"background_mode\"\r\n\r\noriginal\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"bg_color\"\r\n\r\n0,255,0\r\n-----011000010111000001101001--"
response = http.request(request)
puts response.read_body{
"job_id": "job_abc123xyz",
"status": "queued",
"mode": "full_pipeline",
"enqueued_at": "2023-11-07T05:31:56Z",
"poll_url": "/api/render/job_abc123xyz",
"status_url": "/api/render/job_abc123xyz"
}{
"detail": "Invalid or missing API key. Pass it as Authorization: Bearer sk-..."
}{
"detail": {
"error_code": "CS-UORC01-008",
"message": "Insufficient credits. Top up your balance to continue."
}
}{
"detail": {
"error_code": "CS-ORIV-002",
"message": "Character or scene is not ready yet, or a required parameter is missing. Wait until the asset status is ready."
}
}Create Render Job
Start a video render job
curl --request POST \
--url https://apis.viggle.ai/api/render \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: multipart/form-data' \
--form ref_image='@example-file' \
--form ref_image_url=https://example.com/character.png \
--form driving_video='@example-file' \
--form driving_video_url=https://example.com/dance.mp4 \
--form character_id=char_550e8400e29b41d4 \
--form scene_id=scene_660e8400e29b41d4 \
--form model=V3_Preview \
--form background_mode=original \
--form 'bg_color=0,255,0'import requests
url = "https://apis.viggle.ai/api/render"
files = {
"ref_image": ("example-file", open("example-file", "rb")),
"driving_video": ("example-file", open("example-file", "rb"))
}
payload = {
"ref_image_url": "https://example.com/character.png",
"driving_video_url": "https://example.com/dance.mp4",
"character_id": "char_550e8400e29b41d4",
"scene_id": "scene_660e8400e29b41d4",
"model": "V3_Preview",
"background_mode": "original",
"bg_color": "0,255,0"
}
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, data=payload, files=files, headers=headers)
print(response.text)const form = new FormData();
form.append('ref_image', '<string>');
form.append('ref_image_url', 'https://example.com/character.png');
form.append('driving_video', '<string>');
form.append('driving_video_url', 'https://example.com/dance.mp4');
form.append('character_id', 'char_550e8400e29b41d4');
form.append('scene_id', 'scene_660e8400e29b41d4');
form.append('model', 'V3_Preview');
form.append('background_mode', 'original');
form.append('bg_color', '0,255,0');
const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
options.body = form;
fetch('https://apis.viggle.ai/api/render', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://apis.viggle.ai/api/render",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"ref_image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"ref_image_url\"\r\n\r\nhttps://example.com/character.png\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"driving_video\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"driving_video_url\"\r\n\r\nhttps://example.com/dance.mp4\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"character_id\"\r\n\r\nchar_550e8400e29b41d4\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"scene_id\"\r\n\r\nscene_660e8400e29b41d4\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"model\"\r\n\r\nV3_Preview\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"background_mode\"\r\n\r\noriginal\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"bg_color\"\r\n\r\n0,255,0\r\n-----011000010111000001101001--",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: multipart/form-data"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://apis.viggle.ai/api/render"
payload := strings.NewReader("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"ref_image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"ref_image_url\"\r\n\r\nhttps://example.com/character.png\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"driving_video\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"driving_video_url\"\r\n\r\nhttps://example.com/dance.mp4\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"character_id\"\r\n\r\nchar_550e8400e29b41d4\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"scene_id\"\r\n\r\nscene_660e8400e29b41d4\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"model\"\r\n\r\nV3_Preview\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"background_mode\"\r\n\r\noriginal\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"bg_color\"\r\n\r\n0,255,0\r\n-----011000010111000001101001--")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://apis.viggle.ai/api/render")
.header("Authorization", "Bearer <token>")
.body("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"ref_image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"ref_image_url\"\r\n\r\nhttps://example.com/character.png\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"driving_video\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"driving_video_url\"\r\n\r\nhttps://example.com/dance.mp4\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"character_id\"\r\n\r\nchar_550e8400e29b41d4\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"scene_id\"\r\n\r\nscene_660e8400e29b41d4\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"model\"\r\n\r\nV3_Preview\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"background_mode\"\r\n\r\noriginal\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"bg_color\"\r\n\r\n0,255,0\r\n-----011000010111000001101001--")
.asString();require 'uri'
require 'net/http'
url = URI("https://apis.viggle.ai/api/render")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request.body = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"ref_image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"ref_image_url\"\r\n\r\nhttps://example.com/character.png\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"driving_video\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"driving_video_url\"\r\n\r\nhttps://example.com/dance.mp4\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"character_id\"\r\n\r\nchar_550e8400e29b41d4\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"scene_id\"\r\n\r\nscene_660e8400e29b41d4\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"model\"\r\n\r\nV3_Preview\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"background_mode\"\r\n\r\noriginal\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"bg_color\"\r\n\r\n0,255,0\r\n-----011000010111000001101001--"
response = http.request(request)
puts response.read_body{
"job_id": "job_abc123xyz",
"status": "queued",
"mode": "full_pipeline",
"enqueued_at": "2023-11-07T05:31:56Z",
"poll_url": "/api/render/job_abc123xyz",
"status_url": "/api/render/job_abc123xyz"
}{
"detail": "Invalid or missing API key. Pass it as Authorization: Bearer sk-..."
}{
"detail": {
"error_code": "CS-UORC01-008",
"message": "Insufficient credits. Top up your balance to continue."
}
}{
"detail": {
"error_code": "CS-ORIV-002",
"message": "Character or scene is not ready yet, or a required parameter is missing. Wait until the asset status is ready."
}
}multipart/form-data.
- On-Demand: Upload
ref_imageanddriving_videodirectly — no preprocessing, no stored assets. Costs 1 credit/second of video. - Reusable Assets: Pre-create characters and scenes for reuse across renders. Each render costs 1 credit/second.
driving_video uploads are limited to 10 minutes duration and 100 MB file size.Parameters
Send asmultipart/form-data. Supply the character as either ref_image/ref_image_url or a pre-created character_id, and the motion as either driving_video/driving_video_url or a pre-created scene_id.
| Parameter | Type | Description |
|---|---|---|
ref_image | file | Character reference image (PNG, JPG). Use this or ref_image_url or character_id. |
ref_image_url | string | URL to a character image; the server fetches it. |
character_id | string | ID of a ready character (reusable-asset workflow). |
driving_video | file | Driving video (MP4). Use this or driving_video_url or scene_id. Max 10 min / 100 MB. |
driving_video_url | string | URL to a driving video; the server fetches it. |
scene_id | string | ID of a ready scene (reusable-asset workflow). |
model | string | V3_Preview (default) or V4_Preview. Must match how the character/scene was preprocessed. |
background_mode | string | original (default), solid, or transparent. See Compositing. |
bg_color | string | RGB for a solid background, e.g. "0,255,0". Only used when background_mode is solid. |
Response
{
"job_id": "job_abc123xyz",
"status": "queued",
"mode": "full_pipeline",
"enqueued_at": "2026-06-12T08:00:00Z",
"poll_url": "/api/render/job_abc123xyz",
"status_url": "/api/render/job_abc123xyz"
}
| Field | Description |
|---|---|
job_id | Identifier for the render. Poll Get Job Status with it. |
status | Starts at queued. |
poll_url / status_url | Convenience path to poll for status. |
Error Handling
If the request fails, the response includes a structured error with anerror_code:
{
"detail": {
"error_code": "CS-ORIV-001",
"message": "Reference image is required",
"action": "Upload a ref_image (PNG/JPG)"
}
}
| Code | Cause | Fix |
|---|---|---|
CS-ORAU-001 | Missing API key | Add Authorization: Bearer sk-... header |
CS-ORAU-002 | Invalid API key | Check your key is correct |
CS-ORIV-001 | Missing reference image | Upload ref_image |
CS-ORIV-002 | Missing driving video | Upload driving_video or provide scene_id |
CS-ORIV-004 | Video too long | Keep under 10 minutes |
CS-ORCR-001 | Insufficient credits | Top up credits |
error_code and your job ID.
Examples
On-Demand Render (upload files directly)
import requests
url = "https://apis.viggle.ai/api/render"
headers = {"Authorization": "Bearer YOUR_API_KEY"}
with open("character.png", "rb") as img, open("driving.mp4", "rb") as vid:
resp = requests.post(
url,
headers=headers,
files={
"ref_image": ("character.png", img, "image/png"),
"driving_video": ("driving.mp4", vid, "video/mp4"),
},
data={"background_mode": "original"},
)
data = resp.json()
if "detail" in data:
print(f"Error {data['detail']['error_code']}: {data['detail']['message']}")
else:
print(f"Job created: {data['job_id']}")
print(f"Poll: GET /api/render/{data['job_id']}")
const form = new FormData();
form.append("ref_image", await fetch("character.png").then(r => r.blob()), "character.png");
form.append("driving_video", await fetch("driving.mp4").then(r => r.blob()), "driving.mp4");
form.append("background_mode", "original");
const resp = await fetch("https://apis.viggle.ai/api/render", {
method: "POST",
headers: { "Authorization": "Bearer YOUR_API_KEY" },
body: form,
});
const data = await resp.json();
if (data.detail) {
console.error(`Error ${data.detail.error_code}: ${data.detail.message}`);
} else {
console.log(`Job created: ${data.job_id}`);
console.log(`Poll: GET /api/render/${data.job_id}`);
}
curl -X POST "https://apis.viggle.ai/api/render" \
-H "Authorization: Bearer YOUR_API_KEY" \
-F "[email protected]" \
-F "[email protected]" \
-F "background_mode=original"
Reusable Assets Render (pre-created character + scene)
import requests
url = "https://apis.viggle.ai/api/render"
headers = {"Authorization": "Bearer YOUR_API_KEY"}
resp = requests.post(
url,
headers=headers,
data={
"character_id": "char_550e8400e29b41d4",
"scene_id": "scene_660e8400e29b41d4",
"background_mode": "original",
},
)
data = resp.json()
if "detail" in data:
print(f"Error {data['detail']['error_code']}: {data['detail']['message']}")
else:
print(f"Job created: {data['job_id']}")
const form = new FormData();
form.append("character_id", "char_550e8400e29b41d4");
form.append("scene_id", "scene_660e8400e29b41d4");
form.append("background_mode", "original");
const resp = await fetch("https://apis.viggle.ai/api/render", {
method: "POST",
headers: { "Authorization": "Bearer YOUR_API_KEY" },
body: form,
});
const data = await resp.json();
if (data.detail) {
console.error(`Error ${data.detail.error_code}: ${data.detail.message}`);
} else {
console.log(`Job created: ${data.job_id}`);
}
curl -X POST "https://apis.viggle.ai/api/render" \
-H "Authorization: Bearer YOUR_API_KEY" \
-F "character_id=char_550e8400e29b41d4" \
-F "scene_id=scene_660e8400e29b41d4" \
-F "background_mode=original"
Next Steps
After creating a render job, poll Get Job Status every 3-5 seconds (no auth required). Whenstatus is complete, use the cdn_url field to download the final video.Authorizations
API key passed as Bearer token
Body
Character reference image file (PNG, JPG). Use this or ref_image_url.
URL to a character image. The server fetches it. Use instead of ref_image file upload.
"https://example.com/character.png"
Driving video file (MP4). Use this or driving_video_url. Maximum 10 minutes duration and 100 MB file size.
URL to a driving video. The server fetches it. Use instead of driving_video file upload.
"https://example.com/dance.mp4"
ID of a ready character (for preprocessed renders)
"char_550e8400e29b41d4"
ID of a ready scene (for preprocessed renders)
"scene_660e8400e29b41d4"
Avatar model. Defaults to V3_Preview. Scenes preprocessed on one model cannot be rendered on the other.
V4_Preview, V3_Preview Background handling: original (default, person removed via AI inpainting), solid (single color), transparent (alpha mask for compositing)
original, solid, transparent RGB string for solid background color, e.g., "0,255,0". Only used when background_mode is solid.
"0,255,0"
Response
Render job created
"job_abc123xyz"
"queued"
The render mode (e.g. full_pipeline, preprocessed)
"full_pipeline"
URL to poll for job status
"/api/render/job_abc123xyz"
URL to get job status
"/api/render/job_abc123xyz"

