curl --request POST \
--url https://apis.viggle.ai/v1/videos \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: multipart/form-data' \
--form 'prompt=A paper airplane gliding through a sunlit office' \
--form quality=low \
--form first_frame_image='@example-file' \
--form 'first_frame_image_url=<string>' \
--form last_frame_image='@example-file' \
--form 'last_frame_image_url=<string>' \
--form 'reference_video=<string>' \
--form 'reference_video_url=<string>' \
--form 'reference_image=<string>' \
--form 'reference_image_url=<string>' \
--form 'driving_video_url=<string>' \
--form 'character_image_url=<string>' \
--form 'character_image_urls=<string>' \
--form priority=1000 \
--form duration_s=5 \
--form resolution=768p \
--form aspect_ratio=16:9 \
--form seed=1 \
--form watermark=false \
--form reference_video.items='@example-file' \
--form reference_image.items='@example-file'import requests
url = "https://apis.viggle.ai/v1/videos"
files = {
"first_frame_image": ("example-file", open("example-file", "rb")),
"last_frame_image": ("example-file", open("example-file", "rb")),
"reference_video.items": ("example-file", open("example-file", "rb")),
"reference_image.items": ("example-file", open("example-file", "rb"))
}
payload = {
"prompt": "A paper airplane gliding through a sunlit office",
"quality": "low",
"first_frame_image_url": "<string>",
"last_frame_image_url": "<string>",
"reference_video": "<string>",
"reference_video_url": "<string>",
"reference_image": "<string>",
"reference_image_url": "<string>",
"driving_video_url": "<string>",
"character_image_url": "<string>",
"character_image_urls": "<string>",
"priority": "1000",
"duration_s": "5",
"resolution": "768p",
"aspect_ratio": "16:9",
"seed": "1",
"watermark": "false"
}
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, data=payload, files=files, headers=headers)
print(response.text)const form = new FormData();
form.append('prompt', 'A paper airplane gliding through a sunlit office');
form.append('quality', 'low');
form.append('first_frame_image', '<string>');
form.append('first_frame_image_url', '<string>');
form.append('last_frame_image', '<string>');
form.append('last_frame_image_url', '<string>');
form.append('reference_video', '<string>');
form.append('reference_video_url', '<string>');
form.append('reference_image', '<string>');
form.append('reference_image_url', '<string>');
form.append('driving_video_url', '<string>');
form.append('character_image_url', '<string>');
form.append('character_image_urls', '<string>');
form.append('priority', '1000');
form.append('duration_s', '5');
form.append('resolution', '768p');
form.append('aspect_ratio', '16:9');
form.append('seed', '1');
form.append('watermark', 'false');
form.append('reference_video.items', '{
"fileName": "example-file"
}');
form.append('reference_image.items', '{
"fileName": "example-file"
}');
const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
options.body = form;
fetch('https://apis.viggle.ai/v1/videos', 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/v1/videos",
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=\"prompt\"\r\n\r\nA paper airplane gliding through a sunlit office\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"quality\"\r\n\r\nlow\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"first_frame_image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"first_frame_image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"last_frame_image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"last_frame_image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_video\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_video_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_image\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"driving_video_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"character_image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"character_image_urls\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"priority\"\r\n\r\n1000\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"duration_s\"\r\n\r\n5\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"resolution\"\r\n\r\n768p\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"aspect_ratio\"\r\n\r\n16:9\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"seed\"\r\n\r\n1\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"watermark\"\r\n\r\nfalse\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_video.items\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n{\r\n \"fileName\": \"example-file\"\r\n}\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_image.items\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n{\r\n \"fileName\": \"example-file\"\r\n}\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/v1/videos"
payload := strings.NewReader("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"prompt\"\r\n\r\nA paper airplane gliding through a sunlit office\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"quality\"\r\n\r\nlow\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"first_frame_image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"first_frame_image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"last_frame_image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"last_frame_image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_video\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_video_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_image\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"driving_video_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"character_image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"character_image_urls\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"priority\"\r\n\r\n1000\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"duration_s\"\r\n\r\n5\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"resolution\"\r\n\r\n768p\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"aspect_ratio\"\r\n\r\n16:9\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"seed\"\r\n\r\n1\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"watermark\"\r\n\r\nfalse\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_video.items\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n{\r\n \"fileName\": \"example-file\"\r\n}\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_image.items\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n{\r\n \"fileName\": \"example-file\"\r\n}\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/v1/videos")
.header("Authorization", "Bearer <token>")
.body("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"prompt\"\r\n\r\nA paper airplane gliding through a sunlit office\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"quality\"\r\n\r\nlow\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"first_frame_image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"first_frame_image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"last_frame_image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"last_frame_image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_video\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_video_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_image\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"driving_video_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"character_image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"character_image_urls\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"priority\"\r\n\r\n1000\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"duration_s\"\r\n\r\n5\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"resolution\"\r\n\r\n768p\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"aspect_ratio\"\r\n\r\n16:9\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"seed\"\r\n\r\n1\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"watermark\"\r\n\r\nfalse\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_video.items\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n{\r\n \"fileName\": \"example-file\"\r\n}\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_image.items\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n{\r\n \"fileName\": \"example-file\"\r\n}\r\n-----011000010111000001101001--")
.asString();require 'uri'
require 'net/http'
url = URI("https://apis.viggle.ai/v1/videos")
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=\"prompt\"\r\n\r\nA paper airplane gliding through a sunlit office\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"quality\"\r\n\r\nlow\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"first_frame_image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"first_frame_image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"last_frame_image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"last_frame_image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_video\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_video_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_image\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"driving_video_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"character_image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"character_image_urls\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"priority\"\r\n\r\n1000\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"duration_s\"\r\n\r\n5\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"resolution\"\r\n\r\n768p\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"aspect_ratio\"\r\n\r\n16:9\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"seed\"\r\n\r\n1\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"watermark\"\r\n\r\nfalse\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_video.items\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n{\r\n \"fileName\": \"example-file\"\r\n}\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_image.items\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n{\r\n \"fileName\": \"example-file\"\r\n}\r\n-----011000010111000001101001--"
response = http.request(request)
puts response.read_body{
"id": "<string>",
"status": "queued",
"progress": 50,
"created_at": "2023-11-07T05:31:56Z"
}{
"error": {
"code": "UNAUTHENTICATED",
"message": "<string>",
"retryable": true,
"request_id": "<string>",
"details": {},
"remediation": {
"action": "<string>",
"retry_after_ms": 1
}
}
}{
"error": {
"code": "UNAUTHENTICATED",
"message": "<string>",
"retryable": true,
"request_id": "<string>",
"details": {},
"remediation": {
"action": "<string>",
"retry_after_ms": 1
}
}
}{
"error": {
"code": "UNAUTHENTICATED",
"message": "<string>",
"retryable": true,
"request_id": "<string>",
"details": {},
"remediation": {
"action": "<string>",
"retry_after_ms": 1
}
}
}{
"error": {
"code": "UNAUTHENTICATED",
"message": "<string>",
"retryable": true,
"request_id": "<string>",
"details": {},
"remediation": {
"action": "<string>",
"retry_after_ms": 1
}
}
}{
"error": {
"code": "UNAUTHENTICATED",
"message": "<string>",
"retryable": true,
"request_id": "<string>",
"details": {},
"remediation": {
"action": "<string>",
"retry_after_ms": 1
}
}
}{
"error": {
"code": "UNAUTHENTICATED",
"message": "<string>",
"retryable": true,
"request_id": "<string>",
"details": {},
"remediation": {
"action": "<string>",
"retry_after_ms": 1
}
}
}{
"error": {
"code": "UNAUTHENTICATED",
"message": "<string>",
"retryable": true,
"request_id": "<string>",
"details": {},
"remediation": {
"action": "<string>",
"retry_after_ms": 1
}
}
}Generate Video (from Reference Video/Image)
Generate a MiniMax H3 video that carries the subject and/or style of a reference video and up to 4 reference images (omni-reference).
curl --request POST \
--url https://apis.viggle.ai/v1/videos \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: multipart/form-data' \
--form 'prompt=A paper airplane gliding through a sunlit office' \
--form quality=low \
--form first_frame_image='@example-file' \
--form 'first_frame_image_url=<string>' \
--form last_frame_image='@example-file' \
--form 'last_frame_image_url=<string>' \
--form 'reference_video=<string>' \
--form 'reference_video_url=<string>' \
--form 'reference_image=<string>' \
--form 'reference_image_url=<string>' \
--form 'driving_video_url=<string>' \
--form 'character_image_url=<string>' \
--form 'character_image_urls=<string>' \
--form priority=1000 \
--form duration_s=5 \
--form resolution=768p \
--form aspect_ratio=16:9 \
--form seed=1 \
--form watermark=false \
--form reference_video.items='@example-file' \
--form reference_image.items='@example-file'import requests
url = "https://apis.viggle.ai/v1/videos"
files = {
"first_frame_image": ("example-file", open("example-file", "rb")),
"last_frame_image": ("example-file", open("example-file", "rb")),
"reference_video.items": ("example-file", open("example-file", "rb")),
"reference_image.items": ("example-file", open("example-file", "rb"))
}
payload = {
"prompt": "A paper airplane gliding through a sunlit office",
"quality": "low",
"first_frame_image_url": "<string>",
"last_frame_image_url": "<string>",
"reference_video": "<string>",
"reference_video_url": "<string>",
"reference_image": "<string>",
"reference_image_url": "<string>",
"driving_video_url": "<string>",
"character_image_url": "<string>",
"character_image_urls": "<string>",
"priority": "1000",
"duration_s": "5",
"resolution": "768p",
"aspect_ratio": "16:9",
"seed": "1",
"watermark": "false"
}
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, data=payload, files=files, headers=headers)
print(response.text)const form = new FormData();
form.append('prompt', 'A paper airplane gliding through a sunlit office');
form.append('quality', 'low');
form.append('first_frame_image', '<string>');
form.append('first_frame_image_url', '<string>');
form.append('last_frame_image', '<string>');
form.append('last_frame_image_url', '<string>');
form.append('reference_video', '<string>');
form.append('reference_video_url', '<string>');
form.append('reference_image', '<string>');
form.append('reference_image_url', '<string>');
form.append('driving_video_url', '<string>');
form.append('character_image_url', '<string>');
form.append('character_image_urls', '<string>');
form.append('priority', '1000');
form.append('duration_s', '5');
form.append('resolution', '768p');
form.append('aspect_ratio', '16:9');
form.append('seed', '1');
form.append('watermark', 'false');
form.append('reference_video.items', '{
"fileName": "example-file"
}');
form.append('reference_image.items', '{
"fileName": "example-file"
}');
const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
options.body = form;
fetch('https://apis.viggle.ai/v1/videos', 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/v1/videos",
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=\"prompt\"\r\n\r\nA paper airplane gliding through a sunlit office\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"quality\"\r\n\r\nlow\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"first_frame_image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"first_frame_image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"last_frame_image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"last_frame_image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_video\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_video_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_image\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"driving_video_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"character_image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"character_image_urls\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"priority\"\r\n\r\n1000\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"duration_s\"\r\n\r\n5\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"resolution\"\r\n\r\n768p\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"aspect_ratio\"\r\n\r\n16:9\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"seed\"\r\n\r\n1\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"watermark\"\r\n\r\nfalse\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_video.items\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n{\r\n \"fileName\": \"example-file\"\r\n}\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_image.items\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n{\r\n \"fileName\": \"example-file\"\r\n}\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/v1/videos"
payload := strings.NewReader("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"prompt\"\r\n\r\nA paper airplane gliding through a sunlit office\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"quality\"\r\n\r\nlow\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"first_frame_image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"first_frame_image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"last_frame_image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"last_frame_image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_video\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_video_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_image\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"driving_video_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"character_image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"character_image_urls\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"priority\"\r\n\r\n1000\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"duration_s\"\r\n\r\n5\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"resolution\"\r\n\r\n768p\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"aspect_ratio\"\r\n\r\n16:9\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"seed\"\r\n\r\n1\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"watermark\"\r\n\r\nfalse\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_video.items\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n{\r\n \"fileName\": \"example-file\"\r\n}\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_image.items\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n{\r\n \"fileName\": \"example-file\"\r\n}\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/v1/videos")
.header("Authorization", "Bearer <token>")
.body("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"prompt\"\r\n\r\nA paper airplane gliding through a sunlit office\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"quality\"\r\n\r\nlow\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"first_frame_image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"first_frame_image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"last_frame_image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"last_frame_image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_video\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_video_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_image\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"driving_video_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"character_image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"character_image_urls\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"priority\"\r\n\r\n1000\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"duration_s\"\r\n\r\n5\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"resolution\"\r\n\r\n768p\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"aspect_ratio\"\r\n\r\n16:9\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"seed\"\r\n\r\n1\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"watermark\"\r\n\r\nfalse\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_video.items\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n{\r\n \"fileName\": \"example-file\"\r\n}\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_image.items\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n{\r\n \"fileName\": \"example-file\"\r\n}\r\n-----011000010111000001101001--")
.asString();require 'uri'
require 'net/http'
url = URI("https://apis.viggle.ai/v1/videos")
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=\"prompt\"\r\n\r\nA paper airplane gliding through a sunlit office\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"quality\"\r\n\r\nlow\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"first_frame_image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"first_frame_image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"last_frame_image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"last_frame_image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_video\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_video_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_image\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"driving_video_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"character_image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"character_image_urls\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"priority\"\r\n\r\n1000\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"duration_s\"\r\n\r\n5\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"resolution\"\r\n\r\n768p\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"aspect_ratio\"\r\n\r\n16:9\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"seed\"\r\n\r\n1\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"watermark\"\r\n\r\nfalse\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_video.items\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n{\r\n \"fileName\": \"example-file\"\r\n}\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_image.items\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n{\r\n \"fileName\": \"example-file\"\r\n}\r\n-----011000010111000001101001--"
response = http.request(request)
puts response.read_body{
"id": "<string>",
"status": "queued",
"progress": 50,
"created_at": "2023-11-07T05:31:56Z"
}{
"error": {
"code": "UNAUTHENTICATED",
"message": "<string>",
"retryable": true,
"request_id": "<string>",
"details": {},
"remediation": {
"action": "<string>",
"retry_after_ms": 1
}
}
}{
"error": {
"code": "UNAUTHENTICATED",
"message": "<string>",
"retryable": true,
"request_id": "<string>",
"details": {},
"remediation": {
"action": "<string>",
"retry_after_ms": 1
}
}
}{
"error": {
"code": "UNAUTHENTICATED",
"message": "<string>",
"retryable": true,
"request_id": "<string>",
"details": {},
"remediation": {
"action": "<string>",
"retry_after_ms": 1
}
}
}{
"error": {
"code": "UNAUTHENTICATED",
"message": "<string>",
"retryable": true,
"request_id": "<string>",
"details": {},
"remediation": {
"action": "<string>",
"retry_after_ms": 1
}
}
}{
"error": {
"code": "UNAUTHENTICATED",
"message": "<string>",
"retryable": true,
"request_id": "<string>",
"details": {},
"remediation": {
"action": "<string>",
"retry_after_ms": 1
}
}
}{
"error": {
"code": "UNAUTHENTICATED",
"message": "<string>",
"retryable": true,
"request_id": "<string>",
"details": {},
"remediation": {
"action": "<string>",
"retry_after_ms": 1
}
}
}{
"error": {
"code": "UNAUTHENTICATED",
"message": "<string>",
"retryable": true,
"request_id": "<string>",
"details": {},
"remediation": {
"action": "<string>",
"retry_after_ms": 1
}
}
}multipart/form-data with at least one of reference_video, reference_video_url, reference_image, or reference_image_url. Supplying any of these four fields is what selects this mode of POST /v1/videos — reference-video (omni-reference) generation — and produces a Viggle-optimized MiniMax H3 video with native audio.
first_frame_image/last_frame_image there falls back to text-only. There is no source/mode parameter to force reference-video selection independently of these fields, so double-check your request actually includes one of them before relying on this mode.POST /v1/videos endpoint as Generate Video (from Text), Generate Video (from First Frame and/or Text), Generate Video (from First-Last Frames and/or Text), and Generate Video (from Character Animation) — which mode runs is selected by which fields you send, not by a separate parameter. Reference fields cannot be combined with first_frame_image/last_frame_image.
low and high. Reference-conditioned generation costs the same as text-only for the same quality and duration; resolution and aspect_ratio don’t affect price. See Pricing and retention.Request parameters
Sendmultipart/form-data.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
prompt | string | Yes | — | Non-empty text description of the desired video. Still required with reference video/images supplied. |
quality | string | Yes | — | low for faster generation and quicker iteration, or high for higher-fidelity output. Both tiers are billed at the same $0.01/sec rate. |
reference_video | file | See below | — | Reference video uploaded directly. Declared as a repeatable field for forward compatibility, but at most 1 reference video is accepted today, combined with reference_video_url. Not required if at least one reference image is supplied instead. |
reference_video_url | string (URI) | See below | — | Publicly reachable URL of the reference video; the service fetches and re-hosts it. Declared as a repeatable field for forward compatibility, but at most 1 reference video is accepted today, combined with reference_video. |
reference_image | file, repeatable | See below | — | Reference image uploaded directly. Can be repeated, and freely mixed with reference_image_url — combined total across both is capped at 4. |
reference_image_url | string (URI), repeatable | See below | — | Publicly reachable URL of a reference image; the service fetches and re-hosts it. Can be repeated, and freely mixed with reference_image — combined total across both is capped at 4. |
duration_s | number | No | 5 | Target duration in seconds, 3–15. Rounded up to determine the credit charge. |
resolution | string | No | 768p | 480p, 768p, or 1080p. Does not affect price. |
aspect_ratio | string | No | 16:9 | 16:9, 9:16, 1:1, 4:3, 3:4, or 21:9. Does not affect price. |
seed | integer | No | — | ≥ 0. Omit for a random seed. |
watermark | boolean | No | false | Whether to burn in a Viggle watermark. |
priority | integer | No | 1000 | Admission-queue priority tier. Must be one of the server’s configured tiers (currently 1000 or 0). Most callers never need to set this. |
reference_video/reference_video_url/reference_image/reference_image_url is what selects this mode — there’s no separate source parameter. Supplying none of the four does not error; see the warning above — the request is generated as text-to-video instead.
Reference video vs. reference images
You can supply a reference video, one or more reference images, or both together in the same request — a reference video is not required if you supply at least one reference image, and vice versa.- Reference video (
reference_video/reference_video_url): both fields are declared as arrays for forward compatibility, but at most 1 reference video is accepted today across the two combined — supplying more (two files, two URLs, or one of each) answers400 INVALID_REQUEST— “at most 1 reference video(s) allowed”. The reference video itself must be 0.5–600 seconds long and at least 64x64 with even width and height — the same upload constraints enforced elsewhere in this API. This is independent ofduration_s, which controls the duration of the generated output video, not the reference. - Reference images (
reference_image/reference_image_url): each can be repeated and the two forms can be freely mixed, but the combined count across both cannot exceed 4. Going over answers400 INVALID_REQUEST— “at most 4 reference images are allowed”.
first_frame_image/last_frame_image (file or URL form). Supplying both answers 400 INVALID_REQUEST — “reference_video/reference_image cannot be combined with first_frame_image/last_frame_image”.
Response parameters
Returns200 OK — an acceptance acknowledgment, not the final result.
| Field | Type | Always present | Description |
|---|---|---|---|
id | string | Yes | Public video ID, vid_-prefixed. |
status | string | Yes | Always queued on acceptance. |
progress | integer or null | Yes | Always null on acceptance. |
created_at | string | Yes | ISO 8601 creation timestamp, second precision. |
{
"id": "vid_3f2a9c",
"status": "queued",
"progress": null,
"created_at": "2026-08-24T09:12:03Z"
}
GET /v1/videos/{video_id} returns (stage, video_url, alpha_url, completed_at, error). See Get Video for the full shape once the video is processing or done.
Examples
curl https://apis.viggle.ai/v1/videos \
-H "Authorization: Bearer $VIGGLE_API_KEY" \
-F prompt="keep the same outfit and walk forward" \
-F quality=high \
-F reference_video=@./reference.mp4 \
-F reference_image_url=https://example.test/ref1.png \
-F duration_s=8
curl https://apis.viggle.ai/v1/videos \
-H "Authorization: Bearer $VIGGLE_API_KEY" \
-F prompt="a dancer in the same style" \
-F quality=low \
-F reference_video_url=https://example.test/ref.mp4 \
-F reference_image_url=https://example.test/img1.png \
-F reference_image_url=https://example.test/img2.png
curl https://apis.viggle.ai/v1/videos \
-H "Authorization: Bearer $VIGGLE_API_KEY" \
-F prompt="combine these two references" \
-F quality=low \
-F reference_image=@./img1.png \
-F reference_image=@./img2.png
import os, requests
response = requests.post(
"https://apis.viggle.ai/v1/videos",
headers={"Authorization": f"Bearer {os.environ['VIGGLE_API_KEY']}"},
data={
"prompt": "keep the same outfit and walk forward",
"quality": "high",
"reference_video_url": "https://example.test/ref.mp4",
"duration_s": 8,
},
)
response.raise_for_status()
video = response.json()
const form = new FormData();
form.append("prompt", "a dancer in the same style");
form.append("quality", "low");
form.append("reference_video_url", "https://example.test/ref.mp4");
form.append("reference_image_url", "https://example.test/img1.png");
form.append("reference_image_url", "https://example.test/img2.png");
const response = await fetch("https://apis.viggle.ai/v1/videos", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.VIGGLE_API_KEY}` },
body: form,
});
const video = await response.json();
@viggle/sdk
const video = await client.videos.create({
prompt: "keep the same outfit and walk forward",
quality: "high",
referenceVideoUrl: "https://example.com/ref.mp4",
referenceImageUrl: ["https://example.com/img1.png", "https://example.com/img2.png"],
durationS: 8,
});
// video.id, video.status ("queued", ...); poll with client.videos.get(video.id)
Common errors
| Error | Cause |
|---|---|
400 INVALID_REQUEST — “at most 1 reference video(s) allowed” | reference_video and/or reference_video_url together supply more than 1 reference video. |
400 INVALID_REQUEST — “at most 4 reference images are allowed” | reference_image and reference_image_url together exceed 4 images. |
400 INVALID_REQUEST — “reference_video/reference_image cannot be combined with first_frame_image/last_frame_image” | A reference field supplied alongside first_frame_image/last_frame_image (file or URL form). |
Next step
Use Get Video with the returnedid to poll for the result.
Generate Video (from Text)
Generate Video (from First Frame and/or Text)
Generate Video (from First-Last Frames and/or Text)
Generate Video (from Character Animation)
Authorizations
Server-side SDK clients use a project API key. Remote MCP clients use an OAuth access token. Never expose a project API key in browser code.
Headers
Optional caller-supplied correlation ID, up to 128 characters. The service returns the effective value in the response header for tracing and support.
1 - 128Optional source-channel label, up to 128 characters, used to attribute traffic to an SDK, integration, product surface, or internal workflow.
1 - 128Body
Body of POST /v1/videos, multipart/form-data only (character-
animation mode below also accepts a plain application/json body —
see Generate Video (from Character Animation)). Which fields are
supplied selects the generation mode:
- Neither
first_frame_image/first_frame_image_urlnorlast_frame_image/last_frame_image_urlnor any reference or character-animation field supplied: text-to-video. - A first frame supplied, no last frame: first-frame-to-video.
- Both a first frame and a last frame supplied: first+last-frame-to-video.
- Any of
reference_video/reference_video_url/reference_image/reference_image_urlsupplied: reference-video (omni-reference) generation. driving_video_urland/orcharacter_image_url/character_image_urlssupplied: character-animation generation, dispatched to a separate backend from the four modes above. It has noqualitytier, noduration_s/resolution/aspect_ratio/seed, andpromptis optional rather than required; see below andGenerate Video (from Character Animation)for its own fields, pricing, and constraints.
Within a frame slot, supply at most one of the file and the URL
form. Supplying both first_frame_image and first_frame_image_url
(or both last_frame_image and last_frame_image_url) answers
400 INVALID_REQUEST with "supply only one of first_frame_image or
first_frame_image_url" (or the last_frame_* equivalent). A last
frame requires a first frame; supplying a last frame with no first
frame answers 400 INVALID_REQUEST with "a last frame requires a
first frame".
Reference-video mode is selected purely by whether any of the four
reference fields is present — there is no separate source/mode
parameter, and no error if you meant to but forgot: supplying none
of reference_video/reference_video_url/reference_image/
reference_image_url simply generates text-to-video instead (the
first bullet above), the same way omitting first_frame_image/
last_frame_image falls back to text-to-video rather than
erroring. reference_video and reference_video_url are declared
as arrays for forward compatibility, but at most 1 reference video
is accepted today; supplying any combination of the two fields that
adds up to more than 1 (two files, two URLs, or one of each) answers
400 INVALID_REQUEST with "at most 1 reference video(s) allowed".
reference_image and reference_image_url may be mixed freely, but
their combined count cannot exceed 4; going over answers
400 INVALID_REQUEST with "at most 4 reference images are allowed".
Reference fields cannot be combined with
first_frame_image/last_frame_image (file or URL form); doing so
answers 400 INVALID_REQUEST with
"reference_video/reference_image cannot be combined with
first_frame_image/last_frame_image". The reference video itself
(independent of duration_s, the target duration of the generated
video) must be 0.5–600 seconds long and at least 64x64 with even
width and height, the same constraints enforced on uploaded video
elsewhere in this API.
Character-animation mode cannot be combined with quality (or any
frame/reference field above) — doing so answers
400 INVALID_REQUEST with "driving_video_url/character_image_url
cannot be combined with quality". At least one character image is
required (character_image_url and character_image_urls are
mutually exclusive ways to supply them — "supply only one of
character_image_url or character_image_urls" otherwise); up to 4
are accepted when driving_video_url is absent, but only 1 when
it's present ("only one character_image_url is allowed when
driving_video_url is provided"). driving_video_url itself is
optional, single-valued, and — unlike every other video input in
this API — checked against a narrower 5–10 second (inclusive)
duration window rather than 0.5–600 seconds, on top of the same
at-least-64x64/even-dimensions checks.
Billed at ⌈duration_s⌉ × the per-second credit rate for quality
(currently 1 credit/second — $0.01/sec — for both low and high).
resolution and aspect_ratio do not affect price, and
image/video-conditioned generation (first-frame, first-last-frame,
or reference-video) costs the same as text-only for the same
quality and duration. Character-animation mode is billed
differently — a flat rate regardless of actual output duration; see
Generate Video (from Character Animation).
Every generated video includes native audio; there is no separate audio flag or field.
Text description of the desired video. Required and non-empty for text, first-frame, first+last-frame, and reference-video modes. Optional (and merely a style/content hint, not enforced non-empty) for character-animation mode.
1"A paper airplane gliding through a sunlit office"
Generation quality tier — also selects the per-second credit rate charged for this request. low generates faster, for quicker iteration; high generates slower but produces higher-fidelity output. Both tiers are billed at the same $0.01/sec rate. Required for every mode except character-animation, which has no quality tiers and rejects this field outright if supplied.
low, high "low"
First-frame image uploaded directly. Mutually exclusive with first_frame_image_url. Supplying either switches on first-frame-to-video mode. Cannot be combined with any reference_video/reference_image field.
Publicly reachable URL of the first-frame image; the service fetches and re-hosts it. Mutually exclusive with first_frame_image. Cannot be combined with any reference_video/reference_image field.
Last-frame image uploaded directly. Mutually exclusive with last_frame_image_url. Valid only alongside a first frame. Cannot be combined with any reference_video/reference_image field.
Publicly reachable URL of the last-frame image; the service fetches and re-hosts it. Mutually exclusive with last_frame_image. Valid only alongside a first frame. Cannot be combined with any reference_video/reference_image field.
Reference video uploaded directly, for reference-video (omni-reference) generation. Declared as an array for forward compatibility, but at most 1 is accepted today — combined with reference_video_url. Not required if at least one reference image is supplied instead. Must be 0.5–600 seconds long and at least 64x64 with even width/height. Cannot be combined with first_frame_image/last_frame_image.
1Publicly reachable URL of the reference video; the service fetches and re-hosts it. Declared as an array for forward compatibility, but at most 1 is accepted today — combined with reference_video. Same duration/resolution constraints as reference_video.
1Reference images uploaded directly, for reference-video (omni-reference) generation. Up to 4 total, combined with reference_image_url. Can be freely mixed with reference_image_url.
4Publicly reachable URLs of reference images; the service fetches and re-hosts each one. Up to 4 total, combined with reference_image. Can be freely mixed with reference_image.
4Publicly reachable URL (https://) or internal gs:// object of a driving video, for character-animation generation — its motion is applied to the character image(s). Optional and single-valued; a character-animation request can run on character images alone. Must be 5–10 seconds long (inclusive), at least 64x64, and even width/height. Selects character-animation mode together with any character_image_url/character_image_urls; cannot be combined with quality or any frame/reference field above.
Character reference image URL(s) (https:// or gs://), repeatable, for character-animation generation. Mutually exclusive with character_image_urls — supply one field or the other, not both. At least one character image is required across the two fields; up to 4 total when driving_video_url is absent, but only 1 when it's present.
Same as character_image_url, supplied as one field instead of repeated ones — as a JSON array of strings on a multipart request, or natively on a JSON request body. Mutually exclusive with character_image_url.
Admission-queue priority tier, shared by H3 and character-animation modes. Defaults to 1000 (top tier) — most callers never need to set this. Must be one of the server's configured tiers (currently 1000 or 0); an unsupported value answers 400 INVALID_REQUEST with "unsupported priority".
Target video duration in seconds.
3 <= x <= 15Output resolution tier.
480p, 768p, 1080p Output aspect ratio.
16:9, 9:16, 1:1, 4:3, 3:4, 21:9 Deterministic generation seed. Omit for a random seed. H3 modes only — not applicable to character-animation mode.
x >= 0Whether to burn in a Viggle watermark.
Response
Video generation accepted and queued.
Acceptance acknowledgment for POST /v1/videos, shared by all five
generation modes. This is a queued confirmation, not the final
result — poll GET /v1/videos/{video_id} (or watch it via
GET /v1/videos) until status reaches ready, then read
video_url from that response.
Public video ID — vid_-prefixed for the four H3 modes, anim_-prefixed for character-animation mode.
1Lifecycle state at acceptance time; always queued.
queued, processing, ready, failed, cancelled Always null on acceptance.
0 <= x <= 100ISO 8601 creation timestamp, second precision.

