curl -X POST https://api.vibepeak.ai/v1/real-estate/living-property \
-H "Authorization: Bearer vpk_live_xxxxx" \
-H "Content-Type: application/json" \
-d '{
"images": [
{ "url": "https://example.com/property/living-room.jpg", "room_type": "living_room" },
{ "url": "https://example.com/property/kitchen.jpg", "room_type": "kitchen" },
{ "url": "https://example.com/property/bedroom.jpg", "room_type": "bedroom" },
{ "url": "https://example.com/property/bathroom.jpg", "room_type": "bathroom" },
{ "url": "https://example.com/property/exterior.jpg", "room_type": "exterior" }
],
"voice": {
"voice_id": "EXAVITQu4vr4xnSDxMaL",
"language": "en"
},
"modification_mode": "no_modify",
"script": "Welcome to this stunning modern home where comfort meets contemporary design. The spacious living room is filled with natural light and elegant finishes. The kitchen offers sleek cabinetry and generous counter space. Each bedroom feels calm and inviting, while the bright bathroom adds a touch of luxury. Step outside to enjoy a beautiful private garden.",
"webhook_url": "https://yourserver.com/webhooks/vibepeak",
"subtitle": {
"subtitle_style_preset": "classic"
},
"elements_config": {
"enabled": true,
"watermark": {
"url": "https://example.com/logo.png",
"position": "bottom-right",
"size": 20,
"opacity": 100
},
"text": {
"content": "Powered by Vibepeak",
"color": "#FFFFFF",
"font": "Inter",
"size": 20,
"position": "center"
}
}
}'
curl -X POST https://api.vibepeak.ai/v1/real-estate/living-property \
-H "Authorization: Bearer vpk_live_xxxxx" \
-H "Content-Type: application/json" \
-d '{
"images": [
{ "url": "https://example.com/property/bedroom.jpg", "room_type": "bedroom" },
{ "url": "https://example.com/property/kitchen.jpg", "room_type": "kitchen" },
{ "url": "https://example.com/property/living-room.jpg", "room_type": "living_room" },
{ "url": "https://example.com/property/garden.jpg", "room_type": "garden" },
{ "url": "https://example.com/property/exterior.jpg", "room_type": "exterior" }
],
"voice": {
"voice_id": "EXAVITQu4vr4xnSDxMaL",
"language": "en"
},
"modification_mode": "no_modify",
"script": "Follow a full day in this wonderful family home, from the first light of morning to the calm of the evening. Bright bedrooms and a welcoming kitchen set the tone for the day, while the spacious living room becomes the heart of family life. Outside, the garden and the elegant facade complete a home designed to be lived in from sunrise to sunset.",
"selected_family_id": "family-with-kids",
"story_mode": true,
"story_locale": "en",
"webhook_url": "https://yourserver.com/webhooks/vibepeak"
}'
const response = await fetch('https://api.vibepeak.ai/v1/real-estate/living-property', {
method: 'POST',
headers: {
'Authorization': 'Bearer vpk_live_xxxxx',
'Content-Type': 'application/json'
},
body: JSON.stringify({
images: [
{ url: 'https://example.com/property/living-room.jpg', room_type: 'living_room' },
{ url: 'https://example.com/property/kitchen.jpg', room_type: 'kitchen' },
{ url: 'https://example.com/property/bedroom.jpg', room_type: 'bedroom' },
{ url: 'https://example.com/property/bathroom.jpg', room_type: 'bathroom' },
{ url: 'https://example.com/property/exterior.jpg', room_type: 'exterior' }
],
voice: {
voice_id: 'EXAVITQu4vr4xnSDxMaL',
language: 'en'
},
modification_mode: 'no_modify',
script: 'Welcome to this stunning modern home where comfort meets contemporary design. The spacious living room is filled with natural light and elegant finishes. The kitchen offers sleek cabinetry and generous counter space. Each bedroom feels calm and inviting, while the bright bathroom adds a touch of luxury. Step outside to enjoy a beautiful private garden.',
webhook_url: 'https://yourserver.com/webhooks/vibepeak',
subtitle: {
subtitle_style_preset: 'classic'
},
elements_config: {
enabled: true,
watermark: {
url: 'https://example.com/logo.png',
position: 'bottom-right',
size: 20,
opacity: 100
},
text: {
content: 'Powered by Vibepeak',
color: '#FFFFFF',
font: 'Inter',
size: 20,
position: 'center'
}
}
})
});
const task = await response.json();
console.log(`Task created: ${task.task_id}`);
console.log(`Poll at: ${response.headers.get('Location')}`);
import requests
response = requests.post(
'https://api.vibepeak.ai/v1/real-estate/living-property',
headers={
'Authorization': 'Bearer vpk_live_xxxxx',
'Content-Type': 'application/json'
},
json={
'images': [
{'url': 'https://example.com/property/living-room.jpg', 'room_type': 'living_room'},
{'url': 'https://example.com/property/kitchen.jpg', 'room_type': 'kitchen'},
{'url': 'https://example.com/property/bedroom.jpg', 'room_type': 'bedroom'},
{'url': 'https://example.com/property/bathroom.jpg', 'room_type': 'bathroom'},
{'url': 'https://example.com/property/exterior.jpg', 'room_type': 'exterior'}
],
'voice': {
'voice_id': 'EXAVITQu4vr4xnSDxMaL',
'language': 'en'
},
# change_decoration + include_humans_and_pets (default true) → two-step scenes,
# so the script uses the wider 110-140 chars/scene budget (550-700 for 5 images).
'modification_mode': 'change_decoration',
'include_humans_and_pets': True,
'script': 'Welcome to this beautifully renovated apartment where modern comfort meets timeless elegance throughout every room. The bright living room invites you to relax, with large windows that fill the space with warm natural light. The kitchen features sleek cabinetry, premium finishes, and generous counter space for cooking and gathering. Each bedroom offers a calm and restful retreat, while the elegant bathroom adds a genuine touch of luxury. Step outside to discover a private garden, perfect for morning coffee or relaxing evenings under the open sky. The home has been finished to a high standard and is ready for you to move in and enjoy from the very first day.',
'background_music': True,
'subtitle': {
'subtitle_style_preset': 'classic'
},
'elements_config': {
'enabled': True,
'watermark': {
'url': 'https://example.com/logo.png',
'position': 'bottom-right',
'size': 20,
'opacity': 100
},
'text': {
'content': 'Powered by Vibepeak',
'color': '#FFFFFF',
'font': 'Inter',
'size': 20,
'position': 'center'
}
}
}
)
task = response.json()
print(f"Task created: {task['task_id']}")
print(f"Credits charged: {task['credits_charged']}")
{
"task_id": "task_abc123xyz",
"status": "queued",
"message": "Real estate video generation request accepted",
"created_at": "2026-01-19T12:00:00Z",
"credits_charged": 15,
"livemode": true,
"request_id": "req_xyz123",
"_links": {
"self": "/v1/tasks/task_abc123xyz",
"poll_interval_seconds": 30
}
}
{
"task_id": "task_abc123xyz",
"status": "queued",
"message": "Real estate video generation request accepted",
"created_at": "2026-01-19T12:00:00Z",
"credits_charged": 0,
"livemode": false,
"request_id": "req_xyz123",
"_links": {
"self": "/v1/tasks/task_abc123xyz",
"poll_interval_seconds": 30
}
}
{
"error": {
"code": "VALIDATION_ERROR",
"message": "script is required",
"request_id": "req_xyz123",
"details": {
"field": "script",
"issues": [
{
"path": "script",
"message": "Required"
}
]
}
}
}
{
"error": {
"code": "SCRIPT_INVALID_CHARACTERS",
"message": "Script contains characters not supported by text-to-speech: \"🏠\". Emojis and other non-speech symbols are not allowed.",
"request_id": "req_xyz123",
"details": {
"invalid_characters": ["3", "$"]
}
}
}
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Provide either 'subtitle_style_preset' or 'styles', but not both.",
"request_id": "req_xyz123"
}
}
{
"error": {
"code": "SCRIPT_TOO_SHORT",
"message": "Script is too short for 5 image(s). Minimum 325 characters required (65 per scene), but got 200. Either lengthen the script or send fewer images.",
"request_id": "req_xyz123",
"details": {
"script_length": 200,
"min_length": 325,
"max_length": 425,
"image_count": 5,
"chars_per_scene_min": 65,
"chars_per_scene_max": 85
}
}
}
{
"error": {
"code": "SCRIPT_TOO_LONG",
"message": "Script is too long for 5 image(s). Maximum 700 characters allowed (140 per scene), but got 800. Either shorten the script or send more images.",
"request_id": "req_xyz123",
"details": {
"script_length": 800,
"min_length": 550,
"max_length": 700,
"image_count": 5,
"chars_per_scene_min": 110,
"chars_per_scene_max": 140
}
}
}
{
"error": {
"code": "IMAGE_RESOLUTION_TOO_LOW",
"message": "1 image(s) below the minimum resolution. Required: long side ≥ 1280px and short side ≥ 720px.",
"request_id": "req_xyz123",
"details": {
"invalid_images": ["https://example.com/thumbnail.jpg"]
}
}
}
{
"error": {
"code": "VALIDATION_ERROR",
"message": "If elements_config is enabled, you must provide at least a 'watermark' or 'text' configuration.",
"request_id": "req_xyz123",
"details": {
"field": "elements_config.enabled",
"issues": [
{
"path": "elements_config.enabled",
"message": "If elements_config is enabled, you must provide at least a 'watermark' or 'text' configuration."
}
]
}
}
}
{
"error": {
"code": "VALIDATION_ERROR",
"message": "If intro_outro is enabled, you must provide at least an 'intro' or 'outro' configuration.",
"details": {
"field": "elements_config.intro_outro.enabled",
"issues": [
{
"path": "elements_config.intro_outro.enabled",
"message": "If intro_outro is enabled, you must provide at least an 'intro' or 'outro' configuration."
}
]
},
"request_id": "req_xyz123"
}
}
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid hex color",
"request_id": "req_xyz123",
"details": {
"field": "elements_config.text.color",
"issues": [
{
"path": "elements_config.text.color",
"message": "Invalid hex color"
}
]
}
}
}
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Brand color must be a six-digit hex string such as #1A73E8, with no alpha channel",
"details": {
"field": "elements_config.intro_outro.intro.brandColorPrimary",
"issues": [
{
"path": "elements_config.intro_outro.intro.brandColorPrimary",
"message": "Brand color must be a six-digit hex string such as #1A73E8, with no alpha channel"
}
]
},
"request_id": "req_xyz123"
}
}
{
"error": {
"code": "VALIDATION_ERROR",
"message": "brandColorContrast requires brandColorPrimary on the same overlay.",
"details": {
"field": "elements_config.intro_outro.outro.brandColorContrast",
"issues": [
{
"path": "elements_config.intro_outro.outro.brandColorContrast",
"message": "brandColorContrast requires brandColorPrimary on the same overlay."
}
]
},
"request_id": "req_xyz123"
}
}
{
"error": {
"code": "VALIDATION_ERROR",
"message": "title is required by template 'ruled_caps'. Send it in values.title: an omitted field renders nothing.",
"details": {
"field": "elements_config.intro_outro.intro.values.title",
"issues": [
{
"path": "elements_config.intro_outro.intro.values.title",
"message": "title is required by template 'ruled_caps'. Send it in values.title: an omitted field renders nothing."
}
]
},
"request_id": "req_xyz123"
}
}
{
"error": {
"code": "VALIDATION_ERROR",
"message": "agent_name is required by template 'serif_business_card'. Send it in values.agent_name: an omitted field renders nothing.",
"details": {
"field": "elements_config.intro_outro.outro.values.agent_name",
"issues": [
{
"path": "elements_config.intro_outro.outro.values.agent_name",
"message": "agent_name is required by template 'serif_business_card'. Send it in values.agent_name: an omitted field renders nothing."
}
]
},
"request_id": "req_xyz123"
}
}
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Template 'custom_image' requires assets.custom_image: the URL of the image it renders.",
"details": {
"field": "elements_config.intro_outro.outro.assets.custom_image",
"issues": [
{
"path": "elements_config.intro_outro.outro.assets.custom_image",
"message": "Template 'custom_image' requires assets.custom_image: the URL of the image it renders."
}
]
},
"request_id": "req_xyz123"
}
}
{
"error": {
"code": "VOICE_NOT_FOUND",
"message": "Voice ID not found",
"request_id": "req_xyz123"
}
}
{
"error": {
"code": "VOICE_ACCESS_DENIED",
"message": "Voice not accessible",
"request_id": "req_xyz123"
}
}
{
"error": {
"code": "PLAN_NOT_ALLOWED",
"message": "Families are available on the Pro, Max and Enterprise plans. Upgrade your plan to use this feature.",
"request_id": "req_xyz123"
}
}
{
"error": {
"code": "FAMILY_NOT_FOUND",
"message": "Family not found or not accessible with this API key.",
"request_id": "req_xyz123"
}
}
{
"error": {
"code": "STORY_ROOM_TYPE_REQUIRED",
"message": "story_mode requires a room_type on every image so the scenes can be planned.",
"request_id": "req_xyz123",
"details": {
"images_missing_room_type": [1, 4]
}
}
}
{
"error": {
"code": "STORY_PLAN_FAILED",
"message": "Story planning failed. Please retry, or omit story_mode for a standard video.",
"request_id": "req_xyz123"
}
}
{
"error": {
"code": "FAMILY_NOT_READY",
"message": "The family is not ready yet: its member portraits are still generating. Poll the family until it is ready, then retry.",
"request_id": "req_xyz123"
}
}
{
"error": {
"code": "CONCURRENCY_LIMIT_EXCEEDED",
"message": "You have reached your concurrent task limit of 1. Please wait for existing tasks to complete.",
"request_id": "req_xyz123",
"details": {
"limit": 1,
"in_flight": 1,
"plan": "Plus"
}
}
}
{
"error": {
"code": "SERVICE_UNAVAILABLE",
"message": "Video generation service is temporarily unavailable. Please try again later.",
"request_id": "req_xyz123"
}
}
Videos
Create Living Property Video
Create an AI-powered real estate video with virtual staging and automatic narration
POST
/
v1
/
real-estate
/
living-property
curl -X POST https://api.vibepeak.ai/v1/real-estate/living-property \
-H "Authorization: Bearer vpk_live_xxxxx" \
-H "Content-Type: application/json" \
-d '{
"images": [
{ "url": "https://example.com/property/living-room.jpg", "room_type": "living_room" },
{ "url": "https://example.com/property/kitchen.jpg", "room_type": "kitchen" },
{ "url": "https://example.com/property/bedroom.jpg", "room_type": "bedroom" },
{ "url": "https://example.com/property/bathroom.jpg", "room_type": "bathroom" },
{ "url": "https://example.com/property/exterior.jpg", "room_type": "exterior" }
],
"voice": {
"voice_id": "EXAVITQu4vr4xnSDxMaL",
"language": "en"
},
"modification_mode": "no_modify",
"script": "Welcome to this stunning modern home where comfort meets contemporary design. The spacious living room is filled with natural light and elegant finishes. The kitchen offers sleek cabinetry and generous counter space. Each bedroom feels calm and inviting, while the bright bathroom adds a touch of luxury. Step outside to enjoy a beautiful private garden.",
"webhook_url": "https://yourserver.com/webhooks/vibepeak",
"subtitle": {
"subtitle_style_preset": "classic"
},
"elements_config": {
"enabled": true,
"watermark": {
"url": "https://example.com/logo.png",
"position": "bottom-right",
"size": 20,
"opacity": 100
},
"text": {
"content": "Powered by Vibepeak",
"color": "#FFFFFF",
"font": "Inter",
"size": 20,
"position": "center"
}
}
}'
curl -X POST https://api.vibepeak.ai/v1/real-estate/living-property \
-H "Authorization: Bearer vpk_live_xxxxx" \
-H "Content-Type: application/json" \
-d '{
"images": [
{ "url": "https://example.com/property/bedroom.jpg", "room_type": "bedroom" },
{ "url": "https://example.com/property/kitchen.jpg", "room_type": "kitchen" },
{ "url": "https://example.com/property/living-room.jpg", "room_type": "living_room" },
{ "url": "https://example.com/property/garden.jpg", "room_type": "garden" },
{ "url": "https://example.com/property/exterior.jpg", "room_type": "exterior" }
],
"voice": {
"voice_id": "EXAVITQu4vr4xnSDxMaL",
"language": "en"
},
"modification_mode": "no_modify",
"script": "Follow a full day in this wonderful family home, from the first light of morning to the calm of the evening. Bright bedrooms and a welcoming kitchen set the tone for the day, while the spacious living room becomes the heart of family life. Outside, the garden and the elegant facade complete a home designed to be lived in from sunrise to sunset.",
"selected_family_id": "family-with-kids",
"story_mode": true,
"story_locale": "en",
"webhook_url": "https://yourserver.com/webhooks/vibepeak"
}'
const response = await fetch('https://api.vibepeak.ai/v1/real-estate/living-property', {
method: 'POST',
headers: {
'Authorization': 'Bearer vpk_live_xxxxx',
'Content-Type': 'application/json'
},
body: JSON.stringify({
images: [
{ url: 'https://example.com/property/living-room.jpg', room_type: 'living_room' },
{ url: 'https://example.com/property/kitchen.jpg', room_type: 'kitchen' },
{ url: 'https://example.com/property/bedroom.jpg', room_type: 'bedroom' },
{ url: 'https://example.com/property/bathroom.jpg', room_type: 'bathroom' },
{ url: 'https://example.com/property/exterior.jpg', room_type: 'exterior' }
],
voice: {
voice_id: 'EXAVITQu4vr4xnSDxMaL',
language: 'en'
},
modification_mode: 'no_modify',
script: 'Welcome to this stunning modern home where comfort meets contemporary design. The spacious living room is filled with natural light and elegant finishes. The kitchen offers sleek cabinetry and generous counter space. Each bedroom feels calm and inviting, while the bright bathroom adds a touch of luxury. Step outside to enjoy a beautiful private garden.',
webhook_url: 'https://yourserver.com/webhooks/vibepeak',
subtitle: {
subtitle_style_preset: 'classic'
},
elements_config: {
enabled: true,
watermark: {
url: 'https://example.com/logo.png',
position: 'bottom-right',
size: 20,
opacity: 100
},
text: {
content: 'Powered by Vibepeak',
color: '#FFFFFF',
font: 'Inter',
size: 20,
position: 'center'
}
}
})
});
const task = await response.json();
console.log(`Task created: ${task.task_id}`);
console.log(`Poll at: ${response.headers.get('Location')}`);
import requests
response = requests.post(
'https://api.vibepeak.ai/v1/real-estate/living-property',
headers={
'Authorization': 'Bearer vpk_live_xxxxx',
'Content-Type': 'application/json'
},
json={
'images': [
{'url': 'https://example.com/property/living-room.jpg', 'room_type': 'living_room'},
{'url': 'https://example.com/property/kitchen.jpg', 'room_type': 'kitchen'},
{'url': 'https://example.com/property/bedroom.jpg', 'room_type': 'bedroom'},
{'url': 'https://example.com/property/bathroom.jpg', 'room_type': 'bathroom'},
{'url': 'https://example.com/property/exterior.jpg', 'room_type': 'exterior'}
],
'voice': {
'voice_id': 'EXAVITQu4vr4xnSDxMaL',
'language': 'en'
},
# change_decoration + include_humans_and_pets (default true) → two-step scenes,
# so the script uses the wider 110-140 chars/scene budget (550-700 for 5 images).
'modification_mode': 'change_decoration',
'include_humans_and_pets': True,
'script': 'Welcome to this beautifully renovated apartment where modern comfort meets timeless elegance throughout every room. The bright living room invites you to relax, with large windows that fill the space with warm natural light. The kitchen features sleek cabinetry, premium finishes, and generous counter space for cooking and gathering. Each bedroom offers a calm and restful retreat, while the elegant bathroom adds a genuine touch of luxury. Step outside to discover a private garden, perfect for morning coffee or relaxing evenings under the open sky. The home has been finished to a high standard and is ready for you to move in and enjoy from the very first day.',
'background_music': True,
'subtitle': {
'subtitle_style_preset': 'classic'
},
'elements_config': {
'enabled': True,
'watermark': {
'url': 'https://example.com/logo.png',
'position': 'bottom-right',
'size': 20,
'opacity': 100
},
'text': {
'content': 'Powered by Vibepeak',
'color': '#FFFFFF',
'font': 'Inter',
'size': 20,
'position': 'center'
}
}
}
)
task = response.json()
print(f"Task created: {task['task_id']}")
print(f"Credits charged: {task['credits_charged']}")
{
"task_id": "task_abc123xyz",
"status": "queued",
"message": "Real estate video generation request accepted",
"created_at": "2026-01-19T12:00:00Z",
"credits_charged": 15,
"livemode": true,
"request_id": "req_xyz123",
"_links": {
"self": "/v1/tasks/task_abc123xyz",
"poll_interval_seconds": 30
}
}
{
"task_id": "task_abc123xyz",
"status": "queued",
"message": "Real estate video generation request accepted",
"created_at": "2026-01-19T12:00:00Z",
"credits_charged": 0,
"livemode": false,
"request_id": "req_xyz123",
"_links": {
"self": "/v1/tasks/task_abc123xyz",
"poll_interval_seconds": 30
}
}
{
"error": {
"code": "VALIDATION_ERROR",
"message": "script is required",
"request_id": "req_xyz123",
"details": {
"field": "script",
"issues": [
{
"path": "script",
"message": "Required"
}
]
}
}
}
{
"error": {
"code": "SCRIPT_INVALID_CHARACTERS",
"message": "Script contains characters not supported by text-to-speech: \"🏠\". Emojis and other non-speech symbols are not allowed.",
"request_id": "req_xyz123",
"details": {
"invalid_characters": ["3", "$"]
}
}
}
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Provide either 'subtitle_style_preset' or 'styles', but not both.",
"request_id": "req_xyz123"
}
}
{
"error": {
"code": "SCRIPT_TOO_SHORT",
"message": "Script is too short for 5 image(s). Minimum 325 characters required (65 per scene), but got 200. Either lengthen the script or send fewer images.",
"request_id": "req_xyz123",
"details": {
"script_length": 200,
"min_length": 325,
"max_length": 425,
"image_count": 5,
"chars_per_scene_min": 65,
"chars_per_scene_max": 85
}
}
}
{
"error": {
"code": "SCRIPT_TOO_LONG",
"message": "Script is too long for 5 image(s). Maximum 700 characters allowed (140 per scene), but got 800. Either shorten the script or send more images.",
"request_id": "req_xyz123",
"details": {
"script_length": 800,
"min_length": 550,
"max_length": 700,
"image_count": 5,
"chars_per_scene_min": 110,
"chars_per_scene_max": 140
}
}
}
{
"error": {
"code": "IMAGE_RESOLUTION_TOO_LOW",
"message": "1 image(s) below the minimum resolution. Required: long side ≥ 1280px and short side ≥ 720px.",
"request_id": "req_xyz123",
"details": {
"invalid_images": ["https://example.com/thumbnail.jpg"]
}
}
}
{
"error": {
"code": "VALIDATION_ERROR",
"message": "If elements_config is enabled, you must provide at least a 'watermark' or 'text' configuration.",
"request_id": "req_xyz123",
"details": {
"field": "elements_config.enabled",
"issues": [
{
"path": "elements_config.enabled",
"message": "If elements_config is enabled, you must provide at least a 'watermark' or 'text' configuration."
}
]
}
}
}
{
"error": {
"code": "VALIDATION_ERROR",
"message": "If intro_outro is enabled, you must provide at least an 'intro' or 'outro' configuration.",
"details": {
"field": "elements_config.intro_outro.enabled",
"issues": [
{
"path": "elements_config.intro_outro.enabled",
"message": "If intro_outro is enabled, you must provide at least an 'intro' or 'outro' configuration."
}
]
},
"request_id": "req_xyz123"
}
}
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid hex color",
"request_id": "req_xyz123",
"details": {
"field": "elements_config.text.color",
"issues": [
{
"path": "elements_config.text.color",
"message": "Invalid hex color"
}
]
}
}
}
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Brand color must be a six-digit hex string such as #1A73E8, with no alpha channel",
"details": {
"field": "elements_config.intro_outro.intro.brandColorPrimary",
"issues": [
{
"path": "elements_config.intro_outro.intro.brandColorPrimary",
"message": "Brand color must be a six-digit hex string such as #1A73E8, with no alpha channel"
}
]
},
"request_id": "req_xyz123"
}
}
{
"error": {
"code": "VALIDATION_ERROR",
"message": "brandColorContrast requires brandColorPrimary on the same overlay.",
"details": {
"field": "elements_config.intro_outro.outro.brandColorContrast",
"issues": [
{
"path": "elements_config.intro_outro.outro.brandColorContrast",
"message": "brandColorContrast requires brandColorPrimary on the same overlay."
}
]
},
"request_id": "req_xyz123"
}
}
{
"error": {
"code": "VALIDATION_ERROR",
"message": "title is required by template 'ruled_caps'. Send it in values.title: an omitted field renders nothing.",
"details": {
"field": "elements_config.intro_outro.intro.values.title",
"issues": [
{
"path": "elements_config.intro_outro.intro.values.title",
"message": "title is required by template 'ruled_caps'. Send it in values.title: an omitted field renders nothing."
}
]
},
"request_id": "req_xyz123"
}
}
{
"error": {
"code": "VALIDATION_ERROR",
"message": "agent_name is required by template 'serif_business_card'. Send it in values.agent_name: an omitted field renders nothing.",
"details": {
"field": "elements_config.intro_outro.outro.values.agent_name",
"issues": [
{
"path": "elements_config.intro_outro.outro.values.agent_name",
"message": "agent_name is required by template 'serif_business_card'. Send it in values.agent_name: an omitted field renders nothing."
}
]
},
"request_id": "req_xyz123"
}
}
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Template 'custom_image' requires assets.custom_image: the URL of the image it renders.",
"details": {
"field": "elements_config.intro_outro.outro.assets.custom_image",
"issues": [
{
"path": "elements_config.intro_outro.outro.assets.custom_image",
"message": "Template 'custom_image' requires assets.custom_image: the URL of the image it renders."
}
]
},
"request_id": "req_xyz123"
}
}
{
"error": {
"code": "VOICE_NOT_FOUND",
"message": "Voice ID not found",
"request_id": "req_xyz123"
}
}
{
"error": {
"code": "VOICE_ACCESS_DENIED",
"message": "Voice not accessible",
"request_id": "req_xyz123"
}
}
{
"error": {
"code": "PLAN_NOT_ALLOWED",
"message": "Families are available on the Pro, Max and Enterprise plans. Upgrade your plan to use this feature.",
"request_id": "req_xyz123"
}
}
{
"error": {
"code": "FAMILY_NOT_FOUND",
"message": "Family not found or not accessible with this API key.",
"request_id": "req_xyz123"
}
}
{
"error": {
"code": "STORY_ROOM_TYPE_REQUIRED",
"message": "story_mode requires a room_type on every image so the scenes can be planned.",
"request_id": "req_xyz123",
"details": {
"images_missing_room_type": [1, 4]
}
}
}
{
"error": {
"code": "STORY_PLAN_FAILED",
"message": "Story planning failed. Please retry, or omit story_mode for a standard video.",
"request_id": "req_xyz123"
}
}
{
"error": {
"code": "FAMILY_NOT_READY",
"message": "The family is not ready yet: its member portraits are still generating. Poll the family until it is ready, then retry.",
"request_id": "req_xyz123"
}
}
{
"error": {
"code": "CONCURRENCY_LIMIT_EXCEEDED",
"message": "You have reached your concurrent task limit of 1. Please wait for existing tasks to complete.",
"request_id": "req_xyz123",
"details": {
"limit": 1,
"in_flight": 1,
"plan": "Plus"
}
}
}
{
"error": {
"code": "SERVICE_UNAVAILABLE",
"message": "Video generation service is temporarily unavailable. Please try again later.",
"request_id": "req_xyz123"
}
}
Example Output
Creates a new living property video from real estate images. This endpoint uses AI to transform static property photos into dynamic videos with optional virtual staging, AI-generated narration, and background music. The video generation is asynchronous - you’ll receive a task ID to poll for status or configure a webhook to be notified when complete.
Key Features
- Virtual Staging: Add people, furniture, or redecorate rooms using AI
- AI Narration: Provide your own script for professional text-to-speech narration — or set
voiceover_enabled: falsefor a music-only video - Background Music: Optional ambient music that complements your property video
- Story Mode: Turn the video into one continuous day-in-the-life story told through a family cast, with AI-planned scene order and evolving lighting from morning to night
Request Body
object[]
required
Array of image objects for the video. Must contain 5 to 9 images.You can also pass a plain URL string instead of an object — it behaves the same as
{ "url": "..." }.Each image object contains:url(required): Publicly accessible HTTP(S) URL of the property imageroom_type(optional): Type of room for better AI processingmodification_mode(optional): per-image override of the request-levelmodification_mode— omit to inheritinclude_humans_and_pets(optional): per-image override of the request-levelinclude_humans_and_pets— omit to inherit
Show Available room types
Show Available room types
bedroom, kitchen, living_room, bathroom, dining_room, office, garage, basement, attic, patio, balcony, garden, pool, exterior, entrance, hallway, laundry, otherPer-image exceptions. The top-level
modification_mode / include_humans_and_pets apply to every image. To make an exception for one image — say, keep a facade original while the rest of the gallery is restyled — set those fields on that image object only:{
"modification_mode": "change_decoration",
"include_humans_and_pets": true,
"images": [
"https://example.com/property/living-room.jpg",
{
"url": "https://example.com/property/facade.jpg",
"room_type": "exterior",
"modification_mode": "no_modify",
"include_humans_and_pets": false
}
]
}
decoration_style stays request-level — it is a global aesthetic, not a per-image toggle.All image URLs must be unique. Duplicate URLs are not allowed.
Minimum resolution (HD floor): every image’s long side must be at least 1280 px and short side at least 720 px. Images below this threshold are rejected with
IMAGE_RESOLUTION_TOO_LOW. CRMs that expose thumbnail URLs by default usually have a higher-resolution variant — use that one.boolean
default:"true"
Whether the video has a voiceover (narration). Defaults to
true.Set to false to create a music-only video: omit voice and script, and the video is produced with background music only (or silent if background_music is false). Subtitles are not available without a voiceover.object
Voice configuration for text-to-speech narration. Required when
voiceover_enabled is true (the default); omit it together with script when voiceover_enabled is false.Show Voice properties
Show Voice properties
string
required
Voice ID to use for narration. You can find available voices using the List Voices endpoint.
string
required
ISO 639-1 language code for TTS pronunciation (e.g.,
en, es, de, fr, pt).This helps produce more accurate pronunciation for the target language.Use the same language code as the script content for best results.
string
required
How to process the property images using AI.
| Value | Description |
|---|---|
no_modify | Keep rooms as-is, add realistic people for a lived-in feel |
change_decoration | Modernize old or outdated furniture and decor |
The
change_decoration mode uses AI virtual staging to transform your images. Processing may take longer for this mode.Whether people are added is controlled by
include_humans_and_pets. Together with modification_mode, it also selects the per-scene script budget — see script.furnish was previously accepted but is no longer supported. Requests using it are rejected with a VALIDATION_ERROR. Use change_decoration to restyle or furnish the room, or no_modify to keep it unchanged.string
Interior decoration style applied when
modification_mode is change_decoration. Ignored for the other modes. Defaults to a modern aesthetic when omitted.Show Available styles
Show Available styles
scandinavian, minimalist, traditional, mid-century-modern, industrial, mediterranean, modern, bohemian, mountain-rustic, luxury, japandi, wabi-sabi, organic-modern, quiet-luxuryboolean
default:"true"
Whether to add realistic people (and occasionally a pet) to the staged scenes.When enabled together with
change_decoration, the video uses longer two-step scenes (the room is restyled, then animated), which widens the per-scene script budget — see script. Set to false to keep scenes free of people and use the single-step budget.string
Narration script for text-to-speech. Required when
Two-step —
Scripts outside the applicable range are rejected with
voiceover_enabled is true (the default); omit it together with voice when voiceover_enabled is false. The length must scale with the number of images, and the per-scene budget depends on the render mode:Single-step — no_modify, or any mode with include_humans_and_pets set to false. Scenes are ~5 seconds, requiring 65–85 characters per image:| Images | Min characters | Max characters |
|---|---|---|
| 5 | 325 | 425 |
| 9 | 585 | 765 |
change_decoration with include_humans_and_pets set to true (the default). Scenes are ~7 seconds (restyle + animation), requiring 110–140 characters per image:| Images | Min characters | Max characters |
|---|---|---|
| 5 | 550 | 700 |
| 9 | 990 | 1260 |
SCRIPT_TOO_SHORT or SCRIPT_TOO_LONG.Numbers and symbols are allowed. Write the script naturally — numbers (e.g.
3 bedrooms, 580.000 €) and symbols are read correctly by text-to-speech. Only emojis and other non-speech characters (pictographs, control characters) are rejected.Write compelling property descriptions that highlight key features. The script should flow naturally when spoken aloud, and its length must fit the per-scene budget above.
boolean
default:"true"
Enable AI-generated background music.When
true, adds ambient music that complements the property video. The music is automatically mixed at an appropriate volume to not overpower the narration.string
Optional identifier of a family to cast consistently across every scene, instead of the AI casting different people scene to scene.
- For a family you own or one shared by your organization, pass its UUID.
- For a preset family, pass its slug, e.g.
family-with-kids.
ready status, and using it (whether a preset or one of your own) requires a Pro, Max, or Enterprise plan. Members can appear in different combinations and counts from scene to scene, always drawn from the same cast.Omit this field to leave casting behavior unchanged. Using a family does not change the credit cost of the video.Browse available families with List Families, or create your own with Create Family.
boolean
default:"false"
Turn the video into one continuous day-in-the-life story told through the selected family. Instead of independent per-room scenes, the AI plans the whole video at creation time: it orders the scenes from morning to night, picks a time of day for each room, chooses which family members appear in each scene and what they are doing, and evolves the lighting across the day.Requirements when Using Story Mode does not change the credit cost of the video.
story_mode is true:selected_family_idmust be set (the story is told through the family cast). Missing it is rejected withSTORY_FAMILY_REQUIRED.- Every image must carry a
room_typeso the scenes can be planned. Requests with untyped images are rejected withSTORY_ROOM_TYPE_REQUIRED; the error details list the offending image indices. - The endpoint’s usual 5 to 9 images bound applies; Story Mode adds no extra count rules.
Write the script as one continuous narration. With
story_mode, the AI chooses the scene order, so your images may not appear in the order you uploaded them. Avoid per-photo captions tied to upload order; write a single flowing script instead. The final scene order is visible in the story block of the completed task result (see Get Task).string
default:"en"
Language of the generated scene activities in the story plan (2 to 10 characters, e.g.
en, es, pt-BR). Only honored when story_mode is true.object
Subtitle configuration for word-level animated overlays. Use
subtitle_style_preset for quick setup or styles for granular control. Providing both will result in a validation error.Requires voiceover. Subtitles are derived from the narration’s word timing, so omit
subtitle (or set it to false) when voiceover_enabled is false — the request is rejected otherwise.Show Subtitle Config properties
Show Subtitle Config properties
string
Name of a predefined style to apply.
Options:
classic, cinematic, gradient, handwritten, hustle, karaoke_highlight_no_box, karaoke_red_box_phrase, karaoke_word_box_clip, minimal, neon, one_word_red_box, phrase_yellow, retro, tiktok_default, youtube_caption.object
Granular styling properties for subtitle rendering.
Show Styles properties
Show Styles properties
integer
default:"2"
SSA alignment: 1-9 (e.g., 2 for bottom-center).
string
default:"#000000"
Background color in hex format (e.g.,
#000000).integer
default:"100"
Transparency of background box: 0-255.
string
default:"phrase_blocks"
Subtitle reveal behavior. Options:
phrase_blocks, one_word, karaoke_highlight, karaoke_box_word.integer
default:"1"
Border style: 1 (Outline) or 3 (Box).
string
default:"Arial"
System font name.
integer
default:"28"
Font size as a percentage of the safe container width, not pixels (14-100). The renderer fits the longest subtitle line to occupy that percentage of the available width, so it scales with the final video resolution. The default of 28 is a legacy value that renders far smaller than every style preset (all of which use 90); send an explicit value instead of relying on it.
integer
default:"40"
Left margin in pixels (0-500).
integer
default:"40"
Right margin in pixels (0-500).
integer
default:"200"
Vertical/Bottom margin in pixels (0-500).
number
default:"0.3"
Max silence (sec) between words before phrase break (0.01-2).
integer
default:"6"
Automatic line wrapping constraint (1-12).
integer
default:"2"
Thickness of text stroke (0-10).
string
default:"#000000"
Color of text stroke in hex format.
string
default:"#FFFFFF"
Default text color in hex format.
string
default:"#FFFFFF"
Alt color for highlights/karaoke in hex format.
integer
default:"0"
Thickness of text drop shadow (0-10).
string
HTTPS URL to receive webhook notification when the task completes.See Webhooks for payload format and verification details.
Webhook URLs must use HTTPS and cannot point to private/internal networks (SSRF protection).
object
Configuration for visual elements and branding overlays. If not provided, elements are disabled by default.
Show Elements Config properties
Show Elements Config properties
boolean
default:"false"
Global toggle for the elements overlay feature.
object
Watermark (logo) branding configuration.
Show Watermark properties
Show Watermark properties
string
required
URL of the uploaded watermark image. Must be a valid public URL.
string
default:"bottom-right"
Anchor point for the watermark placement. Ignored when
mode is mosaic.
Options: top-left, top-center, top-right, center-left, center, center-right, bottom-left, bottom-center, bottom-right.number
default:"20"
Relative scale percentage of the watermark (0-100). Ignored when
mode is mosaic.number
default:"100"
Transparency level (0 for transparent, 100 for opaque). Applies in both modes.
string
default:"single"
Watermark positioning mode.
single places one logo at position/size. mosaic repeats the logo as a fixed, code-determined tiled pattern across the whole frame instead, ignoring position and size.Options: single, mosaic.integer
default:"-20"
Tile rotation in degrees (
-45 to 45), applied to every tile. Only meaningful when mode is mosaic.object
Text overlay configuration for static labels or call-to-actions.
Show Text properties
Show Text properties
string
required
Text content to be rendered on the video (max 20 characters).
string
default:"#FFFFFF"
Hex color code for the text (e.g.,
#FFFFFF).string
default:"Inter"
Font family for the text overlay.
Options:
Alegreya, DM Mono, Inter, Libre Bodoni, Quicksand, Roboto, Raleway, Noto Sans, Zilla Slab.number
default:"100"
Transparency level of the text (0-100).
number
default:"20"
Font size scale relative to video height (1-100).
string
default:"center"
Anchor point for the text placement. Same options as watermark position.
object
Branded intro and outro overlays rendered over the opening and closing of the video.Each overlay covers roughly the first or last 1.5 seconds of the video and never adds duration. The intro is fully visible from the first frame and animates out; the outro animates in and holds through the final frame. Overlays render on top of the watermark; subtitles stay above everything.There are four valid combinations: intro only (
Each design also ships with a default animation, listed per template in the gallery; A branded pair, with the intro carrying both colors and the outro carrying only a primary:
intro_outro is independent of the top-level enabled flag. The top-level enabled gates watermark and text only; intro_outro carries its own toggle. To add an intro or outro without a watermark or text overlay, send "enabled": false at the top level and "enabled": true inside intro_outro:{
"elements_config": {
"enabled": false,
"intro_outro": {
"enabled": true,
"intro": { "...": "..." }
}
}
}
outro omitted), outro only (intro omitted), both, or "enabled": false (no overlays; any intro/outro objects are ignored). When enabled is true, at least one of intro or outro must be provided, otherwise the request is rejected with VALIDATION_ERROR.Show Intro/Outro properties
Show Intro/Outro properties
boolean
default:"false"
Toggle for the intro/outro overlays. When
true, at least one of intro or outro is required.object
Overlay shown over the opening of the video. Accepts intro template ids only; an outro template id in this slot is rejected.
Show Intro/outro selection properties
Show Intro/outro selection properties
string
required
The id of the design to render, such as
ruled_caps. Every design is shown in the template gallery; GET /v1/intro-outro/templates returns the same catalogue as JSON.The intro slot accepts intro designs only and the outro slot accepts outro designs only; naming one in the wrong slot is a VALIDATION_ERROR.integer
required
Version of the template to render. The current catalogue version is
1; any other value is rejected.string
required
Animation preset id (see the table below). The intro plays the preset as an exit; the outro plays it as an entrance.
object
default:"{}"
Text values keyed by the template’s field ids. The ids are the same for every design of a kind, with one exception:
- intro:
title(required, up to 40 characters) andsubtitle(optional, up to 24) - outro:
agent_name(required, up to 32) andcontact_line(optional, up to 64) - the
custom_imageoutro: no text fields at all. Sendvaluesempty.
title on an intro, or an agent_name on any of the eleven contact-card outros, that is missing, empty or only whitespace is refused by the request schema with 400 VALIDATION_ERROR. details.field names the field as a dotted path, elements_config.intro_outro.intro.values.title or elements_config.intro_outro.outro.values.agent_name, and details.issues repeats it with every other field the schema refused in the same request. No task is created and no credits are charged.An optional field you leave out renders nothing. There is no fallback: an intro sent without subtitle draws no subtitle line, exactly as if you had sent an empty string. The default_value published by GET /v1/intro-outro/templates is sample copy for previewing a design in your own picker, and it is never drawn into a video.String values are limited to 500 characters by this API; the per-field lengths above are what each design was drawn to hold, and a longer value is fitted down to size rather than refused.A key that is not one of the ids above is accepted and then ignored. Only the ids the template declares are read, so
{ "name": "Alex Rivera" } on an outro contributes nothing at all. agent_name is then missing, so that payload is rejected with 400 VALIDATION_ERROR on elements_config.intro_outro.outro.values.agent_name rather than rendering anything. Check your keys against the field reference.object
default:"{}"
Uploaded image URLs keyed by the template’s image field ids. The catalogue declares two, both on outros:
agent_photo, the portrait the eleven contact-card designs draw, and custom_image, the full-frame image the custom_image design requires.custom_image is required on the custom_image outro: leaving it out is a 400 VALIDATION_ERROR whose details.field is elements_config.intro_outro.outro.assets.custom_image. agent_photo is optional, and a contact card sent without one draws no portrait rather than a stand-in.Each URL must be a publicly accessible HTTP(S) URL of at most 2048 characters, and cannot point to a private or internal network. A custom_image must additionally be a JPG, PNG or WEBP of at most 8 MB whose shortest edge is at least 400 px, or the request is rejected with 400 INVALID_PARAMETER. That one is not a schema rejection: the image is fetched and measured after the body validates, so it answers with a details.field and no details.issues.Intros declare no image field, so assets on an intro selection does nothing.Alongside custom_image the server records the URL you sent under a companion key, custom_image_source, so a later re-render starts from your original rather than from an already adapted frame. You never send that key and the renderer ignores it.string
Your agency’s brand color as
#RRGGBB. It paints the line the design leads with: the headline of an intro, the name on an outro card.Six hex digits only, upper or lower case (#1A73E8 and #1a73e8 are both accepted). The three-digit shorthand #1AE and the eight-digit alpha form #1A73E8FF are rejected with VALIDATION_ERROR.Optional, and set per overlay: intro and outro carry their own colors and are branded independently, so you can brand one end and leave the other exactly as delivered.All 27 templates take it. Sent on its own it also paints everything brandColorContrast would, so the design renders in one color rather than half branded. The custom_image outro is the one design with nothing to repaint: it accepts both colors and ignores them.string
Your agency’s secondary color as
#RRGGBB, same format rules. It paints the second line of the design and the furniture drawn around it: rules, underlines, frames, corner brackets, rings, sunbursts, dividers, photo borders and, on glow_caps, the halo the design is built on.Optional, and only valid alongside brandColorPrimary on the same overlay. A brandColorContrast sent on its own is rejected with VALIDATION_ERROR, because a contrast color brands nothing without a primary.When it is omitted, every slot it would have painted takes brandColorPrimary instead.There is no minimum distance between the two colors. Two shades of one color are accepted, and what they render is a design that reads in a single tone.object
Overlay shown over the closing of the video. Accepts outro template ids only. Same properties as
intro; the animation plays as an entrance instead of an exit.custom_image closes on an image of your own instead of a contact card. It is an outro like the other eleven and not an extra scene: it covers the same closing window and adds no duration. Send the image as assets.custom_image, leave values empty, and pick any of the nine animations. brandColorPrimary and brandColorContrast are accepted on it and then ignored, because the design draws no type of its own.When the image’s aspect ratio differs from the video’s, the server extends its background out to the video’s shape before rendering, so nothing in the image is ever cropped. That preparation runs while this request is being accepted, so a POST carrying a custom_image outro takes a few seconds, and up to about 25 seconds when the ratios differ. Allow for it in your client timeout.The image must be a JPG, PNG or WEBP of at most 8 MB whose shortest edge is at least 400 px, or the request is rejected with 400 INVALID_PARAMETER. If the preparation cannot run at all, the request fails with a retryable 503 INTRO_OUTRO_ADAPTATION_UNAVAILABLE before any task is created or any credit is charged. The outro itself costs no extra credits.Show Available templates
Show Available templates
15 intro designs and 12 outro designs. Every one takes
brandColorPrimary and brandColorContrast, although the custom_image outro draws no type of its own and so repaints nothing.The template gallery shows all 27 rendered, in both orientations, with each design’s ids, accepted fields, default animation and the colours it ships with. GET /v1/intro-outro/templates returns the same catalogue as JSON.See How the two colors land below for what each colour paints.Show How the two colors land
Show How the two colors land
Every template takes both colors.
brandColorPrimary goes on the one line the design is read by, and brandColorContrast on everything the design sets apart from it, so a branded frame shows the pair you actually chose rather than one color twice.Nothing is drawn behind the type. The colors replace the ones the design ships with, in the places its designer opened, and no shape is added to the frame. Two shapes are deliberately left out because both are knockouts rather than ornament: the photo gap in sunburst_serif and the ring gap in bordered_cream carry their own design’s background color so that what is under them shows through, and painting either would draw a ring the design does not have.Readability is yours to judge, and nothing is refused for it. Every outro draws its own background plate, and a branded line on one is worth checking against it: quiet_offwhite is near white, bold_ring_card and serif_business_card are white, forest_green is a dark forest green and black_gold is near black. A mid-tone brand color contrasts weakly with all of them. The design’s own type was drawn at 3 to 1 against its plate, so that is the number to aim at, but a color under it is rendered exactly as sent rather than adjusted or turned away. If a line reads thin, a lighter or darker shade of the same color, or a different design, is the fix.Intros have no plate of their own, so there is nothing to measure a color against: what sits behind an intro’s type is your video. Nothing is added to compensate either. Branding is a repaint and never changes a design’s composition: every layer keeps the position, the opacity and the visibility the design ships with, so a branded overlay is the design you picked in the colors you sent and nothing else.Show Available animations
Show Available animations
The same preset list applies to both slots. The intro only ever animates out (it is fully formed at frame zero) and the outro only ever animates in (it holds through the final frame).
| Animation ID | Motion |
|---|---|
fade | Opacity fade |
slide_up | Slides toward the top edge |
slide_down | Slides toward the bottom edge |
slide_left | Slides toward the left edge |
slide_right | Slides toward the right edge |
scale | Scales in or out |
blur | Blur dissolve |
wipe | Directional wipe |
stagger | Elements animate one after another |
animation is required on every selection, so it is a recommendation rather than a fallback.No color is refused for how it looks. Any
#RRGGBB reaches the render on any design: two shades of one color are fine and simply render the design in a single tone, and a color that reads thinly on a card’s own background is drawn as sent rather than adjusted or turned away. Only the shape is validated, so a value that is not six hex digits, or a brandColorContrast with no brandColorPrimary, is a VALIDATION_ERROR.A malformed color, or a brandColorContrast sent without a brandColorPrimary, is caught earlier: those are rejected up front with a 400 VALIDATION_ERROR and no task is created.{
"elements_config": {
"enabled": false,
"intro_outro": {
"enabled": true,
"intro": {
"templateId": "ruled_caps",
"templateVersion": 1,
"animation": "fade",
"values": { "title": "Sunset Villa", "subtitle": "Marbella, Spain" },
"assets": {},
"brandColorPrimary": "#1A73E8",
"brandColorContrast": "#FFFFFF"
},
"outro": {
"templateId": "serif_business_card",
"templateVersion": 1,
"animation": "slide_up",
"values": { "agent_name": "Alex Rivera", "contact_line": "[email protected] · +34 600 000 000" },
"assets": { "agent_photo": "https://example.com/agent-photo.jpg" },
"brandColorPrimary": "#1A73E8"
}
}
}
}
On this endpoint the overlays are burned inside the main render, so the task does not pass through a separate
intro_outro status while they are applied.Test Mode
string
default:"success"
Sandbox-only scenario selector. Honored only for test-mode (
vpk_test_) keys and silently ignored for live keys, so it is safe to leave in shared request-building code.| Value | Outcome |
|---|---|
success | Synthetic task completes with a watermarked sample video |
fail | Synthetic task fails with a sanitized, public-safe error |
slow | Like success, but completes after a noticeably longer delay |
Test mode never spends credits or runs the real pipeline. See Test Mode for the full sandbox model.
Response
Returns a202 Accepted response with task details.
string
required
Initial task status. Always
queued for new tasks.string
required
Human-readable confirmation message.
string
required
Task creation timestamp (ISO 8601 format).
integer
required
Number of credits charged for this request (15 credits). Always
0 for test-mode requests.boolean
required
true for live (vpk_live_) requests; false for test-mode (vpk_test_) requests. Use this to tell a real task from a sandbox one. See Test Mode.string
required
Unique request ID for support reference.
object
required
HATEOAS links for navigation.
self: URL to poll for task statuspoll_interval_seconds: Recommended polling interval (30 seconds)
Response Headers
| Header | Description |
|---|---|
Location | URL to poll for task status (/v1/tasks/{taskId}) |
Retry-After | Recommended polling interval in seconds (30) |
curl -X POST https://api.vibepeak.ai/v1/real-estate/living-property \
-H "Authorization: Bearer vpk_live_xxxxx" \
-H "Content-Type: application/json" \
-d '{
"images": [
{ "url": "https://example.com/property/living-room.jpg", "room_type": "living_room" },
{ "url": "https://example.com/property/kitchen.jpg", "room_type": "kitchen" },
{ "url": "https://example.com/property/bedroom.jpg", "room_type": "bedroom" },
{ "url": "https://example.com/property/bathroom.jpg", "room_type": "bathroom" },
{ "url": "https://example.com/property/exterior.jpg", "room_type": "exterior" }
],
"voice": {
"voice_id": "EXAVITQu4vr4xnSDxMaL",
"language": "en"
},
"modification_mode": "no_modify",
"script": "Welcome to this stunning modern home where comfort meets contemporary design. The spacious living room is filled with natural light and elegant finishes. The kitchen offers sleek cabinetry and generous counter space. Each bedroom feels calm and inviting, while the bright bathroom adds a touch of luxury. Step outside to enjoy a beautiful private garden.",
"webhook_url": "https://yourserver.com/webhooks/vibepeak",
"subtitle": {
"subtitle_style_preset": "classic"
},
"elements_config": {
"enabled": true,
"watermark": {
"url": "https://example.com/logo.png",
"position": "bottom-right",
"size": 20,
"opacity": 100
},
"text": {
"content": "Powered by Vibepeak",
"color": "#FFFFFF",
"font": "Inter",
"size": 20,
"position": "center"
}
}
}'
curl -X POST https://api.vibepeak.ai/v1/real-estate/living-property \
-H "Authorization: Bearer vpk_live_xxxxx" \
-H "Content-Type: application/json" \
-d '{
"images": [
{ "url": "https://example.com/property/bedroom.jpg", "room_type": "bedroom" },
{ "url": "https://example.com/property/kitchen.jpg", "room_type": "kitchen" },
{ "url": "https://example.com/property/living-room.jpg", "room_type": "living_room" },
{ "url": "https://example.com/property/garden.jpg", "room_type": "garden" },
{ "url": "https://example.com/property/exterior.jpg", "room_type": "exterior" }
],
"voice": {
"voice_id": "EXAVITQu4vr4xnSDxMaL",
"language": "en"
},
"modification_mode": "no_modify",
"script": "Follow a full day in this wonderful family home, from the first light of morning to the calm of the evening. Bright bedrooms and a welcoming kitchen set the tone for the day, while the spacious living room becomes the heart of family life. Outside, the garden and the elegant facade complete a home designed to be lived in from sunrise to sunset.",
"selected_family_id": "family-with-kids",
"story_mode": true,
"story_locale": "en",
"webhook_url": "https://yourserver.com/webhooks/vibepeak"
}'
const response = await fetch('https://api.vibepeak.ai/v1/real-estate/living-property', {
method: 'POST',
headers: {
'Authorization': 'Bearer vpk_live_xxxxx',
'Content-Type': 'application/json'
},
body: JSON.stringify({
images: [
{ url: 'https://example.com/property/living-room.jpg', room_type: 'living_room' },
{ url: 'https://example.com/property/kitchen.jpg', room_type: 'kitchen' },
{ url: 'https://example.com/property/bedroom.jpg', room_type: 'bedroom' },
{ url: 'https://example.com/property/bathroom.jpg', room_type: 'bathroom' },
{ url: 'https://example.com/property/exterior.jpg', room_type: 'exterior' }
],
voice: {
voice_id: 'EXAVITQu4vr4xnSDxMaL',
language: 'en'
},
modification_mode: 'no_modify',
script: 'Welcome to this stunning modern home where comfort meets contemporary design. The spacious living room is filled with natural light and elegant finishes. The kitchen offers sleek cabinetry and generous counter space. Each bedroom feels calm and inviting, while the bright bathroom adds a touch of luxury. Step outside to enjoy a beautiful private garden.',
webhook_url: 'https://yourserver.com/webhooks/vibepeak',
subtitle: {
subtitle_style_preset: 'classic'
},
elements_config: {
enabled: true,
watermark: {
url: 'https://example.com/logo.png',
position: 'bottom-right',
size: 20,
opacity: 100
},
text: {
content: 'Powered by Vibepeak',
color: '#FFFFFF',
font: 'Inter',
size: 20,
position: 'center'
}
}
})
});
const task = await response.json();
console.log(`Task created: ${task.task_id}`);
console.log(`Poll at: ${response.headers.get('Location')}`);
import requests
response = requests.post(
'https://api.vibepeak.ai/v1/real-estate/living-property',
headers={
'Authorization': 'Bearer vpk_live_xxxxx',
'Content-Type': 'application/json'
},
json={
'images': [
{'url': 'https://example.com/property/living-room.jpg', 'room_type': 'living_room'},
{'url': 'https://example.com/property/kitchen.jpg', 'room_type': 'kitchen'},
{'url': 'https://example.com/property/bedroom.jpg', 'room_type': 'bedroom'},
{'url': 'https://example.com/property/bathroom.jpg', 'room_type': 'bathroom'},
{'url': 'https://example.com/property/exterior.jpg', 'room_type': 'exterior'}
],
'voice': {
'voice_id': 'EXAVITQu4vr4xnSDxMaL',
'language': 'en'
},
# change_decoration + include_humans_and_pets (default true) → two-step scenes,
# so the script uses the wider 110-140 chars/scene budget (550-700 for 5 images).
'modification_mode': 'change_decoration',
'include_humans_and_pets': True,
'script': 'Welcome to this beautifully renovated apartment where modern comfort meets timeless elegance throughout every room. The bright living room invites you to relax, with large windows that fill the space with warm natural light. The kitchen features sleek cabinetry, premium finishes, and generous counter space for cooking and gathering. Each bedroom offers a calm and restful retreat, while the elegant bathroom adds a genuine touch of luxury. Step outside to discover a private garden, perfect for morning coffee or relaxing evenings under the open sky. The home has been finished to a high standard and is ready for you to move in and enjoy from the very first day.',
'background_music': True,
'subtitle': {
'subtitle_style_preset': 'classic'
},
'elements_config': {
'enabled': True,
'watermark': {
'url': 'https://example.com/logo.png',
'position': 'bottom-right',
'size': 20,
'opacity': 100
},
'text': {
'content': 'Powered by Vibepeak',
'color': '#FFFFFF',
'font': 'Inter',
'size': 20,
'position': 'center'
}
}
}
)
task = response.json()
print(f"Task created: {task['task_id']}")
print(f"Credits charged: {task['credits_charged']}")
Example: mosaic watermark
Setelements_config.watermark.mode to mosaic to tile the logo across the whole frame instead of placing it once at position. position and size are ignored in mosaic mode; rotation controls the tile angle (-45 to 45, default -20).
curl -X POST https://api.vibepeak.ai/v1/real-estate/living-property \
-H "Authorization: Bearer vpk_live_xxxxx" \
-H "Content-Type: application/json" \
-d '{
"images": [
"https://example.com/property/living-room.jpg",
"https://example.com/property/kitchen.jpg",
"https://example.com/property/bedroom.jpg",
"https://example.com/property/bathroom.jpg",
"https://example.com/property/exterior.jpg"
],
"voice": {
"voice_id": "EXAVITQu4vr4xnSDxMaL",
"language": "en"
},
"modification_mode": "no_modify",
"script": "Welcome to this stunning modern home where comfort meets contemporary design. The spacious living room is filled with natural light and elegant finishes. The kitchen offers sleek cabinetry and generous counter space. Each bedroom feels calm and inviting, while the bright bathroom adds a touch of luxury. Step outside to enjoy a beautiful private garden.",
"elements_config": {
"enabled": true,
"watermark": {
"url": "https://example.com/logo.png",
"opacity": 60,
"mode": "mosaic",
"rotation": -20
}
}
}'
const response = await fetch('https://api.vibepeak.ai/v1/real-estate/living-property', {
method: 'POST',
headers: {
'Authorization': 'Bearer vpk_live_xxxxx',
'Content-Type': 'application/json'
},
body: JSON.stringify({
images: [
'https://example.com/property/living-room.jpg',
'https://example.com/property/kitchen.jpg',
'https://example.com/property/bedroom.jpg',
'https://example.com/property/bathroom.jpg',
'https://example.com/property/exterior.jpg'
],
voice: {
voice_id: 'EXAVITQu4vr4xnSDxMaL',
language: 'en'
},
modification_mode: 'no_modify',
script: 'Welcome to this stunning modern home where comfort meets contemporary design. The spacious living room is filled with natural light and elegant finishes. The kitchen offers sleek cabinetry and generous counter space. Each bedroom feels calm and inviting, while the bright bathroom adds a touch of luxury. Step outside to enjoy a beautiful private garden.',
elements_config: {
enabled: true,
watermark: {
url: 'https://example.com/logo.png',
opacity: 60,
mode: 'mosaic',
rotation: -20
}
}
})
});
const task = await response.json();
console.log(`Task created: ${task.task_id}`);
import requests
response = requests.post(
'https://api.vibepeak.ai/v1/real-estate/living-property',
headers={
'Authorization': 'Bearer vpk_live_xxxxx',
'Content-Type': 'application/json'
},
json={
'images': [
'https://example.com/property/living-room.jpg',
'https://example.com/property/kitchen.jpg',
'https://example.com/property/bedroom.jpg',
'https://example.com/property/bathroom.jpg',
'https://example.com/property/exterior.jpg'
],
'voice': {
'voice_id': 'EXAVITQu4vr4xnSDxMaL',
'language': 'en'
},
'modification_mode': 'no_modify',
'script': 'Welcome to this stunning modern home where comfort meets contemporary design. The spacious living room is filled with natural light and elegant finishes. The kitchen offers sleek cabinetry and generous counter space. Each bedroom feels calm and inviting, while the bright bathroom adds a touch of luxury. Step outside to enjoy a beautiful private garden.',
'elements_config': {
'enabled': True,
'watermark': {
'url': 'https://example.com/logo.png',
'opacity': 60,
'mode': 'mosaic',
'rotation': -20
}
}
}
)
task = response.json()
print(f"Task created: {task['task_id']}")
Example: custom image outro
To close on a flyer, a floor plan or any image of your own instead of a contact card, pick thecustom_image outro. It takes one asset and no text, so values stays empty, and it rides the same closing window as every other outro: it adds no duration to the video.
If the image’s aspect ratio does not match the video’s, the server extends its background out to the video’s shape before rendering, so the image is never cropped. That runs while this request is being accepted, which is why the POST below can take a few seconds, and up to about 25 seconds when the ratios differ. The image must be a JPG, PNG or WEBP of at most 8 MB whose shortest edge is at least 400 px, and it costs no extra credits.
curl -X POST https://api.vibepeak.ai/v1/real-estate/living-property \
-H "Authorization: Bearer vpk_live_xxxxx" \
-H "Content-Type: application/json" \
-d '{
"images": [
{ "url": "https://example.com/property/living-room.jpg", "room_type": "living_room" },
{ "url": "https://example.com/property/kitchen.jpg", "room_type": "kitchen" },
{ "url": "https://example.com/property/bedroom.jpg", "room_type": "bedroom" }
],
"voice": {
"voice_id": "EXAVITQu4vr4xnSDxMaL",
"language": "en"
},
"modification_mode": "no_modify",
"script": "Welcome to this stunning modern home where comfort meets contemporary design. The spacious living room is filled with natural light and elegant finishes. The kitchen offers sleek cabinetry and generous counter space.",
"elements_config": {
"enabled": false,
"intro_outro": {
"enabled": true,
"outro": {
"templateId": "custom_image",
"templateVersion": 1,
"animation": "fade",
"values": {},
"assets": { "custom_image": "https://example.com/listing-flyer.jpg" }
}
}
}
}'
const response = await fetch('https://api.vibepeak.ai/v1/real-estate/living-property', {
method: 'POST',
headers: {
'Authorization': 'Bearer vpk_live_xxxxx',
'Content-Type': 'application/json'
},
body: JSON.stringify({
images: [
{ url: 'https://example.com/property/living-room.jpg', room_type: 'living_room' },
{ url: 'https://example.com/property/kitchen.jpg', room_type: 'kitchen' },
{ url: 'https://example.com/property/bedroom.jpg', room_type: 'bedroom' }
],
voice: {
voice_id: 'EXAVITQu4vr4xnSDxMaL',
language: 'en'
},
modification_mode: 'no_modify',
script: 'Welcome to this stunning modern home where comfort meets contemporary design...',
elements_config: {
enabled: false,
intro_outro: {
enabled: true,
outro: {
templateId: 'custom_image',
templateVersion: 1,
animation: 'fade',
values: {},
assets: { custom_image: 'https://example.com/listing-flyer.jpg' }
}
}
}
})
});
const task = await response.json();
console.log(`Task created: ${task.task_id}`);
import requests
response = requests.post(
'https://api.vibepeak.ai/v1/real-estate/living-property',
headers={
'Authorization': 'Bearer vpk_live_xxxxx',
'Content-Type': 'application/json'
},
timeout=60,
json={
'images': [
{'url': 'https://example.com/property/living-room.jpg', 'room_type': 'living_room'},
{'url': 'https://example.com/property/kitchen.jpg', 'room_type': 'kitchen'},
{'url': 'https://example.com/property/bedroom.jpg', 'room_type': 'bedroom'}
],
'voice': {
'voice_id': 'EXAVITQu4vr4xnSDxMaL',
'language': 'en'
},
'modification_mode': 'no_modify',
'script': 'Welcome to this stunning modern home where comfort meets contemporary design...',
'elements_config': {
'enabled': False,
'intro_outro': {
'enabled': True,
'outro': {
'templateId': 'custom_image',
'templateVersion': 1,
'animation': 'fade',
'values': {},
'assets': {'custom_image': 'https://example.com/listing-flyer.jpg'}
}
}
}
}
)
task = response.json()
print(f"Task created: {task['task_id']}")
{
"task_id": "task_abc123xyz",
"status": "queued",
"message": "Real estate video generation request accepted",
"created_at": "2026-01-19T12:00:00Z",
"credits_charged": 15,
"livemode": true,
"request_id": "req_xyz123",
"_links": {
"self": "/v1/tasks/task_abc123xyz",
"poll_interval_seconds": 30
}
}
{
"task_id": "task_abc123xyz",
"status": "queued",
"message": "Real estate video generation request accepted",
"created_at": "2026-01-19T12:00:00Z",
"credits_charged": 0,
"livemode": false,
"request_id": "req_xyz123",
"_links": {
"self": "/v1/tasks/task_abc123xyz",
"poll_interval_seconds": 30
}
}
{
"error": {
"code": "VALIDATION_ERROR",
"message": "script is required",
"request_id": "req_xyz123",
"details": {
"field": "script",
"issues": [
{
"path": "script",
"message": "Required"
}
]
}
}
}
{
"error": {
"code": "SCRIPT_INVALID_CHARACTERS",
"message": "Script contains characters not supported by text-to-speech: \"🏠\". Emojis and other non-speech symbols are not allowed.",
"request_id": "req_xyz123",
"details": {
"invalid_characters": ["3", "$"]
}
}
}
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Provide either 'subtitle_style_preset' or 'styles', but not both.",
"request_id": "req_xyz123"
}
}
{
"error": {
"code": "SCRIPT_TOO_SHORT",
"message": "Script is too short for 5 image(s). Minimum 325 characters required (65 per scene), but got 200. Either lengthen the script or send fewer images.",
"request_id": "req_xyz123",
"details": {
"script_length": 200,
"min_length": 325,
"max_length": 425,
"image_count": 5,
"chars_per_scene_min": 65,
"chars_per_scene_max": 85
}
}
}
{
"error": {
"code": "SCRIPT_TOO_LONG",
"message": "Script is too long for 5 image(s). Maximum 700 characters allowed (140 per scene), but got 800. Either shorten the script or send more images.",
"request_id": "req_xyz123",
"details": {
"script_length": 800,
"min_length": 550,
"max_length": 700,
"image_count": 5,
"chars_per_scene_min": 110,
"chars_per_scene_max": 140
}
}
}
{
"error": {
"code": "IMAGE_RESOLUTION_TOO_LOW",
"message": "1 image(s) below the minimum resolution. Required: long side ≥ 1280px and short side ≥ 720px.",
"request_id": "req_xyz123",
"details": {
"invalid_images": ["https://example.com/thumbnail.jpg"]
}
}
}
{
"error": {
"code": "VALIDATION_ERROR",
"message": "If elements_config is enabled, you must provide at least a 'watermark' or 'text' configuration.",
"request_id": "req_xyz123",
"details": {
"field": "elements_config.enabled",
"issues": [
{
"path": "elements_config.enabled",
"message": "If elements_config is enabled, you must provide at least a 'watermark' or 'text' configuration."
}
]
}
}
}
{
"error": {
"code": "VALIDATION_ERROR",
"message": "If intro_outro is enabled, you must provide at least an 'intro' or 'outro' configuration.",
"details": {
"field": "elements_config.intro_outro.enabled",
"issues": [
{
"path": "elements_config.intro_outro.enabled",
"message": "If intro_outro is enabled, you must provide at least an 'intro' or 'outro' configuration."
}
]
},
"request_id": "req_xyz123"
}
}
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid hex color",
"request_id": "req_xyz123",
"details": {
"field": "elements_config.text.color",
"issues": [
{
"path": "elements_config.text.color",
"message": "Invalid hex color"
}
]
}
}
}
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Brand color must be a six-digit hex string such as #1A73E8, with no alpha channel",
"details": {
"field": "elements_config.intro_outro.intro.brandColorPrimary",
"issues": [
{
"path": "elements_config.intro_outro.intro.brandColorPrimary",
"message": "Brand color must be a six-digit hex string such as #1A73E8, with no alpha channel"
}
]
},
"request_id": "req_xyz123"
}
}
{
"error": {
"code": "VALIDATION_ERROR",
"message": "brandColorContrast requires brandColorPrimary on the same overlay.",
"details": {
"field": "elements_config.intro_outro.outro.brandColorContrast",
"issues": [
{
"path": "elements_config.intro_outro.outro.brandColorContrast",
"message": "brandColorContrast requires brandColorPrimary on the same overlay."
}
]
},
"request_id": "req_xyz123"
}
}
{
"error": {
"code": "VALIDATION_ERROR",
"message": "title is required by template 'ruled_caps'. Send it in values.title: an omitted field renders nothing.",
"details": {
"field": "elements_config.intro_outro.intro.values.title",
"issues": [
{
"path": "elements_config.intro_outro.intro.values.title",
"message": "title is required by template 'ruled_caps'. Send it in values.title: an omitted field renders nothing."
}
]
},
"request_id": "req_xyz123"
}
}
{
"error": {
"code": "VALIDATION_ERROR",
"message": "agent_name is required by template 'serif_business_card'. Send it in values.agent_name: an omitted field renders nothing.",
"details": {
"field": "elements_config.intro_outro.outro.values.agent_name",
"issues": [
{
"path": "elements_config.intro_outro.outro.values.agent_name",
"message": "agent_name is required by template 'serif_business_card'. Send it in values.agent_name: an omitted field renders nothing."
}
]
},
"request_id": "req_xyz123"
}
}
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Template 'custom_image' requires assets.custom_image: the URL of the image it renders.",
"details": {
"field": "elements_config.intro_outro.outro.assets.custom_image",
"issues": [
{
"path": "elements_config.intro_outro.outro.assets.custom_image",
"message": "Template 'custom_image' requires assets.custom_image: the URL of the image it renders."
}
]
},
"request_id": "req_xyz123"
}
}
{
"error": {
"code": "VOICE_NOT_FOUND",
"message": "Voice ID not found",
"request_id": "req_xyz123"
}
}
{
"error": {
"code": "VOICE_ACCESS_DENIED",
"message": "Voice not accessible",
"request_id": "req_xyz123"
}
}
{
"error": {
"code": "PLAN_NOT_ALLOWED",
"message": "Families are available on the Pro, Max and Enterprise plans. Upgrade your plan to use this feature.",
"request_id": "req_xyz123"
}
}
{
"error": {
"code": "FAMILY_NOT_FOUND",
"message": "Family not found or not accessible with this API key.",
"request_id": "req_xyz123"
}
}
{
"error": {
"code": "STORY_ROOM_TYPE_REQUIRED",
"message": "story_mode requires a room_type on every image so the scenes can be planned.",
"request_id": "req_xyz123",
"details": {
"images_missing_room_type": [1, 4]
}
}
}
{
"error": {
"code": "STORY_PLAN_FAILED",
"message": "Story planning failed. Please retry, or omit story_mode for a standard video.",
"request_id": "req_xyz123"
}
}
{
"error": {
"code": "FAMILY_NOT_READY",
"message": "The family is not ready yet: its member portraits are still generating. Poll the family until it is ready, then retry.",
"request_id": "req_xyz123"
}
}
{
"error": {
"code": "CONCURRENCY_LIMIT_EXCEEDED",
"message": "You have reached your concurrent task limit of 1. Please wait for existing tasks to complete.",
"request_id": "req_xyz123",
"details": {
"limit": 1,
"in_flight": 1,
"plan": "Plus"
}
}
}
{
"error": {
"code": "SERVICE_UNAVAILABLE",
"message": "Video generation service is temporarily unavailable. Please try again later.",
"request_id": "req_xyz123"
}
}
Error Codes
| Code | Status | Description |
|---|---|---|
INVALID_JSON | 400 | Request body is not valid JSON (malformed/truncated payload) |
VALIDATION_ERROR | 400 | Invalid request parameters |
INVALID_IMAGE_URL | 400 | One or more image URLs are inaccessible or invalid |
INVALID_WATERMARK_URL | 400 | The elements_config watermark URL is inaccessible or does not return an image |
VALIDATION_ERROR | 400 | A required intro/outro field is missing or blank: values.title on an intro, values.agent_name on a contact-card outro, assets.custom_image on the custom_image outro. details.field carries the dotted path and details.issues every refused field |
INVALID_PARAMETER | 400 | The custom_image outro image is not a JPG, PNG or WEBP of at most 8 MB with a shortest edge of at least 400 px |
IMAGE_RESOLUTION_TOO_LOW | 400 | One or more images are below the HD floor (long ≥ 1280 px, short ≥ 720 px) |
SCRIPT_TOO_SHORT | 400 | Script is shorter than the per-scene minimum (image_count × 65 single-step, × 120 two-step) |
SCRIPT_TOO_LONG | 400 | Script is longer than the per-scene maximum (image_count × 85 single-step, × 150 two-step) |
SCRIPT_INVALID_CHARACTERS | 400 | Script contains emojis or other non-speech characters not supported by TTS |
VOICE_NOT_FOUND | 404 | The specified voice ID does not exist |
VOICE_ACCESS_DENIED | 403 | The specified voice is not accessible to your account |
FAMILY_NOT_FOUND | 404 | The selected_family_id doesn’t exist, or isn’t a preset, yours, or shared by your organization |
FAMILY_NOT_READY | 422 | The selected family exists but isn’t in ready status yet |
STORY_FAMILY_REQUIRED | 400 | story_mode is true but selected_family_id is missing |
STORY_ROOM_TYPE_REQUIRED | 400 | story_mode is true but one or more images lack a room_type (details list the image indices) |
STORY_PLAN_FAILED | 502 | Story planning failed; no credits were charged. Retry, or omit story_mode for a standard video |
STORY_MODE_UNAVAILABLE | 503 | Story Mode is temporarily unavailable. Retry later, or omit story_mode for a standard video |
INVALID_API_KEY | 401 | Invalid or missing API key |
PLAN_REQUIRED | 403 | Plan doesn’t include API access |
PLAN_NOT_ALLOWED | 403 | Your plan doesn’t allow using a family (requires Pro, Max, or Enterprise) |
INSUFFICIENT_CREDITS | 402 | Not enough credits to process the request |
CONCURRENCY_LIMIT_EXCEEDED | 429 | Concurrent task limit reached |
SERVICE_UNAVAILABLE | 503 | Video generation service temporarily unavailable |
INTRO_OUTRO_ADAPTATION_UNAVAILABLE | 503 | The custom_image outro could not be prepared. Retryable: no task was created and no credits were charged |
Credits
This endpoint charges 15 credits per request upon successful task creation. If the task fails during processing, credits are not refunded.Processing Time
Video generation typically takes 3-5 minutes depending on:- Number of images
- Selected modification mode (
change_decorationtakes longer) - Current system load
Retry-After header (30 seconds) as a guide for polling frequency.
Next Steps
After creating a task:- Poll for status: Use Get Task to check progress
- Wait for webhook: If configured, receive notification when complete
- Download video: Access the video URL from the completed task result

