Genfire Public API

Full API Reference

Use Genfire as a production content engine for images, videos, speech, music, sound effects, lip-sync, product extraction, workflow automation, and webhook-driven orchestration.

Base URL

/v1

https://api.genfire.ai/v1

Auth

Bearer

API key or OAuth access token

Async Pattern

Runs

Poll GET /runs/{'{runId}'} for progress

Machine Contract

OpenAPI 3.1

Download the JSON contract

Common Conventions

  • Send Authorization: Bearer ... on every protected endpoint.
  • Send Idempotency-Key on mutating generation, workflow, batch, and product extraction endpoints that require it.
  • Most long-running operations return a run resource immediately and finish asynchronously.
  • Errors follow one JSON shape. Example:
{
  "type": "https://api.genfire.ai/errors/invalid_prompt",
  "title": "Invalid Prompt",
  "status": 400,
  "detail": "prompt is required.",
  "code": "invalid_prompt",
  "request_id": "req_123"
}

Discovery

Public Model Aliases

Always use these aliases in API requests. Do not send internal provider model ids.

image_generation

Genfire v1

image.genfire_v1

Genfire's signature image model — tuned for ad/product creative.

{
  "aspect_ratios": [
    "1:1",
    "16:9",
    "9:16",
    "4:3",
    "3:4"
  ],
  "max_count": 4,
  "max_reference_images": 16
}

image_generation

Nano Banana 2

image.nano_banana_2 default

Google's general-purpose image model. Fast, broad subject coverage. Default.

{
  "aspect_ratios": [
    "1:1",
    "16:9",
    "9:16",
    "4:3",
    "3:4",
    "21:9",
    "9:21"
  ],
  "max_count": 4
}

image_generation

Nano Banana Pro

image.nano_banana_pro

Premium photoreal image generation, higher fidelity than Nano Banana 2.

{
  "aspect_ratios": [
    "1:1",
    "16:9",
    "9:16",
    "4:3",
    "3:4"
  ],
  "max_count": 4
}

image_generation

Nano Banana

image.nano_banana

Standard speed and quality. Cheaper than Pro for high-volume use.

{
  "aspect_ratios": [
    "1:1",
    "16:9",
    "9:16",
    "4:3",
    "3:4"
  ],
  "max_count": 4
}

image_generation

Nano Banana Lite

image.nano_banana_lite

Gemini 3.1 Flash Lite Image — ultra-low latency, cheapest tier. Supports editing.

{
  "aspect_ratios": [
    "1:1",
    "16:9",
    "9:16",
    "4:3",
    "3:4",
    "21:9",
    "9:21"
  ],
  "max_count": 4
}

image_generation

Nano Banana 2 Lite

image.nano_banana_2_lite

Gemini 3.1 Flash Lite Image (v2) — ultra-low latency text-to-image. No edit endpoint.

{
  "aspect_ratios": [
    "1:1",
    "16:9",
    "9:16",
    "4:3",
    "3:4",
    "21:9",
    "9:21"
  ],
  "max_count": 4
}

image_generation

GPT Image 2

image.gpt_image_2

OpenAI GPT Image 2 — premium photorealistic generation.

{
  "aspect_ratios": [
    "1:1",
    "16:9",
    "9:16",
    "4:3",
    "3:4"
  ],
  "max_count": 4,
  "max_reference_images": 16
}

image_generation

Seedream 4.5

image.seedream_v45

ByteDance Seedream 4.5 — strong product and ad visuals, photoreal.

{
  "aspect_ratios": [
    "1:1",
    "16:9",
    "9:16"
  ],
  "max_count": 4
}

image_generation

Seedream 5.0 Lite

image.seedream_v5_lite

ByteDance Seedream 5.0 Lite — multilingual text rendering, web-search-aware.

{
  "aspect_ratios": [
    "1:1",
    "16:9",
    "9:16"
  ],
  "max_count": 4
}

image_generation

Seedream 5.0 Pro

image.seedream_v5_pro

ByteDance Seedream 5.0 Pro — flagship photoreal image + multi-reference edit, up to 2K, up to 10 reference images.

{
  "aspect_ratios": [
    "1:1",
    "16:9",
    "9:16"
  ],
  "max_count": 6
}

image_generation

Qwen Image 2

image.qwen_image_2

Alibaba Qwen Image 2 — strong typography, posters, 2K generation.

{
  "aspect_ratios": [
    "1:1",
    "16:9",
    "9:16",
    "4:3",
    "3:4"
  ],
  "max_count": 4
}

image_generation

Qwen Image 2 Pro

image.qwen_image_2_pro

Premium Qwen Image 2 with enhanced detail.

{
  "aspect_ratios": [
    "1:1",
    "16:9",
    "9:16",
    "4:3",
    "3:4"
  ],
  "max_count": 4
}

image_generation

Qwen Image 3

image.qwen_image_3

Alibaba Qwen Image 3 — bilingual (CN/EN) text rendering up to 2K. Edit mode takes 1-3 reference images, addressed as "image 1".."image 3" in the prompt.

{
  "aspect_ratios": [
    "1:1",
    "16:9",
    "9:16",
    "4:3",
    "3:4"
  ],
  "max_count": 4,
  "max_prompt_chars": 800,
  "max_reference_images": 3
}

image_generation

Recraft V4 Vector

image.recraft_v4_vector

Recraft V4 vector output — a true SVG rather than a raster image. Logos, icons and flat illustration that has to scale cleanly.

{
  "aspect_ratios": [
    "1:1",
    "16:9",
    "9:16",
    "4:3",
    "3:4"
  ],
  "max_count": 4
}

image_generation

Recraft V4 Pro Vector

image.recraft_v4_pro_vector

Premium Recraft V4 vector output — true SVG at the Pro tier’s fidelity.

{
  "aspect_ratios": [
    "1:1",
    "16:9",
    "9:16",
    "4:3",
    "3:4"
  ],
  "max_count": 4
}

image_generation

Recraft V4.1

image.recraft_v41

Recraft V4.1 — sharper prompt control and cleaner composition than V4. Tuned for brand systems and editorial work.

{
  "aspect_ratios": [
    "1:1",
    "16:9",
    "9:16",
    "4:3",
    "3:4"
  ],
  "max_count": 4
}

image_generation

Recraft V4.1 Pro

image.recraft_v41_pro

Recraft V4.1 at the Pro tier — high-resolution raster for large-format and production work.

{
  "aspect_ratios": [
    "1:1",
    "16:9",
    "9:16",
    "4:3",
    "3:4"
  ],
  "max_count": 4
}

image_generation

Recraft V4.1 Vector

image.recraft_v41_vector

Recraft V4.1 vector output — true SVG.

{
  "aspect_ratios": [
    "1:1",
    "16:9",
    "9:16",
    "4:3",
    "3:4"
  ],
  "max_count": 4
}

image_generation

Recraft V4.1 Pro Vector

image.recraft_v41_pro_vector

Recraft V4.1 Pro vector output — true SVG at the Pro tier’s fidelity.

{
  "aspect_ratios": [
    "1:1",
    "16:9",
    "9:16",
    "4:3",
    "3:4"
  ],
  "max_count": 4
}

image_generation

Recraft V4.1 Utility

image.recraft_v41_utility

A faster, lighter V4.1 runtime for high-volume work — ideation, A/B exploration and content pipelines. Same price and parameters as image.recraft_v41; the difference is throughput.

{
  "aspect_ratios": [
    "1:1",
    "16:9",
    "9:16",
    "4:3",
    "3:4"
  ],
  "max_count": 4
}

image_generation

Recraft V4.1 Utility Pro

image.recraft_v41_utility_pro

V4.1 Pro output on the faster Utility runtime — large-format work at pipeline scale. Same price and parameters as image.recraft_v41_pro.

{
  "aspect_ratios": [
    "1:1",
    "16:9",
    "9:16",
    "4:3",
    "3:4"
  ],
  "max_count": 4
}

image_generation

Recraft V4 Styles

image.recraft_v4_style

Recraft V4 with a custom style. Supply a custom style either as `style_id` (trained earlier) or as 1-10 `image_urls` style references, which trains one inline and returns its `style_id` for reuse.

{
  "aspect_ratios": [
    "1:1",
    "16:9",
    "9:16",
    "4:3",
    "3:4"
  ],
  "max_count": 4,
  "max_reference_images": 10
}

image_generation

Recraft V4 Styles Pro

image.recraft_v4_style_pro

Recraft V4 Styles at the Pro tier. Supply a custom style either as `style_id` (trained earlier) or as 1-10 `image_urls` style references, which trains one inline and returns its `style_id` for reuse.

{
  "aspect_ratios": [
    "1:1",
    "16:9",
    "9:16",
    "4:3",
    "3:4"
  ],
  "max_count": 4,
  "max_reference_images": 10
}

image_generation

Recraft V4 Styles Vector

image.recraft_v4_style_vector

Recraft V4 Styles with true SVG output. Supply a custom style either as `style_id` (trained earlier) or as 1-10 `image_urls` style references, which trains one inline and returns its `style_id` for reuse.

{
  "aspect_ratios": [
    "1:1",
    "16:9",
    "9:16",
    "4:3",
    "3:4"
  ],
  "max_count": 4,
  "max_reference_images": 10
}

image_generation

Recraft V4 Styles Pro Vector

image.recraft_v4_style_pro_vector

Recraft V4 Styles, Pro tier, true SVG output. Supply a custom style either as `style_id` (trained earlier) or as 1-10 `image_urls` style references, which trains one inline and returns its `style_id` for reuse.

{
  "aspect_ratios": [
    "1:1",
    "16:9",
    "9:16",
    "4:3",
    "3:4"
  ],
  "max_count": 4,
  "max_reference_images": 10
}

image_generation

Recraft V4

image.recraft_v4

Design-grade image generation with reliable text rendering.

{
  "aspect_ratios": [
    "1:1",
    "16:9",
    "9:16",
    "4:3",
    "3:4"
  ],
  "max_count": 4
}

image_generation

Recraft V4 Pro

image.recraft_v4_pro

Premium Recraft V4 — top quality for marketing/branding visuals.

{
  "aspect_ratios": [
    "1:1",
    "16:9",
    "9:16",
    "4:3",
    "3:4"
  ],
  "max_count": 4
}

image_generation

Grok Imagine

image.grok_imagine

xAI Grok Imagine — stylized, strong prompt following.

{
  "aspect_ratios": [
    "1:1",
    "16:9",
    "9:16"
  ],
  "max_count": 4
}

image_generation

Grok Imagine Pro

image.grok_imagine_pro

xAI Grok Imagine Pro (Quality mode) — sharper detail, stronger text rendering, up to 2K.

{
  "aspect_ratios": [
    "1:1",
    "16:9",
    "9:16",
    "4:3",
    "3:4",
    "3:2",
    "2:3",
    "2:1",
    "1:2",
    "20:9",
    "9:20",
    "19.5:9",
    "9:19.5"
  ],
  "max_count": 4,
  "resolutions": [
    "1K",
    "2K"
  ]
}

image_generation

Grok Imagine 2.0

image.grok_imagine_2

xAI Grok Imagine 2.0 — the latest Grok Imagine generation. Up to 2K, 13 aspect ratios, and a quality tier (low | medium, default medium). Edit accepts up to 3 reference images.

{
  "aspect_ratios": [
    "1:1",
    "16:9",
    "9:16",
    "4:3",
    "3:4",
    "3:2",
    "2:3",
    "2:1",
    "1:2",
    "20:9",
    "9:20",
    "19.5:9",
    "9:19.5"
  ],
  "max_count": 4,
  "resolutions": [
    "1K",
    "2K"
  ],
  "qualities": [
    "low",
    "medium"
  ],
  "max_input_images": 3
}

image_generation

Muse Image

image.muse_image

Meta Muse Image — faithful instruction-following with accurate fine detail (text, plots, QR codes). Edit mode does precise, localized changes and composes from up to 10 reference images. No resolution or quality control; omitting aspect_ratio lets Muse size the output from the prompt.

{
  "aspect_ratios": [
    "21:9",
    "16:9",
    "4:3",
    "3:2",
    "1:1",
    "2:3",
    "3:4",
    "9:16",
    "9:21"
  ],
  "max_count": 4,
  "max_reference_images": 10
}

video_generation

Flux 3

video.flux_3

Black Forest Labs Flux 3 — frontier video with synchronized audio included at no extra cost. Routes to text/image-to-video, first-last-frame, keyframe pinning (keyframes[]), or extend (source_video_url). 5-20s, 720p or 1080p.

{
  "aspect_ratios": [
    "auto",
    "21:9",
    "2:1",
    "16:9",
    "4:3",
    "1:1",
    "3:4",
    "9:16"
  ],
  "duration_seconds": [
    5,
    6,
    7,
    8,
    9,
    10,
    11,
    12,
    13,
    14,
    15,
    16,
    17,
    18,
    19,
    20
  ],
  "resolutions": [
    "720p",
    "1080p"
  ],
  "supports_audio": true,
  "max_keyframes": 10,
  "source_video_max_seconds": 15,
  "source_video_max_mb": 50
}

video_generation

Flux 3 Draft

video.flux_3_draft

Cheap 720p Flux 3 preview (~3.5x less than full quality). Returns a draft_cache_url alongside the video; pass that back to this model to render the same shot at full 1080p. Same four routing modes as Flux 3.

{
  "aspect_ratios": [
    "auto",
    "21:9",
    "2:1",
    "16:9",
    "4:3",
    "1:1",
    "3:4",
    "9:16"
  ],
  "duration_seconds": [
    5,
    6,
    7,
    8,
    9,
    10,
    11,
    12,
    13,
    14,
    15,
    16,
    17,
    18,
    19,
    20
  ],
  "resolutions": [
    "720p"
  ],
  "supports_audio": true,
  "max_keyframes": 10,
  "source_video_max_seconds": 15,
  "source_video_max_mb": 50
}

video_generation

Veo 3.1

video.veo_3_1 default

Google Veo 3.1 — premium text/image-to-video with native audio. Supports first-last-frame interpolation. Default.

{
  "aspect_ratios": [
    "16:9",
    "9:16",
    "1:1"
  ],
  "duration_seconds": [
    4,
    5,
    8
  ],
  "supports_audio": true
}

video_generation

Veo 3.1 Fast

video.veo_3_1_fast

Cheaper, faster Veo 3.1 variant. Supports first-last-frame interpolation.

{
  "aspect_ratios": [
    "16:9",
    "9:16",
    "1:1"
  ],
  "duration_seconds": [
    4,
    5,
    8
  ],
  "supports_audio": true
}

video_generation

Veo 3.1 Lite

video.veo_3_1_lite

Lower-cost Lite variant of Veo 3.1. Supports first-last-frame interpolation.

{
  "aspect_ratios": [
    "16:9",
    "9:16",
    "1:1"
  ],
  "duration_seconds": [
    4,
    5,
    8
  ],
  "supports_audio": true
}

video_generation

Veo 3.1 Extend

video.veo_3_1_extend

Extend an existing Veo-created video by up to 7 seconds. Requires source_video_url.

{
  "aspect_ratios": [
    "16:9",
    "9:16"
  ],
  "duration_seconds": [
    7
  ],
  "supports_audio": true
}

video_generation

Veo 3

video.veo_3

Veo 3 — high-quality cinematic generation with audio (predecessor to Veo 3.1).

{
  "aspect_ratios": [
    "16:9",
    "9:16"
  ],
  "duration_seconds": [
    8
  ],
  "supports_audio": true
}

video_generation

Gemini Omni Flash 1.1

video.gemini_omni_flash_v11

Google Gemini Omni Flash 1.1 — adds a 360p-4k resolution ladder, an end-frame on image-to-video, and reference video clips. 3-10s, 16:9 or 9:16. Control pacing and audio in the prompt.

{
  "aspect_ratios": [
    "16:9",
    "9:16"
  ],
  "duration_seconds": [
    3,
    4,
    5,
    6,
    7,
    8,
    9,
    10
  ],
  "resolutions": [
    "360p",
    "720p",
    "1080p",
    "4k"
  ],
  "reference_image_urls": 10,
  "reference_video_urls": 3,
  "supports_audio": false
}

video_generation

Gemini Omni Flash

video.gemini_omni_flash

Google Gemini Omni Flash — fast, low-cost text/image-to-video. Supports reference images and video-to-video editing. 3-10s, 16:9 or 9:16. Control pacing and audio in the prompt.

{
  "aspect_ratios": [
    "16:9",
    "9:16"
  ],
  "duration_seconds": [
    3,
    4,
    5,
    6,
    7,
    8,
    9,
    10
  ],
  "supports_audio": false
}

video_generation

Veo 3 Fast

video.veo_3_fast

Cheaper Veo 3 variant — same quality tier, faster turnaround.

{
  "aspect_ratios": [
    "16:9",
    "9:16"
  ],
  "duration_seconds": [
    8
  ],
  "supports_audio": true
}

video_generation

Kling O3 Standard

video.kling_o3

Kling O3 standard — smooth motion, strong subject consistency.

{
  "aspect_ratios": [
    "16:9",
    "9:16",
    "1:1"
  ],
  "duration_seconds": [
    5,
    10
  ],
  "supports_audio": true
}

video_generation

Kling O3 Pro

video.kling_o3_pro

Pro tier of Kling O3 — better quality at higher cost. Supports video-to-video reference (use source_video_url + reference_image_urls).

{
  "aspect_ratios": [
    "16:9",
    "9:16",
    "1:1"
  ],
  "duration_seconds": [
    5,
    10
  ],
  "supports_audio": true
}

video_generation

Kling O3 4K

video.kling_o3_4k

Kling O3 at 4K resolution. Higher cost, top-tier quality.

{
  "aspect_ratios": [
    "16:9",
    "9:16",
    "1:1"
  ],
  "duration_seconds": [
    5,
    10
  ],
  "resolution": "4k",
  "supports_audio": true
}

video_generation

Kling V3 Standard

video.kling_v3

Kling V3 standard.

{
  "aspect_ratios": [
    "16:9",
    "9:16",
    "1:1"
  ],
  "duration_seconds": [
    5,
    10
  ],
  "supports_audio": true
}

video_generation

Kling V3 Pro

video.kling_v3_pro

Kling V3 pro — top quality.

{
  "aspect_ratios": [
    "16:9",
    "9:16",
    "1:1"
  ],
  "duration_seconds": [
    5,
    10
  ],
  "supports_audio": true
}

video_generation

Kling V3 Motion Control

video.kling_v3_motion_control

Transfer motion from a reference video onto a character image. Requires both image_url (character) and source_video_url (motion reference).

{
  "aspect_ratios": [
    "16:9",
    "9:16",
    "1:1"
  ],
  "duration_seconds": [
    5
  ]
}

video_generation

Kling V3 Pro Motion Control

video.kling_v3_pro_motion_control

Pro-tier Kling V3 motion-control — higher quality character animation. Requires both image_url and source_video_url.

{
  "aspect_ratios": [
    "16:9",
    "9:16",
    "1:1"
  ],
  "duration_seconds": [
    5
  ]
}

video_generation

Kling V3 4K

video.kling_v3_4k

Kling V3 at 4K resolution.

{
  "aspect_ratios": [
    "16:9",
    "9:16",
    "1:1"
  ],
  "duration_seconds": [
    5,
    10
  ],
  "resolution": "4k",
  "supports_audio": true
}

video_generation

Kling 2.6

video.kling_v26

Kling 2.6 — text/image to video. Kling 2.6 has a single generation tier; this alias resolves to the same endpoints as video.kling_v26_pro.

{
  "aspect_ratios": [
    "16:9",
    "9:16",
    "1:1"
  ],
  "duration_seconds": [
    5,
    10
  ]
}

video_generation

Kling 2.6 Pro

video.kling_v26_pro

Kling 2.6 pro tier — higher quality.

{
  "aspect_ratios": [
    "16:9",
    "9:16",
    "1:1"
  ],
  "duration_seconds": [
    5,
    10
  ]
}

video_generation

Kling 2.6 Motion Control

video.kling_v26_motion_control

Motion-control variant of Kling 2.6 (legacy). Requires image_url + source_video_url.

{
  "aspect_ratios": [
    "16:9",
    "9:16",
    "1:1"
  ],
  "duration_seconds": [
    5
  ]
}

video_generation

Kling 2.5 Turbo Pro

video.kling_v25_turbo

Faster Kling variant (legacy but reliable).

{
  "aspect_ratios": [
    "16:9",
    "9:16",
    "1:1"
  ],
  "duration_seconds": [
    5,
    10
  ]
}

video_generation

Kling 2.1 Master

video.kling_v21_master

Kling 2.1 Master (legacy) — enhanced quality.

{
  "aspect_ratios": [
    "16:9",
    "9:16",
    "1:1"
  ],
  "duration_seconds": [
    5,
    10
  ]
}

video_generation

Sora 2

video.sora_2

OpenAI Sora 2 — text and image to video, 4–20s.

{
  "aspect_ratios": [
    "16:9",
    "9:16",
    "1:1"
  ],
  "duration_seconds": [
    4,
    8,
    12,
    16,
    20
  ]
}

video_generation

H3 Max

video.hailuo_03_max

fal's post-trained MiniMax H3 variant — stronger prompt adherence and higher throughput, from text or a first frame (with optional last-frame keyframe). Caps at 768p and has no reference mode; use video.hailuo_03 for references or 2K.

{
  "aspect_ratios": [
    "21:9",
    "16:9",
    "4:3",
    "1:1",
    "3:4",
    "9:16"
  ],
  "duration_seconds": [
    5,
    6,
    7,
    8,
    9,
    10,
    11,
    12,
    13,
    14,
    15
  ],
  "resolutions": [
    "480p",
    "768p"
  ]
}

video_generation

Hailuo 03

video.hailuo_03

MiniMax Hailuo 03 — 2K video from text, a first frame (with optional last-frame keyframe), or reference images/videos/audio.

{
  "aspect_ratios": [
    "21:9",
    "16:9",
    "4:3",
    "1:1",
    "3:4",
    "9:16"
  ],
  "duration_seconds": [
    5,
    6,
    7,
    8,
    9,
    10,
    11,
    12,
    13,
    14,
    15
  ],
  "resolutions": [
    "768p",
    "2k"
  ],
  "reference_image_urls": 9,
  "reference_video_urls": 3,
  "reference_audio_urls": 3,
  "reference_media_seconds": [
    2,
    15
  ]
}

video_generation

Hailuo 2.3

video.hailuo_23

MiniMax Hailuo 2.3 — dynamic video generation.

{
  "aspect_ratios": [
    "16:9",
    "9:16",
    "1:1"
  ],
  "duration_seconds": [
    6,
    10
  ]
}

video_generation

Hailuo 2.3 Pro

video.hailuo_23_pro

MiniMax Hailuo 2.3 Pro tier.

{
  "aspect_ratios": [
    "16:9",
    "9:16",
    "1:1"
  ],
  "duration_seconds": [
    6,
    10
  ]
}

video_generation

Hailuo 02

video.hailuo_02

MiniMax Hailuo 02 (legacy) — image-to-video standard tier.

{
  "aspect_ratios": [
    "16:9",
    "9:16",
    "1:1"
  ],
  "duration_seconds": [
    6,
    10
  ]
}

video_generation

Hailuo 02 Fast

video.hailuo_02_fast

Faster Hailuo 02 image-to-video variant.

{
  "aspect_ratios": [
    "16:9",
    "9:16",
    "1:1"
  ],
  "duration_seconds": [
    6,
    10
  ]
}

video_generation

Hailuo 2.3 Fast

video.hailuo_23_fast

Faster Hailuo 2.3 image-to-video standard tier.

{
  "aspect_ratios": [
    "16:9",
    "9:16",
    "1:1"
  ],
  "duration_seconds": [
    6,
    10
  ]
}

video_generation

Hailuo 2.3 Fast Pro

video.hailuo_23_fast_pro

Faster Hailuo 2.3 pro-tier image-to-video.

{
  "aspect_ratios": [
    "16:9",
    "9:16",
    "1:1"
  ],
  "duration_seconds": [
    6,
    10
  ]
}

video_generation

Luma Dream Machine

video.luma_dream_machine

Luma Dream Machine — fluid motion, distinctive style.

{
  "aspect_ratios": [
    "16:9",
    "9:16",
    "1:1"
  ],
  "duration_seconds": [
    5,
    9
  ]
}

video_generation

WAN 2.2

video.wan_v22

WAN 2.2 — strong character animation.

{
  "aspect_ratios": [
    "16:9",
    "9:16",
    "1:1"
  ],
  "duration_seconds": [
    5,
    8
  ]
}

video_generation

WAN 2.5 Preview

video.wan_25_preview

WAN 2.5 preview — newer than 2.2, may change without notice.

{
  "aspect_ratios": [
    "16:9",
    "9:16",
    "1:1"
  ],
  "duration_seconds": [
    5,
    8
  ]
}

video_generation

WAN Animate (Replace)

video.wan_animate_replace

WAN animate-replace — swap subject in source video using a reference image. Requires image_url + source_video_url.

{
  "aspect_ratios": [
    "16:9",
    "9:16",
    "1:1"
  ],
  "duration_seconds": [
    5
  ]
}

video_generation

WAN Animate (Move)

video.wan_animate_move

WAN animate-move — animate static images with natural motion from a reference video. Requires image_url + source_video_url.

{
  "aspect_ratios": [
    "16:9",
    "9:16",
    "1:1"
  ],
  "duration_seconds": [
    5
  ]
}

video_generation

Seedance 2.0

video.seedance_2_0

ByteDance Seedance 2.0 — text/image/reference to video. Supports up to 4k.

{
  "aspect_ratios": [
    "auto",
    "21:9",
    "16:9",
    "4:3",
    "1:1",
    "3:4",
    "9:16"
  ],
  "duration_seconds": [
    4,
    5,
    6,
    7,
    8,
    9,
    10,
    11,
    12,
    13,
    14,
    15
  ],
  "resolutions": [
    "480p",
    "720p",
    "1080p",
    "4k"
  ],
  "supports_audio": true
}

video_generation

Seedance 2.0 Fast

video.seedance_2_0_fast

Faster, cheaper Seedance 2.0 variant. Caps at 720p.

{
  "aspect_ratios": [
    "auto",
    "21:9",
    "16:9",
    "4:3",
    "1:1",
    "3:4",
    "9:16"
  ],
  "duration_seconds": [
    4,
    5,
    6,
    7,
    8,
    9,
    10,
    11,
    12,
    13,
    14,
    15
  ],
  "resolutions": [
    "480p",
    "720p"
  ],
  "supports_audio": true
}

video_generation

Seedance 2.0 Mini

video.seedance_2_0_mini

Smallest, cheapest Seedance 2.0 variant. Caps at 720p; no bitrate_mode.

{
  "aspect_ratios": [
    "auto",
    "21:9",
    "16:9",
    "4:3",
    "1:1",
    "3:4",
    "9:16"
  ],
  "duration_seconds": [
    4,
    5,
    6,
    7,
    8,
    9,
    10,
    11,
    12,
    13,
    14,
    15
  ],
  "resolutions": [
    "480p",
    "720p"
  ],
  "supports_audio": true
}

video_generation

Seedance 2.5

video.seedance_2_5

ByteDance Seedance 2.5 — text/image/reference to video. 4-30s clips with native audio; reference-to-video takes up to 30 images, 10 videos, and 10 audio clips. 480p/720p/1080p (no 4k) and no speed tiers.

{
  "aspect_ratios": [
    "auto",
    "21:9",
    "16:9",
    "4:3",
    "1:1",
    "3:4",
    "9:16"
  ],
  "duration_seconds": [
    4,
    5,
    6,
    7,
    8,
    9,
    10,
    11,
    12,
    13,
    14,
    15,
    16,
    17,
    18,
    19,
    20,
    21,
    22,
    23,
    24,
    25,
    26,
    27,
    28,
    29,
    30
  ],
  "resolutions": [
    "480p",
    "720p",
    "1080p"
  ],
  "supports_audio": true,
  "max_reference_images": 30,
  "max_reference_videos": 10,
  "max_reference_audio": 10
}

video_generation

Wan 3.0

video.wan_3

Alibaba Wan 3.0 — text/image/reference to video. 2-30s clips with native synchronized audio; reference-to-video takes up to 10 images, 5 videos, and 5 audio clips. 480p/720p/1080p (default 1080p, no 4k) and no speed tiers.

{
  "aspect_ratios": [
    "adaptive",
    "16:9",
    "4:3",
    "1:1",
    "3:4",
    "9:16"
  ],
  "duration_seconds": [
    2,
    3,
    4,
    5,
    6,
    7,
    8,
    9,
    10,
    11,
    12,
    13,
    14,
    15,
    16,
    17,
    18,
    19,
    20,
    21,
    22,
    23,
    24,
    25,
    26,
    27,
    28,
    29,
    30
  ],
  "resolutions": [
    "480p",
    "720p",
    "1080p"
  ],
  "supports_audio": true,
  "max_reference_images": 10,
  "max_reference_videos": 5,
  "max_reference_audio": 5
}

video_generation

Wan 3.0 Prime

video.wan_3_prime

Alibaba Wan 3.0 Prime — the faster, higher-fidelity Wan 3.0 tier at 1.4x the price. Identical inputs: text/image/reference to video, 2-30s, native audio, up to 10 image + 5 video + 5 audio references, 480p/720p/1080p.

{
  "aspect_ratios": [
    "adaptive",
    "16:9",
    "4:3",
    "1:1",
    "3:4",
    "9:16"
  ],
  "duration_seconds": [
    2,
    3,
    4,
    5,
    6,
    7,
    8,
    9,
    10,
    11,
    12,
    13,
    14,
    15,
    16,
    17,
    18,
    19,
    20,
    21,
    22,
    23,
    24,
    25,
    26,
    27,
    28,
    29,
    30
  ],
  "resolutions": [
    "480p",
    "720p",
    "1080p"
  ],
  "supports_audio": true,
  "max_reference_images": 10,
  "max_reference_videos": 5,
  "max_reference_audio": 5
}

video_generation

Grok Imagine Video

video.grok_video

xAI Grok Imagine — high-fidelity text/image to video.

{
  "aspect_ratios": [
    "16:9",
    "4:3",
    "3:2",
    "1:1",
    "2:3",
    "3:4",
    "9:16"
  ],
  "duration_seconds": [
    1,
    2,
    3,
    4,
    5,
    6,
    7,
    8,
    9,
    10
  ],
  "resolutions": [
    "480p",
    "720p"
  ]
}

video_generation

Grok Imagine Video v1.5

video.grok_video_v15

xAI Grok Imagine v1.5 — text-to-video, image-to-video, or reference-to-video from up to 7 reference images.

{
  "duration_seconds": [
    1,
    2,
    3,
    4,
    5,
    6,
    7,
    8,
    9,
    10,
    11,
    12,
    13,
    14,
    15
  ],
  "resolutions": [
    "480p",
    "720p",
    "1080p"
  ],
  "aspect_ratios": [
    "16:9",
    "4:3",
    "3:2",
    "1:1",
    "2:3",
    "3:4",
    "9:16"
  ]
}

video_generation

Grok Imagine Edit

video.grok_video_edit

Edit existing videos with text prompts. Requires source_video_url.

{
  "aspect_ratios": [
    "16:9",
    "9:16",
    "1:1"
  ],
  "duration_seconds": [
    4,
    5,
    8,
    10
  ]
}

video_generation

Grok Imagine Extend

video.grok_video_extend

Extend an existing video by 2–10s. Requires source_video_url.

{
  "aspect_ratios": [
    "16:9",
    "9:16",
    "1:1"
  ],
  "duration_seconds": [
    2,
    5,
    10
  ]
}

video_generation

Happy Horse v1.1

video.happy_horse

Alibaba Happy Horse v1.1 — text/image/reference-to-video, plus video-edit.

{
  "aspect_ratios": [
    "16:9",
    "9:16",
    "1:1",
    "4:3",
    "3:4",
    "21:9",
    "9:21",
    "5:4",
    "4:5"
  ],
  "duration_seconds": [
    3,
    4,
    5,
    6,
    7,
    8,
    9,
    10,
    11,
    12,
    13,
    14,
    15
  ]
}

speech_generation

ElevenLabs Turbo v2.5

speech.elevenlabs_turbo_v2_5 default

Low-latency TTS, balance of quality and speed. Default.

{
  "max_characters": 40000
}

speech_generation

ElevenLabs Flash v2.5

speech.elevenlabs_flash_v2_5

Fastest ElevenLabs TTS, lowest cost.

{
  "max_characters": 40000
}

speech_generation

ElevenLabs v3

speech.elevenlabs_v3

Highest-quality expressive voice generation.

{
  "max_characters": 40000
}

speech_generation

ElevenLabs Multilingual v2

speech.elevenlabs_multilingual_v2

29 languages, high fidelity.

{
  "max_characters": 40000
}

speech_generation

Seed Audio 1.0

speech.seed_audio_1_0

ByteDance Seed Audio 1.0 — general text-to-audio: natural multilingual TTS plus full audio scenes (dialogue, ambience, radio dramas) from a prompt. voice_id is OPTIONAL and takes a Seed preset name (e.g. `vivi_mixed_en_zh_ja_es_id`, `mindy_en_es_id_pt_zh`, `kian_en_zh`, `sophie_en_zh`, `magnus_en_zh`) — NOT an ElevenLabs/cloned voice id; omit it to let the model narrate. Accepts up to 3 reference audio clips via audio_urls (reference them in the prompt as @Audio1–@Audio3) OR one reference image via image_url, plus speed/volume/pitch, output_format (wav|mp3|pcm|ogg_opus) and sample_rate. Billed per second (billed seconds ≈ ceil(text length / 15)).

{
  "max_characters": 2048,
  "max_reference_audio": 3
}

music_generation

ElevenLabs Music v1

music.elevenlabs_music_v1 default

Prompt-based music generation up to 10 minutes. Also accepts a `composition_plan` (MusicPrompt: positive/negative_global_styles + sections[] with lyrics lines) instead of a prompt for full structural control; `respect_sections_durations` controls how strictly section durations are enforced.

{
  "max_duration_seconds": 600
}

music_generation

ElevenLabs Music v2

music.elevenlabs_music_v2

ElevenLabs music_v2 — higher-quality music generation up to 10 minutes from a prompt, or a chunk-based `composition_plan` (chunks[] with text incl. [Section]/{direction} markup, duration_ms, positive/negative_styles, optional per-chunk audio conditioning refs + `seed`).

{
  "max_duration_seconds": 600
}

music_generation

Lyria 3 Pro

music.lyria3_pro

Google Lyria 3 Pro — full structured songs up to 3 minutes with vocals, lyrics, and multi-language support. Accepts an optional image_url for inspiration (no negative prompting). Flat per-generation fee (duration is not configurable).

{
  "max_duration_seconds": 180,
  "prompt_max_length": 5000
}

music_generation

MiniMax Music 3

music.minimax_music_3

MiniMax Music 3 — sings YOUR lyrics. `lyrics` is REQUIRED (structure tags like [verse]/[chorus] must each sit on their own line) alongside a `prompt` describing genre, BPM, key, vocals and arrangement. `duration_seconds` is an upper bound of 1-300 (default 60; the model may finish earlier) and billing is per second of that bound. Also accepts `num_inference_steps` (1-100, default 30), `guidance_scale` (0-20, default 1.7) and `seed`. Returns 44.1 kHz stereo WAV. No image input, no negative prompting, no composition_plan.

{
  "max_duration_seconds": 300,
  "prompt_max_length": 5000
}

sound_effect_generation

ElevenLabs SFX

sfx.elevenlabs_v1 default

Sound effect generation up to 30s.

{
  "max_duration_seconds": 30
}

transcription

OpenAI Whisper v1

transcription.whisper_v1 default

Speech-to-text with word and segment timestamps. Accepts a direct audio/video URL or a YouTube URL. Async — returns a queued run; poll genfire_get_run for the transcript.

{
  "max_file_mb": 500,
  "max_duration_seconds": 7200
}

image_editing

BRIA Background Remove

image_edit.bria_background_remove default

Remove the background from an image. Returns a transparent PNG.

{
  "input": "image_url"
}

video_upscaling

Topaz Video Upscale

video_upscale.fal_video_upscaler default

Upscale a video by 2x or 4x with Topaz (Proteus). Billed per second by output resolution. Async — returns a queued run; poll genfire_get_run for completion.

{
  "scale_factors": [
    2,
    4
  ]
}

video_upscaling

Flux Video Upscale

video_upscale.flux_video_upscale

Upscale a video 1.5x–3x with FLUX 3 super-resolution. Two modes: precise (source-faithful) and creative (adds detail, accepts an optional guiding prompt). Source must be MP4, at most 20s and 50MB. Billed per second of output by resolution and mode — materially pricier than Topaz. Async — returns a queued run; poll genfire_get_run for completion.

{
  "scale_factors": [
    1.5,
    2,
    2.5,
    3
  ],
  "min_scale_factor": 1.5,
  "max_scale_factor": 3,
  "max_duration_seconds": 20,
  "max_file_mb": 50,
  "modes": [
    "precise",
    "creative"
  ]
}

image_upscaling

Topaz Upscale

image_upscale.topaz_upscale_image default

Upscale an image by 2x or 4x. Async — returns a queued run; poll genfire_get_run for completion.

{
  "scale_factors": [
    2,
    4
  ]
}

lipsync_generation

Lipsync 2 Pro

lipsync.lipsync_2_pro default

High-quality lip-sync at 480p or 720p. Default.

{
  "resolutions": [
    "480p",
    "720p"
  ]
}

lipsync_generation

Sync Lipsync v2 Pro

lipsync.sync_lipsync_v2_pro

Alternative lip-sync engine.

{
  "resolutions": [
    "480p",
    "720p"
  ]
}

lipsync_generation

Sync Lipsync v3

lipsync.sync_lipsync_v3

Premium lip-sync engine — higher fidelity than v2 Pro.

{
  "resolutions": [
    "480p",
    "720p"
  ]
}

model_3d_generation

Meshy v7

3d.meshy_v7 default

Convert one image (or 1–4 images of the same object from different angles) into a textured 3D model. Outputs GLB/FBX/OBJ/USDZ/BLEND/STL plus optional PBR maps, auto-rigging, and animation. Adds ultra_mode over v6 — higher-fidelity geometry with finer surface detail (single image only). Game-ready — GLB loads natively in three.js / model-viewer. Async — returns a queued run; poll genfire_get_run for the model URLs. Processing takes 5–10 minutes.

{
  "max_images": 4,
  "output_formats": [
    "glb",
    "fbx",
    "obj",
    "usdz",
    "blend",
    "stl"
  ],
  "target_polycount": {
    "min": 100,
    "max": 300000,
    "default": 30000
  },
  "topology": [
    "quad",
    "triangle"
  ],
  "ultra_mode": "single image only"
}

model_3d_generation

Meshy v6

3d.meshy_v6

Previous-generation Meshy. Same inputs and outputs as v7 minus ultra_mode — pin this only to reproduce earlier results. Converts one image (or 1–4 images of the same object from different angles) into a textured 3D model. Outputs GLB/FBX/OBJ/USDZ/BLEND/STL plus optional PBR maps, auto-rigging, and animation. Async — returns a queued run; poll genfire_get_run for the model URLs. Processing takes 5–10 minutes.

{
  "max_images": 4,
  "output_formats": [
    "glb",
    "fbx",
    "obj",
    "usdz",
    "blend",
    "stl"
  ],
  "target_polycount": {
    "min": 100,
    "max": 300000,
    "default": 30000
  },
  "topology": [
    "quad",
    "triangle"
  ]
}

game_generation

Genfire Games

game.genfire_v1 default

Describe a game and get a fully-playable browser game (self-contained HTML, Phaser/canvas/Three.js). The completed run carries a public play_url you can open or share. Iterate by passing game_id with a change prompt. Async — returns a queued run; the codegen runs on a worker (usually 1–3 min). Poll GET /runs/{id} until status is completed, then read output.play_url.

{
  "output": "playable_html",
  "shareable": true
}

app_generation

Genfire App Builder

app.genfire_v1 default

Describe an app and get a working full-stack single-file web app (UI + in-browser data layer, hosted live). The completed run carries a public live_url you can open or share. Iterate by passing app_id with a change prompt. Async — returns a queued run; codegen runs on a worker (usually 1–3 min). Poll GET /runs/{id} until status is completed, then read output.live_url.

{
  "output": "live_web_app",
  "shareable": true
}

faceless_reel_generation

Faceless Reel

reel.faceless default

End-to-end vertical (9:16) short: LLM script → voiceover → style-locked images → music → captioned video. Driven by a niche preset + visual style; cost varies with duration and music — call POST /v1/faceless-reels/estimate-cost for a per-config estimate.

{
  "aspect_ratios": [
    "9:16"
  ],
  "target_duration_sec": {
    "min": 10,
    "max": 120,
    "default": null
  },
  "music_sources": [
    "none",
    "preset",
    "ai",
    "library"
  ],
  "catalogs": [
    "presets",
    "styles",
    "music-presets",
    "caption-presets"
  ]
}

explainer_generation

Explainer

explainer.omni default

Long-form narrated explainer/documentary (20s–10min, 16:9 or 9:16): script → expressive voiceover → style-locked frames → Gemini Omni Flash video clips → composed film with optional captions. Pass `script` (structured beats) to author the entire creative contract with YOUR OWN model — narration, per-scene shot-specs, motion notes, render modes, reference routing, emphasis words and recurring cast — and Genfire only renders; or pass just `topic` and Genfire writes the script. Cost varies with duration — call POST /v1/explainers/estimate-cost first.

{
  "aspect_ratios": [
    "16:9",
    "9:16"
  ],
  "target_duration_sec": {
    "min": 20,
    "max": 600,
    "default": 60
  },
  "music_sources": [
    "none",
    "preset",
    "ai",
    "library"
  ],
  "script_beats": {
    "min": 3,
    "max": 100
  },
  "reference_images": {
    "max": 8
  },
  "cast_members": {
    "max": 3
  },
  "caption_modes": [
    "full",
    "keywords"
  ],
  "caption_positions": [
    "top",
    "middle",
    "bottom"
  ],
  "catalogs": [
    "styles"
  ]
}

music_video_generation

Music Video

music-video.omni default

Auto-produced AI music video (9:16 or 16:9) from a song: song → beat/section analysis → style-locked anchor frame → per-scene Gemini Omni Flash video clips cut to the music → composed video with optional karaoke lyric captions. Bring your own song via `song_url` (with optional lyrics/sections/word timestamps), or pass an inline `song` prompt and Genfire generates the track first (ElevenLabs music_v2, billed separately). Cost scales with song length and scene_density — call POST /v1/music-videos/estimate-cost first.

{
  "aspect_ratios": [
    "9:16",
    "16:9"
  ],
  "scene_densities": [
    "low",
    "medium",
    "high"
  ],
  "song_duration_sec": {
    "min": 1,
    "max": 300
  },
  "inline_song_duration_ms": {
    "min": 10000,
    "max": 600000
  },
  "reference_images": {
    "max": 8
  },
  "catalogs": [
    "styles"
  ]
}

picture_book_generation

Picture Book

picture-book.gpt-image-2 default

A complete illustrated picture book from a story idea or script: the free planner writes/splits the text to the age band, then a style anchor, one reference sheet per cast member, every page and both covers render on GPT Image 2 (edit endpoint, anchor + sheets as references) so characters stay consistent. Text is typeset in post (default) or lettered by the model; print formats render at KDP trim + bleed and export as print-ready PDFs (interior, cover, ebook, images zip). Async: poll GET /v1/runs/:id (progress stages included), then read GET /v1/picture-books/:id. Call POST /v1/picture-books/estimate-cost first — cost scales with pages × quality.

{
  "age_bands": [
    "board",
    "picture",
    "early-reader"
  ],
  "qualities": [
    "low",
    "medium"
  ],
  "lettering_modes": [
    "typeset",
    "lettered"
  ],
  "pages": {
    "min": 4,
    "max": 48
  },
  "cast": {
    "max": 4
  },
  "export_kinds": [
    "interior-pdf",
    "cover-pdf",
    "ebook-pdf",
    "images-zip"
  ],
  "catalogs": [
    "styles",
    "formats",
    "age_bands"
  ]
}

Outcome Layer

Workflow Catalog

Use workflows when you want a business outcome such as hook generation, a creative pack, or UGC ad variants instead of a raw media primitive.

Workflow

hook_pack

available

Generate three monetizable UGC-style hooks plus a supporting body and CTA.

Input Schema
{
  "type": "object",
  "required": [
    "prompt"
  ],
  "properties": {
    "prompt": {
      "type": "string"
    },
    "audience": {
      "type": "string"
    },
    "tone": {
      "type": "string",
      "enum": [
        "casual",
        "professional",
        "humorous",
        "educational",
        "persuasive",
        "emotional"
      ]
    },
    "length": {
      "type": "string",
      "enum": [
        "short",
        "medium",
        "long"
      ]
    },
    "target_duration": {
      "type": "number"
    },
    "keywords": {
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "additional_requirements": {
      "type": "string"
    }
  }
}
Output Schema
{
  "type": "object",
  "properties": {
    "hooks": {
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "body": {
      "type": "string"
    },
    "call_to_action": {
      "type": "string"
    },
    "full_script": {
      "type": "string"
    }
  }
}
Example Request Body
{
  "prompt": "Portable blender for busy professionals",
  "audience": "Remote workers who skip breakfast",
  "tone": "persuasive",
  "length": "short",
  "target_duration": 20,
  "keywords": [
    "protein shake",
    "commute",
    "healthy"
  ],
  "additional_requirements": "Lead with convenience and save time."
}
Example Output
{
  "workflow": "hook_pack",
  "topic": "Portable blender for busy professionals",
  "hooks": [
    "If breakfast keeps losing to your calendar, this fixes it.",
    "I stopped skipping protein the day I threw this in my bag.",
    "This is how I make a full shake before my first meeting."
  ],
  "body": "Portable, fast, and easy to clean for daily use.",
  "call_to_action": "Try it before your next busy week.",
  "full_script": "If breakfast keeps losing to your calendar...",
  "word_count": 96,
  "estimated_duration": 22
}

Workflow

ugc_ad

available

Generate an outcome-oriented UGC ad script with hooks, body, CTA, and a full spoken script.

Input Schema
{
  "type": "object",
  "required": [
    "prompt"
  ],
  "properties": {
    "prompt": {
      "type": "string"
    },
    "audience": {
      "type": "string"
    },
    "tone": {
      "type": "string",
      "enum": [
        "casual",
        "professional",
        "humorous",
        "educational",
        "persuasive",
        "emotional"
      ]
    },
    "length": {
      "type": "string",
      "enum": [
        "short",
        "medium",
        "long"
      ]
    },
    "target_duration": {
      "type": "number"
    },
    "keywords": {
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "additional_requirements": {
      "type": "string"
    }
  }
}
Output Schema
{
  "type": "object",
  "properties": {
    "hooks": {
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "body": {
      "type": "string"
    },
    "call_to_action": {
      "type": "string"
    },
    "full_script": {
      "type": "string"
    }
  }
}
Example Request Body
{
  "prompt": "Blue light glasses for creators",
  "audience": "Designers and editors working late",
  "tone": "casual",
  "length": "medium"
}
Example Output
{
  "workflow": "ugc_ad",
  "topic": "Blue light glasses for creators",
  "hooks": [
    "I did not realize how cooked my eyes were by 6pm."
  ],
  "body": "Comfort-focused UGC body copy.",
  "call_to_action": "Use them on your next edit sprint.",
  "full_script": "I did not realize how cooked my eyes were..."
}

Workflow

ugc_ad_video

available

One run → a finished UGC video ad: researches and writes the script (brand/product aware), generates the talking-avatar product shot on Hailuo 03 (with optional avatar template voice), and burns styled captions. Async — poll the returned run for the video URL. Cost = the component script workflow + the Hailuo 03 generation (captions are free).

Input Schema
{
  "type": "object",
  "required": [
    "prompt"
  ],
  "properties": {
    "prompt": {
      "type": "string",
      "description": "The product/offer brief the ad should sell. Required unless a finished `script` is supplied."
    },
    "script": {
      "type": "string",
      "description": "Skip script generation and use this exact spoken script."
    },
    "brand_id": {
      "type": "string",
      "description": "Ground the ad on a stored brand: its featured product photo fills the product slot and its voice/palette/words-to-avoid condition the script. The same brand_id contract as image/video generation and faceless reels."
    },
    "product_url": {
      "type": "string",
      "format": "uri",
      "description": "Product page URL — switches script generation to the product-aware creative_pack research flow."
    },
    "product_image_url": {
      "type": "string",
      "format": "uri",
      "description": "Product photo the creator presents on camera (reference image)."
    },
    "avatar_template_id": {
      "type": "string",
      "description": "Avatar from the Genfire template library — brings the face AND (by default) its voice sample."
    },
    "avatar_image_url": {
      "type": "string",
      "format": "uri",
      "description": "Custom avatar/creator face image (alternative to avatar_template_id)."
    },
    "use_avatar_voice": {
      "type": "boolean",
      "default": true,
      "description": "Condition the speech on the avatar template's voice sample when one exists."
    },
    "audience": {
      "type": "string"
    },
    "tone": {
      "type": "string",
      "enum": [
        "casual",
        "professional",
        "humorous",
        "educational",
        "persuasive",
        "emotional"
      ]
    },
    "scene": {
      "type": "string",
      "description": "Optional scene direction (e.g. \"in a car, golden hour\")."
    },
    "duration_seconds": {
      "type": "number",
      "minimum": 5,
      "maximum": 60,
      "default": 12,
      "description": "Up to 60s: ads longer than 15s chain multiple voice/face-conditioned takes with jump cuts (the native UGC edit)."
    },
    "aspect_ratio": {
      "type": "string",
      "enum": [
        "9:16",
        "16:9",
        "1:1",
        "3:4",
        "4:3",
        "21:9"
      ],
      "default": "9:16"
    },
    "resolution": {
      "type": "string",
      "enum": [
        "768p",
        "2k"
      ],
      "default": "768p"
    },
    "captions": {
      "type": "boolean",
      "default": true
    },
    "caption_preset_id": {
      "type": "string",
      "default": "hormozi"
    },
    "caption_position": {
      "type": "string",
      "enum": [
        "top",
        "middle",
        "bottom"
      ],
      "default": "bottom"
    },
    "caption_words_per_line": {
      "type": "number",
      "minimum": 1,
      "maximum": 6
    },
    "broll": {
      "type": "string",
      "enum": [
        "none",
        "auto",
        "stock",
        "stills",
        "video"
      ],
      "default": "auto",
      "description": "Multi-scene cutaways while the avatar voice continues. auto (default) = one product-fidelity still + FREE stock clips timed to spoken keywords; stock = all free Pexels; stills = generated images; video = Hailuo 03 clips (premium)."
    },
    "broll_count": {
      "type": "number",
      "minimum": 1,
      "maximum": 3,
      "default": 2
    },
    "reference_ad_research_id": {
      "type": "string",
      "description": "A stored competitor-ad analysis (from POST /v1/ads/analyze or the agent's analyze_competitor_ad) — the script follows that proven format for YOUR product; assets and wording are never copied."
    }
  }
}
Output Schema
{
  "type": "object",
  "properties": {
    "video_url": {
      "type": "string"
    },
    "captioned": {
      "type": "boolean"
    },
    "script": {
      "type": "string"
    },
    "hooks": {
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "source_video_id": {
      "type": "string"
    },
    "duration_seconds": {
      "type": "number"
    },
    "aspect_ratio": {
      "type": "string"
    }
  }
}
Example Request Body
{
  "prompt": "Blue light glasses for creators",
  "product_url": "https://example.com/products/blue-light-glasses",
  "product_image_url": "https://example.com/products/blue-light-glasses/hero.jpg",
  "avatar_template_id": "tmpl_ugc_creator_04",
  "duration_seconds": 12,
  "aspect_ratio": "9:16",
  "captions": true
}
Example Output
{
  "workflow": "ugc_ad_video",
  "video_url": "https://storage.googleapis.com/genfire/ads/final_ad.mp4",
  "captioned": true,
  "script": "I did not realize how cooked my eyes were by 6pm — these fixed it...",
  "hooks": [
    "I did not realize how cooked my eyes were by 6pm."
  ],
  "source_video_id": "vid_abc123",
  "duration_seconds": 12,
  "aspect_ratio": "9:16"
}

Workflow

ad_remix

available

One winning ad → variants with the nouns swapped, the cut and pacing kept. Engine: Gemini Omni Flash 1.1, two routes chosen per variant. EDIT (every change is words): the footage itself is edited, so the setting, framing, motion and product are kept by construction — a ≤10s source goes whole, a longer one is cut on its own hard cuts into ≤10s segments and each is edited; variants that ACCUMULATE (each one's changes extend the previous one's, in order) are CHAINED — each edits the previous variant's output with only what it adds, so a new creator carries through outfit → location → language. REFERENCE (a change shows an image): the source is split on its own hard cuts into ≤9s segments (each fed three ≤3s slices of itself as references). MIXED (words AND a picture in the same variant — "make her Persian and put her in this hoodie"): the server SPLITS it into an implicit two-step chain and still returns ONE variant — an intermediate leg (id `{id}.edit`, `intermediate: true`) renders the words-only changes on the edit route, then the deliverable renders the image-backed ones on the reference route with its slices cut from THAT LEG'S OUTPUT (`chain_from`), so a words-only person swap actually lands instead of coming back as the original person. Both legs are billed; only the deliverable appears in output.variants[], the leg appears under output.intermediates[]. Never restructure a request to work around routing — put every change on one variant and let the server split it. A creator change that carries a face image is DESCRIBED in words by the server and the picture is never sent with footage (the engine refuses a face next to footage) — the new person is a look-alike of the description; picker cards (creator portrait, outfit flat lay, empty location) are generated AFTER each video from its own frame so the card is what rendered. Every (variant × segment) is one generation, cards ~1 credit each, and the segments are concatenated on the planned boundaries with the sound the model rendered — it renders speech, ambience and music with the picture, mouths in sync, so a creator swap or a language change ({ what: "language", description: "Spanish" }) comes back dubbed with no lipsync step. The original track (or a supplied one) can be laid back on instead. Each output is cut-diffed against the source and returns a fidelity score. Async — poll the returned run; output.variants[] carries a video_url per variant. Cost = segments × variants × per-second Omni pricing at the chosen resolution — quote it first with POST /v1/ads/remix (dry run).

Input Schema
{
  "type": "object",
  "required": [
    "source_video_url"
  ],
  "properties": {
    "source_video_url": {
      "type": "string",
      "format": "uri",
      "description": "The winning ad, as a public https URL (a Genfire run output URL works). Clean sources only — burned-in captions come back as garbled text."
    },
    "product_image_url": {
      "type": "string",
      "format": "uri",
      "description": "The product, PINNED: an Element image or product photo that rides every REFERENCE generation as a fixed object reference (\"the product, exactly as shown\"). Without it the model re-draws the product from the reference slices and it drifts between variants. It is NOT sent on an edit-route call — that endpoint has no image pool, so there the product is held from the footage by the keep-list (\"exactly as it is in the video\") and the plan says so in developer_notes. A `product` CHANGE pointing at this same image is folded back into the pin rather than honoured as a change, so repeating the product photo can never push a variant onto the reference route on its own. The pin steps aside entirely for a variant that changes the product to a DIFFERENT image."
    },
    "changes": {
      "type": "array",
      "minItems": 1,
      "maxItems": 10,
      "description": "ONE variant: what to change. Use this OR `variants`.",
      "items": {
        "type": "object",
        "required": [
          "what"
        ],
        "properties": {
          "what": {
            "type": "string",
            "description": "\"creator\", \"outfit\", \"location\", \"product\" get tuned phrasing; anything else (\"the drink she is holding\", \"time of day\") is honoured generically."
          },
          "image_url": {
            "type": "string",
            "format": "uri",
            "description": "Reference image showing the replacement (an Element, a product photo, an outfit or location still). For a CREATOR change the face is described in words server-side and the picture is never sent with footage — the engine refuses that — so the result is a look-alike, not that exact face; the creator card in the output is made from the render."
          },
          "description": {
            "type": "string",
            "description": "Plain-English detail. Required when there is no image_url or preset."
          },
          "preset": {
            "type": "string",
            "description": "A named preset with the wording already written (no image slot used; `what` may be omitted). look: anime, retro-collage, bold-urban, green-contrast, warm-glow, neon-cyberpunk, claymation, comic-pop, doodle-notes, vhs-retro, paper-craft, watercolor, noir-film, hud-tracking · location: marble-kitchen, gym-floor, car-interior, golden-hour-street, cafe-terrace, beach-boardwalk, city-rooftop-dusk, bedroom-morning, home-office, city-park, airplane-wing, volcano-rim, doll-size, moving-car-roof · time: golden-hour, blue-hour, midday, overcast, night, indoor-evening · weather: light-rain, snow, fog, heat-haze · wardrobe: athleisure, streetwear, business-casual, evening-wear, cozy-knit, workwear · camera: handheld-phone, tripod-locked, slow-push-in, wider-lens · language: en, es, de, fr, it, pt-br, ja, ko, zh, hi, ar. The dry run lists them under `presets`."
          }
        }
      }
    },
    "variants": {
      "type": "array",
      "minItems": 1,
      "maxItems": 12,
      "description": "SEVERAL variants, each a full remix of the whole ad. Use this OR `changes`.",
      "items": {
        "type": "object",
        "required": [
          "changes"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "changes": {
            "type": "array",
            "minItems": 1,
            "maxItems": 10,
            "items": {
              "type": "object"
            }
          },
          "direction": {
            "type": "string",
            "description": "Free-text direction for this variant, appended verbatim."
          },
          "audio": {
            "description": "\"generated\" (default — the model's own sound, in sync with its mouths), \"original\" (the source track laid back on), \"none\", an audio URL, or { mode: generated|original|replace|none, url }."
          }
        }
      }
    },
    "audio": {
      "description": "Run-level soundtrack default: \"generated\" (the sound the model rendered with the picture — default), \"original\" (the source track laid back on), \"none\", an http(s) audio URL, or { mode, url }. A variant's own `audio` wins."
    },
    "aspect_ratio": {
      "type": "string",
      "enum": [
        "9:16",
        "16:9"
      ],
      "default": "9:16",
      "description": "Match the source."
    },
    "resolution": {
      "type": "string",
      "enum": [
        "360p",
        "720p",
        "1080p",
        "4k"
      ],
      "default": "1080p",
      "description": "720p for drafts — cost scales ~10x across the ladder."
    },
    "cards": {
      "type": "boolean",
      "default": true,
      "description": "Make picker cards from each variant's output — a creator portrait, an outfit flat lay, an empty location — for the changes it introduces (~1 credit each). false to skip."
    }
  }
}
Output Schema
{
  "type": "object",
  "properties": {
    "engine": {
      "type": "string"
    },
    "route": {
      "type": "string",
      "enum": [
        "edit",
        "reference",
        "mixed"
      ]
    },
    "segments": {
      "type": "number"
    },
    "generation_count": {
      "type": "number"
    },
    "cards": {
      "type": "number",
      "description": "How many picker cards were planned."
    },
    "intermediates": {
      "type": "array",
      "description": "Debugging only: the words-only legs the server inserted for variants that mixed words with pictures. Each was billed and rendered; none is a deliverable — they never appear in variants[] and can never be the run's video_url.",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "completed",
              "failed"
            ]
          },
          "intermediate": {
            "type": "boolean"
          },
          "video_url": {
            "type": "string"
          },
          "chain_from": {
            "type": "string"
          },
          "error": {
            "type": "string"
          }
        }
      }
    },
    "variants": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "completed",
              "failed"
            ]
          },
          "video_url": {
            "type": "string"
          },
          "duration_seconds": {
            "type": "number"
          },
          "qa": {
            "type": "object",
            "description": "Cut-diff against the source: fidelity 0-1, matched/missing/extra cuts, mean drift."
          },
          "audio_track": {
            "type": "string",
            "enum": [
              "generated",
              "original",
              "replace",
              "none"
            ],
            "description": "Which soundtrack shipped on this variant."
          },
          "thumbnail_url": {
            "type": "string"
          },
          "cards": {
            "type": "object",
            "description": "Picker cards made from THIS output: { creator?, outfit?, location? } → image URL. The card is what rendered."
          },
          "chain_from": {
            "type": "string",
            "description": "The variant this one was rendered on top of — an earlier variant it accumulates on, or the intermediate leg the server inserted when this variant mixed words-only changes with image-backed ones."
          },
          "creator_reference_url": {
            "type": "string",
            "description": "The face the caller picked for the creator change — described, never sent to the engine."
          },
          "library_video_id": {
            "type": "string"
          },
          "error": {
            "type": "string"
          }
        }
      }
    }
  }
}

Workflow

creative_pack

available

Build a product-aware creative pack with analysis, angles, hooks, and a monetizable script.

Input Schema
{
  "type": "object",
  "properties": {
    "prompt": {
      "type": "string"
    },
    "product_url": {
      "type": "string",
      "format": "uri"
    },
    "product_name": {
      "type": "string"
    },
    "product_description": {
      "type": "string"
    },
    "category": {
      "type": "string"
    },
    "audience": {
      "type": "string"
    },
    "tone": {
      "type": "string",
      "enum": [
        "casual",
        "professional",
        "humorous",
        "educational",
        "persuasive",
        "emotional"
      ]
    },
    "length": {
      "type": "string",
      "enum": [
        "short",
        "medium",
        "long"
      ]
    },
    "image_urls": {
      "type": "array",
      "items": {
        "type": "string",
        "format": "uri"
      }
    },
    "additional_requirements": {
      "type": "string"
    }
  }
}
Output Schema
{
  "type": "object",
  "properties": {
    "product": {
      "type": "object"
    },
    "analysis": {
      "type": "object"
    },
    "hooks": {
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "body": {
      "type": "string"
    },
    "call_to_action": {
      "type": "string"
    },
    "full_script": {
      "type": "string"
    }
  }
}
Example Request Body
{
  "product_url": "https://example.com/products/matte-black-water-bottle"
}
Example Output
{
  "workflow": "creative_pack",
  "product": {
    "name": "Matte Black Water Bottle",
    "description": "Insulated stainless steel water bottle",
    "category": "hydration",
    "price": "$39",
    "images": [
      "https://example.com/image-1.jpg"
    ]
  },
  "analysis": {
    "marketingAngles": [
      "Premium feel",
      "Keeps drinks cold",
      "Daily carry convenience"
    ]
  },
  "hooks": [
    "This bottle still had ice after my entire workout and commute."
  ],
  "body": "Creative body copy built from product analysis.",
  "call_to_action": "Upgrade your daily carry.",
  "full_script": "This bottle still had ice..."
}

Workflow

product_ad_variants

available

Generate multiple UGC-style ad script variants for the same product or offer.

Input Schema
{
  "type": "object",
  "properties": {
    "prompt": {
      "type": "string"
    },
    "product_name": {
      "type": "string"
    },
    "product_description": {
      "type": "string"
    },
    "audience": {
      "type": "string"
    },
    "tone": {
      "type": "string",
      "enum": [
        "casual",
        "professional",
        "humorous",
        "educational",
        "persuasive",
        "emotional"
      ]
    },
    "length": {
      "type": "string",
      "enum": [
        "short",
        "medium",
        "long"
      ]
    },
    "variant_count": {
      "type": "number",
      "minimum": 1,
      "maximum": 5
    },
    "additional_requirements": {
      "type": "string"
    }
  }
}
Output Schema
{
  "type": "object",
  "properties": {
    "variant_count": {
      "type": "number"
    },
    "variants": {
      "type": "array",
      "items": {
        "type": "object"
      }
    }
  }
}
Example Request Body
{
  "product_name": "Portable espresso maker",
  "product_description": "Travel-friendly espresso maker for commuters",
  "audience": "Commuters and travelers",
  "tone": "persuasive",
  "length": "short",
  "variant_count": 3
}
Example Output
{
  "workflow": "product_ad_variants",
  "prompt": "Portable espresso maker: Travel-friendly espresso maker for commuters",
  "variant_count": 3,
  "variants": [
    {
      "index": 0,
      "strategy": "Question-led hook with direct pain point.",
      "hooks": [
        "Why are you still settling for station coffee?"
      ],
      "body": "Variant body",
      "call_to_action": "Carry café-level espresso anywhere.",
      "full_script": "Why are you still settling for station coffee?"
    }
  ]
}

Reference

Authentication

POST /oauth/token

Issue an OAuth access token

Use OAuth client credentials for machine-to-machine access. API keys are supported on the same `/v1` endpoints and are usually the simplest option.

Auth: No auth
Idempotency-Key: Not required

Body Fields

grant_type string required

Must be `client_credentials`.

client_id string required

The OAuth client id created in the developer portal.

client_secret string required

The OAuth client secret shown only when the client is created.

scope string optional

Optional space-separated scopes. Omit to receive the client’s default scopes.

curl Example

curl https://api.genfire.ai/v1/oauth/token \
  -H "Content-Type: application/json" \
  -d '{
  "grant_type": "client_credentials",
  "client_id": "gfo_oauth_123",
  "client_secret": "gfs_live_secret",
  "scope": "models:read runs:read images:write"
}'

Response Example

{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.example",
  "token_type": "Bearer",
  "expires_in": 3600,
  "scope": "models:read runs:read images:write"
}

Request Example Body

{
  "grant_type": "client_credentials",
  "client_id": "gfo_oauth_123",
  "client_secret": "gfs_live_secret",
  "scope": "models:read runs:read images:write"
}

Notes

  • You can also send `client_id:client_secret` with HTTP Basic auth instead of putting them in JSON.
  • The returned access token is used in the same `Authorization: Bearer ...` header as an API key.

Reference

CLI Auth

POST /cli/auth/sessions

Start a CLI auth session

Begins the browser-based PKCE handshake used by the Genfire CLI. The CLI generates a 43-128 character base64url `code_verifier`, derives `code_challenge = BASE64URL(SHA256(verifier))`, calls this endpoint, and opens `verification_url` in the user’s browser.

Auth: No auth
Idempotency-Key: Not required

Body Fields

client_id string required

Public CLI client id. Currently only `genfire-cli`.

code_challenge string required

BASE64URL(SHA256(code_verifier)). 43-128 characters.

code_challenge_method string required

Must be `S256`.

scopes array optional

Optional list of scopes the CLI is requesting. Omit for the default key scopes.

label string optional

Optional human label shown to the user on the consent page (e.g. `genfire-cli (laptop)`).

curl Example

curl https://api.genfire.ai/v1/cli/auth/sessions \
  -H "Content-Type: application/json" \
  -d '{
  "client_id": "genfire-cli",
  "code_challenge": "E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM",
  "code_challenge_method": "S256",
  "scopes": [
    "account:read",
    "credits:read",
    "models:read",
    "runs:read",
    "images:write",
    "videos:write",
    "uploads:write"
  ],
  "label": "genfire-cli (laptop)"
}'

Response Example

{
  "session_id": "clisess_8f3c4a2b1d6e7f9a0b1c2d3e",
  "verification_url": "https://genfire.ai/cli-auth?session=clisess_8f3c4a2b1d6e7f9a0b1c2d3e",
  "expires_at": "2026-05-04T17:21:25.985Z",
  "requested_scopes": [
    "account:read",
    "images:write",
    "uploads:write"
  ],
  "label": "genfire-cli (laptop)"
}

Request Example Body

{
  "client_id": "genfire-cli",
  "code_challenge": "E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM",
  "code_challenge_method": "S256",
  "scopes": [
    "account:read",
    "credits:read",
    "models:read",
    "runs:read",
    "images:write",
    "videos:write",
    "uploads:write"
  ],
  "label": "genfire-cli (laptop)"
}

Notes

  • Sessions expire after 10 minutes if not approved.
  • Poll `GET /cli/auth/sessions/{sessionId}` to discover when the user has approved (or denied) the session.
GET /cli/auth/sessions/{sessionId}

Poll the status of a CLI auth session

Returns the current status of a CLI auth session. The CLI polls this endpoint while the user completes the browser flow.

Auth: No auth
Idempotency-Key: Not required

Parameters

sessionId path required

Session id returned from `POST /cli/auth/sessions`.

Body Fields

No body fields for this endpoint.

curl Example

curl https://api.genfire.ai/v1/cli/auth/sessions/{sessionId}

Response Example

{
  "session_id": "clisess_8f3c4a2b1d6e7f9a0b1c2d3e",
  "status": "approved",
  "label": "genfire-cli (laptop)",
  "requested_scopes": [
    "account:read",
    "images:write",
    "uploads:write"
  ],
  "expires_at": "2026-05-04T17:21:25.985Z"
}

Notes

  • Status transitions: `pending` → `approved` (or `denied`) → `consumed` (after exchange).
  • A `consumed` or `expired` status means the CLI must restart the login flow.
POST /cli/auth/sessions/{sessionId}/exchange

Exchange an approved CLI auth session for an API key

Once `GET /cli/auth/sessions/{sessionId}` reports `approved`, the CLI submits its original `code_verifier` here. The server verifies `SHA256(code_verifier) === code_challenge`, then returns the freshly minted API key exactly once.

Auth: No auth
Idempotency-Key: Not required

Parameters

sessionId path required

Session id returned from `POST /cli/auth/sessions`.

Body Fields

code_verifier string required

The original PKCE code_verifier the CLI generated when starting the session.

curl Example

curl https://api.genfire.ai/v1/cli/auth/sessions/{sessionId}/exchange \
  -H "Content-Type: application/json" \
  -d '{
  "code_verifier": "M25iVXpKU3puUjFaYWg3T1NDTDQtcW1ROUY5YXlwalNoc0hhakxifmZHag"
}'

Response Example

{
  "api_key": "gfa_live_abc123.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "scopes": [
    "account:read",
    "images:write",
    "uploads:write"
  ],
  "label": "genfire-cli (laptop)",
  "session_expires_at": "2026-05-04T17:21:25.985Z"
}

Request Example Body

{
  "code_verifier": "M25iVXpKU3puUjFaYWg3T1NDTDQtcW1ROUY5YXlwalNoc0hhakxifmZHag"
}

Notes

  • The `api_key` is returned exactly once. Store it securely (the CLI uses the OS keychain).
  • Sessions are single-use. Once exchanged, the same session cannot be exchanged again.
  • A 428 response means the user has not yet approved the session — keep polling.
  • A 410 response means the session expired or was already exchanged. Restart the CLI login.

Reference

Account

GET /account
account:read

Get the authenticated account

Returns the public API account linked to the calling API key or OAuth client, plus `min_supported_plugin_versions` — the minimum build of each official Genfire plugin (`genfire-photoshop`, `genfire-premiere`, `genfire-aftereffects`, `genfire-blender`, `genfire-resolve`, `genfire-cli`) this API still supports.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Body Fields

No body fields for this endpoint.

curl Example

curl https://api.genfire.ai/v1/account \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "id": "acct_user_123",
  "object": "account",
  "display_name": "Genfire Developer",
  "email": "owner@example.com",
  "plan": "pro",
  "status": "active",
  "min_supported_plugin_versions": {
    "genfire-cli": "0.0.0",
    "genfire-photoshop": "0.0.0",
    "genfire-premiere": "0.0.0",
    "genfire-aftereffects": "0.0.0",
    "genfire-blender": "0.0.0",
    "genfire-resolve": "0.0.0"
  },
  "created_at": "2026-03-25T12:00:00.000Z",
  "updated_at": "2026-03-25T12:00:00.000Z"
}

Notes

  • Desktop plugins should call this at startup and compare their own version against their entry in `min_supported_plugin_versions`. A build below its floor should tell the user to update rather than continue and fail cryptically later. `0.0.0` means no floor is set for that client.
  • Send `User-Agent: genfire-<host>/<version> (<hostName>/<hostVersion>; <platform>)` — e.g. `genfire-photoshop/1.2.0 (photoshop/26.1; darwin)`. It is recorded per request so per-client usage and failures can be attributed.
GET /account/credits
credits:read

Get the current credit balance

Shows the credit balance for the authenticated account. Pass `team_id` to read a WORKSPACE credit pool instead — that is the balance a run carrying the same `team_id` will actually draw from, and it also returns your own month-to-date usage and monthly cap on that workspace, which can block a run even when the pool is healthy.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Parameters

team_id query optional

Read this workspace's shared pool instead of the personal balance (`GET /v1/teams`). Requires the `teams:read` scope; 404 `invalid_team_id` when you are not a member.

Body Fields

No body fields for this endpoint.

curl Example

curl https://api.genfire.ai/v1/account/credits \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "account_id": "acct_user_123",
  "balance": 250,
  "currency": "credits"
}

Notes

  • With `team_id` the response additionally carries `team_name`, `my_usage_this_month`, `my_cap`, `my_remaining` and `role`. Without it, `team_id` is null and `balance` is the personal balance.

Reference

Discovery

GET /models
models:read

List public model aliases

Use model aliases from this endpoint instead of internal provider ids. The aliases are stable and safe to pass back into generation endpoints.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Body Fields

No body fields for this endpoint.

curl Example

curl https://api.genfire.ai/v1/models \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "object": "list",
  "data": [
    {
      "id": "image.genfire_v1",
      "object": "model",
      "capability": "image_generation",
      "name": "Genfire v1",
      "description": "Genfire's signature image model — tuned for ad/product creative.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "1:1",
          "16:9",
          "9:16",
          "4:3",
          "3:4"
        ],
        "max_count": 4,
        "max_reference_images": 16
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": true,
        "reference_images": true,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": true,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "image.nano_banana_2",
      "object": "model",
      "capability": "image_generation",
      "name": "Nano Banana 2",
      "description": "Google's general-purpose image model. Fast, broad subject coverage. Default.",
      "status": "available",
      "is_default": true,
      "limits": {
        "aspect_ratios": [
          "1:1",
          "16:9",
          "9:16",
          "4:3",
          "3:4",
          "21:9",
          "9:21"
        ],
        "max_count": 4
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": true,
        "reference_images": true,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": true,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "image.nano_banana_pro",
      "object": "model",
      "capability": "image_generation",
      "name": "Nano Banana Pro",
      "description": "Premium photoreal image generation, higher fidelity than Nano Banana 2.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "1:1",
          "16:9",
          "9:16",
          "4:3",
          "3:4"
        ],
        "max_count": 4
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": true,
        "reference_images": true,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": true,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "image.nano_banana",
      "object": "model",
      "capability": "image_generation",
      "name": "Nano Banana",
      "description": "Standard speed and quality. Cheaper than Pro for high-volume use.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "1:1",
          "16:9",
          "9:16",
          "4:3",
          "3:4"
        ],
        "max_count": 4
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": true,
        "reference_images": true,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "image.nano_banana_lite",
      "object": "model",
      "capability": "image_generation",
      "name": "Nano Banana Lite",
      "description": "Gemini 3.1 Flash Lite Image — ultra-low latency, cheapest tier. Supports editing.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "1:1",
          "16:9",
          "9:16",
          "4:3",
          "3:4",
          "21:9",
          "9:21"
        ],
        "max_count": 4
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": true,
        "reference_images": true,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "image.nano_banana_2_lite",
      "object": "model",
      "capability": "image_generation",
      "name": "Nano Banana 2 Lite",
      "description": "Gemini 3.1 Flash Lite Image (v2) — ultra-low latency text-to-image. No edit endpoint.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "1:1",
          "16:9",
          "9:16",
          "4:3",
          "3:4",
          "21:9",
          "9:21"
        ],
        "max_count": 4
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": false,
        "reference_images": false,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "image.gpt_image_2",
      "object": "model",
      "capability": "image_generation",
      "name": "GPT Image 2",
      "description": "OpenAI GPT Image 2 — premium photorealistic generation.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "1:1",
          "16:9",
          "9:16",
          "4:3",
          "3:4"
        ],
        "max_count": 4,
        "max_reference_images": 16
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": true,
        "reference_images": true,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": true,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "image.seedream_v45",
      "object": "model",
      "capability": "image_generation",
      "name": "Seedream 4.5",
      "description": "ByteDance Seedream 4.5 — strong product and ad visuals, photoreal.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "1:1",
          "16:9",
          "9:16"
        ],
        "max_count": 4
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": true,
        "reference_images": true,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "image.seedream_v5_lite",
      "object": "model",
      "capability": "image_generation",
      "name": "Seedream 5.0 Lite",
      "description": "ByteDance Seedream 5.0 Lite — multilingual text rendering, web-search-aware.",
      "status": "preview",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "1:1",
          "16:9",
          "9:16"
        ],
        "max_count": 4
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": true,
        "reference_images": true,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "image.seedream_v5_pro",
      "object": "model",
      "capability": "image_generation",
      "name": "Seedream 5.0 Pro",
      "description": "ByteDance Seedream 5.0 Pro — flagship photoreal image + multi-reference edit, up to 2K, up to 10 reference images.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "1:1",
          "16:9",
          "9:16"
        ],
        "max_count": 6
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": true,
        "reference_images": true,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "image.qwen_image_2",
      "object": "model",
      "capability": "image_generation",
      "name": "Qwen Image 2",
      "description": "Alibaba Qwen Image 2 — strong typography, posters, 2K generation.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "1:1",
          "16:9",
          "9:16",
          "4:3",
          "3:4"
        ],
        "max_count": 4
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": true,
        "reference_images": true,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "image.qwen_image_2_pro",
      "object": "model",
      "capability": "image_generation",
      "name": "Qwen Image 2 Pro",
      "description": "Premium Qwen Image 2 with enhanced detail.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "1:1",
          "16:9",
          "9:16",
          "4:3",
          "3:4"
        ],
        "max_count": 4
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": true,
        "reference_images": true,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "image.qwen_image_3",
      "object": "model",
      "capability": "image_generation",
      "name": "Qwen Image 3",
      "description": "Alibaba Qwen Image 3 — bilingual (CN/EN) text rendering up to 2K. Edit mode takes 1-3 reference images, addressed as \"image 1\"..\"image 3\" in the prompt.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "1:1",
          "16:9",
          "9:16",
          "4:3",
          "3:4"
        ],
        "max_count": 4,
        "max_prompt_chars": 800,
        "max_reference_images": 3
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": true,
        "reference_images": true,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "image.recraft_v4_vector",
      "object": "model",
      "capability": "image_generation",
      "name": "Recraft V4 Vector",
      "description": "Recraft V4 vector output — a true SVG rather than a raster image. Logos, icons and flat illustration that has to scale cleanly.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "1:1",
          "16:9",
          "9:16",
          "4:3",
          "3:4"
        ],
        "max_count": 4
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": false,
        "reference_images": false,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "image.recraft_v4_pro_vector",
      "object": "model",
      "capability": "image_generation",
      "name": "Recraft V4 Pro Vector",
      "description": "Premium Recraft V4 vector output — true SVG at the Pro tier’s fidelity.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "1:1",
          "16:9",
          "9:16",
          "4:3",
          "3:4"
        ],
        "max_count": 4
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": false,
        "reference_images": false,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "image.recraft_v41",
      "object": "model",
      "capability": "image_generation",
      "name": "Recraft V4.1",
      "description": "Recraft V4.1 — sharper prompt control and cleaner composition than V4. Tuned for brand systems and editorial work.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "1:1",
          "16:9",
          "9:16",
          "4:3",
          "3:4"
        ],
        "max_count": 4
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": false,
        "reference_images": false,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "image.recraft_v41_pro",
      "object": "model",
      "capability": "image_generation",
      "name": "Recraft V4.1 Pro",
      "description": "Recraft V4.1 at the Pro tier — high-resolution raster for large-format and production work.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "1:1",
          "16:9",
          "9:16",
          "4:3",
          "3:4"
        ],
        "max_count": 4
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": false,
        "reference_images": false,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "image.recraft_v41_vector",
      "object": "model",
      "capability": "image_generation",
      "name": "Recraft V4.1 Vector",
      "description": "Recraft V4.1 vector output — true SVG.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "1:1",
          "16:9",
          "9:16",
          "4:3",
          "3:4"
        ],
        "max_count": 4
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": false,
        "reference_images": false,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "image.recraft_v41_pro_vector",
      "object": "model",
      "capability": "image_generation",
      "name": "Recraft V4.1 Pro Vector",
      "description": "Recraft V4.1 Pro vector output — true SVG at the Pro tier’s fidelity.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "1:1",
          "16:9",
          "9:16",
          "4:3",
          "3:4"
        ],
        "max_count": 4
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": false,
        "reference_images": false,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "image.recraft_v41_utility",
      "object": "model",
      "capability": "image_generation",
      "name": "Recraft V4.1 Utility",
      "description": "A faster, lighter V4.1 runtime for high-volume work — ideation, A/B exploration and content pipelines. Same price and parameters as image.recraft_v41; the difference is throughput.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "1:1",
          "16:9",
          "9:16",
          "4:3",
          "3:4"
        ],
        "max_count": 4
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": false,
        "reference_images": false,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "image.recraft_v41_utility_pro",
      "object": "model",
      "capability": "image_generation",
      "name": "Recraft V4.1 Utility Pro",
      "description": "V4.1 Pro output on the faster Utility runtime — large-format work at pipeline scale. Same price and parameters as image.recraft_v41_pro.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "1:1",
          "16:9",
          "9:16",
          "4:3",
          "3:4"
        ],
        "max_count": 4
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": false,
        "reference_images": false,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "image.recraft_v4_style",
      "object": "model",
      "capability": "image_generation",
      "name": "Recraft V4 Styles",
      "description": "Recraft V4 with a custom style. Supply a custom style either as `style_id` (trained earlier) or as 1-10 `image_urls` style references, which trains one inline and returns its `style_id` for reuse.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "1:1",
          "16:9",
          "9:16",
          "4:3",
          "3:4"
        ],
        "max_count": 4,
        "max_reference_images": 10
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": true,
        "reference_images": true,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "image.recraft_v4_style_pro",
      "object": "model",
      "capability": "image_generation",
      "name": "Recraft V4 Styles Pro",
      "description": "Recraft V4 Styles at the Pro tier. Supply a custom style either as `style_id` (trained earlier) or as 1-10 `image_urls` style references, which trains one inline and returns its `style_id` for reuse.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "1:1",
          "16:9",
          "9:16",
          "4:3",
          "3:4"
        ],
        "max_count": 4,
        "max_reference_images": 10
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": true,
        "reference_images": true,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "image.recraft_v4_style_vector",
      "object": "model",
      "capability": "image_generation",
      "name": "Recraft V4 Styles Vector",
      "description": "Recraft V4 Styles with true SVG output. Supply a custom style either as `style_id` (trained earlier) or as 1-10 `image_urls` style references, which trains one inline and returns its `style_id` for reuse.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "1:1",
          "16:9",
          "9:16",
          "4:3",
          "3:4"
        ],
        "max_count": 4,
        "max_reference_images": 10
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": true,
        "reference_images": true,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "image.recraft_v4_style_pro_vector",
      "object": "model",
      "capability": "image_generation",
      "name": "Recraft V4 Styles Pro Vector",
      "description": "Recraft V4 Styles, Pro tier, true SVG output. Supply a custom style either as `style_id` (trained earlier) or as 1-10 `image_urls` style references, which trains one inline and returns its `style_id` for reuse.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "1:1",
          "16:9",
          "9:16",
          "4:3",
          "3:4"
        ],
        "max_count": 4,
        "max_reference_images": 10
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": true,
        "reference_images": true,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "image.recraft_v4",
      "object": "model",
      "capability": "image_generation",
      "name": "Recraft V4",
      "description": "Design-grade image generation with reliable text rendering.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "1:1",
          "16:9",
          "9:16",
          "4:3",
          "3:4"
        ],
        "max_count": 4
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": false,
        "reference_images": false,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "image.recraft_v4_pro",
      "object": "model",
      "capability": "image_generation",
      "name": "Recraft V4 Pro",
      "description": "Premium Recraft V4 — top quality for marketing/branding visuals.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "1:1",
          "16:9",
          "9:16",
          "4:3",
          "3:4"
        ],
        "max_count": 4
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": false,
        "reference_images": false,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "image.grok_imagine",
      "object": "model",
      "capability": "image_generation",
      "name": "Grok Imagine",
      "description": "xAI Grok Imagine — stylized, strong prompt following.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "1:1",
          "16:9",
          "9:16"
        ],
        "max_count": 4
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": true,
        "reference_images": true,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "image.grok_imagine_pro",
      "object": "model",
      "capability": "image_generation",
      "name": "Grok Imagine Pro",
      "description": "xAI Grok Imagine Pro (Quality mode) — sharper detail, stronger text rendering, up to 2K.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "1:1",
          "16:9",
          "9:16",
          "4:3",
          "3:4",
          "3:2",
          "2:3",
          "2:1",
          "1:2",
          "20:9",
          "9:20",
          "19.5:9",
          "9:19.5"
        ],
        "max_count": 4,
        "resolutions": [
          "1K",
          "2K"
        ]
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": true,
        "reference_images": true,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "image.grok_imagine_2",
      "object": "model",
      "capability": "image_generation",
      "name": "Grok Imagine 2.0",
      "description": "xAI Grok Imagine 2.0 — the latest Grok Imagine generation. Up to 2K, 13 aspect ratios, and a quality tier (low | medium, default medium). Edit accepts up to 3 reference images.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "1:1",
          "16:9",
          "9:16",
          "4:3",
          "3:4",
          "3:2",
          "2:3",
          "2:1",
          "1:2",
          "20:9",
          "9:20",
          "19.5:9",
          "9:19.5"
        ],
        "max_count": 4,
        "resolutions": [
          "1K",
          "2K"
        ],
        "qualities": [
          "low",
          "medium"
        ],
        "max_input_images": 3
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": true,
        "reference_images": true,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "image.muse_image",
      "object": "model",
      "capability": "image_generation",
      "name": "Muse Image",
      "description": "Meta Muse Image — faithful instruction-following with accurate fine detail (text, plots, QR codes). Edit mode does precise, localized changes and composes from up to 10 reference images. No resolution or quality control; omitting aspect_ratio lets Muse size the output from the prompt.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "21:9",
          "16:9",
          "4:3",
          "3:2",
          "1:1",
          "2:3",
          "3:4",
          "9:16",
          "9:21"
        ],
        "max_count": 4,
        "max_reference_images": 10
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": true,
        "reference_images": true,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "video.flux_3",
      "object": "model",
      "capability": "video_generation",
      "name": "Flux 3",
      "description": "Black Forest Labs Flux 3 — frontier video with synchronized audio included at no extra cost. Routes to text/image-to-video, first-last-frame, keyframe pinning (keyframes[]), or extend (source_video_url). 5-20s, 720p or 1080p.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "auto",
          "21:9",
          "2:1",
          "16:9",
          "4:3",
          "1:1",
          "3:4",
          "9:16"
        ],
        "duration_seconds": [
          5,
          6,
          7,
          8,
          9,
          10,
          11,
          12,
          13,
          14,
          15,
          16,
          17,
          18,
          19,
          20
        ],
        "resolutions": [
          "720p",
          "1080p"
        ],
        "supports_audio": true,
        "max_keyframes": 10,
        "source_video_max_seconds": 15,
        "source_video_max_mb": 50
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": true,
        "reference_images": false,
        "source_video": true,
        "motion_control": false,
        "first_last_frame": true,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": true,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "video.flux_3_draft",
      "object": "model",
      "capability": "video_generation",
      "name": "Flux 3 Draft",
      "description": "Cheap 720p Flux 3 preview (~3.5x less than full quality). Returns a draft_cache_url alongside the video; pass that back to this model to render the same shot at full 1080p. Same four routing modes as Flux 3.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "auto",
          "21:9",
          "2:1",
          "16:9",
          "4:3",
          "1:1",
          "3:4",
          "9:16"
        ],
        "duration_seconds": [
          5,
          6,
          7,
          8,
          9,
          10,
          11,
          12,
          13,
          14,
          15,
          16,
          17,
          18,
          19,
          20
        ],
        "resolutions": [
          "720p"
        ],
        "supports_audio": true,
        "max_keyframes": 10,
        "source_video_max_seconds": 15,
        "source_video_max_mb": 50
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": true,
        "reference_images": false,
        "source_video": true,
        "motion_control": false,
        "first_last_frame": true,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": true,
        "video_to_video_reference": false,
        "draft_enhance": true
      }
    },
    {
      "id": "video.veo_3_1",
      "object": "model",
      "capability": "video_generation",
      "name": "Veo 3.1",
      "description": "Google Veo 3.1 — premium text/image-to-video with native audio. Supports first-last-frame interpolation. Default.",
      "status": "available",
      "is_default": true,
      "limits": {
        "aspect_ratios": [
          "16:9",
          "9:16",
          "1:1"
        ],
        "duration_seconds": [
          4,
          5,
          8
        ],
        "supports_audio": true
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": true,
        "reference_images": true,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": true,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "video.veo_3_1_fast",
      "object": "model",
      "capability": "video_generation",
      "name": "Veo 3.1 Fast",
      "description": "Cheaper, faster Veo 3.1 variant. Supports first-last-frame interpolation.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "16:9",
          "9:16",
          "1:1"
        ],
        "duration_seconds": [
          4,
          5,
          8
        ],
        "supports_audio": true
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": true,
        "reference_images": false,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": true,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "video.veo_3_1_lite",
      "object": "model",
      "capability": "video_generation",
      "name": "Veo 3.1 Lite",
      "description": "Lower-cost Lite variant of Veo 3.1. Supports first-last-frame interpolation.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "16:9",
          "9:16",
          "1:1"
        ],
        "duration_seconds": [
          4,
          5,
          8
        ],
        "supports_audio": true
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": true,
        "reference_images": false,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": true,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "video.veo_3_1_extend",
      "object": "model",
      "capability": "video_generation",
      "name": "Veo 3.1 Extend",
      "description": "Extend an existing Veo-created video by up to 7 seconds. Requires source_video_url.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "16:9",
          "9:16"
        ],
        "duration_seconds": [
          7
        ],
        "supports_audio": true
      },
      "capabilities": {
        "text_to_output": false,
        "image_to_output": false,
        "reference_images": false,
        "source_video": true,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "video.veo_3",
      "object": "model",
      "capability": "video_generation",
      "name": "Veo 3",
      "description": "Veo 3 — high-quality cinematic generation with audio (predecessor to Veo 3.1).",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "16:9",
          "9:16"
        ],
        "duration_seconds": [
          8
        ],
        "supports_audio": true
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": true,
        "reference_images": false,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "video.gemini_omni_flash_v11",
      "object": "model",
      "capability": "video_generation",
      "name": "Gemini Omni Flash 1.1",
      "description": "Google Gemini Omni Flash 1.1 — adds a 360p-4k resolution ladder, an end-frame on image-to-video, and reference video clips. 3-10s, 16:9 or 9:16. Control pacing and audio in the prompt.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "16:9",
          "9:16"
        ],
        "duration_seconds": [
          3,
          4,
          5,
          6,
          7,
          8,
          9,
          10
        ],
        "resolutions": [
          "360p",
          "720p",
          "1080p",
          "4k"
        ],
        "reference_image_urls": 10,
        "reference_video_urls": 3,
        "supports_audio": false
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": true,
        "reference_images": true,
        "source_video": true,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": true,
        "reference_media": true,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "video.gemini_omni_flash",
      "object": "model",
      "capability": "video_generation",
      "name": "Gemini Omni Flash",
      "description": "Google Gemini Omni Flash — fast, low-cost text/image-to-video. Supports reference images and video-to-video editing. 3-10s, 16:9 or 9:16. Control pacing and audio in the prompt.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "16:9",
          "9:16"
        ],
        "duration_seconds": [
          3,
          4,
          5,
          6,
          7,
          8,
          9,
          10
        ],
        "supports_audio": false
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": true,
        "reference_images": true,
        "source_video": true,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "video.veo_3_fast",
      "object": "model",
      "capability": "video_generation",
      "name": "Veo 3 Fast",
      "description": "Cheaper Veo 3 variant — same quality tier, faster turnaround.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "16:9",
          "9:16"
        ],
        "duration_seconds": [
          8
        ],
        "supports_audio": true
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": true,
        "reference_images": false,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "video.kling_o3",
      "object": "model",
      "capability": "video_generation",
      "name": "Kling O3 Standard",
      "description": "Kling O3 standard — smooth motion, strong subject consistency.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "16:9",
          "9:16",
          "1:1"
        ],
        "duration_seconds": [
          5,
          10
        ],
        "supports_audio": true
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": true,
        "reference_images": true,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": true,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": true,
        "draft_enhance": false
      }
    },
    {
      "id": "video.kling_o3_pro",
      "object": "model",
      "capability": "video_generation",
      "name": "Kling O3 Pro",
      "description": "Pro tier of Kling O3 — better quality at higher cost. Supports video-to-video reference (use source_video_url + reference_image_urls).",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "16:9",
          "9:16",
          "1:1"
        ],
        "duration_seconds": [
          5,
          10
        ],
        "supports_audio": true
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": true,
        "reference_images": true,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": true,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": true,
        "draft_enhance": false
      }
    },
    {
      "id": "video.kling_o3_4k",
      "object": "model",
      "capability": "video_generation",
      "name": "Kling O3 4K",
      "description": "Kling O3 at 4K resolution. Higher cost, top-tier quality.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "16:9",
          "9:16",
          "1:1"
        ],
        "duration_seconds": [
          5,
          10
        ],
        "resolution": "4k",
        "supports_audio": true
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": true,
        "reference_images": true,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": true,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "video.kling_v3",
      "object": "model",
      "capability": "video_generation",
      "name": "Kling V3 Standard",
      "description": "Kling V3 standard.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "16:9",
          "9:16",
          "1:1"
        ],
        "duration_seconds": [
          5,
          10
        ],
        "supports_audio": true
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": true,
        "reference_images": false,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": true,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "video.kling_v3_pro",
      "object": "model",
      "capability": "video_generation",
      "name": "Kling V3 Pro",
      "description": "Kling V3 pro — top quality.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "16:9",
          "9:16",
          "1:1"
        ],
        "duration_seconds": [
          5,
          10
        ],
        "supports_audio": true
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": true,
        "reference_images": false,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": true,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "video.kling_v3_motion_control",
      "object": "model",
      "capability": "video_generation",
      "name": "Kling V3 Motion Control",
      "description": "Transfer motion from a reference video onto a character image. Requires both image_url (character) and source_video_url (motion reference).",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "16:9",
          "9:16",
          "1:1"
        ],
        "duration_seconds": [
          5
        ]
      },
      "capabilities": {
        "text_to_output": false,
        "image_to_output": false,
        "reference_images": false,
        "source_video": false,
        "motion_control": true,
        "first_last_frame": false,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "video.kling_v3_pro_motion_control",
      "object": "model",
      "capability": "video_generation",
      "name": "Kling V3 Pro Motion Control",
      "description": "Pro-tier Kling V3 motion-control — higher quality character animation. Requires both image_url and source_video_url.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "16:9",
          "9:16",
          "1:1"
        ],
        "duration_seconds": [
          5
        ]
      },
      "capabilities": {
        "text_to_output": false,
        "image_to_output": false,
        "reference_images": false,
        "source_video": false,
        "motion_control": true,
        "first_last_frame": false,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "video.kling_v3_4k",
      "object": "model",
      "capability": "video_generation",
      "name": "Kling V3 4K",
      "description": "Kling V3 at 4K resolution.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "16:9",
          "9:16",
          "1:1"
        ],
        "duration_seconds": [
          5,
          10
        ],
        "resolution": "4k",
        "supports_audio": true
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": true,
        "reference_images": false,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": true,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "video.kling_v26",
      "object": "model",
      "capability": "video_generation",
      "name": "Kling 2.6",
      "description": "Kling 2.6 — text/image to video. Kling 2.6 has a single generation tier; this alias resolves to the same endpoints as video.kling_v26_pro.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "16:9",
          "9:16",
          "1:1"
        ],
        "duration_seconds": [
          5,
          10
        ]
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": true,
        "reference_images": false,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": true,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "video.kling_v26_pro",
      "object": "model",
      "capability": "video_generation",
      "name": "Kling 2.6 Pro",
      "description": "Kling 2.6 pro tier — higher quality.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "16:9",
          "9:16",
          "1:1"
        ],
        "duration_seconds": [
          5,
          10
        ]
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": true,
        "reference_images": false,
        "source_video": false,
        "motion_control": true,
        "first_last_frame": false,
        "end_frame": true,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "video.kling_v26_motion_control",
      "object": "model",
      "capability": "video_generation",
      "name": "Kling 2.6 Motion Control",
      "description": "Motion-control variant of Kling 2.6 (legacy). Requires image_url + source_video_url.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "16:9",
          "9:16",
          "1:1"
        ],
        "duration_seconds": [
          5
        ]
      },
      "capabilities": {
        "text_to_output": false,
        "image_to_output": false,
        "reference_images": false,
        "source_video": false,
        "motion_control": true,
        "first_last_frame": false,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "video.kling_v25_turbo",
      "object": "model",
      "capability": "video_generation",
      "name": "Kling 2.5 Turbo Pro",
      "description": "Faster Kling variant (legacy but reliable).",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "16:9",
          "9:16",
          "1:1"
        ],
        "duration_seconds": [
          5,
          10
        ]
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": true,
        "reference_images": false,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "video.kling_v21_master",
      "object": "model",
      "capability": "video_generation",
      "name": "Kling 2.1 Master",
      "description": "Kling 2.1 Master (legacy) — enhanced quality.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "16:9",
          "9:16",
          "1:1"
        ],
        "duration_seconds": [
          5,
          10
        ]
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": true,
        "reference_images": false,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "video.sora_2",
      "object": "model",
      "capability": "video_generation",
      "name": "Sora 2",
      "description": "OpenAI Sora 2 — text and image to video, 4–20s.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "16:9",
          "9:16",
          "1:1"
        ],
        "duration_seconds": [
          4,
          8,
          12,
          16,
          20
        ]
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": true,
        "reference_images": false,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "video.hailuo_03_max",
      "object": "model",
      "capability": "video_generation",
      "name": "H3 Max",
      "description": "fal's post-trained MiniMax H3 variant — stronger prompt adherence and higher throughput, from text or a first frame (with optional last-frame keyframe). Caps at 768p and has no reference mode; use video.hailuo_03 for references or 2K.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "21:9",
          "16:9",
          "4:3",
          "1:1",
          "3:4",
          "9:16"
        ],
        "duration_seconds": [
          5,
          6,
          7,
          8,
          9,
          10,
          11,
          12,
          13,
          14,
          15
        ],
        "resolutions": [
          "480p",
          "768p"
        ]
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": true,
        "reference_images": false,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": true,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "video.hailuo_03",
      "object": "model",
      "capability": "video_generation",
      "name": "Hailuo 03",
      "description": "MiniMax Hailuo 03 — 2K video from text, a first frame (with optional last-frame keyframe), or reference images/videos/audio.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "21:9",
          "16:9",
          "4:3",
          "1:1",
          "3:4",
          "9:16"
        ],
        "duration_seconds": [
          5,
          6,
          7,
          8,
          9,
          10,
          11,
          12,
          13,
          14,
          15
        ],
        "resolutions": [
          "768p",
          "2k"
        ],
        "reference_image_urls": 9,
        "reference_video_urls": 3,
        "reference_audio_urls": 3,
        "reference_media_seconds": [
          2,
          15
        ]
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": true,
        "reference_images": true,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": true,
        "reference_media": true,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "video.hailuo_23",
      "object": "model",
      "capability": "video_generation",
      "name": "Hailuo 2.3",
      "description": "MiniMax Hailuo 2.3 — dynamic video generation.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "16:9",
          "9:16",
          "1:1"
        ],
        "duration_seconds": [
          6,
          10
        ]
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": true,
        "reference_images": false,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "video.hailuo_23_pro",
      "object": "model",
      "capability": "video_generation",
      "name": "Hailuo 2.3 Pro",
      "description": "MiniMax Hailuo 2.3 Pro tier.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "16:9",
          "9:16",
          "1:1"
        ],
        "duration_seconds": [
          6,
          10
        ]
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": true,
        "reference_images": false,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "video.hailuo_02",
      "object": "model",
      "capability": "video_generation",
      "name": "Hailuo 02",
      "description": "MiniMax Hailuo 02 (legacy) — image-to-video standard tier.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "16:9",
          "9:16",
          "1:1"
        ],
        "duration_seconds": [
          6,
          10
        ]
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": true,
        "reference_images": false,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": true,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "video.hailuo_02_fast",
      "object": "model",
      "capability": "video_generation",
      "name": "Hailuo 02 Fast",
      "description": "Faster Hailuo 02 image-to-video variant.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "16:9",
          "9:16",
          "1:1"
        ],
        "duration_seconds": [
          6,
          10
        ]
      },
      "capabilities": {
        "text_to_output": false,
        "image_to_output": true,
        "reference_images": false,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "video.hailuo_23_fast",
      "object": "model",
      "capability": "video_generation",
      "name": "Hailuo 2.3 Fast",
      "description": "Faster Hailuo 2.3 image-to-video standard tier.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "16:9",
          "9:16",
          "1:1"
        ],
        "duration_seconds": [
          6,
          10
        ]
      },
      "capabilities": {
        "text_to_output": false,
        "image_to_output": true,
        "reference_images": false,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "video.hailuo_23_fast_pro",
      "object": "model",
      "capability": "video_generation",
      "name": "Hailuo 2.3 Fast Pro",
      "description": "Faster Hailuo 2.3 pro-tier image-to-video.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "16:9",
          "9:16",
          "1:1"
        ],
        "duration_seconds": [
          6,
          10
        ]
      },
      "capabilities": {
        "text_to_output": false,
        "image_to_output": true,
        "reference_images": false,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "video.luma_dream_machine",
      "object": "model",
      "capability": "video_generation",
      "name": "Luma Dream Machine",
      "description": "Luma Dream Machine — fluid motion, distinctive style.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "16:9",
          "9:16",
          "1:1"
        ],
        "duration_seconds": [
          5,
          9
        ]
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": true,
        "reference_images": false,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "video.wan_v22",
      "object": "model",
      "capability": "video_generation",
      "name": "WAN 2.2",
      "description": "WAN 2.2 — strong character animation.",
      "status": "preview",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "16:9",
          "9:16",
          "1:1"
        ],
        "duration_seconds": [
          5,
          8
        ]
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": true,
        "reference_images": false,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "video.wan_25_preview",
      "object": "model",
      "capability": "video_generation",
      "name": "WAN 2.5 Preview",
      "description": "WAN 2.5 preview — newer than 2.2, may change without notice.",
      "status": "preview",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "16:9",
          "9:16",
          "1:1"
        ],
        "duration_seconds": [
          5,
          8
        ]
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": true,
        "reference_images": false,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "video.wan_animate_replace",
      "object": "model",
      "capability": "video_generation",
      "name": "WAN Animate (Replace)",
      "description": "WAN animate-replace — swap subject in source video using a reference image. Requires image_url + source_video_url.",
      "status": "preview",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "16:9",
          "9:16",
          "1:1"
        ],
        "duration_seconds": [
          5
        ]
      },
      "capabilities": {
        "text_to_output": false,
        "image_to_output": false,
        "reference_images": false,
        "source_video": false,
        "motion_control": true,
        "first_last_frame": false,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "video.wan_animate_move",
      "object": "model",
      "capability": "video_generation",
      "name": "WAN Animate (Move)",
      "description": "WAN animate-move — animate static images with natural motion from a reference video. Requires image_url + source_video_url.",
      "status": "preview",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "16:9",
          "9:16",
          "1:1"
        ],
        "duration_seconds": [
          5
        ]
      },
      "capabilities": {
        "text_to_output": false,
        "image_to_output": false,
        "reference_images": false,
        "source_video": false,
        "motion_control": true,
        "first_last_frame": false,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "video.seedance_2_0",
      "object": "model",
      "capability": "video_generation",
      "name": "Seedance 2.0",
      "description": "ByteDance Seedance 2.0 — text/image/reference to video. Supports up to 4k.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "auto",
          "21:9",
          "16:9",
          "4:3",
          "1:1",
          "3:4",
          "9:16"
        ],
        "duration_seconds": [
          4,
          5,
          6,
          7,
          8,
          9,
          10,
          11,
          12,
          13,
          14,
          15
        ],
        "resolutions": [
          "480p",
          "720p",
          "1080p",
          "4k"
        ],
        "supports_audio": true
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": true,
        "reference_images": true,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": true,
        "reference_media": true,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "video.seedance_2_0_fast",
      "object": "model",
      "capability": "video_generation",
      "name": "Seedance 2.0 Fast",
      "description": "Faster, cheaper Seedance 2.0 variant. Caps at 720p.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "auto",
          "21:9",
          "16:9",
          "4:3",
          "1:1",
          "3:4",
          "9:16"
        ],
        "duration_seconds": [
          4,
          5,
          6,
          7,
          8,
          9,
          10,
          11,
          12,
          13,
          14,
          15
        ],
        "resolutions": [
          "480p",
          "720p"
        ],
        "supports_audio": true
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": true,
        "reference_images": true,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": true,
        "reference_media": true,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "video.seedance_2_0_mini",
      "object": "model",
      "capability": "video_generation",
      "name": "Seedance 2.0 Mini",
      "description": "Smallest, cheapest Seedance 2.0 variant. Caps at 720p; no bitrate_mode.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "auto",
          "21:9",
          "16:9",
          "4:3",
          "1:1",
          "3:4",
          "9:16"
        ],
        "duration_seconds": [
          4,
          5,
          6,
          7,
          8,
          9,
          10,
          11,
          12,
          13,
          14,
          15
        ],
        "resolutions": [
          "480p",
          "720p"
        ],
        "supports_audio": true
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": true,
        "reference_images": true,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": true,
        "reference_media": true,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "video.seedance_2_5",
      "object": "model",
      "capability": "video_generation",
      "name": "Seedance 2.5",
      "description": "ByteDance Seedance 2.5 — text/image/reference to video. 4-30s clips with native audio; reference-to-video takes up to 30 images, 10 videos, and 10 audio clips. 480p/720p/1080p (no 4k) and no speed tiers.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "auto",
          "21:9",
          "16:9",
          "4:3",
          "1:1",
          "3:4",
          "9:16"
        ],
        "duration_seconds": [
          4,
          5,
          6,
          7,
          8,
          9,
          10,
          11,
          12,
          13,
          14,
          15,
          16,
          17,
          18,
          19,
          20,
          21,
          22,
          23,
          24,
          25,
          26,
          27,
          28,
          29,
          30
        ],
        "resolutions": [
          "480p",
          "720p",
          "1080p"
        ],
        "supports_audio": true,
        "max_reference_images": 30,
        "max_reference_videos": 10,
        "max_reference_audio": 10
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": true,
        "reference_images": true,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": true,
        "reference_media": true,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "video.wan_3",
      "object": "model",
      "capability": "video_generation",
      "name": "Wan 3.0",
      "description": "Alibaba Wan 3.0 — text/image/reference to video. 2-30s clips with native synchronized audio; reference-to-video takes up to 10 images, 5 videos, and 5 audio clips. 480p/720p/1080p (default 1080p, no 4k) and no speed tiers.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "adaptive",
          "16:9",
          "4:3",
          "1:1",
          "3:4",
          "9:16"
        ],
        "duration_seconds": [
          2,
          3,
          4,
          5,
          6,
          7,
          8,
          9,
          10,
          11,
          12,
          13,
          14,
          15,
          16,
          17,
          18,
          19,
          20,
          21,
          22,
          23,
          24,
          25,
          26,
          27,
          28,
          29,
          30
        ],
        "resolutions": [
          "480p",
          "720p",
          "1080p"
        ],
        "supports_audio": true,
        "max_reference_images": 10,
        "max_reference_videos": 5,
        "max_reference_audio": 5
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": true,
        "reference_images": true,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": true,
        "reference_media": true,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "video.wan_3_prime",
      "object": "model",
      "capability": "video_generation",
      "name": "Wan 3.0 Prime",
      "description": "Alibaba Wan 3.0 Prime — the faster, higher-fidelity Wan 3.0 tier at 1.4x the price. Identical inputs: text/image/reference to video, 2-30s, native audio, up to 10 image + 5 video + 5 audio references, 480p/720p/1080p.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "adaptive",
          "16:9",
          "4:3",
          "1:1",
          "3:4",
          "9:16"
        ],
        "duration_seconds": [
          2,
          3,
          4,
          5,
          6,
          7,
          8,
          9,
          10,
          11,
          12,
          13,
          14,
          15,
          16,
          17,
          18,
          19,
          20,
          21,
          22,
          23,
          24,
          25,
          26,
          27,
          28,
          29,
          30
        ],
        "resolutions": [
          "480p",
          "720p",
          "1080p"
        ],
        "supports_audio": true,
        "max_reference_images": 10,
        "max_reference_videos": 5,
        "max_reference_audio": 5
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": true,
        "reference_images": true,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": true,
        "reference_media": true,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "video.grok_video",
      "object": "model",
      "capability": "video_generation",
      "name": "Grok Imagine Video",
      "description": "xAI Grok Imagine — high-fidelity text/image to video.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "16:9",
          "4:3",
          "3:2",
          "1:1",
          "2:3",
          "3:4",
          "9:16"
        ],
        "duration_seconds": [
          1,
          2,
          3,
          4,
          5,
          6,
          7,
          8,
          9,
          10
        ],
        "resolutions": [
          "480p",
          "720p"
        ]
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": true,
        "reference_images": true,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "video.grok_video_v15",
      "object": "model",
      "capability": "video_generation",
      "name": "Grok Imagine Video v1.5",
      "description": "xAI Grok Imagine v1.5 — text-to-video, image-to-video, or reference-to-video from up to 7 reference images.",
      "status": "available",
      "is_default": false,
      "limits": {
        "duration_seconds": [
          1,
          2,
          3,
          4,
          5,
          6,
          7,
          8,
          9,
          10,
          11,
          12,
          13,
          14,
          15
        ],
        "resolutions": [
          "480p",
          "720p",
          "1080p"
        ],
        "aspect_ratios": [
          "16:9",
          "4:3",
          "3:2",
          "1:1",
          "2:3",
          "3:4",
          "9:16"
        ]
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": true,
        "reference_images": true,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "video.grok_video_edit",
      "object": "model",
      "capability": "video_generation",
      "name": "Grok Imagine Edit",
      "description": "Edit existing videos with text prompts. Requires source_video_url.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "16:9",
          "9:16",
          "1:1"
        ],
        "duration_seconds": [
          4,
          5,
          8,
          10
        ]
      },
      "capabilities": {
        "text_to_output": false,
        "image_to_output": false,
        "reference_images": false,
        "source_video": true,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "video.grok_video_extend",
      "object": "model",
      "capability": "video_generation",
      "name": "Grok Imagine Extend",
      "description": "Extend an existing video by 2–10s. Requires source_video_url.",
      "status": "available",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "16:9",
          "9:16",
          "1:1"
        ],
        "duration_seconds": [
          2,
          5,
          10
        ]
      },
      "capabilities": {
        "text_to_output": false,
        "image_to_output": false,
        "reference_images": false,
        "source_video": true,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "video.happy_horse",
      "object": "model",
      "capability": "video_generation",
      "name": "Happy Horse v1.1",
      "description": "Alibaba Happy Horse v1.1 — text/image/reference-to-video, plus video-edit.",
      "status": "preview",
      "is_default": false,
      "limits": {
        "aspect_ratios": [
          "16:9",
          "9:16",
          "1:1",
          "4:3",
          "3:4",
          "21:9",
          "9:21",
          "5:4",
          "4:5"
        ],
        "duration_seconds": [
          3,
          4,
          5,
          6,
          7,
          8,
          9,
          10,
          11,
          12,
          13,
          14,
          15
        ]
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": true,
        "reference_images": true,
        "source_video": true,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "speech.elevenlabs_turbo_v2_5",
      "object": "model",
      "capability": "speech_generation",
      "name": "ElevenLabs Turbo v2.5",
      "description": "Low-latency TTS, balance of quality and speed. Default.",
      "status": "available",
      "is_default": true,
      "limits": {
        "max_characters": 40000
      }
    },
    {
      "id": "speech.elevenlabs_flash_v2_5",
      "object": "model",
      "capability": "speech_generation",
      "name": "ElevenLabs Flash v2.5",
      "description": "Fastest ElevenLabs TTS, lowest cost.",
      "status": "available",
      "is_default": false,
      "limits": {
        "max_characters": 40000
      }
    },
    {
      "id": "speech.elevenlabs_v3",
      "object": "model",
      "capability": "speech_generation",
      "name": "ElevenLabs v3",
      "description": "Highest-quality expressive voice generation.",
      "status": "available",
      "is_default": false,
      "limits": {
        "max_characters": 40000
      }
    },
    {
      "id": "speech.elevenlabs_multilingual_v2",
      "object": "model",
      "capability": "speech_generation",
      "name": "ElevenLabs Multilingual v2",
      "description": "29 languages, high fidelity.",
      "status": "available",
      "is_default": false,
      "limits": {
        "max_characters": 40000
      }
    },
    {
      "id": "speech.seed_audio_1_0",
      "object": "model",
      "capability": "speech_generation",
      "name": "Seed Audio 1.0",
      "description": "ByteDance Seed Audio 1.0 — general text-to-audio: natural multilingual TTS plus full audio scenes (dialogue, ambience, radio dramas) from a prompt. voice_id is OPTIONAL and takes a Seed preset name (e.g. `vivi_mixed_en_zh_ja_es_id`, `mindy_en_es_id_pt_zh`, `kian_en_zh`, `sophie_en_zh`, `magnus_en_zh`) — NOT an ElevenLabs/cloned voice id; omit it to let the model narrate. Accepts up to 3 reference audio clips via audio_urls (reference them in the prompt as @Audio1–@Audio3) OR one reference image via image_url, plus speed/volume/pitch, output_format (wav|mp3|pcm|ogg_opus) and sample_rate. Billed per second (billed seconds ≈ ceil(text length / 15)).",
      "status": "available",
      "is_default": false,
      "limits": {
        "max_characters": 2048,
        "max_reference_audio": 3
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": true,
        "reference_images": false,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "music.elevenlabs_music_v1",
      "object": "model",
      "capability": "music_generation",
      "name": "ElevenLabs Music v1",
      "description": "Prompt-based music generation up to 10 minutes. Also accepts a `composition_plan` (MusicPrompt: positive/negative_global_styles + sections[] with lyrics lines) instead of a prompt for full structural control; `respect_sections_durations` controls how strictly section durations are enforced.",
      "status": "available",
      "is_default": true,
      "limits": {
        "max_duration_seconds": 600
      }
    },
    {
      "id": "music.elevenlabs_music_v2",
      "object": "model",
      "capability": "music_generation",
      "name": "ElevenLabs Music v2",
      "description": "ElevenLabs music_v2 — higher-quality music generation up to 10 minutes from a prompt, or a chunk-based `composition_plan` (chunks[] with text incl. [Section]/{direction} markup, duration_ms, positive/negative_styles, optional per-chunk audio conditioning refs + `seed`).",
      "status": "available",
      "is_default": false,
      "limits": {
        "max_duration_seconds": 600
      }
    },
    {
      "id": "music.lyria3_pro",
      "object": "model",
      "capability": "music_generation",
      "name": "Lyria 3 Pro",
      "description": "Google Lyria 3 Pro — full structured songs up to 3 minutes with vocals, lyrics, and multi-language support. Accepts an optional image_url for inspiration (no negative prompting). Flat per-generation fee (duration is not configurable).",
      "status": "available",
      "is_default": false,
      "limits": {
        "max_duration_seconds": 180,
        "prompt_max_length": 5000
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": true,
        "reference_images": false,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "music.minimax_music_3",
      "object": "model",
      "capability": "music_generation",
      "name": "MiniMax Music 3",
      "description": "MiniMax Music 3 — sings YOUR lyrics. `lyrics` is REQUIRED (structure tags like [verse]/[chorus] must each sit on their own line) alongside a `prompt` describing genre, BPM, key, vocals and arrangement. `duration_seconds` is an upper bound of 1-300 (default 60; the model may finish earlier) and billing is per second of that bound. Also accepts `num_inference_steps` (1-100, default 30), `guidance_scale` (0-20, default 1.7) and `seed`. Returns 44.1 kHz stereo WAV. No image input, no negative prompting, no composition_plan.",
      "status": "available",
      "is_default": false,
      "limits": {
        "max_duration_seconds": 300,
        "prompt_max_length": 5000
      },
      "capabilities": {
        "text_to_output": true,
        "image_to_output": false,
        "reference_images": false,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "sfx.elevenlabs_v1",
      "object": "model",
      "capability": "sound_effect_generation",
      "name": "ElevenLabs SFX",
      "description": "Sound effect generation up to 30s.",
      "status": "available",
      "is_default": true,
      "limits": {
        "max_duration_seconds": 30
      }
    },
    {
      "id": "transcription.whisper_v1",
      "object": "model",
      "capability": "transcription",
      "name": "OpenAI Whisper v1",
      "description": "Speech-to-text with word and segment timestamps. Accepts a direct audio/video URL or a YouTube URL. Async — returns a queued run; poll genfire_get_run for the transcript.",
      "status": "available",
      "is_default": true,
      "limits": {
        "max_file_mb": 500,
        "max_duration_seconds": 7200
      }
    },
    {
      "id": "image_edit.bria_background_remove",
      "object": "model",
      "capability": "image_editing",
      "name": "BRIA Background Remove",
      "description": "Remove the background from an image. Returns a transparent PNG.",
      "status": "available",
      "is_default": true,
      "limits": {
        "input": "image_url"
      }
    },
    {
      "id": "video_upscale.fal_video_upscaler",
      "object": "model",
      "capability": "video_upscaling",
      "name": "Topaz Video Upscale",
      "description": "Upscale a video by 2x or 4x with Topaz (Proteus). Billed per second by output resolution. Async — returns a queued run; poll genfire_get_run for completion.",
      "status": "available",
      "is_default": true,
      "limits": {
        "scale_factors": [
          2,
          4
        ]
      }
    },
    {
      "id": "video_upscale.flux_video_upscale",
      "object": "model",
      "capability": "video_upscaling",
      "name": "Flux Video Upscale",
      "description": "Upscale a video 1.5x–3x with FLUX 3 super-resolution. Two modes: precise (source-faithful) and creative (adds detail, accepts an optional guiding prompt). Source must be MP4, at most 20s and 50MB. Billed per second of output by resolution and mode — materially pricier than Topaz. Async — returns a queued run; poll genfire_get_run for completion.",
      "status": "available",
      "is_default": false,
      "limits": {
        "scale_factors": [
          1.5,
          2,
          2.5,
          3
        ],
        "min_scale_factor": 1.5,
        "max_scale_factor": 3,
        "max_duration_seconds": 20,
        "max_file_mb": 50,
        "modes": [
          "precise",
          "creative"
        ]
      }
    },
    {
      "id": "image_upscale.topaz_upscale_image",
      "object": "model",
      "capability": "image_upscaling",
      "name": "Topaz Upscale",
      "description": "Upscale an image by 2x or 4x. Async — returns a queued run; poll genfire_get_run for completion.",
      "status": "available",
      "is_default": true,
      "limits": {
        "scale_factors": [
          2,
          4
        ]
      }
    },
    {
      "id": "lipsync.lipsync_2_pro",
      "object": "model",
      "capability": "lipsync_generation",
      "name": "Lipsync 2 Pro",
      "description": "High-quality lip-sync at 480p or 720p. Default.",
      "status": "available",
      "is_default": true,
      "limits": {
        "resolutions": [
          "480p",
          "720p"
        ]
      }
    },
    {
      "id": "lipsync.sync_lipsync_v2_pro",
      "object": "model",
      "capability": "lipsync_generation",
      "name": "Sync Lipsync v2 Pro",
      "description": "Alternative lip-sync engine.",
      "status": "available",
      "is_default": false,
      "limits": {
        "resolutions": [
          "480p",
          "720p"
        ]
      }
    },
    {
      "id": "lipsync.sync_lipsync_v3",
      "object": "model",
      "capability": "lipsync_generation",
      "name": "Sync Lipsync v3",
      "description": "Premium lip-sync engine — higher fidelity than v2 Pro.",
      "status": "available",
      "is_default": false,
      "limits": {
        "resolutions": [
          "480p",
          "720p"
        ]
      }
    },
    {
      "id": "3d.meshy_v7",
      "object": "model",
      "capability": "model_3d_generation",
      "name": "Meshy v7",
      "description": "Convert one image (or 1–4 images of the same object from different angles) into a textured 3D model. Outputs GLB/FBX/OBJ/USDZ/BLEND/STL plus optional PBR maps, auto-rigging, and animation. Adds ultra_mode over v6 — higher-fidelity geometry with finer surface detail (single image only). Game-ready — GLB loads natively in three.js / model-viewer. Async — returns a queued run; poll genfire_get_run for the model URLs. Processing takes 5–10 minutes.",
      "status": "available",
      "is_default": true,
      "limits": {
        "max_images": 4,
        "output_formats": [
          "glb",
          "fbx",
          "obj",
          "usdz",
          "blend",
          "stl"
        ],
        "target_polycount": {
          "min": 100,
          "max": 300000,
          "default": 30000
        },
        "topology": [
          "quad",
          "triangle"
        ],
        "ultra_mode": "single image only"
      },
      "capabilities": {
        "text_to_output": false,
        "image_to_output": true,
        "reference_images": true,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "3d.meshy_v6",
      "object": "model",
      "capability": "model_3d_generation",
      "name": "Meshy v6",
      "description": "Previous-generation Meshy. Same inputs and outputs as v7 minus ultra_mode — pin this only to reproduce earlier results. Converts one image (or 1–4 images of the same object from different angles) into a textured 3D model. Outputs GLB/FBX/OBJ/USDZ/BLEND/STL plus optional PBR maps, auto-rigging, and animation. Async — returns a queued run; poll genfire_get_run for the model URLs. Processing takes 5–10 minutes.",
      "status": "available",
      "is_default": false,
      "limits": {
        "max_images": 4,
        "output_formats": [
          "glb",
          "fbx",
          "obj",
          "usdz",
          "blend",
          "stl"
        ],
        "target_polycount": {
          "min": 100,
          "max": 300000,
          "default": 30000
        },
        "topology": [
          "quad",
          "triangle"
        ]
      },
      "capabilities": {
        "text_to_output": false,
        "image_to_output": true,
        "reference_images": true,
        "source_video": false,
        "motion_control": false,
        "first_last_frame": false,
        "end_frame": false,
        "reference_media": false,
        "masked_inpaint": false,
        "keyframes": false,
        "video_to_video_reference": false,
        "draft_enhance": false
      }
    },
    {
      "id": "game.genfire_v1",
      "object": "model",
      "capability": "game_generation",
      "name": "Genfire Games",
      "description": "Describe a game and get a fully-playable browser game (self-contained HTML, Phaser/canvas/Three.js). The completed run carries a public play_url you can open or share. Iterate by passing game_id with a change prompt. Async — returns a queued run; the codegen runs on a worker (usually 1–3 min). Poll GET /runs/{id} until status is completed, then read output.play_url.",
      "status": "available",
      "is_default": true,
      "limits": {
        "output": "playable_html",
        "shareable": true
      }
    },
    {
      "id": "app.genfire_v1",
      "object": "model",
      "capability": "app_generation",
      "name": "Genfire App Builder",
      "description": "Describe an app and get a working full-stack single-file web app (UI + in-browser data layer, hosted live). The completed run carries a public live_url you can open or share. Iterate by passing app_id with a change prompt. Async — returns a queued run; codegen runs on a worker (usually 1–3 min). Poll GET /runs/{id} until status is completed, then read output.live_url.",
      "status": "available",
      "is_default": true,
      "limits": {
        "output": "live_web_app",
        "shareable": true
      }
    },
    {
      "id": "reel.faceless",
      "object": "model",
      "capability": "faceless_reel_generation",
      "name": "Faceless Reel",
      "description": "End-to-end vertical (9:16) short: LLM script → voiceover → style-locked images → music → captioned video. Driven by a niche preset + visual style; cost varies with duration and music — call POST /v1/faceless-reels/estimate-cost for a per-config estimate.",
      "status": "available",
      "is_default": true,
      "limits": {
        "aspect_ratios": [
          "9:16"
        ],
        "target_duration_sec": {
          "min": 10,
          "max": 120,
          "default": null
        },
        "music_sources": [
          "none",
          "preset",
          "ai",
          "library"
        ],
        "catalogs": [
          "presets",
          "styles",
          "music-presets",
          "caption-presets"
        ]
      }
    },
    {
      "id": "explainer.omni",
      "object": "model",
      "capability": "explainer_generation",
      "name": "Explainer",
      "description": "Long-form narrated explainer/documentary (20s–10min, 16:9 or 9:16): script → expressive voiceover → style-locked frames → Gemini Omni Flash video clips → composed film with optional captions. Pass `script` (structured beats) to author the entire creative contract with YOUR OWN model — narration, per-scene shot-specs, motion notes, render modes, reference routing, emphasis words and recurring cast — and Genfire only renders; or pass just `topic` and Genfire writes the script. Cost varies with duration — call POST /v1/explainers/estimate-cost first.",
      "status": "available",
      "is_default": true,
      "limits": {
        "aspect_ratios": [
          "16:9",
          "9:16"
        ],
        "target_duration_sec": {
          "min": 20,
          "max": 600,
          "default": 60
        },
        "music_sources": [
          "none",
          "preset",
          "ai",
          "library"
        ],
        "script_beats": {
          "min": 3,
          "max": 100
        },
        "reference_images": {
          "max": 8
        },
        "cast_members": {
          "max": 3
        },
        "caption_modes": [
          "full",
          "keywords"
        ],
        "caption_positions": [
          "top",
          "middle",
          "bottom"
        ],
        "catalogs": [
          "styles"
        ]
      }
    },
    {
      "id": "music-video.omni",
      "object": "model",
      "capability": "music_video_generation",
      "name": "Music Video",
      "description": "Auto-produced AI music video (9:16 or 16:9) from a song: song → beat/section analysis → style-locked anchor frame → per-scene Gemini Omni Flash video clips cut to the music → composed video with optional karaoke lyric captions. Bring your own song via `song_url` (with optional lyrics/sections/word timestamps), or pass an inline `song` prompt and Genfire generates the track first (ElevenLabs music_v2, billed separately). Cost scales with song length and scene_density — call POST /v1/music-videos/estimate-cost first.",
      "status": "available",
      "is_default": true,
      "limits": {
        "aspect_ratios": [
          "9:16",
          "16:9"
        ],
        "scene_densities": [
          "low",
          "medium",
          "high"
        ],
        "song_duration_sec": {
          "min": 1,
          "max": 300
        },
        "inline_song_duration_ms": {
          "min": 10000,
          "max": 600000
        },
        "reference_images": {
          "max": 8
        },
        "catalogs": [
          "styles"
        ]
      }
    },
    {
      "id": "picture-book.gpt-image-2",
      "object": "model",
      "capability": "picture_book_generation",
      "name": "Picture Book",
      "description": "A complete illustrated picture book from a story idea or script: the free planner writes/splits the text to the age band, then a style anchor, one reference sheet per cast member, every page and both covers render on GPT Image 2 (edit endpoint, anchor + sheets as references) so characters stay consistent. Text is typeset in post (default) or lettered by the model; print formats render at KDP trim + bleed and export as print-ready PDFs (interior, cover, ebook, images zip). Async: poll GET /v1/runs/:id (progress stages included), then read GET /v1/picture-books/:id. Call POST /v1/picture-books/estimate-cost first — cost scales with pages × quality.",
      "status": "available",
      "is_default": true,
      "limits": {
        "age_bands": [
          "board",
          "picture",
          "early-reader"
        ],
        "qualities": [
          "low",
          "medium"
        ],
        "lettering_modes": [
          "typeset",
          "lettered"
        ],
        "pages": {
          "min": 4,
          "max": 48
        },
        "cast": {
          "max": 4
        },
        "export_kinds": [
          "interior-pdf",
          "cover-pdf",
          "ebook-pdf",
          "images-zip"
        ],
        "catalogs": [
          "styles",
          "formats",
          "age_bands"
        ]
      }
    }
  ]
}
GET /models/pricing
models:read

Get per-model base pricing

Returns the BASE credits per unit for every model. This is a base rate: the actual charge also scales with resolution, quality, duration, audio, count, and 3D add-ons. For the EXACT quote of a specific configuration, call POST /v1/models/estimate-cost.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Body Fields

No body fields for this endpoint.

curl Example

curl https://api.genfire.ai/v1/models/pricing \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "object": "list",
  "data": [
    {
      "model": "image.nano_banana_2",
      "capability": "image_generation",
      "unit": "per_image",
      "credits": 7,
      "operation_key": "nano_banana_2"
    },
    {
      "model": "video.veo_3_1",
      "capability": "video_generation",
      "unit": "per_second",
      "credits": 30,
      "operation_key": "veo31_fast",
      "notes": "Base per-second rate. Resolution and count scale the cost — call POST /v1/models/estimate-cost for the exact quote. Audio adds a multiplier when generate_audio=true."
    },
    {
      "model": "video.seedance_2_0",
      "capability": "video_generation",
      "unit": "per_second",
      "credits": 30,
      "operation_key": "seedance_2_0",
      "notes": "Base (720p) per-second rate; 1080p ×2.25, 4K ×5.25. Call POST /v1/models/estimate-cost for the exact quote."
    },
    {
      "model": "video.seedance_2_5",
      "capability": "video_generation",
      "unit": "per_second",
      "credits": 47,
      "operation_key": "seedance_2_5",
      "notes": "Base (720p) per-second rate; 480p ×0.47, 1080p ×2.5 (fal bills 1080p at a higher token rate, so it is NOT 2.0's ×2.25). No 4k tier. Call POST /v1/models/estimate-cost for the exact quote."
    },
    {
      "model": "speech.elevenlabs_turbo_v2_5",
      "capability": "speech_generation",
      "unit": "per_second",
      "credits": 1,
      "operation_key": "elevenlabs_tts_turbo_v2_5",
      "notes": "Billed seconds ≈ ceil(character_count / 15)."
    }
  ]
}

Notes

  • Unit values: `per_image` (image models, max 4 per request), `per_second` (video / speech / music / SFX / lipsync — speech bills seconds ≈ ceil(chars/15)), `per_generation` (flat, e.g. Lyria music and 3D mesh).
  • `credits` is a BASE rate. Video resolution multiplies it (e.g. Seedance 2.0 1080p ×2.25, 4K ×5.25; Seedance 2.5 480p ×0.47); image 2K ×1.5 / 4K ×3 and GPT Image 2 quality ×6/×22; 3D texturing/PBR/rigging add-ons; audio-off discount on some video. Call POST /v1/models/estimate-cost for the exact number.
POST /models/estimate-cost
models:read

Estimate exact generation cost

Returns the EXACT credits a specific generation config will cost — accounting for resolution, quality, duration, audio, count, and 3D add-ons. Unlike GET /models/pricing (base rate), this equals what will actually be billed. Read-only; no idempotency key required.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Body Fields

model string required

Model alias from GET /v1/models, e.g. video.seedance_2_0.

resolution string optional

Video/image resolution (e.g. 720p, 1080p, 4k, 2K).

duration number optional

Video duration in seconds (also used for lipsync audio when no audio_url).

generate_audio boolean optional

Whether audio is generated (affects some video models).

count number optional

Number of outputs (video/image).

quality string optional

Image quality tier — GPT Image 2 / Genfire (low/medium/high) and Grok Imagine 2.0 (low/medium).

should_texture boolean optional

3D: include base-color textures (default true).

enable_pbr boolean optional

3D: include PBR maps.

enable_rigging boolean optional

3D: include auto-rigging.

text string optional

Speech text (character_count derived from length).

character_count number optional

Speech character count (alternative to text).

duration_seconds number optional

Music / SFX duration in seconds.

audio_url string optional

Lipsync: audio URL (duration estimated when duration omitted).

curl Example

curl https://api.genfire.ai/v1/models/estimate-cost \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "model": "video.seedance_2_0",
  "resolution": "1080p",
  "duration": 15,
  "generate_audio": true
}'

Response Example

{
  "object": "cost_estimate",
  "model": "video.seedance_2_0",
  "capability": "video_generation",
  "credits": 1013,
  "unit": "total",
  "breakdown": {
    "operation_key": "seedance_2_0",
    "base_rate": 30,
    "duration_seconds": 15,
    "resolution": "1080p",
    "resolution_multiplier": 2.25,
    "audio_multiplier": 1,
    "video_count": 1
  }
}

Request Example Body

{
  "model": "video.seedance_2_0",
  "resolution": "1080p",
  "duration": 15,
  "generate_audio": true
}

Notes

  • The returned `credits` is the exact charge for the given config — quote == charge.
GET /audio/voices
models:read

List voices for speech generation

Returns the voice ids accepted by `voice_id` on `/audio/speech`. By default this lists the voices you have cloned (their ids look like `fal_cloned_<id>`); a cloned voice id is otherwise only shown once at clone time in the dashboard, so this is the way to discover it programmatically. Pass `?include=stock` to also return built-in ElevenLabs stock voices.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Parameters

include query optional

Comma-separated extra sources to include. Currently only `stock` is supported, which appends built-in ElevenLabs voices.

Body Fields

No body fields for this endpoint.

curl Example

curl https://api.genfire.ai/v1/audio/voices \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "object": "list",
  "data": [
    {
      "id": "fal_cloned_abc123",
      "object": "voice",
      "name": "My Cloned Voice",
      "type": "cloned",
      "provider": "fal_qwen3",
      "preview_url": "https://cdn.genfire.ai/voice-clones/preview-abc123.wav",
      "created_at": "2026-05-01T12:00:00.000Z"
    }
  ]
}

Notes

  • Cloned voices are scoped to the authenticated account — you only ever see your own.
  • Stock voices are large and account-global, so they are excluded unless `include=stock` is passed.

Reference

Usage

GET /usage
runs:read

Get aggregated API usage

Aggregate API usage for the authenticated account over a date range. Returns totals (credits spent, run counts) plus a breakdown grouped by model, capability, or day. Default range is the last 30 days; max range is 365 days.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Parameters

start_date query optional

Inclusive lower bound (ISO date or full timestamp). Defaults to 30 days ago.

end_date query optional

Exclusive upper bound. Defaults to now.

group_by query optional

Bucketing for the breakdown: `model`, `capability`, `day`, or `none`.

Default: model

capability query optional

Optional filter, e.g. `video_generation`.

Body Fields

No body fields for this endpoint.

curl Example

curl https://api.genfire.ai/v1/usage \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "object": "usage_summary",
  "period": {
    "start": "2026-04-01T00:00:00.000Z",
    "end": "2026-04-30T23:59:59.999Z"
  },
  "group_by": "model",
  "totals": {
    "credits_spent": 4823,
    "runs_count": 187,
    "successful_runs": 178,
    "failed_runs": 9
  },
  "breakdown": [
    {
      "group": "video.veo_3_1",
      "credits_spent": 2400,
      "runs_count": 30,
      "successful_runs": 30,
      "failed_runs": 0,
      "avg_credits_per_run": 80
    },
    {
      "group": "image.nano_banana_2",
      "credits_spent": 423,
      "runs_count": 141,
      "successful_runs": 138,
      "failed_runs": 3,
      "avg_credits_per_run": 3
    }
  ]
}

Notes

  • Buckets are sorted by `credits_spent` descending, except `group_by=day` which is sorted chronologically.
  • Counts only include runs that hit `/v1` endpoints. Dashboard generations and workflow runs initiated outside the public API are not included.

Reference

Uploads

POST /uploads
uploads:write

Create a signed upload URL

Allocates a pre-signed PUT URL so a client can upload a local file directly to Genfire storage without proxying bytes through the API. Use the returned `asset_url` as `image_url`, `video_url`, or `audio_url` in subsequent generation requests.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Body Fields

filename string required

Original filename. The extension is preserved in the stored object path.

content_type string optional

MIME type for the upload. Pinned into the signed URL — the PUT must send the same `Content-Type`.

Default: application/octet-stream

size_bytes number optional

Optional declared file size. Rejected if greater than the 5 GB ceiling.

curl Example

curl https://api.genfire.ai/v1/uploads \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "filename": "reference.png",
  "content_type": "image/png",
  "size_bytes": 124000
}'

Response Example

{
  "asset_id": "asset_8f3c4a2b1d6e7f9a0b1c2d3e",
  "upload_url": "https://storage.googleapis.com/genfire-uploads/...?X-Goog-Signature=...",
  "asset_url": "https://storage.googleapis.com/genfire-uploads/...?X-Goog-Signature=...",
  "content_type": "image/png",
  "expires_at": "2026-05-12T02:21:25.985Z"
}

Request Example Body

{
  "filename": "reference.png",
  "content_type": "image/png",
  "size_bytes": 124000
}

Notes

  • PUT the file bytes to `upload_url` within 15 minutes. The signed URL is pinned to the `content_type` you submitted — sending a different `Content-Type` header will be rejected by the storage layer.
  • `asset_url` is a 7-day signed READ URL. Re-upload the asset before this point if you need long-lived references.
  • Maximum upload size is 5 GB.

Reference

Influencers

GET /influencers
influencers:read

List your trained influencers

Returns the influencer characters owned by the authenticated account that are in `ready` status. Use the returned `id` and `handle` in the `mentions` array of an image generation request to inject the character.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Body Fields

No body fields for this endpoint.

curl Example

curl https://api.genfire.ai/v1/influencers \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "object": "list",
  "data": [
    {
      "id": "model_abc123def456",
      "object": "influencer",
      "handle": "sarah",
      "display_name": "Sarah Chen",
      "status": "ready",
      "generation_state": "ready",
      "source_type": "uploaded",
      "preview_url": "https://firebasestorage.googleapis.com/...",
      "face_url": "https://firebasestorage.googleapis.com/...",
      "sheet_url": "https://firebasestorage.googleapis.com/...",
      "created_at": "2026-04-12T10:30:00.000Z",
      "updated_at": "2026-04-12T10:35:00.000Z"
    }
  ]
}

Notes

  • Drafts and archived influencers are NOT returned. Train and finalize them in the dashboard before they can be referenced.
GET /influencers/{influencerId}
influencers:read

Get a single influencer by id

Returns full details for one influencer the authenticated account owns.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Parameters

influencerId path required

Influencer id from `GET /v1/influencers`.

Body Fields

No body fields for this endpoint.

curl Example

curl https://api.genfire.ai/v1/influencers/{influencerId} \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "id": "model_abc123def456",
  "object": "influencer",
  "handle": "sarah",
  "display_name": "Sarah Chen",
  "status": "ready",
  "generation_state": "ready",
  "source_type": "uploaded",
  "preview_url": "https://firebasestorage.googleapis.com/...",
  "face_url": "https://firebasestorage.googleapis.com/...",
  "sheet_url": "https://firebasestorage.googleapis.com/...",
  "created_at": "2026-04-12T10:30:00.000Z",
  "updated_at": "2026-04-12T10:35:00.000Z"
}

Notes

  • 404 if the influencer does not exist or is not owned by the authenticated account.
POST /influencers
influencers:write

Create an influencer (from photos or from scratch)

Creates a reusable influencer character in one of two modes: 1. **From photos** — supply `photo_urls` (1–8 reference photos of a real person). The bytes are copied into durable storage and a 4-panel character reference sheet is generated to lock the identity. 2. **From scratch** — supply `appearance` (no photos). A brand-new person is generated from the described traits: first a hero photo, then the reference sheet from it. Provide exactly one of `photo_urls` or `appearance`. The call returns immediately with `status: "creating"`; the generation runs asynchronously (~30–90s). Poll `GET /v1/influencers/{id}` until `status` is `ready` (or `failed`). Billable: sheet (and, for from-scratch, hero) generation charges credits.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Required

Body Fields

handle string required

Short @-mention handle (letters, digits, underscores), e.g. `maya`. Lowercased automatically. Must be unique within your account. This is the influencer's only name — the `display_name` in responses is derived from it.

photo_urls string[] optional

FROM-PHOTOS mode. 1–8 absolute https URLs of reference photos. Upload local files via `POST /v1/uploads` first and pass the returned `asset_url`s here. Mutually exclusive with `appearance`.

appearance object optional

FROM-SCRATCH mode. Generate a new person from traits. Fields: `gender` (string, required — e.g. "woman", "man"), `heritage` (string, required — race/ethnicity, e.g. "korean"), `age` (string, required — one of `18-21`, `21-25`, `25-30`, `30-40`, `40+`), `prompt` (string, optional — free-text descriptor, e.g. "freckles, platinum bob, green eyes, editorial look"). Mutually exclusive with `photo_urls`.

curl Example

curl https://api.genfire.ai/v1/influencers \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Idempotency-Key: unique_request_key" \
  -H "Content-Type: application/json" \
  -d '{
  "handle": "maya",
  "appearance": {
    "gender": "woman",
    "heritage": "korean",
    "age": "21-25",
    "prompt": "freckles, platinum blonde bob, green eyes, editorial fashion look"
  }
}'

Response Example

{
  "id": "model_abc123def456",
  "object": "influencer",
  "handle": "maya",
  "display_name": "Maya",
  "status": "creating",
  "generation_state": "draft",
  "source_type": "generated",
  "preview_url": null,
  "face_url": null,
  "sheet_url": null,
  "created_at": "2026-06-18T10:30:00.000Z",
  "updated_at": "2026-06-18T10:30:00.000Z"
}

Request Example Body

{
  "handle": "maya",
  "appearance": {
    "gender": "woman",
    "heritage": "korean",
    "age": "21-25",
    "prompt": "freckles, platinum blonde bob, green eyes, editorial fashion look"
  }
}

Notes

  • Requires the `influencers:write` scope and an `Idempotency-Key` header.
  • Provide exactly one of `photo_urls` (clone from photos) or `appearance` (generate from scratch).
  • Asynchronous: the response is `status: "creating"`. Poll `GET /v1/influencers/{id}` until `ready`.
  • Creation produces TWO images in sequence — the hero `face_url`, then the `sheet_url` built from it. Each appears on the polled record as soon as it lands, and `generation_state` advances `draft` → `face_generated` → `sheet_generated` → `ready`, so a UI can show per-artefact progress instead of one opaque spinner.
  • Billable: generating the reference sheet (and, for from-scratch, the hero photo) charges credits against your account.
  • Once `ready`, reference the influencer in image generation via the `mentions` array using the returned `id` and `handle`.

Reference

Projects

GET /projects
projects:read

List your projects

Returns every project the authenticated account can see — its own, plus any shared with a workspace it belongs to. A project is a named folder of work (videos, images, audio, elements); the same projects the Video Studio shows in its rail. Folders are projects with `parent_id` set and nest exactly one level.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Parameters

parent_id query optional

Filter. A root project id lists only that project's folders; the literal `root` lists only top-level projects. Omit for the whole tree.

Body Fields

No body fields for this endpoint.

curl Example

curl https://api.genfire.ai/v1/projects \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "object": "list",
  "data": [
    {
      "id": "col_abc123",
      "object": "project",
      "name": "Summer Campaign",
      "description": null,
      "brief": "Warm, sun-bleached, shot on 35mm.",
      "parent_id": null,
      "is_folder": false,
      "cover_url": "https://firebasestorage.googleapis.com/...",
      "team_id": null,
      "role": "owner",
      "item_count": 12,
      "created_at": "2026-08-01T10:30:00.000Z",
      "updated_at": "2026-08-24T18:02:00.000Z"
    },
    {
      "id": "col_def456",
      "object": "project",
      "name": "Scene 01",
      "description": null,
      "brief": null,
      "parent_id": "col_abc123",
      "is_folder": true,
      "cover_url": null,
      "team_id": null,
      "role": "owner",
      "item_count": 4,
      "created_at": "2026-08-02T09:00:00.000Z",
      "updated_at": "2026-08-24T18:02:00.000Z"
    }
  ]
}

Notes

  • `role` is the authenticated caller's role on the project: `owner` when they created it, otherwise their role on the workspace it is shared with.
  • Pass a project id as `project_id` on a generation request to file that generation's output into it automatically — see the generation endpoints.
GET /projects/{projectId}
projects:read

Open a project and list what is in it

Returns one project plus its filed `items`, each hydrated to a real media `url` you can pass straight back into a generation request (as `image_url`, `reference_image_urls`, or a lip-sync `video_url`). Also returns the project `brief` — the creative direction the user wrote for it.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Parameters

projectId path required

Project id from `GET /v1/projects`.

Body Fields

No body fields for this endpoint.

curl Example

curl https://api.genfire.ai/v1/projects/{projectId} \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "id": "col_abc123",
  "object": "project",
  "name": "Summer Campaign",
  "description": null,
  "brief": "Warm, sun-bleached, shot on 35mm.",
  "parent_id": null,
  "is_folder": false,
  "cover_url": "https://firebasestorage.googleapis.com/...",
  "team_id": null,
  "role": "owner",
  "item_count": 2,
  "items": [
    {
      "asset_id": "img_abc123",
      "asset_type": "image",
      "title": "bottle on warm sand, 35mm",
      "url": "https://firebasestorage.googleapis.com/...",
      "thumbnail_url": "https://firebasestorage.googleapis.com/...",
      "added_at": "2026-08-24T18:02:00.000Z"
    },
    {
      "asset_id": "vid_def456",
      "asset_type": "video",
      "title": "hero pour, slow motion",
      "url": "https://firebasestorage.googleapis.com/...",
      "thumbnail_url": "https://firebasestorage.googleapis.com/...",
      "added_at": "2026-08-24T18:05:00.000Z"
    }
  ],
  "created_at": "2026-08-01T10:30:00.000Z",
  "updated_at": "2026-08-24T18:05:00.000Z"
}

Notes

  • An item whose asset is still generating, or has since been deleted, comes back with `url: null` rather than failing the read.
  • Items are capped at 200 per response; a project holds at most 500.
  • 404 if the project does not exist or the account has no access to it.
POST /projects
projects:write

Create a project or a folder

Creates a project. Pass `parent_id` to create a FOLDER inside an existing root project instead — folders nest one level only, so a folder cannot contain folders. Free and synchronous.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Body Fields

name string required

Project name, e.g. `Summer Campaign` or `Scene 01`.

description string optional

Optional short description.

parent_id string optional

Create this as a folder inside the given ROOT project. The parent must be a root the caller can edit.

curl Example

curl https://api.genfire.ai/v1/projects \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Summer Campaign"
}'

Response Example

{
  "id": "col_abc123",
  "object": "project",
  "name": "Summer Campaign",
  "description": null,
  "brief": null,
  "parent_id": null,
  "is_folder": false,
  "cover_url": null,
  "team_id": null,
  "role": "owner",
  "item_count": 0,
  "items": [],
  "created_at": "2026-08-26T10:30:00.000Z",
  "updated_at": "2026-08-26T10:30:00.000Z"
}

Request Example Body

{
  "name": "Summer Campaign"
}

Notes

  • A folder created inside a workspace-shared project inherits the share.
  • 409-equivalent 400 if `parent_id` names a folder rather than a root project.
PATCH /projects/{projectId}
projects:write

Rename a project, edit its brief, or re-file it

Partial update. Supply any of `name`, `brief` or `parent_id`.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Parameters

projectId path required

Project id from `GET /v1/projects`.

Body Fields

name string optional

New project name.

brief string optional

The project's creative brief, shown in the studio and returned by `GET /v1/projects/{projectId}`.

parent_id string | null optional

Move this project under a root project, or `null` to promote it to a root. One-level nesting is enforced: a project that already has folders cannot become a folder.

curl Example

curl https://api.genfire.ai/v1/projects/{projectId} \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "brief": "Warm, sun-bleached, shot on 35mm."
}'

Response Example

{
  "id": "col_abc123",
  "object": "project",
  "name": "Summer Campaign",
  "description": null,
  "brief": "Warm, sun-bleached, shot on 35mm.",
  "parent_id": null,
  "is_folder": false,
  "cover_url": "https://firebasestorage.googleapis.com/...",
  "team_id": null,
  "role": "owner",
  "item_count": 12,
  "created_at": "2026-08-01T10:30:00.000Z",
  "updated_at": "2026-08-26T10:31:00.000Z"
}

Request Example Body

{
  "brief": "Warm, sun-bleached, shot on 35mm."
}

Notes

  • Requires edit access: the owner, or an owner/admin/editor of the workspace the project is shared with.
DELETE /projects/{projectId}
projects:write

Delete a project

Deletes the project. The media it held is NOT deleted — it stays in your library and simply stops being filed here.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Parameters

projectId path required

Project id from `GET /v1/projects`.

Body Fields

No body fields for this endpoint.

curl Example

curl https://api.genfire.ai/v1/projects/{projectId} \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "id": "col_abc123",
  "object": "project",
  "deleted": true
}

Notes

  • Owner only. A workspace admin who did not create the project cannot delete it.
POST /projects/{projectId}/items
projects:write

File assets into a project

Adds existing assets to a project. Use this for work that already exists; for NEW generations pass `project_id` on the generation request instead and the output files itself when the run completes.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Parameters

projectId path required

Project id from `GET /v1/projects`.

Body Fields

items object[] required

Assets to file. Each is `{ asset_id, asset_type }` where `asset_type` is one of `video`, `image`, `audio`, `element`, plus an optional `title` and `thumbnail_url`. Image and video ids come from a completed run (`resource_id`, or `internal_refs.image_ids`); element ids from `GET /v1/elements`.

curl Example

curl https://api.genfire.ai/v1/projects/{projectId}/items \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "items": [
    {
      "asset_id": "img_abc123",
      "asset_type": "image",
      "title": "bottle on warm sand"
    },
    {
      "asset_id": "elem_abc123",
      "asset_type": "element"
    }
  ]
}'

Response Example

{
  "id": "col_abc123",
  "object": "project",
  "name": "Summer Campaign",
  "item_count": 14,
  "added": 2,
  "updated_at": "2026-08-26T10:32:00.000Z"
}

Request Example Body

{
  "items": [
    {
      "asset_id": "img_abc123",
      "asset_type": "image",
      "title": "bottle on warm sand"
    },
    {
      "asset_id": "elem_abc123",
      "asset_type": "element"
    }
  ]
}

Notes

  • De-duplicated by `asset_id`: re-filing something already in the project is a no-op, and `added` reports how many were actually new.
  • A project holds 500 items; exceeding it is a 400.
  • Filing into a workspace-shared project makes your own assets readable by that workspace. You can only widen access to assets you own.
DELETE /projects/{projectId}/items
projects:write

Unfile assets from a project

Removes assets from a project. The media itself is not deleted — it stays in your library.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Parameters

projectId path required

Project id from `GET /v1/projects`.

Body Fields

asset_ids string[] required

Asset ids to unfile, from `GET /v1/projects/{projectId}` items.

curl Example

curl https://api.genfire.ai/v1/projects/{projectId}/items \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "id": "col_abc123",
  "object": "project",
  "name": "Summer Campaign",
  "item_count": 13,
  "removed": 1,
  "updated_at": "2026-08-26T10:33:00.000Z"
}

Request Example Body

{
  "asset_ids": [
    "img_abc123"
  ]
}

Notes

  • An asset removed from the last workspace project holding it loses that workspace's read access again.

Reference

Elements

GET /elements
elements:read

List your reusable image elements

Returns the named image "elements" (reusable props — a product, logo, object) owned by the authenticated account. Reference an element in a video prompt by writing `@<handle>`.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Body Fields

No body fields for this endpoint.

curl Example

curl https://api.genfire.ai/v1/elements \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "object": "list",
  "data": [
    {
      "id": "elem_abc123",
      "object": "element",
      "handle": "redbottle",
      "name": "Red Bottle",
      "image_url": "https://firebasestorage.googleapis.com/...",
      "thumbnail_url": "https://firebasestorage.googleapis.com/...",
      "source_type": "upload",
      "aspect_ratio": "1:1",
      "created_at": "2026-06-29T10:30:00.000Z",
      "updated_at": "2026-06-29T10:30:00.000Z"
    }
  ]
}

Notes

  • Element `@<handle>` mentions resolve only on reference-capable video models (Seedance, Wan 3.0, Veo 3.1 reference, Gemini Omni Flash reference, Hailuo 03 reference, or Grok reference). The element image is appended to the reference pool and the handle is rewritten for you — to "the <name>" where references bind by description, or to `@Image{n}` where they bind by POSITION (Wan 3.0, Hailuo 03 reference). They are ignored by image models and by Kling/Happy Horse, whose own tokens ARE the array index.
GET /elements/{elementId}
elements:read

Get a single element by id

Returns full details for one element the authenticated account owns.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Parameters

elementId path required

Element id from `GET /v1/elements`.

Body Fields

No body fields for this endpoint.

curl Example

curl https://api.genfire.ai/v1/elements/{elementId} \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "id": "elem_abc123",
  "object": "element",
  "handle": "redbottle",
  "name": "Red Bottle",
  "image_url": "https://firebasestorage.googleapis.com/...",
  "thumbnail_url": "https://firebasestorage.googleapis.com/...",
  "source_type": "upload",
  "aspect_ratio": "1:1",
  "created_at": "2026-06-29T10:30:00.000Z",
  "updated_at": "2026-06-29T10:30:00.000Z"
}

Notes

  • 404 if the element does not exist or is not owned by the authenticated account.
POST /elements
elements:write

Create an element from an image

Creates a reusable named image element from a single image URL. Synchronous and free (no generation): the element is returned immediately in `ready` status. Once created, write `@<handle>` in a video generation `prompt` to drop the element image into the scene on reference-capable models.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Body Fields

name string required

Human-friendly name, e.g. `Red Bottle`. Also used as the in-prompt phrase ("the Red Bottle") when the `@handle` is resolved.

image_url string required

Absolute https URL of the element image. Upload a local file via `POST /v1/uploads` first and pass the returned `asset_url`.

handle string optional

Short @-mention handle (letters, digits, underscores), e.g. `redbottle`. Lowercased automatically. Auto-derived from `name` if omitted. Must be unique within your account.

aspect_ratio string optional

Optional aspect ratio of the image, e.g. `1:1`, `9:16`. Informational only.

project_id string optional

File the new element into one of your PROJECTS (`GET /v1/projects`), the same way the studio files an element created while a project is open. Access is checked before the element is created; the response echoes `project_id` (null if filing failed).

curl Example

curl https://api.genfire.ai/v1/elements \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Red Bottle",
  "handle": "redbottle",
  "image_url": "https://storage.googleapis.com/.../bottle.png"
}'

Response Example

{
  "id": "elem_abc123",
  "object": "element",
  "handle": "redbottle",
  "name": "Red Bottle",
  "image_url": "https://firebasestorage.googleapis.com/...",
  "thumbnail_url": "https://firebasestorage.googleapis.com/...",
  "source_type": "upload",
  "aspect_ratio": "1:1",
  "created_at": "2026-06-29T10:30:00.000Z",
  "updated_at": "2026-06-29T10:30:00.000Z"
}

Request Example Body

{
  "name": "Red Bottle",
  "handle": "redbottle",
  "image_url": "https://storage.googleapis.com/.../bottle.png"
}

Notes

  • Requires the `elements:write` scope.
  • Not billable — no generation runs; the supplied image URL is stored as the element.
  • To use: write `@<handle>` in a `POST /v1/videos/generations` prompt on a reference-capable model (Seedance, Veo 3.1 reference, or Grok reference).
DELETE /elements/{elementId}
elements:write

Delete an element

Removes an element from your library. The underlying image is not affected; only the named `@handle` reference is deleted.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Parameters

elementId path required

Element id from `GET /v1/elements`.

Body Fields

No body fields for this endpoint.

curl Example

curl https://api.genfire.ai/v1/elements/{elementId} \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "id": "elem_abc123",
  "object": "element",
  "deleted": true
}

Notes

  • 404 if the element does not exist or is not owned by the authenticated account.

Reference

Brands

POST /brands/ingestions
brands:write

Create a brand profile from a website URL

Ingests a website into a full brand profile: renders the site in a headless browser, captures desktop/mobile screenshots, extracts the logo, colors, and fonts from the rendered page, scrapes product data, and runs vision + copy analysis to build a structured brand voice. Asynchronous: returns a queued run — poll `GET /v1/runs/{id}`; the completed output carries `brand_id`.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Body Fields

url string required

The brand or product website URL, e.g. `https://example.com`. A bare domain is accepted (https is assumed).

curl Example

curl https://api.genfire.ai/v1/brands/ingestions \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "url": "https://example.com"
}'

Response Example

{
  "id": "run_abc123",
  "object": "run",
  "capability": "brand_ingestion",
  "status": "queued",
  "output": null
}

Request Example Body

{
  "url": "https://example.com"
}

Notes

  • Requires the `brands:write` scope and an `Idempotency-Key` header.
  • Free — brand ingestion never charges credits.
  • Typical duration is 30–90 seconds. When the run completes, `output.brand_id` identifies the brand; fetch it with `GET /v1/brands/{brandId}`.
  • Ingestion visits at most the pasted URL plus 2 discovered pages (about/product), honoring robots.txt for discovered pages.
POST /brands
brands:write

Create a brand from supplied fields

Creates a brand profile from fields you provide. Unlike `POST /v1/brands/ingestions`, this never fetches a website or any third-party URL — `website_url` is stored as metadata only. Use it when you already have the brand details, or on surfaces where URL ingestion is not permitted. Synchronous: returns the created brand.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Body Fields

name string required

Brand name.

tagline string optional

Short positioning line.

description string optional

What the brand sells and who it serves.

website_url string optional

Stored for reference only — this endpoint never visits it.

logo_url string optional

URL of an already-hosted logo image.

icon_url string optional

URL of an already-hosted icon or favicon.

colors array optional

Palette entries, e.g. `[{ "hex": "#FF5A1F", "role": "primary" }]`.

fonts array optional

Typography entries, e.g. `[{ "name": "Inter", "role": "heading" }]`.

voice object optional

Structured brand voice (tone, do/dont, vocabulary).

style string optional

Free-text visual style direction.

image_urls array optional

Reference imagery already hosted elsewhere.

default_language string optional

BCP-47 language tag, e.g. `en-US`.

default_country string optional

ISO 3166-1 alpha-2 country code, e.g. `US`.

curl Example

curl https://api.genfire.ai/v1/brands \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Acme",
  "tagline": "Ship faster",
  "colors": [
    {
      "hex": "#FF5A1F",
      "role": "primary"
    }
  ],
  "fonts": [
    {
      "name": "Inter",
      "role": "heading"
    }
  ]
}'

Response Example

{
  "id": "brand_abc123",
  "object": "brand",
  "name": "Acme",
  "tagline": "Ship faster",
  "colors": [
    {
      "hex": "#FF5A1F",
      "role": "primary"
    }
  ],
  "status": "ready",
  "created_at": "2026-08-13T01:00:00.000Z",
  "updated_at": "2026-08-13T01:00:00.000Z"
}

Request Example Body

{
  "name": "Acme",
  "tagline": "Ship faster",
  "colors": [
    {
      "hex": "#FF5A1F",
      "role": "primary"
    }
  ],
  "fonts": [
    {
      "name": "Inter",
      "role": "heading"
    }
  ]
}

Notes

  • Requires the `brands:write` scope and an `Idempotency-Key` header.
  • Free — creating a brand never charges credits.
  • Add products afterwards with `POST /v1/brands/{brandId}/products`, and refine fields with `PATCH /v1/brands/{brandId}`.
GET /brands
brands:read

List your brands

Returns the brand profiles owned by the authenticated account: identity, visual kit (logo, colors, fonts), structured voice, screenshots, and status.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Body Fields

No body fields for this endpoint.

curl Example

curl https://api.genfire.ai/v1/brands \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "object": "list",
  "data": [
    {
      "id": "brand_abc123",
      "object": "brand",
      "name": "Acme",
      "tagline": "Ship faster",
      "website_url": "https://acme.com",
      "logo_url": "https://firebasestorage.googleapis.com/...",
      "colors": [
        {
          "hex": "#FF5A1F",
          "role": "primary"
        }
      ],
      "fonts": [
        {
          "name": "Inter",
          "role": "heading",
          "source": "google-fonts",
          "google_fonts_url": "https://fonts.googleapis.com/css2?family=Inter"
        }
      ],
      "status": "ready",
      "created_at": "2026-07-21T10:30:00.000Z",
      "updated_at": "2026-07-21T10:31:30.000Z"
    }
  ]
}
GET /brands/{brandId}
brands:read

Get a brand with its products

Returns the full brand profile — identity, colors, fonts, structured voice (tone, audience, value props, words to use/avoid), screenshots — plus its scraped product records.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Parameters

brandId path required

Brand id from `GET /v1/brands` or a completed ingestion run's `output.brand_id`.

Body Fields

No body fields for this endpoint.

curl Example

curl https://api.genfire.ai/v1/brands/{brandId} \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "id": "brand_abc123",
  "object": "brand",
  "name": "Acme",
  "voice": {
    "tone_adjectives": [
      "confident",
      "direct"
    ],
    "formality": 3,
    "target_audience": "Small e-commerce teams",
    "value_props": [
      "Launch ads in minutes"
    ],
    "summary": "Write like a helpful expert: short sentences, concrete outcomes, no hype."
  },
  "products": [
    {
      "id": "prod_1",
      "object": "brand_product",
      "name": "Acme Starter Kit",
      "images": [
        "https://..."
      ],
      "price": "49.00"
    }
  ],
  "status": "ready"
}

Notes

  • While ingestion is in progress `status` is `ingesting`; profile fields fill in when it completes.
  • 404 if the brand does not exist or is not owned by the authenticated account.
PATCH /brands/{brandId}
brands:write

Edit a brand

Updates editable brand fields (name, tagline, description, colors, voice, style, logo_url, icon_url, default_language, default_country). Fields not present in the body are left unchanged.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Parameters

brandId path required

Brand id.

Body Fields

No body fields for this endpoint.

curl Example

curl https://api.genfire.ai/v1/brands/{brandId} \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "tagline": "Ship faster",
  "colors": [
    {
      "hex": "#FF5A1F",
      "role": "primary"
    }
  ]
}'

Response Example

{
  "id": "brand_abc123",
  "object": "brand",
  "name": "Acme",
  "tagline": "Ship faster",
  "status": "ready"
}

Request Example Body

{
  "tagline": "Ship faster",
  "colors": [
    {
      "hex": "#FF5A1F",
      "role": "primary"
    }
  ]
}
DELETE /brands/{brandId}
brands:write

Delete a brand

Deletes a brand profile and its product records.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Parameters

brandId path required

Brand id.

Body Fields

No body fields for this endpoint.

curl Example

curl https://api.genfire.ai/v1/brands/{brandId} \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "id": "brand_abc123",
  "object": "brand",
  "deleted": true
}

Reference

Moodboards

GET /moodboards
moodboards:read

List your moodboards

Returns the moodboards owned by the authenticated account — each a saved aesthetic: its images, the analyzed style profile (taste profile, keywords, avoids, measured palette, exemplar image ids, composed prompt fragment), and any free-text guidelines. Boards hidden in the dashboard are omitted. Boards are created and edited in the Genfire dashboard; the API consumes them via `moodboard_id` on `POST /v1/images/generations`. Boards shared with you by a team are not listed here but remain usable by id.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Body Fields

No body fields for this endpoint.

curl Example

curl https://api.genfire.ai/v1/moodboards \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "object": "list",
  "data": [
    {
      "id": "mb_abc123",
      "object": "moodboard",
      "name": "Analog Grain",
      "image_count": 18,
      "images": [
        {
          "id": "img_1",
          "url": "https://storage.googleapis.com/...",
          "thumbnail_url": "https://storage.googleapis.com/...",
          "source": "upload"
        }
      ],
      "analysis": {
        "status": "ready",
        "taste_profile": "Sun-bleached 35mm film photography with soft grain...",
        "keywords": [
          "35mm film",
          "soft grain",
          "muted pastels"
        ],
        "avoids": [
          "digital sharpness",
          "HDR"
        ],
        "palette": {
          "hexes": [
            "#D9C7B2",
            "#8A9B8E"
          ],
          "primary": "#D9C7B2",
          "accent": "#8A9B8E"
        },
        "exemplar_image_ids": [
          "img_1"
        ],
        "prompt_fragment": "In the exact visual style of this moodboard: ..."
      },
      "guidelines": "Always keep skin tones warm.",
      "cover_image_id": "img_1",
      "created_at": "2026-08-10T10:30:00.000Z",
      "updated_at": "2026-08-12T09:12:00.000Z"
    }
  ]
}
GET /moodboards/{moodboardId}
moodboards:read

Get a moodboard

Returns one moodboard: its images and the analyzed style profile. Team members a board is shared with can read (and generate with) it; only the owner can edit it in the dashboard. While analysis is running, `analysis.status` is `analyzing` and the style fields fill in when it completes — the board still grounds generations meanwhile (guidelines and reference images apply even before the analysis is ready).

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Parameters

moodboardId path required

Moodboard id from `GET /v1/moodboards` or a forked preset.

Body Fields

No body fields for this endpoint.

curl Example

curl https://api.genfire.ai/v1/moodboards/{moodboardId} \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "id": "mb_abc123",
  "object": "moodboard",
  "name": "Analog Grain",
  "image_count": 18,
  "analysis": {
    "status": "ready",
    "keywords": [
      "35mm film",
      "soft grain"
    ],
    "prompt_fragment": "In the exact visual style of this moodboard: ..."
  },
  "guidelines": null,
  "cover_image_id": "img_1"
}

Notes

  • 404 if the moodboard does not exist, or is neither owned by nor shared with the authenticated account.
GET /moodboards/presets
moodboards:read

List house-curated preset moodboards

Returns the house-curated preset boards — ready-made aesthetics anyone can fork. Every preset ships with a completed analysis, so a fork is instantly usable in generation with no re-analysis.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Body Fields

No body fields for this endpoint.

curl Example

curl https://api.genfire.ai/v1/moodboards/presets \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "object": "list",
  "data": [
    {
      "id": "preset_abc123",
      "object": "moodboard_preset",
      "name": "Editorial Noir",
      "order": 1,
      "image_count": 12,
      "analysis": {
        "status": "ready",
        "keywords": [
          "high-contrast monochrome"
        ]
      },
      "guidelines": "Keep highlights blown, shadows crushed."
    }
  ]
}
POST /moodboards/presets/{presetId}/fork
moodboards:read

Fork a preset into your own moodboards

Copies a house preset into your own moodboards — the copy is fully yours afterwards and lands with a ready analysis, immediately usable as `moodboard_id` in generation. Free and synchronous; nothing is fetched from third parties.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Parameters

presetId path required

Preset id from `GET /v1/moodboards/presets`.

Body Fields

No body fields for this endpoint.

curl Example

curl https://api.genfire.ai/v1/moodboards/presets/{presetId}/fork \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "id": "mb_new456",
  "object": "moodboard",
  "name": "Editorial Noir",
  "image_count": 12,
  "analysis": {
    "status": "ready"
  }
}

Notes

  • Guarded by `moodboards:read` — the API has no moodboards:write scope because board authoring stays in the dashboard; forking only copies house content into your own account.
  • Free — forking a preset never charges credits.
  • Retrying the call creates another copy (forks are not idempotent); delete duplicates in the dashboard.
  • 400 `fork_preset_failed` when your account is at the moodboard limit (200 boards) — delete a board and retry.

Reference

Teams

GET /teams
teams:read

List your workspaces

Returns the teams (workspaces) the authenticated account belongs to, each with your role on it, the member count and the shared CREDIT POOL balance. Agencies typically keep one workspace per client. Pass a workspace id as `team_id` on a generating request to bill that pool instead of your personal balance. Teams are created, invited to and configured in the Genfire dashboard; the API consumes them.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Body Fields

No body fields for this endpoint.

curl Example

curl https://api.genfire.ai/v1/teams \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "object": "list",
  "data": [
    {
      "id": "team_abc123",
      "object": "team",
      "name": "Acme Skin",
      "role": "admin",
      "is_owner": false,
      "member_count": 4,
      "seat_limit": 10,
      "pool": {
        "balance": 12400,
        "currency": "credits"
      },
      "created_at": "2026-06-01T09:00:00.000Z",
      "updated_at": "2026-08-18T10:00:00.000Z"
    }
  ]
}

Notes

  • There is no stateful "select workspace" call. `team_id` is named on each request that spends, so the payer is explicit at the point of payment — a remembered selection going stale would quietly charge a different client.
GET /teams/{teamId}
teams:read

Get one workspace

Returns one workspace with its pool balance plus YOUR month-to-date usage and monthly cap on it. Both numbers matter before a run: a member can be well under the pool balance and still blocked by their own cap.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Parameters

teamId path required

Team id from `GET /v1/teams`.

Body Fields

No body fields for this endpoint.

curl Example

curl https://api.genfire.ai/v1/teams/{teamId} \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "id": "team_abc123",
  "object": "team",
  "name": "Acme Skin",
  "role": "admin",
  "is_owner": false,
  "member_count": 4,
  "pool": {
    "balance": 12400,
    "currency": "credits"
  },
  "my_usage_this_month": 820,
  "my_cap": 5000
}

Notes

  • 404 when the team does not exist OR you are not a member — the two are indistinguishable on purpose, so ids cannot be probed.

Reference

Video

POST /videos/analyses
videos:write

Analyse a video scene by scene

Understand what is VISUALLY in a video. Frames are sampled across the whole clip and read by a vision model, returning a summary, a scene list (start/end seconds, description, shot type, subjects, on-screen text, camera movement) and the structural beats in order. This is not transcription — `POST /v1/audio/transcriptions` reads what is SAID, this reads what is SHOWN, and a silent product film transcribes to nothing while analysing fully. Use it to break a competitor ad down, turn a reference video into a shot list, or answer "what happens at 0:14?". Asynchronous: returns a queued run — poll `GET /v1/runs/{id}`. Typically 1–3 minutes, longer for a YouTube source.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Required

Body Fields

video_url string optional

The video to analyse. Provide exactly one of video_url or youtube_url.

youtube_url string optional

A YouTube link to analyse. Provide exactly one of video_url or youtube_url.

depth string optional

`summary` (3–6 major movements), `scenes` (one entry per meaningful beat), or `shot-list` (one entry per camera setup, for a shot-for-shot recreation).

Default: scenes

team_id string optional

Bill a workspace pool instead of your balance (`GET /v1/teams`). You must be a member with a spending role.

curl Example

curl https://api.genfire.ai/v1/videos/analyses \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Idempotency-Key: unique_request_key" \
  -H "Content-Type: application/json" \
  -d '{
  "youtube_url": "https://www.youtube.com/watch?v=example",
  "depth": "shot-list"
}'

Response Example

{
  "id": "run_abc123",
  "object": "run",
  "status": "queued",
  "capability": "video_analysis",
  "endpoint": "videos.analyses.create",
  "created_at": "2026-08-19T12:00:00.000Z"
}

Request Example Body

{
  "youtube_url": "https://www.youtube.com/watch?v=example",
  "depth": "shot-list"
}

Notes

  • The completed run output carries `summary`, `scenes[]`, `hooks_and_beats[]`, `duration_seconds` and `frames_analyzed`.
  • Scene timestamps are clamped to the measured video length — a model that runs past the end is truncated rather than returned as a time nothing can seek to.
  • Frames are samples, so a scene boundary falls somewhere between two of them; treat the times as close, not frame-exact.
  • Videos are capped at 500MB. A `video_url` is validated against the outbound-network guard, including every redirect hop.

Reference

Marketing Studio

POST /marketing/products
marketing:read

Store a product from a URL

Scrape a product page and STORE the result on one of your brands in a single call, returning a product you can immediately reference as `product_id` when generating. `POST /v1/products/extract` scrapes the same page but only returns the data — nothing persists, so its result cannot fill a template slot. The product lands through the same path as every other add, so its images are mirrored into Genfire storage rather than left hotlinking the source store.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Body Fields

brand_id string required

The brand to store the product on (`GET /v1/brands`). Must be a brand you own.

url string required

The product page to read.

title string optional

Override the scraped product name. Required when the page yields none.

description string optional

Override the scraped description.

curl Example

curl https://api.genfire.ai/v1/marketing/products \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "brand_id": "brand_abc123",
  "url": "https://acme.com/products/vitamin-c-serum"
}'

Response Example

{
  "id": "prod_abc",
  "object": "marketing_product",
  "name": "Vitamin C Serum",
  "brand_id": "brand_abc123",
  "image_url": "https://storage.googleapis.com/...",
  "images": [
    "https://storage.googleapis.com/..."
  ],
  "price": "$28",
  "source_url": "https://acme.com/products/vitamin-c-serum",
  "source": "web",
  "extraction_source": "metadata",
  "cached": false
}

Request Example Body

{
  "brand_id": "brand_abc123",
  "url": "https://acme.com/products/vitamin-c-serum"
}

Notes

  • Also requires `brands:write` — the product is stored on a brand.
  • 422 `product_extraction_failed` when the page yields no product; pass the fields directly to `POST /v1/brands/{brandId}/products` instead.
  • Shares the 24h scrape cache with `POST /v1/products/extract`.
GET /marketing/templates
marketing:read

Browse the ad-template library

Returns the curated Marketing Studio library — finished ads (product shots, motion, UGC, paid-social stills, posters, marketplace imagery) each carrying the RECIPE that produced it. A recipe is not just a prompt: it declares which typed reference slots (product / avatar) a caller must fill and in what ORDER the composed prompt cites them, which is what makes a template recreatable against your own product rather than merely inspiring. Run one by passing its id as `marketing_template_id` to `POST /v1/images/generations` or `POST /v1/videos/generations`. `search` matches titles, descriptions and the creative direction itself, so terms like "unboxing" or "marble counter" narrow the library.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Parameters

search query optional

Free-text match over title, description, ad format and the recipe prompt. Every whitespace-separated term must appear, so extra words narrow the result.

ad_format query optional

One of `product-shot`, `motion`, `ugc`, `ads`, `posters`, `marketplace`. See `GET /v1/marketing/ad-formats`.

media_type query optional

`image` or `video`. An image template runs through `/images/generations`; a video template through `/videos/generations`.

requires_avatar query optional

Set `true` for templates with a person in frame (those offering or requiring an avatar slot).

limit query optional

Page size, 1–100.

Default: 24

cursor query optional

`next_cursor` from the previous page.

Body Fields

No body fields for this endpoint.

curl Example

curl https://api.genfire.ai/v1/marketing/templates \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "object": "list",
  "data": [
    {
      "id": "razorcandy-ugc-3",
      "object": "marketing_template",
      "title": "Flash-lit hand hold",
      "description": "",
      "label": "UGC",
      "ad_format": "ugc",
      "media_type": "image",
      "media_url": "https://storage.googleapis.com/...",
      "thumbnail_url": "https://storage.googleapis.com/...",
      "aspect_ratio": "4:5",
      "featured": true,
      "recipe": {
        "mode": "image",
        "model": "image.nano_banana_pro",
        "prompt": "the person in image 2 holding {{product}} up to the camera, hard direct phone flash...",
        "aspect_ratio": "4:5",
        "resolution": "2K",
        "duration": null,
        "slots": {
          "product": "required",
          "avatar": "optional"
        },
        "slot_order": [
          "product",
          "avatar"
        ],
        "slot_binding": null,
        "required_inputs": [
          "product_image_url"
        ],
        "optional_inputs": [
          "avatar_image_url"
        ]
      },
      "created_at": "2026-08-18T12:00:00.000Z"
    }
  ],
  "has_more": true,
  "next_cursor": "razorcandy-ugc-3"
}

Notes

  • Read `recipe.required_inputs` before generating — it names the exact request fields the run is rejected without.
  • Do NOT copy `recipe.prompt` into your own `prompt`. Pass `marketing_template_id` and the server composes it, substituting the slot tokens with the positions your references are actually sent in. A `prompt` you send alongside is ADDITIVE — say what to change.
GET /marketing/templates/{templateId}
marketing:read

Get one ad template

Returns one template with its full recipe, plus up to 12 same-format siblings for "more like this".

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Parameters

templateId path required

Template id from `GET /v1/marketing/templates`.

Body Fields

No body fields for this endpoint.

curl Example

curl https://api.genfire.ai/v1/marketing/templates/{templateId} \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "id": "razorcandy-ugc-3",
  "object": "marketing_template",
  "ad_format": "ugc",
  "media_type": "image",
  "recipe": {
    "mode": "image",
    "model": "image.nano_banana_pro",
    "required_inputs": [
      "product_image_url"
    ],
    "optional_inputs": [
      "avatar_image_url"
    ]
  },
  "siblings": [
    {
      "id": "thirstcult-ugc-1",
      "object": "marketing_template",
      "ad_format": "ugc"
    }
  ]
}

Notes

  • 404 `marketing_template_not_found` if the id does not exist.
GET /marketing/ad-formats
marketing:read

List the ad formats

The six kinds of ad the library is filed under, each with what it is for, the media it produces, the slot shape it implies, and a live count of how many templates it holds.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Body Fields

No body fields for this endpoint.

curl Example

curl https://api.genfire.ai/v1/marketing/ad-formats \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "object": "list",
  "data": [
    {
      "id": "ugc",
      "object": "marketing_ad_format",
      "label": "UGC",
      "description": "Creator-style content shot to look like a real phone, not a studio...",
      "media_types": [
        "image",
        "video"
      ],
      "typical_slots": "product required, avatar required or optional",
      "template_count": 119
    }
  ]
}
GET /marketing/formats
marketing:read

List the creative formats (genres)

The GENRE — what kind of piece this is. Video genres: unboxing, ASMR unboxing, reboxing, try-on, tutorial, before-after, mess-to-fresh, crush test, mystery box, POV, giant product, hyper motion, selfie testimonial, direct-to-camera, secret hack, couple at home, TV spot, obsession, product showcase. Still-ad genres: headline, special offer, customer quote, star review, key features, benefits checklist, comparison, then-vs-now, social proof, comment, stat surround, bundle, why-we-are-different, behind the product, personal note, magazine, colour block, bold statement, whiteboard explainer, UGC side-by-side, organic post, scroll break. Pass an id as `marketing_format_id` on either generate endpoint. Composes ONTO a template, or stands alone with your own prompt.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Parameters

search query optional

Match over id, label, description and the fragment itself.

mode query optional

`image` or `video` — several genres are one or the other only.

ad_format query optional

Only genres most at home on this shelf. A hint, never a restriction.

Body Fields

No body fields for this endpoint.

curl Example

curl https://api.genfire.ai/v1/marketing/formats \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "object": "list",
  "data": [
    {
      "id": "unboxing-asmr",
      "object": "marketing_format",
      "label": "ASMR unboxing",
      "description": "Unboxing shot for texture and sound rather than speech.",
      "modes": [
        "video"
      ],
      "suits": [
        "ugc",
        "motion"
      ],
      "prompt_fragment": "Shoot this as an ASMR unboxing: no talking, very close framing on hands and materials..."
    }
  ]
}

Notes

  • A FORMAT is not a HOOK. A format describes the whole piece; a hook occupies only its opening beat. They are independent axes precisely so a stunt opening can ride on a tutorial.
GET /marketing/hooks
marketing:read

List the opening hooks

The OPENING MECHANIC — what physically happens in the first two seconds to stop a scroll. These are events, not copy angles: the product flying at the creator who ducks and comes up holding it, an impossible indoor blizzard that leaves the product untouched, gravity failing, the camera operator knocking into the creator, a silence held a beat too long. Each is typed `stunt` (breaks physics or plausibility) or `subtle` (stays believable and relies on human reaction). Every fragment hands off to whatever genre follows, so any hook composes with any format. Pass an id as `marketing_hook_id` on either generate endpoint.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Parameters

search query optional

Match over id, label, description, type and the fragment itself.

mode query optional

`image` or `video`. Most hooks are video-first — an opening beat needs time to happen.

type query optional

`stunt` or `subtle`.

Body Fields

No body fields for this endpoint.

curl Example

curl https://api.genfire.ai/v1/marketing/hooks \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "object": "list",
  "data": [
    {
      "id": "product-dodge",
      "object": "marketing_hook",
      "label": "Product dodge",
      "description": "The product flies at the creator, who ducks and comes up holding it.",
      "type": "stunt",
      "modes": [
        "video"
      ],
      "prompt_fragment": "Open on a stunt: the product flies in fast from off-camera straight at the person..."
    }
  ]
}
GET /marketing/settings
marketing:read

List the scene settings

The ENVIRONMENT a shot lives in, in two categories. `realistic` places the piece somewhere real — marble kitchen, bathroom vanity, bedroom, gym floor, desk, golden hour, city street, car interior, retail shelf. `unrealistic` is scroll-stopping by location alone: sitting on an airliner wing mid-flight, at the rim of an active volcano, shrunk to doll size beside a full-size product, on the roof of a moving car — always directed to be played completely straight. Each fragment names its light as well as its surfaces, because an environment without a light source renders as a composite rather than a photograph. Pass an id as `marketing_setting_id` on either generate endpoint.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Parameters

search query optional

Match over id, label, description, category and the fragment itself.

category query optional

`realistic` or `unrealistic`.

Body Fields

No body fields for this endpoint.

curl Example

curl https://api.genfire.ai/v1/marketing/settings \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "object": "list",
  "data": [
    {
      "id": "marble-kitchen",
      "object": "marketing_setting",
      "label": "Marble kitchen",
      "description": "Bright modern kitchen, stone counters, daylight.",
      "category": "realistic",
      "prompt_fragment": "Relocate the scene to a bright modern kitchen..."
    },
    {
      "id": "volcano-rim",
      "object": "marketing_setting",
      "label": "Volcano rim",
      "description": "Beside active lava, unhurried.",
      "category": "unrealistic",
      "prompt_fragment": "Relocate the scene to the rim of an active volcano..."
    }
  ]
}
GET /marketing/avatars
marketing:read

List avatars you can put in an ad

One list over two sources: your own trained influencers AND the house avatar library. Both fill the same avatar slot, so they are returned together (influencers first) with `source` saying which is which. An influencer row also carries `influencer_id` — prefer those when the same face has to recur across many pieces, because identity binds through the influencer's conditioning photos rather than resemblance to one image. Pass an `id` as `avatar_id` on either generate endpoint.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Parameters

search query optional

Match over name, handle and the scene/gender/age tags.

source query optional

`user` for your trained influencers only, `preset` for the house library only. Omit for both.

scene query optional

House-library scene tag: ugc, car, studio, podcast, interview, lifestyle, office, outdoor.

gender query optional

male, female, or neutral (house library only).

age query optional

young-adult, adult, middle-aged, or senior (house library only).

limit query optional

Page size, 1–100.

Default: 24

cursor query optional

`next_cursor` from the previous page.

Body Fields

No body fields for this endpoint.

curl Example

curl https://api.genfire.ai/v1/marketing/avatars \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "object": "list",
  "data": [
    {
      "id": "influencer:abc123",
      "object": "marketing_avatar",
      "source": "influencer",
      "name": "Genny",
      "handle": "genny",
      "image_url": "https://storage.googleapis.com/...",
      "status": "ready",
      "influencer_id": "abc123",
      "scenes": [],
      "gender": null,
      "age": null
    },
    {
      "id": "preset:tpl_9f",
      "object": "marketing_avatar",
      "source": "preset",
      "name": "Studio creator",
      "handle": null,
      "image_url": "https://storage.googleapis.com/...",
      "status": "ready",
      "influencer_id": null,
      "scenes": [
        "ugc"
      ],
      "gender": "female",
      "age": "young-adult"
    }
  ],
  "has_more": false,
  "next_cursor": null
}

Notes

  • Avatars without an image are omitted — they cannot fill a slot.
GET /marketing/products
marketing:read

List your stored products

Every product on every brand you own, flattened — "which product is this ad for?" is not a per-brand question. `source` is `web` when the product was scraped from the brand's own site and `upload` when it was added directly. Pass an `id` as `product_id` on either generate endpoint to fill a template's product slot without re-uploading anything.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Parameters

search query optional

Match over product name, description, brand name and USPs.

brand_id query optional

Restrict to one brand (`GET /v1/brands`).

limit query optional

Page size, 1–100.

Default: 24

cursor query optional

`next_cursor` from the previous page.

Body Fields

No body fields for this endpoint.

curl Example

curl https://api.genfire.ai/v1/marketing/products \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "object": "list",
  "data": [
    {
      "id": "prod_abc",
      "object": "marketing_product",
      "name": "Vitamin C Serum",
      "description": "30ml brightening serum",
      "brand_id": "brand_abc123",
      "brand_name": "Acme Skin",
      "image_url": "https://storage.googleapis.com/...",
      "images": [
        "https://storage.googleapis.com/..."
      ],
      "price": "$28",
      "source_url": "https://acme.com/serum",
      "source": "web",
      "usps": [
        "Vegan",
        "Fragrance-free"
      ]
    }
  ],
  "has_more": false,
  "next_cursor": null
}

Notes

  • Requires `brands:read` in addition to `marketing:read` — the products come from the brand store.
  • Products with no image are omitted; they cannot fill a product slot.
  • Empty list? Ingest a brand first with `POST /v1/brands/ingestions`, or pass a photo directly as `product_image_url`.

Reference

Games

POST /games/generations
images:write

Generate a browser game

Build a fully-playable, self-contained HTML browser game (Phaser / canvas / Three.js) from a text prompt. The generated game is hosted automatically; once the run completes its `play_url` is public and anyone can open it — no install. Iterate on an existing game by passing its `game_id` with a change prompt. Async — returns a queued run immediately and the codegen runs on a worker (usually 1–3 min); poll `GET /runs/{id}` until `status` is `completed`, then read `output.play_url`.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Required

Body Fields

prompt string required

What game to build — or, with `game_id`, the change to make (e.g. "make it faster, add a boss").

game_id string optional

Iterate on an existing game: pass the `game_id` from a prior generation. The stored game is re-generated in place at the same `play_url`.

model string optional

Codegen model alias (e.g. `claude-opus-5`, `claude-sonnet-5`). Defaults to Opus.

asset_urls array optional

Up to 16 asset URLs (images / GLB / audio from other Genfire endpoints) to wire into the game as sprites, textures, or sound.

multiplayer boolean optional

Build with realtime multiplayer via the Genfire relay. Players join with the same `?room=` link.

Default: false

curl Example

curl https://api.genfire.ai/v1/games/generations \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Idempotency-Key: unique_request_key" \
  -H "Content-Type: application/json" \
  -d '{
  "prompt": "A neon endless-runner where you dodge obstacles and collect coins",
  "multiplayer": false
}'

Response Example

{
  "id": "run_game_123",
  "object": "run",
  "status": "queued",
  "capability": "game_generation",
  "endpoint": "games.generations.create",
  "model": "game.genfire_v1",
  "request_id": "run_game_123",
  "input_summary": {
    "prompt": "A neon endless-runner where you dodge obstacles and collect coins",
    "iterate": false
  },
  "output": null,
  "usage": null,
  "error": null,
  "resource_id": "game_123",
  "provider_request_id": null,
  "created_at": "2026-03-25T12:00:00.000Z",
  "updated_at": "2026-03-25T12:00:00.000Z",
  "completed_at": null
}

Request Example Body

{
  "prompt": "A neon endless-runner where you dodge obstacles and collect coins",
  "multiplayer": false
}

Notes

  • Guarded by `images:write` — game generation also produces a cover thumbnail via image generation.
  • Async: the POST returns a `queued` run with `output: null`. Poll `GET /runs/{id}` until `status` is `completed`; the run output then contains `game_id`, `play_url`, `thumbnail_url`, and `title`. The `play_url` is shareable as soon as it appears; use `POST /games/{gameId}/publish` to also list it in the public gallery.
POST /games/{gameId}/publish
images:write

Publish or unpublish a game

Publish a completed game you own to the public Genfire games gallery (genfire.ai/games), where anyone can discover and play it. Pass `{ "publish": false }` to remove it from the gallery again. The game's `play_url` is shareable whether or not it is published — publishing only controls the public marketplace listing.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Parameters

gameId path required

The `game_id` of a completed game from `POST /games/generations`.

Body Fields

publish boolean optional

true (default) to publish to the public gallery; false to unpublish.

Default: true

curl Example

curl https://api.genfire.ai/v1/games/{gameId}/publish \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "publish": true
}'

Response Example

{
  "id": "game_abc123",
  "object": "game",
  "is_public": true
}

Request Example Body

{
  "publish": true
}

Notes

  • Returns 404 if the game does not exist, is not owned by the authenticated account, or is not in a completed state.

Reference

Runs

GET /runs
runs:read

List recent runs

Lists recent runs for the authenticated account. Use this to inspect async activity across generation endpoints and workflows.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Parameters

status query optional

Optional run status filter such as `queued`, `processing`, `completed`, or `failed`.

capability query optional

Optional capability filter such as `image_generation` or `workflow.hook_pack`.

app query optional

Optional in-product surface filter — e.g. `marketing-studio`. Returns the runs made in that surface from BOTH origins: pieces created in the Genfire dashboard AND ones created through this API with the surface's own parameters (a `marketing_template_id` run tags itself the same way the dashboard bar does), so it is that surface's whole history rather than an API-only slice. Every run's own surface is echoed back as `app`. Runs that named no surface have `app: null` and are excluded whenever this filter is set. Uses the deep-scan path, so the response also carries `scanned` and `has_more`.

limit query optional

Maximum number of runs to return.

Default: 25

Body Fields

No body fields for this endpoint.

curl Example

curl https://api.genfire.ai/v1/runs \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "object": "list",
  "data": [
    {
      "id": "run_img_123",
      "object": "run",
      "status": "completed",
      "capability": "image_generation",
      "endpoint": "images.generations.create",
      "model": "image.nano_banana_2",
      "request_id": "run_img_123",
      "input_summary": {
        "prompt": "Studio product photo of a matte black water bottle",
        "model": "image.nano_banana_2",
        "aspect_ratio": "1:1",
        "count": 1
      },
      "output": {
        "images": [
          {
            "url": "https://cdn.genfire.ai/output/image-001.png"
          }
        ],
        "output_url": "https://cdn.genfire.ai/output/image-001.png"
      },
      "usage": {
        "credits": 8
      },
      "error": null,
      "resource_id": null,
      "provider_request_id": null,
      "created_at": "2026-03-25T12:00:00.000Z",
      "updated_at": "2026-03-25T12:00:02.000Z",
      "completed_at": "2026-03-25T12:00:02.000Z"
    },
    {
      "id": "run_vid_123",
      "object": "run",
      "status": "queued",
      "capability": "video_generation",
      "endpoint": "videos.generations.create",
      "model": "video.veo_3_1",
      "request_id": "run_vid_123",
      "input_summary": {
        "prompt": "Cinematic close-up of a luxury watch with soft lighting",
        "model": "video.veo_3_1",
        "aspect_ratio": "16:9",
        "duration": 8,
        "has_image": false,
        "generate_audio": true
      },
      "output": null,
      "usage": null,
      "error": null,
      "resource_id": "video_123",
      "provider_request_id": "provider_req_123",
      "created_at": "2026-03-25T12:00:00.000Z",
      "updated_at": "2026-03-25T12:00:00.000Z",
      "completed_at": null
    }
  ]
}
GET /runs/{runId}
runs:read

Get a run by id

Use the run id returned by a generation endpoint or workflow execution to inspect status, output, usage, and provider metadata.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Parameters

runId path required

The run id returned by the API.

wait query optional

LONG-POLL: hold the request until the run reaches a terminal state (`completed` or `failed`) or this many seconds elapse, then return whatever state the run is in. Accepts 0–30 (values above 30 are capped, not rejected); omit or pass 0 for the default immediate response. One long-poll costs one request against your rate limit however long it is held, so `?wait=30` uses roughly a fifteenth of the requests a 2s polling loop would. A non-numeric value returns 400 `invalid_wait`.

Default: 0

Body Fields

No body fields for this endpoint.

curl Example

curl https://api.genfire.ai/v1/runs/{runId} \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "id": "run_img_123",
  "object": "run",
  "status": "completed",
  "capability": "image_generation",
  "endpoint": "images.generations.create",
  "model": "image.nano_banana_2",
  "request_id": "run_img_123",
  "input_summary": {
    "prompt": "Studio product photo of a matte black water bottle",
    "model": "image.nano_banana_2",
    "aspect_ratio": "1:1",
    "count": 1
  },
  "output": {
    "images": [
      {
        "url": "https://cdn.genfire.ai/output/image-001.png"
      }
    ],
    "output_url": "https://cdn.genfire.ai/output/image-001.png"
  },
  "usage": {
    "credits": 8
  },
  "error": null,
  "resource_id": null,
  "provider_request_id": null,
  "created_at": "2026-03-25T12:00:00.000Z",
  "updated_at": "2026-03-25T12:00:02.000Z",
  "completed_at": "2026-03-25T12:00:02.000Z"
}
GET /runs/{runId}/output
runs:read

Get the output envelope for a run

Returns just the terminal output envelope for a run, which is useful when you only need the final payload.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Parameters

runId path required

The run id returned by the API.

Body Fields

No body fields for this endpoint.

curl Example

curl https://api.genfire.ai/v1/runs/{runId}/output \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "id": "run_img_123",
  "object": "run_output",
  "status": "completed",
  "capability": "image_generation",
  "output": {
    "images": [
      {
        "url": "https://cdn.genfire.ai/output/image-001.png"
      }
    ],
    "output_url": "https://cdn.genfire.ai/output/image-001.png"
  },
  "error": null,
  "completed_at": "2026-03-25T12:00:02.000Z"
}

Reference

Generation

POST /images/generations
images:write

Generate images

Create one or more images using a public image model alias. This endpoint usually completes synchronously and returns a completed run.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Required

Body Fields

prompt string required

The image prompt. May include @<handle> mentions when paired with a `mentions` array.

model string optional

Optional image model alias from `/models`. Models with an internal edit variant accept `mentions`, `image_url`, and `image_urls` for influencer-conditioned or multi-image edits.

Default: image.nano_banana_2

aspect_ratio string optional

Image aspect ratio.

Default: 1:1

count integer optional

Number of images to generate, from 1 to 4.

Default: 1

image_url string optional

Optional single source image URL. When provided with an edit-capable model, the request is routed through the model's edit variant. Use `image_urls` for multi-image edits.

image_urls array optional

Optional list of up to 14 source image URLs for a multi-image edit. Supported by GPT Image 2, Seedream, Qwen Image 2 and Nano Banana; Grok uses at most the first 3. Routes through the model's edit variant.

mask_url string optional

Optional MASKED INPAINT: an absolute http(s) URL to a mask image (white = repaint, black = keep) the same size as the source. Only the white region is regenerated; everything else is preserved. Requires `image_url` (or `image_urls`) — a mask alone is rejected with 400 `mask_requires_source_image`. Only accepted by models whose `capabilities.masked_inpaint` is true on `GET /v1/models` (image.gpt_image_2, image.genfire_v1, image.nano_banana_2, image.nano_banana_pro); any other model returns 400 `model_lacks_mask_support` rather than silently ignoring the mask and billing a full-frame rewrite. Upload the mask with `POST /v1/uploads` and pass the returned `asset_url`; data: URIs are rejected with 400 `invalid_mask_url`, and the URL is checked against the same SSRF guard as every other caller-supplied URL (400 `unsafe_outbound_url`).

mentions array optional

Optional `[{ handle, influencer_id }]` to inject a trained influencer character into the image. The model is auto-switched to its edit variant and the influencer's reference photos are added as conditioning. Currently a single mention per request is supported.

brand_id string optional

Optional id of one of your brands (`GET /v1/brands`). Grounds the generation server-side: the brand's real product images are attached as edit sources and its colors/style/voice are prepended to the prompt. Invalid or unowned id → 404 `invalid_brand_id`.

moodboard_id string optional

Optional id of one of your moodboards (`GET /v1/moodboards`, or a board shared with you). Requires the `moodboards:read` scope in addition to `images:write` (403 `insufficient_scope` otherwise — the board's style text echoes back through the run record). Styles the generation server-side: the board's composed style fragment is prepended to the prompt and its exemplar images are attached as edit sources. Composes with `brand_id` — the brand prefix leads and brand references take the reference slots first. Unknown or inaccessible id → 404 `invalid_moodboard_id`; other resolution failures → 400 `invalid_moodboard_id`. On models without an internal edit variant the style applies as prompt text only (no exemplar attachment). The run's `input` records `moodboard_id` and `moodboard_strength`, so `GET /runs/{id}` shows what styled the run.

moodboard_strength string optional

How hard the moodboard steers: `subtle` (prompt fragment only, no reference images), `balanced` (fragment + up to 3 exemplars), or `strong` (fragment + as many exemplars as fit under the 14-image cap). Any other value → 400 `invalid_moodboard_strength`. Only meaningful with `moodboard_id`.

Default: balanced

project_id string optional

File this generation's output into one of your PROJECTS (`GET /v1/projects`) the moment the run completes — the same thing the Video Studio does when you have that project open. Access is checked before the run is created, so an unknown id or one you cannot edit is a 404 `project_not_found` / 403 `project_forbidden` at request time rather than a silently unfiled result. Filing itself is best-effort and never fails a run you have already paid for. The run echoes it back as `project_id`.

team_id string optional

Bill this generation to a WORKSPACE (team) credit pool instead of your balance (`GET /v1/teams`). Membership and a spending role are asserted before the run is created — 404 `invalid_team_id` when you are not a member, 403 `team_role_cannot_spend` when your role cannot spend. Requires the `teams:read` scope. The run echoes it back as `team_id`.

marketing_template_id string optional

Optional id of a Marketing Studio ad template (`GET /v1/marketing/templates`). Composes the request server-side from the template RECIPE: the recipe prompt has its `{{product}}` / `{{avatar}}` tokens replaced with the positions your slot media is actually sent in, the slot media is emitted in the recipe's own `slot_order` AHEAD of any brand/moodboard references, and the template's model, aspect ratio, resolution and count are applied unless you pass your own. Fill the fields the template lists under `recipe.required_inputs`; a missing one → 400 `marketing_slot_missing`. Passing a template for the other media type → 400 `marketing_template_mode_mismatch`. Unknown id → 404 `marketing_template_not_found`. A template whose model has no /v1 alias → 400 `template_model_unavailable` (pass an explicit `model` to run it anyway). A `prompt` you send alongside is ADDITIVE — it says what to CHANGE, so do NOT re-send the recipe prompt.

marketing_format_id string optional

Optional GENRE (`GET /v1/marketing/formats`) — unboxing, tutorial, before-after, star review, comparison and so on. Fragments compose in the order genre → hook → setting, so the genre defines the piece, the hook claims its opening beat, and the setting relocates whatever those produced. WITH `marketing_template_id` the recipe is the base and the three fragments follow it, with your own `prompt` last as a change note. WITHOUT a template your `prompt` IS the base subject description and the fragments are directives applied to it, so they follow your prompt instead. Works WITHOUT a template. Unknown id → 400 `invalid_marketing_format_id`; a genre that does not apply to this media type → 400 `format_mode_mismatch`.

marketing_hook_id string optional

Optional OPENING MECHANIC (`GET /v1/marketing/hooks`) — a physical event in the first two seconds, not a copy angle: the product flying at the creator, an indoor blizzard, the camera being knocked, a held silence. `stunt` or `subtle`. Independent of the format, so any hook can open any genre. Works WITHOUT a template. Unknown id → 400 `invalid_marketing_hook_id`; a hook that does not apply to this media type → 400 `hook_mode_mismatch`.

marketing_setting_id string optional

Optional ENVIRONMENT (`GET /v1/marketing/settings`) — `realistic` (marble kitchen, gym floor, golden hour) or `unrealistic` (airplane wing, volcano rim, shrunk to doll size). Written as a relocation directive so it overrides the scene a template describes. Works without a template. Unknown id → 400 `invalid_marketing_setting_id`.

product_image_url string optional

Fills the template's PRODUCT slot. Takes precedence over `product_id`.

avatar_image_url string optional

Fills the template's AVATAR slot — who appears in the ad. Takes precedence over `avatar_id`. Rejected with 400 `avatar_not_supported_by_template` on a start-frame video template, which animates the product photo itself and has no avatar slot.

product_id string optional

Fills the PRODUCT slot from your stored brand products (`GET /v1/marketing/products`) — no re-upload. Unknown or imageless id → 400 `invalid_product_id`.

avatar_id string optional

Fills the AVATAR slot from your trained influencers or the house avatar library (`GET /v1/marketing/avatars`). Accepts the prefixed id (`influencer:abc`, `preset:xyz`), a bare influencer id, or an @handle. Unknown id → 400 `invalid_avatar_id`.

quality string optional

Quality tier. image.gpt_image_2 / image.genfire_v1: low, medium, high, auto — cost low=1×, medium=6×, high=22×. image.grok_imagine_2: low or medium only, priced as separate base rates (low is cheaper); anything else is rejected.

Default: medium

resolution string optional

Output resolution: 1K, 2K, 4K. image.grok_imagine_pro and image.grok_imagine_2 accept 1K/2K on BOTH the text-to-image and edit paths (4K is rejected). Nano Banana family (image.nano_banana, image.nano_banana_2, image.nano_banana_pro) is edit-only — the request must supply image_url or mentions to route through the model edit variant. Affects cost: 1K=1×, 2K=1.5×, 4K=3×.

async boolean optional

When true, returns the QUEUED run immediately and generates in the background — poll `GET /runs/{id}` (or subscribe to webhooks) for completion, exactly like video. Credits are pre-checked up front (402 on insufficient balance). Defaults to false (the request holds until the images are ready). The same request dedupes to the same run whether called sync or async.

Default: false

curl Example

curl https://api.genfire.ai/v1/images/generations \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Idempotency-Key: unique_request_key" \
  -H "Content-Type: application/json" \
  -d '{
  "prompt": "Studio product photo of a matte black water bottle on dark stone",
  "model": "image.nano_banana_2",
  "aspect_ratio": "1:1",
  "count": 1
}'

Response Example

{
  "id": "run_img_123",
  "object": "run",
  "status": "completed",
  "capability": "image_generation",
  "endpoint": "images.generations.create",
  "model": "image.nano_banana_2",
  "request_id": "run_img_123",
  "input_summary": {
    "prompt": "Studio product photo of a matte black water bottle",
    "model": "image.nano_banana_2",
    "aspect_ratio": "1:1",
    "count": 1
  },
  "output": {
    "images": [
      {
        "url": "https://cdn.genfire.ai/output/image-001.png"
      }
    ],
    "output_url": "https://cdn.genfire.ai/output/image-001.png"
  },
  "usage": {
    "credits": 8
  },
  "error": null,
  "resource_id": null,
  "provider_request_id": null,
  "created_at": "2026-03-25T12:00:00.000Z",
  "updated_at": "2026-03-25T12:00:02.000Z",
  "completed_at": "2026-03-25T12:00:02.000Z"
}

Request Example Body

{
  "prompt": "Studio product photo of a matte black water bottle on dark stone",
  "model": "image.nano_banana_2",
  "aspect_ratio": "1:1",
  "count": 1
}

Notes

  • Masked inpainting: pass `image_url` + `mask_url` + a prompt describing the change. The mask is a black-and-white PNG matching the source dimensions — white marks the pixels to repaint. Filter your model picker on `capabilities.masked_inpaint` from `GET /v1/models`.
  • When `mentions` is supplied: the model must have an internal edit variant (most do — see `/models`). The server resolves the influencer, replaces `@<handle>` in the prompt with `the character`, appends an identity directive, and adds up to four reference images as conditioning.
  • Influencers must be in status `ready`. Drafts and archived ones cannot be referenced.
POST /videos/generations
videos:write

Generate videos

Create a video run. Routing is automatic from the inputs you supply: prompt only → text-to-video, +image_url → image-to-video, +reference_image_urls (or Wan 3.0's file_url / web_url) → reference-to-video, +source_video_url → video-edit/extend, +image_url +source_video_url → motion-control, +first_frame_url +last_frame_url → first-last-frame interpolation. Each video model declares which combinations it supports under `capabilities` on `GET /models`.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Required

Body Fields

prompt string required

The video prompt.

model string optional

Optional video model alias from `/models`.

Default: video.veo_3_1

aspect_ratio string optional

Video aspect ratio.

Default: 16:9

duration integer optional

Target duration in seconds.

Default: 5

resolution string optional

Output resolution (e.g. 480p, 720p, 1080p, 4k). Supported values and pricing are per-model — see `resolutions` under `/models`. Higher resolutions cost more credits.

image_url string optional

Source image for image-to-video, or character image for motion-control.

source_video_url string optional

Source video for video-edit, video-extend, or motion-control modes.

reference_image_urls array optional

Reference image URLs for reference-to-video mode. Up to 9 on most models; `video.seedance_2_5` accepts up to 30, and the `video.wan_3*` tiers and both Gemini Omni Flash tiers accept up to 10 (see `limits.max_reference_images` on GET /models).

file_url string optional

Wan 3.0 only (`video.wan_3`, `video.wan_3_prime`). URL of a document to base the video on — the model reads it and builds the shot from its contents. Selects reference-to-video on its own, and turns on Wan's reasoning pass automatically. Sending it to any other model returns 400 `unsupported_source_url`.

web_url string optional

Wan 3.0 only (`video.wan_3`, `video.wan_3_prime`). URL of a PUBLIC webpage to base the video on — pages behind a login cannot be read. Selects reference-to-video on its own, and turns on Wan's reasoning pass automatically. Sending it to any other model returns 400 `unsupported_source_url`.

reference_video_urls array optional

Seedance, Hailuo 03, Wan 3.0 and Gemini Omni Flash 1.1 only (3 on `video.gemini_omni_flash_v11`; the older `video.gemini_omni_flash` and `video.hailuo_03_max` accept none). Up to 3 reference clips on `video.hailuo_03` and the `video.seedance_2_0*` models (cited as `Video 1`…); up to 10 on `video.seedance_2_5` (cited as `@Video1`…); up to 5 on `video.wan_3` / `video.wan_3_prime`, 15s TOTAL across the pool and at least 16 fps each (cited as `Video 1`…). Each clip is roughly 2–30s.

reference_audio_urls array optional

Seedance, Hailuo 03 and Wan 3.0 only. Up to 3 reference audio clips on `video.hailuo_03` and the `video.seedance_2_0*` models, up to 10 on `video.seedance_2_5`, up to 5 (15s total) on `video.wan_3` / `video.wan_3_prime`. Cite them positionally in the prompt (`Audio 1` on Hailuo 03, `@Audio1` on Seedance) — this is how you give an on-camera character a consistent voice ("the woman in Image 1 speaks with the voice in Audio 1"). Cannot be the only reference: pair it with at least one reference image or video.

first_frame_url string optional

First-frame image for first-last-frame interpolation. Must be paired with last_frame_url.

last_frame_url string optional

Last-frame image for first-last-frame interpolation. Must be paired with first_frame_url.

generate_audio boolean optional

Whether to include generated audio when supported.

Default: true

bitrate_mode string optional

Output encoding bitrate for Seedance 2.0 Standard/Fast: `standard` or `high`. `high` requests a larger, higher-quality encode at no extra credit cost. Ignored by Seedance 2.0 Mini and by Seedance 2.5 (neither schema has the field).

Default: standard

elements array optional

Kling O3 only. Up to 3 structured elements (characters/objects), referenced in the prompt as `@Element1`, `@Element2`, `@Element3`. Passing elements selects the reference-to-video endpoint. Each element is an object: `{ frontal_image_url: string (main view), reference_image_urls?: string[] (1–3 extra angles), video_url?: string (a 3–10s driving clip — at most ONE element may carry a video), voice_id?: string (from POST /videos/voices) }`. Each element must have a frontal_image_url OR a video_url.

multi_prompt array optional

Kling O3 only. Multi-shot sequence: an array of `{ prompt: string, duration?: string ("1"–"15" seconds) }`. When provided it replaces the top-level `prompt` for shot structure.

shot_type string optional

Kling O3 only. Multi-shot structure: `customize` (you define shots) or `intelligent` (the model decides). Default `customize`.

start_image_url string optional

Kling O3 reference-to-video only. Image to use as the first frame of the generated video.

project_id string optional

File this generation's output into one of your PROJECTS (`GET /v1/projects`) the moment the run completes — the same thing the Video Studio does when you have that project open. Access is checked before the run is created, so an unknown id or one you cannot edit is a 404 `project_not_found` / 403 `project_forbidden` at request time rather than a silently unfiled result. Filing itself is best-effort and never fails a run you have already paid for. The run echoes it back as `project_id`.

team_id string optional

Bill this generation to a WORKSPACE (team) credit pool instead of your balance (`GET /v1/teams`). Membership and a spending role are asserted before the run is created — 404 `invalid_team_id` when you are not a member, 403 `team_role_cannot_spend` when your role cannot spend. Requires the `teams:read` scope. The run echoes it back as `team_id`.

marketing_template_id string optional

Optional id of a Marketing Studio ad template (`GET /v1/marketing/templates`). Composes the request server-side from the template RECIPE: the recipe prompt has its `{{product}}` / `{{avatar}}` tokens replaced with the positions your slot media is actually sent in, the slot media is emitted in the recipe's own `slot_order` AHEAD of any brand/moodboard references, and the template's model, aspect ratio, resolution and duration are applied unless you pass your own. Fill the fields the template lists under `recipe.required_inputs`; a missing one → 400 `marketing_slot_missing`. Passing a template for the other media type → 400 `marketing_template_mode_mismatch`. Unknown id → 404 `marketing_template_not_found`. A template whose model has no /v1 alias → 400 `template_model_unavailable` (pass an explicit `model` to run it anyway). A `prompt` you send alongside is ADDITIVE — it says what to CHANGE, so do NOT re-send the recipe prompt.

marketing_format_id string optional

Optional GENRE (`GET /v1/marketing/formats`) — unboxing, tutorial, before-after, star review, comparison and so on. Fragments compose in the order genre → hook → setting, so the genre defines the piece, the hook claims its opening beat, and the setting relocates whatever those produced. WITH `marketing_template_id` the recipe is the base and the three fragments follow it, with your own `prompt` last as a change note. WITHOUT a template your `prompt` IS the base subject description and the fragments are directives applied to it, so they follow your prompt instead. Works WITHOUT a template. Unknown id → 400 `invalid_marketing_format_id`; a genre that does not apply to this media type → 400 `format_mode_mismatch`.

marketing_hook_id string optional

Optional OPENING MECHANIC (`GET /v1/marketing/hooks`) — a physical event in the first two seconds, not a copy angle: the product flying at the creator, an indoor blizzard, the camera being knocked, a held silence. `stunt` or `subtle`. Independent of the format, so any hook can open any genre. Works WITHOUT a template. Unknown id → 400 `invalid_marketing_hook_id`; a hook that does not apply to this media type → 400 `hook_mode_mismatch`.

marketing_setting_id string optional

Optional ENVIRONMENT (`GET /v1/marketing/settings`) — `realistic` (marble kitchen, gym floor, golden hour) or `unrealistic` (airplane wing, volcano rim, shrunk to doll size). Written as a relocation directive so it overrides the scene a template describes. Works without a template. Unknown id → 400 `invalid_marketing_setting_id`.

product_image_url string optional

Fills the template's PRODUCT slot. Takes precedence over `product_id`.

avatar_image_url string optional

Fills the template's AVATAR slot — who appears in the ad. Takes precedence over `avatar_id`. Rejected with 400 `avatar_not_supported_by_template` on a start-frame video template, which animates the product photo itself and has no avatar slot.

product_id string optional

Fills the PRODUCT slot from your stored brand products (`GET /v1/marketing/products`) — no re-upload. Unknown or imageless id → 400 `invalid_product_id`.

avatar_id string optional

Fills the AVATAR slot from your trained influencers or the house avatar library (`GET /v1/marketing/avatars`). Accepts the prefixed id (`influencer:abc`, `preset:xyz`), a bare influencer id, or an @handle. Unknown id → 400 `invalid_avatar_id`.

end_image_url string optional

Last frame the clip lands on, paired with `image_url` for image-to-video. Supported by every model whose `capabilities.endFrame` is true at GET /v1/models — the Seedance, Kling V3/O3/2.6, and Hailuo 03/02 families. Sending it to any other model, or in a mode other than image-to-video (Kling O3 reference excepted), returns a 400 rather than silently dropping the input.

curl Example

curl https://api.genfire.ai/v1/videos/generations \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Idempotency-Key: unique_request_key" \
  -H "Content-Type: application/json" \
  -d '{
  "prompt": "Cinematic close-up of a luxury watch with soft lighting",
  "model": "video.veo_3_1",
  "aspect_ratio": "16:9",
  "duration": 8,
  "generate_audio": true
}'

Response Example

{
  "id": "run_vid_123",
  "object": "run",
  "status": "queued",
  "capability": "video_generation",
  "endpoint": "videos.generations.create",
  "model": "video.veo_3_1",
  "request_id": "run_vid_123",
  "input_summary": {
    "prompt": "Cinematic close-up of a luxury watch with soft lighting",
    "model": "video.veo_3_1",
    "aspect_ratio": "16:9",
    "duration": 8,
    "has_image": false,
    "generate_audio": true
  },
  "output": null,
  "usage": null,
  "error": null,
  "resource_id": "video_123",
  "provider_request_id": "provider_req_123",
  "created_at": "2026-03-25T12:00:00.000Z",
  "updated_at": "2026-03-25T12:00:00.000Z",
  "completed_at": null
}

Request Example Body

{
  "prompt": "Cinematic close-up of a luxury watch with soft lighting",
  "model": "video.veo_3_1",
  "aspect_ratio": "16:9",
  "duration": 8,
  "generate_audio": true
}

Notes

  • Poll `GET /runs/{runId}` until the run moves to `completed` or `failed`.
  • Per-model duration / aspect-ratio / resolution limits are returned by `/models`; passing an unsupported value returns a 400 listing the allowed values.
  • If you provide an input combination the model does not declare in `capabilities`, you get `unsupported_input_combination`.
  • The structured fields `elements`, `multi_prompt`, `shot_type`, and `start_image_url` apply to Kling O3 models only (`video.kling_o3`, `video.kling_o3_pro`, `video.kling_o3_4k`) and are ignored by every other model. Create a Kling `voice_id` for an element with POST `/videos/voices`.
  • `end_image_url` is NOT O3-only: pair it with `image_url` on any model whose `capabilities.endFrame` is true (Seedance 2.0 all tiers, Seedance 2.5, Kling V3/O3/2.6, Hailuo 03, Hailuo 02 Standard) and the clip interpolates from the start image to that last frame. On Kling O3 it rides the reference endpoint alongside `start_image_url`.
  • Kling O3 Standard/Pro also support video-to-video reference: pass `source_video_url` together with `reference_image_urls` (or `elements`) to restyle a source clip while binding reference characters.
  • Hailuo 03 (`video.hailuo_03`) and the Seedance models additionally accept `reference_video_urls` and `reference_audio_urls`; `video.gemini_omni_flash_v11` accepts `reference_video_urls` but no audio pool. Both Gemini Omni Flash tiers cite references with Google's zero-indexed tags — `<IMAGE_REF_0>` for the first entry of `reference_image_urls`, `<VIDEO_REF_0>` for the first reference clip — and expect each reference's role declared in words ("Use Image1 as a character reference"); a house `@Image1` chip is converted to the tag for you. `video.hailuo_03_max` has no reference mode at all. Cite every reference positionally in the prompt — `Image 1`/`Video 1`/`Audio 1` on Hailuo 03, `@Image1`/`@Video1`/`@Audio1` on Seedance — or the model has no reason to bind it. An `@handle` mention of one of your influencers automatically attaches both its conditioning images AND its voice clip, with the citation written for you.
  • Seedance 2.5 (`video.seedance_2_5`) is the long-form Seedance: 4-30s in a single pass, up to 30 image + 10 video + 10 audio references, 480p/720p/1080p (no 4k), and no `bitrate_mode`. Omit `duration` to let the model pick its own length.
  • Wan 3.0 (`video.wan_3`) and Wan 3.0 Prime (`video.wan_3_prime`) share one schema: 2-30s, 480p/720p/1080p (default 1080p, no 4k), native synchronized audio, start + end frame, and up to 10 image + 5 video + 5 audio references cited positionally as `Image 1` / `Video 1` / `Audio 1`. They also accept `file_url` (a document) or `web_url` (a public page) as the source the video is built from. Pricing is per second and anchored to 1080p — 720p bills half and 480p a quarter. Prime is the faster, higher-fidelity tier at 1.4x the base price.
POST /videos/voices
videos:write

Create a Kling voice

Register a custom Kling voice from a short audio/video sample (5–30s, clean single-voice `.mp3/.wav/.mp4/.mov`). Returns a `voice_id` that can be bound to a Kling O3 element (`elements[].voice_id`) on POST `/videos/generations` so that element speaks in the cloned voice. Synchronous. This is Kling's own voice registry — the id is only meaningful to Kling video models.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Required

Body Fields

voice_url string required

URL of the voice sample. `.mp3/.wav` audio or `.mp4/.mov` video, 5–30 seconds, clean single-voice audio.

curl Example

curl https://api.genfire.ai/v1/videos/voices \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Idempotency-Key: unique_request_key" \
  -H "Content-Type: application/json" \
  -d '{
  "voice_url": "https://example.com/voice-sample.mp3"
}'

Response Example

{
  "voice_id": "kling_voice_abc123"
}

Request Example Body

{
  "voice_url": "https://example.com/voice-sample.mp3"
}

Notes

  • Bind the returned `voice_id` to an element: `elements: [{ frontal_image_url: "…", voice_id: "kling_voice_abc123" }]` on POST `/videos/generations` with a Kling O3 model.
POST /images/background-remove
images:write

Remove image background

Remove the background from an image using BRIA. Returns a transparent PNG. Synchronous — typically completes in a couple seconds.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Required

Body Fields

image_url string required

Absolute URL of the source image.

project_id string optional

File this generation's output into one of your PROJECTS (`GET /v1/projects`) when the run completes. Access is checked before the run is created; filing itself is best-effort.

curl Example

curl https://api.genfire.ai/v1/images/background-remove \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Idempotency-Key: unique_request_key" \
  -H "Content-Type: application/json" \
  -d '{
  "image_url": "https://example.com/photo.jpg"
}'

Response Example

{
  "id": "run_bg_123",
  "object": "run",
  "status": "completed",
  "capability": "image_editing",
  "endpoint": "images.background_remove.create",
  "model": "image_edit.bria_background_remove",
  "request_id": "run_bg_123",
  "input_summary": {
    "model": "image_edit.bria_background_remove",
    "image_url": "https://example.com/photo.jpg"
  },
  "output": {
    "images": [
      {
        "url": "https://cdn.genfire.ai/output/bg-removed.png"
      }
    ],
    "output_url": "https://cdn.genfire.ai/output/bg-removed.png"
  },
  "usage": {
    "credits": 1
  },
  "error": null,
  "resource_id": null,
  "provider_request_id": null,
  "created_at": "2026-04-30T12:00:00.000Z",
  "updated_at": "2026-04-30T12:00:01.500Z",
  "completed_at": "2026-04-30T12:00:01.500Z"
}

Request Example Body

{
  "image_url": "https://example.com/photo.jpg"
}
POST /videos/upscale
videos:write

Upscale a video

Upscale a video with Topaz (2x/4x) or Flux (1.5x-3x, FLUX 3 super-resolution). Async — returns a queued run; poll `/runs/{runId}` for completion (typically 1-5 min).

Auth: Bearer API key or OAuth access token
Idempotency-Key: Required

Body Fields

source_video_url string required

Absolute URL of the source video.

model string optional

`video_upscale.fal_video_upscaler` (Topaz) or `video_upscale.flux_video_upscale` (Flux).

Default: video_upscale.fal_video_upscaler

scale_factor number optional

Topaz: 2 or 4. Flux: any value from 1.5 to 3.

Default: 2

mode string optional

Flux only. `precise` keeps the source faithful; `creative` adds detail.

Default: creative

prompt string optional

Flux only, optional. Guides the creative pass.

curl Example

curl https://api.genfire.ai/v1/videos/upscale \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Idempotency-Key: unique_request_key" \
  -H "Content-Type: application/json" \
  -d '{
  "source_video_url": "https://cdn.genfire.ai/video.mp4",
  "scale_factor": 2
}'

Response Example

{
  "id": "run_upscale_123",
  "object": "run",
  "status": "queued",
  "capability": "video_upscaling",
  "endpoint": "videos.upscale.create",
  "model": "video_upscale.fal_video_upscaler",
  "request_id": "run_upscale_123",
  "input_summary": {
    "model": "video_upscale.fal_video_upscaler",
    "scale_factor": 2
  },
  "output": null,
  "usage": null,
  "error": null,
  "resource_id": null,
  "provider_request_id": "fal_req_abc",
  "created_at": "2026-04-30T12:00:00.000Z",
  "updated_at": "2026-04-30T12:00:00.500Z",
  "completed_at": null
}

Request Example Body

{
  "source_video_url": "https://cdn.genfire.ai/video.mp4",
  "scale_factor": 2
}

Notes

  • Billed per second of video against a tier resolved from the OUTPUT resolution. Flux additionally prices `creative` above `precise`, and costs several times the Topaz rate at every tier.
  • Flux requires an MP4 source of at most 20 seconds and 50MB; over either limit the request is rejected before any credits are reserved.
  • Poll `GET /runs/{runId}` until status is `completed` or `failed`.
POST /images/upscale
images:write

Upscale an image

Upscale an image by 2x or 4x using the Topaz upscaler. Async — returns a queued run; poll `/runs/{runId}` for completion (typically 1-2 min).

Auth: Bearer API key or OAuth access token
Idempotency-Key: Required

Body Fields

source_image_url string required

Absolute URL of the source image.

scale_factor integer optional

Either 2 or 4.

Default: 2

curl Example

curl https://api.genfire.ai/v1/images/upscale \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Idempotency-Key: unique_request_key" \
  -H "Content-Type: application/json" \
  -d '{
  "source_image_url": "https://cdn.genfire.ai/image.png",
  "scale_factor": 2
}'

Response Example

{
  "id": "run_img_upscale_123",
  "object": "run",
  "status": "queued",
  "capability": "image_upscaling",
  "endpoint": "images.upscale.create",
  "model": "image_upscale.topaz_upscale_image",
  "request_id": "run_img_upscale_123",
  "input_summary": {
    "model": "image_upscale.topaz_upscale_image",
    "scale_factor": 2
  },
  "output": null,
  "usage": null,
  "error": null,
  "resource_id": null,
  "provider_request_id": "fal_req_def",
  "created_at": "2026-04-30T12:00:00.000Z",
  "updated_at": "2026-04-30T12:00:00.500Z",
  "completed_at": null
}

Request Example Body

{
  "source_image_url": "https://cdn.genfire.ai/image.png",
  "scale_factor": 2
}

Notes

  • Costs scale with the scale factor (4x costs more than 2x).
  • Poll `GET /runs/{runId}` until status is `completed` or `failed`.
POST /videos/compose
videos:write

Cut generated scenes into one finished video

The ASSEMBLY step. Every other generation endpoint makes ONE piece of media; this one cuts pieces you already have into a single finished film — clips in playback order, each optionally carrying its own voiceover, plus audio tracks pinned to absolute timeline positions. This is how a multi-scene ad is produced from primitives: generate each scene with `POST /v1/videos/generations`, generate each line with `POST /v1/audio/speech`, then send them here with one clip per scene and that scene's line as its `audio_url`. It renders through the same ffmpeg engine the faceless-reel, explainer and music-video pipelines use. TIMING, two ways, and they compose: • PER CLIP (`clips[].audio_url`) — the line belongs to that scene and travels with it through every trim and crossfade, so no offset is ever computed by the caller. A line longer than its footage holds the last frame until it finishes (`hold_last_frame: false` cuts instead). • ABSOLUTE (`audio[].start_sec`) — a track pinned to the finished timeline: narration spanning scenes at 0, a looped music bed at `volume: 0.15`, a stinger at 12.4s. Up to 32 tracks, each with its own level. Asynchronous (a long compose is minutes): returns a queued run — poll `GET /v1/runs/{id}`. FREE: no model runs, so no credits are charged; the clips and voiceovers were billed when they were generated.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Required

Body Fields

clips object[] required

Scenes in playback order, 1-60. Each: `url` (absolute https), `kind` ("video" default | "image"), `audio_url` (THIS scene's voiceover), `audio_mode` ("replace" default | "mix" to keep the clip's own sound ducked underneath), `hold_last_frame` (default true), `duration_sec` (image only — defaults to its own audio's length, else 5s), `trim_in_sec`, `trim_out_sec`, `transition_ms` (crossfade INTO this clip; 0 = hard cut), `motion` + `motion_intensity` (image Ken-Burns), `mute_audio`.

audio object[] optional

Up to 32 tracks placed at absolute positions on the finished timeline. Each: `url`, `start_sec` (default 0), `volume` (0-1, default 1), `loop` (repeat until the video ends — for a music bed), `fade_in_sec`, `fade_out_sec` (relative to the track's own start/end, not the timeline).

aspect_ratio string optional

"16:9" (default), "9:16", "1:1", "4:5" or "21:9". Every clip is scaled/cropped to it.

Default: 16:9

fit string optional

"cover" (default) crops clips to fill the frame; "contain" letterboxes them.

Default: cover

transition_ms number optional

Default crossfade for clips that name none. 0 = hard cuts throughout.

Default: 0

clip_audio_volume number optional

Duck EVERY clip's own source audio to this level (0-1) so the tracks sit on top. 0 silences the clips entirely.

captions object optional

{ preset_id, position?, animation?, words_per_line? } — burn captions onto the finished cut, transcribed from its own audio. Preset ids come from `GET /v1/faceless-reels/caption-presets`. Free, and cosmetic: a caption failure ships the uncaptioned render rather than failing the compose.

project_id string optional

File the finished video into one of your PROJECTS (`GET /v1/projects`) when the compose completes.

title string optional

Title for the finished video in your library.

curl Example

curl https://api.genfire.ai/v1/videos/compose \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Idempotency-Key: unique_request_key" \
  -H "Content-Type: application/json" \
  -d '{
  "clips": [
    {
      "url": "https://storage.googleapis.com/.../scene1.mp4",
      "audio_url": "https://storage.googleapis.com/.../line1.mp3",
      "transition_ms": 0
    },
    {
      "url": "https://storage.googleapis.com/.../scene2.mp4",
      "audio_url": "https://storage.googleapis.com/.../line2.mp3",
      "transition_ms": 250
    },
    {
      "url": "https://storage.googleapis.com/.../pack.png",
      "kind": "image",
      "duration_sec": 2.5,
      "motion": "kenburns-in"
    }
  ],
  "audio": [
    {
      "url": "https://storage.googleapis.com/.../bed.mp3",
      "start_sec": 0,
      "volume": 0.15,
      "loop": true
    },
    {
      "url": "https://storage.googleapis.com/.../whoosh.mp3",
      "start_sec": 12.4,
      "volume": 0.6
    }
  ],
  "aspect_ratio": "9:16",
  "captions": {
    "preset_id": "hormozi"
  },
  "title": "Summer serum ad"
}'

Response Example

{
  "id": "run_9f2c8b1a4d6e4f7a8b9c0d1e2f3a4b5c",
  "object": "run",
  "status": "queued",
  "capability": "video_compose",
  "endpoint": "videos.compose.create",
  "created_at": "2026-08-26T10:30:00.000Z"
}

Request Example Body

{
  "clips": [
    {
      "url": "https://storage.googleapis.com/.../scene1.mp4",
      "audio_url": "https://storage.googleapis.com/.../line1.mp3",
      "transition_ms": 0
    },
    {
      "url": "https://storage.googleapis.com/.../scene2.mp4",
      "audio_url": "https://storage.googleapis.com/.../line2.mp3",
      "transition_ms": 250
    },
    {
      "url": "https://storage.googleapis.com/.../pack.png",
      "kind": "image",
      "duration_sec": 2.5,
      "motion": "kenburns-in"
    }
  ],
  "audio": [
    {
      "url": "https://storage.googleapis.com/.../bed.mp3",
      "start_sec": 0,
      "volume": 0.15,
      "loop": true
    },
    {
      "url": "https://storage.googleapis.com/.../whoosh.mp3",
      "start_sec": 12.4,
      "volume": 0.6
    }
  ],
  "aspect_ratio": "9:16",
  "captions": {
    "preset_id": "hormozi"
  },
  "title": "Summer serum ad"
}

Notes

  • Asynchronous: poll `GET /v1/runs/{id}`. The completed run's `output` carries `video_url`, `duration_seconds`, `width`/`height`, and `clips` — where EVERY scene actually landed (`start_sec`/`end_sec`) after trims, holds and crossfade overlaps. Read that back when placing a timed track against a cut you have not seen.
  • FREE. No model runs, so no credits are charged.
  • Clips cap at 60 and tracks at 32. Every url must be an absolute https URL and is checked against the same SSRF guard as any other caller-supplied URL (400 `unsafe_outbound_url`).
  • A crossfade is dropped back to a hard cut wherever it would not fit (longer than either neighbour, or squeezing a clip body under ~3 frames) rather than corrupting the join.
POST /lipsync/generations
lipsync:write

Generate a lip-synced video

Lip-sync an existing video to either a hosted audio file or a base64-encoded audio payload.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Required

Body Fields

video_url string required

Absolute URL to the source video.

audio_url string optional

Absolute URL to the source audio.

audio_base64 string optional

Base64-encoded audio content. Provide this instead of `audio_url` when uploading audio inline.

audio_file_name string optional

Optional file name to associate with inline audio.

title string optional

Optional title used for the internal video record.

Default: AI Lip-sync Video

description string optional

Optional description for the internal video record.

sync_mode string optional

How the video should align to the audio.

Default: cut_off

model string optional

Optional lipsync model alias from `/models`.

Default: lipsync.lipsync_2_pro

duration number optional

Optional duration hint between 1 and 300 seconds.

project_id string optional

File this generation's output into one of your PROJECTS (`GET /v1/projects`) when the run completes. Access is checked before the run is created; filing itself is best-effort.

curl Example

curl https://api.genfire.ai/v1/lipsync/generations \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Idempotency-Key: unique_request_key" \
  -H "Content-Type: application/json" \
  -d '{
  "video_url": "https://example.com/source-video.mp4",
  "audio_url": "https://example.com/source-audio.mp3",
  "sync_mode": "cut_off",
  "model": "lipsync.lipsync_2_pro"
}'

Response Example

{
  "id": "run_vid_123",
  "object": "run",
  "status": "queued",
  "capability": "lipsync_generation",
  "endpoint": "lipsync.generations.create",
  "model": "lipsync.lipsync_2_pro",
  "request_id": "run_vid_123",
  "input_summary": {
    "prompt": "Cinematic close-up of a luxury watch with soft lighting",
    "model": "video.veo_3_1",
    "aspect_ratio": "16:9",
    "duration": 8,
    "has_image": false,
    "generate_audio": true
  },
  "output": null,
  "usage": null,
  "error": null,
  "resource_id": "video_123",
  "provider_request_id": "provider_req_123",
  "created_at": "2026-03-25T12:00:00.000Z",
  "updated_at": "2026-03-25T12:00:00.000Z",
  "completed_at": null
}

Request Example Body

{
  "video_url": "https://example.com/source-video.mp4",
  "audio_url": "https://example.com/source-audio.mp3",
  "sync_mode": "cut_off",
  "model": "lipsync.lipsync_2_pro"
}

Notes

  • Provide either `audio_url` or `audio_base64`.
  • This endpoint is async and usually returns a queued run first.
POST /audio/speech
audio:write

Generate speech audio

Text-to-speech generation using a public speech model alias.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Required

Body Fields

text string required

The text to speak. For `speech.seed_audio_1_0` this is a free-form audio prompt (max 2048 chars) that can also describe scenes/dialogue and reference audio inputs as @Audio1–@Audio3.

voice_id string optional

The voice id to use: either a stock ElevenLabs voice id or one of your cloned voice ids (`fal_cloned_<id>`). List options via `/audio/voices`. Required for ElevenLabs models. For `speech.seed_audio_1_0` it is OPTIONAL and takes a Seed preset name (e.g. `vivi_mixed_en_zh_ja_es_id`) instead.

model string optional

Optional speech model alias from `/models`.

Default: speech.elevenlabs_turbo_v2_5

voice_name string optional

Optional human-readable voice name passed through to the audio generator.

output_format string optional

Optional output format when supported by the backing provider. For `speech.seed_audio_1_0`: one of `wav`, `mp3`, `pcm`, `ogg_opus` (default `mp3`).

audio_urls string[] optional

Seed Audio 1.0 only — up to 3 reference audio URLs (each ≤30s / 10MB), referenced in the prompt as @Audio1–@Audio3. Cannot be combined with `image_url`.

image_url string optional

Seed Audio 1.0 only — a single reference image URL (jpeg/png/webp ≤10MB). Cannot be combined with `audio_urls`.

sample_rate number optional

Seed Audio 1.0 only — output sample rate in Hz: 8000, 16000, 24000 (default), 32000, 44100 or 48000.

speed number optional

Seed Audio 1.0 only — speech speed 0.5–2 (1 = normal).

volume number optional

Seed Audio 1.0 only — volume 0.5–2 (1 = normal).

pitch number optional

Seed Audio 1.0 only — pitch shift in semitones, -12 to 12 (0 = normal).

curl Example

curl https://api.genfire.ai/v1/audio/speech \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Idempotency-Key: unique_request_key" \
  -H "Content-Type: application/json" \
  -d '{
  "text": "Introducing the new Genfire creative workflow.",
  "voice_id": "voice_abc123",
  "model": "speech.elevenlabs_turbo_v2_5"
}'

Response Example

{
  "id": "run_speech_123",
  "object": "run",
  "status": "completed",
  "capability": "speech_generation",
  "endpoint": "audio.speech.create",
  "model": "speech.elevenlabs_turbo_v2_5",
  "request_id": "run_img_123",
  "input_summary": {
    "prompt": "Studio product photo of a matte black water bottle",
    "model": "image.nano_banana_2",
    "aspect_ratio": "1:1",
    "count": 1
  },
  "output": {
    "audio_id": "audio_123",
    "audio_url": "https://cdn.genfire.ai/output/audio-123.mp3",
    "duration": 6.4
  },
  "usage": {
    "credits": 8
  },
  "error": null,
  "resource_id": null,
  "provider_request_id": null,
  "created_at": "2026-03-25T12:00:00.000Z",
  "updated_at": "2026-03-25T12:00:02.000Z",
  "completed_at": "2026-03-25T12:00:02.000Z"
}

Request Example Body

{
  "text": "Introducing the new Genfire creative workflow.",
  "voice_id": "voice_abc123",
  "model": "speech.elevenlabs_turbo_v2_5"
}
POST /audio/music
audio:write

Generate music

Create music from a prompt or a structured composition plan. You can request a simple audio result or a more detailed music result with timestamps.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Required

Body Fields

prompt string optional

Description of the music you want generated. Required unless `composition_plan` is provided; the two cannot be combined.

composition_plan object optional

Structured composition plan instead of a prompt (ElevenLabs only). music_v1 shape: `{ positive_global_styles[], negative_global_styles[], sections[] }` with per-section styles, duration_ms (3000-120000) and lyric lines. music_v2 shape: `{ chunks[] }` where each chunk has `text` (may carry [Section] and {direction} markup), `duration_ms`, `positive_styles[]` and optional audio-conditioning refs. Duration and billing derive from the plan's summed durations.

model string optional

Optional music model alias from `/models`. A chunks-shaped `composition_plan` implies `music.elevenlabs_music_v2`.

Default: music.elevenlabs_music_v1

duration_seconds number optional

Desired music length in seconds. ElevenLabs prompt mode: 3-600 (default 30; ignored with `composition_plan`). MiniMax Music 3: an upper bound of 1-300 (default 60) that billing is charged on — the model may finish earlier. Lyria 3 Pro ignores it and produces a flat-length song.

Default: 30

lyrics string optional

The lyrics to sing. REQUIRED for `music.minimax_music_3` — that model writes none of its own. Structure tags ([intro], [verse], [pre-chorus], [chorus], [post-chorus], [bridge], [instrumental], [solo], [outro]) must each be on their own line; Genfire splits a tag off a shared line for you so no lyric is silently dropped. Ignored by ElevenLabs (use `composition_plan`) and Lyria 3 Pro (it writes its own).

num_inference_steps integer optional

MiniMax Music 3 only: flow-matching Euler steps per 8-second chunk, 1-100. Higher is better quality and slower.

Default: 30

guidance_scale number optional

MiniMax Music 3 only: classifier-free guidance scale of the flow-matching stage, 0-20. Higher follows the prompt more literally.

Default: 1.7

include_details boolean optional

Return detailed music metadata when supported (ElevenLabs only).

Default: false

with_timestamps boolean optional

Include timestamps when `include_details` is true (ElevenLabs only).

Default: false

force_instrumental boolean optional

Guarantee instrumental output (ElevenLabs prompt mode only).

respect_sections_durations boolean optional

With a music_v1 `composition_plan`: enforce section durations exactly instead of letting the model flex them (music_v2 always enforces them).

Default: true

seed integer optional

Random seed for reproducible results (ElevenLabs `composition_plan` mode, or MiniMax Music 3). The seed actually used is returned in the run output.

image_url string optional

Optional image URL used as inspiration for the generated music. Lyria 3 Pro only — the model matches the mood and theme of the image.

negative_prompt string optional

Deprecated — no current music model supports negative prompting (Lyria 3 rejects it, MiniMax Music 3 has no such field); the field is ignored.

output_format string optional

Optional output format when supported by the backing provider (ElevenLabs default `auto` picks the best mp3 for the model).

curl Example

curl https://api.genfire.ai/v1/audio/music \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Idempotency-Key: unique_request_key" \
  -H "Content-Type: application/json" \
  -d '{
  "prompt": "Confident electronic music bed for a product launch video",
  "model": "music.elevenlabs_music_v1",
  "duration_seconds": 30,
  "include_details": false
}'

Response Example

{
  "id": "run_music_123",
  "object": "run",
  "status": "completed",
  "capability": "music_generation",
  "endpoint": "audio.music.create",
  "model": "music.elevenlabs_music_v1",
  "request_id": "run_img_123",
  "input_summary": {
    "prompt": "Studio product photo of a matte black water bottle",
    "model": "image.nano_banana_2",
    "aspect_ratio": "1:1",
    "count": 1
  },
  "output": {
    "audio_id": "audio_music_123",
    "audio_url": "https://cdn.genfire.ai/output/music-123.mp3",
    "duration": 30
  },
  "usage": {
    "credits": 8
  },
  "error": null,
  "resource_id": null,
  "provider_request_id": null,
  "created_at": "2026-03-25T12:00:00.000Z",
  "updated_at": "2026-03-25T12:00:02.000Z",
  "completed_at": "2026-03-25T12:00:02.000Z"
}

Request Example Body

{
  "prompt": "Confident electronic music bed for a product launch video",
  "model": "music.elevenlabs_music_v1",
  "duration_seconds": 30,
  "include_details": false
}
POST /audio/sfx
audio:write

Generate sound effects

Generate short sound effects or foley-style audio from a text prompt.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Required

Body Fields

prompt string required

The sound effect prompt.

model string optional

Optional sound effect model alias from `/models`.

Default: sfx.elevenlabs_v1

duration_seconds number optional

Optional desired duration in seconds.

output_format string optional

Optional output format when supported by the backing provider.

prompt_influence number optional

Optional prompt influence value when supported.

loop boolean optional

Whether to generate a loop-friendly result when supported.

curl Example

curl https://api.genfire.ai/v1/audio/sfx \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Idempotency-Key: unique_request_key" \
  -H "Content-Type: application/json" \
  -d '{
  "prompt": "Heavy metal door slam in a large warehouse",
  "model": "sfx.elevenlabs_v1",
  "duration_seconds": 4
}'

Response Example

{
  "id": "run_sfx_123",
  "object": "run",
  "status": "completed",
  "capability": "sound_effect_generation",
  "endpoint": "audio.sfx.create",
  "model": "sfx.elevenlabs_v1",
  "request_id": "run_img_123",
  "input_summary": {
    "prompt": "Studio product photo of a matte black water bottle",
    "model": "image.nano_banana_2",
    "aspect_ratio": "1:1",
    "count": 1
  },
  "output": {
    "audio_id": "audio_sfx_123",
    "audio_url": "https://cdn.genfire.ai/output/sfx-123.mp3",
    "duration": 4.1
  },
  "usage": {
    "credits": 8
  },
  "error": null,
  "resource_id": null,
  "provider_request_id": null,
  "created_at": "2026-03-25T12:00:00.000Z",
  "updated_at": "2026-03-25T12:00:02.000Z",
  "completed_at": "2026-03-25T12:00:02.000Z"
}

Request Example Body

{
  "prompt": "Heavy metal door slam in a large warehouse",
  "model": "sfx.elevenlabs_v1",
  "duration_seconds": 4
}
POST /audio/transcriptions
audio:write

Transcribe audio or video (speech-to-text)

Transcribe speech to text with word- and segment-level timestamps using OpenAI Whisper. Provide exactly one of `audio_url`, `video_url`, or `youtube_url`. Video sources have their audio extracted automatically. Billed per second of media duration.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Required

Body Fields

audio_url string optional

URL of a direct audio file (mp3, wav, m4a, aac, ogg, flac, opus, webm, wma). One of audio_url / video_url / youtube_url is required.

video_url string optional

URL of a direct video file; audio is extracted before transcription.

youtube_url string optional

A YouTube URL to download and transcribe (max 2 hours).

model string optional

Optional transcription model alias from `/models`.

Default: transcription.whisper_v1

curl Example

curl https://api.genfire.ai/v1/audio/transcriptions \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Idempotency-Key: unique_request_key" \
  -H "Content-Type: application/json" \
  -d '{
  "audio_url": "https://cdn.genfire.ai/uploads/interview.mp3",
  "model": "transcription.whisper_v1"
}'

Response Example

{
  "id": "run_transcription_123",
  "object": "run",
  "status": "completed",
  "capability": "transcription",
  "endpoint": "audio.transcriptions.create",
  "model": "transcription.whisper_v1",
  "request_id": "run_img_123",
  "input_summary": {
    "prompt": "Studio product photo of a matte black water bottle",
    "model": "image.nano_banana_2",
    "aspect_ratio": "1:1",
    "count": 1
  },
  "output": {
    "transcript_id": "audio_txn_123",
    "text": "Welcome to the Genfire creative workflow.",
    "language": "en",
    "duration": 3.2,
    "words": [
      {
        "word": "Welcome",
        "start": 0,
        "end": 0.4,
        "probability": 1
      }
    ],
    "segments": [
      {
        "id": 0,
        "start": 0,
        "end": 3.2,
        "text": "Welcome to the Genfire creative workflow."
      }
    ],
    "audio_url": "https://storage.googleapis.com/genfire/extracted-audio/123.mp3"
  },
  "usage": {
    "credits": 8
  },
  "error": null,
  "resource_id": null,
  "provider_request_id": null,
  "created_at": "2026-03-25T12:00:00.000Z",
  "updated_at": "2026-03-25T12:00:02.000Z",
  "completed_at": "2026-03-25T12:00:02.000Z"
}

Request Example Body

{
  "audio_url": "https://cdn.genfire.ai/uploads/interview.mp3",
  "model": "transcription.whisper_v1"
}

Notes

  • Max media size 500MB; max duration 2 hours.
  • Async — usually returns a queued run first; poll the run until `status` is `completed`, then read `output.text` / `output.words` / `output.segments`.
  • YouTube transcription is supported but downloads third-party content — ensure your use complies with the source platform’s terms.
POST /products/extract
products:write

Extract product data from a URL

Scrape product details from a public product page and return the result inside a run envelope.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Required

Body Fields

url string required

A public product page URL. Private, local, and unsafe targets are blocked.

curl Example

curl https://api.genfire.ai/v1/products/extract \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Idempotency-Key: unique_request_key" \
  -H "Content-Type: application/json" \
  -d '{
  "url": "https://example.com/products/matte-black-water-bottle"
}'

Response Example

{
  "id": "run_product_123",
  "object": "run",
  "status": "completed",
  "capability": "product_extraction",
  "endpoint": "products.extract.create",
  "model": null,
  "request_id": "run_img_123",
  "input_summary": {
    "prompt": "Studio product photo of a matte black water bottle",
    "model": "image.nano_banana_2",
    "aspect_ratio": "1:1",
    "count": 1
  },
  "output": {
    "product": {
      "success": true,
      "title": "Matte Black Water Bottle",
      "description": "Insulated stainless steel water bottle",
      "category": "hydration",
      "price": "$39",
      "images": [
        "https://example.com/product.jpg"
      ]
    },
    "cached": false
  },
  "usage": {
    "credits": 8
  },
  "error": null,
  "resource_id": null,
  "provider_request_id": null,
  "created_at": "2026-03-25T12:00:00.000Z",
  "updated_at": "2026-03-25T12:00:02.000Z",
  "completed_at": "2026-03-25T12:00:02.000Z"
}

Request Example Body

{
  "url": "https://example.com/products/matte-black-water-bottle"
}

Notes

  • Unsafe or private-network targets are rejected before scraping begins.

Reference

Workflows

GET /workflows
workflows:read

List executable workflows

Returns the workflow catalog. Use this when you want a higher-level outcome rather than raw media generation.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Body Fields

No body fields for this endpoint.

curl Example

curl https://api.genfire.ai/v1/workflows \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "object": "list",
  "data": [
    {
      "id": "hook_pack",
      "object": "workflow",
      "name": "Hook Pack",
      "description": "Generate three monetizable UGC-style hooks plus a supporting body and CTA.",
      "status": "available",
      "input_schema": {
        "type": "object",
        "required": [
          "prompt"
        ],
        "properties": {
          "prompt": {
            "type": "string"
          },
          "audience": {
            "type": "string"
          },
          "tone": {
            "type": "string",
            "enum": [
              "casual",
              "professional",
              "humorous",
              "educational",
              "persuasive",
              "emotional"
            ]
          },
          "length": {
            "type": "string",
            "enum": [
              "short",
              "medium",
              "long"
            ]
          },
          "target_duration": {
            "type": "number"
          },
          "keywords": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "additional_requirements": {
            "type": "string"
          }
        }
      },
      "output_schema": {
        "type": "object",
        "properties": {
          "hooks": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "body": {
            "type": "string"
          },
          "call_to_action": {
            "type": "string"
          },
          "full_script": {
            "type": "string"
          }
        }
      }
    },
    {
      "id": "ugc_ad",
      "object": "workflow",
      "name": "UGC Ad Script",
      "description": "Generate an outcome-oriented UGC ad script with hooks, body, CTA, and a full spoken script.",
      "status": "available",
      "input_schema": {
        "type": "object",
        "required": [
          "prompt"
        ],
        "properties": {
          "prompt": {
            "type": "string"
          },
          "audience": {
            "type": "string"
          },
          "tone": {
            "type": "string",
            "enum": [
              "casual",
              "professional",
              "humorous",
              "educational",
              "persuasive",
              "emotional"
            ]
          },
          "length": {
            "type": "string",
            "enum": [
              "short",
              "medium",
              "long"
            ]
          },
          "target_duration": {
            "type": "number"
          },
          "keywords": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "additional_requirements": {
            "type": "string"
          }
        }
      },
      "output_schema": {
        "type": "object",
        "properties": {
          "hooks": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "body": {
            "type": "string"
          },
          "call_to_action": {
            "type": "string"
          },
          "full_script": {
            "type": "string"
          }
        }
      }
    },
    {
      "id": "ugc_ad_video",
      "object": "workflow",
      "name": "UGC Ad Video",
      "description": "One run → a finished UGC video ad: researches and writes the script (brand/product aware), generates the talking-avatar product shot on Hailuo 03 (with optional avatar template voice), and burns styled captions. Async — poll the returned run for the video URL. Cost = the component script workflow + the Hailuo 03 generation (captions are free).",
      "status": "available",
      "input_schema": {
        "type": "object",
        "required": [
          "prompt"
        ],
        "properties": {
          "prompt": {
            "type": "string",
            "description": "The product/offer brief the ad should sell. Required unless a finished `script` is supplied."
          },
          "script": {
            "type": "string",
            "description": "Skip script generation and use this exact spoken script."
          },
          "brand_id": {
            "type": "string",
            "description": "Ground the ad on a stored brand: its featured product photo fills the product slot and its voice/palette/words-to-avoid condition the script. The same brand_id contract as image/video generation and faceless reels."
          },
          "product_url": {
            "type": "string",
            "format": "uri",
            "description": "Product page URL — switches script generation to the product-aware creative_pack research flow."
          },
          "product_image_url": {
            "type": "string",
            "format": "uri",
            "description": "Product photo the creator presents on camera (reference image)."
          },
          "avatar_template_id": {
            "type": "string",
            "description": "Avatar from the Genfire template library — brings the face AND (by default) its voice sample."
          },
          "avatar_image_url": {
            "type": "string",
            "format": "uri",
            "description": "Custom avatar/creator face image (alternative to avatar_template_id)."
          },
          "use_avatar_voice": {
            "type": "boolean",
            "default": true,
            "description": "Condition the speech on the avatar template's voice sample when one exists."
          },
          "audience": {
            "type": "string"
          },
          "tone": {
            "type": "string",
            "enum": [
              "casual",
              "professional",
              "humorous",
              "educational",
              "persuasive",
              "emotional"
            ]
          },
          "scene": {
            "type": "string",
            "description": "Optional scene direction (e.g. \"in a car, golden hour\")."
          },
          "duration_seconds": {
            "type": "number",
            "minimum": 5,
            "maximum": 60,
            "default": 12,
            "description": "Up to 60s: ads longer than 15s chain multiple voice/face-conditioned takes with jump cuts (the native UGC edit)."
          },
          "aspect_ratio": {
            "type": "string",
            "enum": [
              "9:16",
              "16:9",
              "1:1",
              "3:4",
              "4:3",
              "21:9"
            ],
            "default": "9:16"
          },
          "resolution": {
            "type": "string",
            "enum": [
              "768p",
              "2k"
            ],
            "default": "768p"
          },
          "captions": {
            "type": "boolean",
            "default": true
          },
          "caption_preset_id": {
            "type": "string",
            "default": "hormozi"
          },
          "caption_position": {
            "type": "string",
            "enum": [
              "top",
              "middle",
              "bottom"
            ],
            "default": "bottom"
          },
          "caption_words_per_line": {
            "type": "number",
            "minimum": 1,
            "maximum": 6
          },
          "broll": {
            "type": "string",
            "enum": [
              "none",
              "auto",
              "stock",
              "stills",
              "video"
            ],
            "default": "auto",
            "description": "Multi-scene cutaways while the avatar voice continues. auto (default) = one product-fidelity still + FREE stock clips timed to spoken keywords; stock = all free Pexels; stills = generated images; video = Hailuo 03 clips (premium)."
          },
          "broll_count": {
            "type": "number",
            "minimum": 1,
            "maximum": 3,
            "default": 2
          },
          "reference_ad_research_id": {
            "type": "string",
            "description": "A stored competitor-ad analysis (from POST /v1/ads/analyze or the agent's analyze_competitor_ad) — the script follows that proven format for YOUR product; assets and wording are never copied."
          }
        }
      },
      "output_schema": {
        "type": "object",
        "properties": {
          "video_url": {
            "type": "string"
          },
          "captioned": {
            "type": "boolean"
          },
          "script": {
            "type": "string"
          },
          "hooks": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "source_video_id": {
            "type": "string"
          },
          "duration_seconds": {
            "type": "number"
          },
          "aspect_ratio": {
            "type": "string"
          }
        }
      }
    },
    {
      "id": "ad_remix",
      "object": "workflow",
      "name": "Ad Remix",
      "description": "One winning ad → variants with the nouns swapped, the cut and pacing kept. Engine: Gemini Omni Flash 1.1, two routes chosen per variant. EDIT (every change is words): the footage itself is edited, so the setting, framing, motion and product are kept by construction — a ≤10s source goes whole, a longer one is cut on its own hard cuts into ≤10s segments and each is edited; variants that ACCUMULATE (each one's changes extend the previous one's, in order) are CHAINED — each edits the previous variant's output with only what it adds, so a new creator carries through outfit → location → language. REFERENCE (a change shows an image): the source is split on its own hard cuts into ≤9s segments (each fed three ≤3s slices of itself as references). MIXED (words AND a picture in the same variant — \"make her Persian and put her in this hoodie\"): the server SPLITS it into an implicit two-step chain and still returns ONE variant — an intermediate leg (id `{id}.edit`, `intermediate: true`) renders the words-only changes on the edit route, then the deliverable renders the image-backed ones on the reference route with its slices cut from THAT LEG'S OUTPUT (`chain_from`), so a words-only person swap actually lands instead of coming back as the original person. Both legs are billed; only the deliverable appears in output.variants[], the leg appears under output.intermediates[]. Never restructure a request to work around routing — put every change on one variant and let the server split it. A creator change that carries a face image is DESCRIBED in words by the server and the picture is never sent with footage (the engine refuses a face next to footage) — the new person is a look-alike of the description; picker cards (creator portrait, outfit flat lay, empty location) are generated AFTER each video from its own frame so the card is what rendered. Every (variant × segment) is one generation, cards ~1 credit each, and the segments are concatenated on the planned boundaries with the sound the model rendered — it renders speech, ambience and music with the picture, mouths in sync, so a creator swap or a language change ({ what: \"language\", description: \"Spanish\" }) comes back dubbed with no lipsync step. The original track (or a supplied one) can be laid back on instead. Each output is cut-diffed against the source and returns a fidelity score. Async — poll the returned run; output.variants[] carries a video_url per variant. Cost = segments × variants × per-second Omni pricing at the chosen resolution — quote it first with POST /v1/ads/remix (dry run).",
      "status": "available",
      "input_schema": {
        "type": "object",
        "required": [
          "source_video_url"
        ],
        "properties": {
          "source_video_url": {
            "type": "string",
            "format": "uri",
            "description": "The winning ad, as a public https URL (a Genfire run output URL works). Clean sources only — burned-in captions come back as garbled text."
          },
          "product_image_url": {
            "type": "string",
            "format": "uri",
            "description": "The product, PINNED: an Element image or product photo that rides every REFERENCE generation as a fixed object reference (\"the product, exactly as shown\"). Without it the model re-draws the product from the reference slices and it drifts between variants. It is NOT sent on an edit-route call — that endpoint has no image pool, so there the product is held from the footage by the keep-list (\"exactly as it is in the video\") and the plan says so in developer_notes. A `product` CHANGE pointing at this same image is folded back into the pin rather than honoured as a change, so repeating the product photo can never push a variant onto the reference route on its own. The pin steps aside entirely for a variant that changes the product to a DIFFERENT image."
          },
          "changes": {
            "type": "array",
            "minItems": 1,
            "maxItems": 10,
            "description": "ONE variant: what to change. Use this OR `variants`.",
            "items": {
              "type": "object",
              "required": [
                "what"
              ],
              "properties": {
                "what": {
                  "type": "string",
                  "description": "\"creator\", \"outfit\", \"location\", \"product\" get tuned phrasing; anything else (\"the drink she is holding\", \"time of day\") is honoured generically."
                },
                "image_url": {
                  "type": "string",
                  "format": "uri",
                  "description": "Reference image showing the replacement (an Element, a product photo, an outfit or location still). For a CREATOR change the face is described in words server-side and the picture is never sent with footage — the engine refuses that — so the result is a look-alike, not that exact face; the creator card in the output is made from the render."
                },
                "description": {
                  "type": "string",
                  "description": "Plain-English detail. Required when there is no image_url or preset."
                },
                "preset": {
                  "type": "string",
                  "description": "A named preset with the wording already written (no image slot used; `what` may be omitted). look: anime, retro-collage, bold-urban, green-contrast, warm-glow, neon-cyberpunk, claymation, comic-pop, doodle-notes, vhs-retro, paper-craft, watercolor, noir-film, hud-tracking · location: marble-kitchen, gym-floor, car-interior, golden-hour-street, cafe-terrace, beach-boardwalk, city-rooftop-dusk, bedroom-morning, home-office, city-park, airplane-wing, volcano-rim, doll-size, moving-car-roof · time: golden-hour, blue-hour, midday, overcast, night, indoor-evening · weather: light-rain, snow, fog, heat-haze · wardrobe: athleisure, streetwear, business-casual, evening-wear, cozy-knit, workwear · camera: handheld-phone, tripod-locked, slow-push-in, wider-lens · language: en, es, de, fr, it, pt-br, ja, ko, zh, hi, ar. The dry run lists them under `presets`."
                }
              }
            }
          },
          "variants": {
            "type": "array",
            "minItems": 1,
            "maxItems": 12,
            "description": "SEVERAL variants, each a full remix of the whole ad. Use this OR `changes`.",
            "items": {
              "type": "object",
              "required": [
                "changes"
              ],
              "properties": {
                "id": {
                  "type": "string"
                },
                "changes": {
                  "type": "array",
                  "minItems": 1,
                  "maxItems": 10,
                  "items": {
                    "type": "object"
                  }
                },
                "direction": {
                  "type": "string",
                  "description": "Free-text direction for this variant, appended verbatim."
                },
                "audio": {
                  "description": "\"generated\" (default — the model's own sound, in sync with its mouths), \"original\" (the source track laid back on), \"none\", an audio URL, or { mode: generated|original|replace|none, url }."
                }
              }
            }
          },
          "audio": {
            "description": "Run-level soundtrack default: \"generated\" (the sound the model rendered with the picture — default), \"original\" (the source track laid back on), \"none\", an http(s) audio URL, or { mode, url }. A variant's own `audio` wins."
          },
          "aspect_ratio": {
            "type": "string",
            "enum": [
              "9:16",
              "16:9"
            ],
            "default": "9:16",
            "description": "Match the source."
          },
          "resolution": {
            "type": "string",
            "enum": [
              "360p",
              "720p",
              "1080p",
              "4k"
            ],
            "default": "1080p",
            "description": "720p for drafts — cost scales ~10x across the ladder."
          },
          "cards": {
            "type": "boolean",
            "default": true,
            "description": "Make picker cards from each variant's output — a creator portrait, an outfit flat lay, an empty location — for the changes it introduces (~1 credit each). false to skip."
          }
        }
      },
      "output_schema": {
        "type": "object",
        "properties": {
          "engine": {
            "type": "string"
          },
          "route": {
            "type": "string",
            "enum": [
              "edit",
              "reference",
              "mixed"
            ]
          },
          "segments": {
            "type": "number"
          },
          "generation_count": {
            "type": "number"
          },
          "cards": {
            "type": "number",
            "description": "How many picker cards were planned."
          },
          "intermediates": {
            "type": "array",
            "description": "Debugging only: the words-only legs the server inserted for variants that mixed words with pictures. Each was billed and rendered; none is a deliverable — they never appear in variants[] and can never be the run's video_url.",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "status": {
                  "type": "string",
                  "enum": [
                    "completed",
                    "failed"
                  ]
                },
                "intermediate": {
                  "type": "boolean"
                },
                "video_url": {
                  "type": "string"
                },
                "chain_from": {
                  "type": "string"
                },
                "error": {
                  "type": "string"
                }
              }
            }
          },
          "variants": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "status": {
                  "type": "string",
                  "enum": [
                    "completed",
                    "failed"
                  ]
                },
                "video_url": {
                  "type": "string"
                },
                "duration_seconds": {
                  "type": "number"
                },
                "qa": {
                  "type": "object",
                  "description": "Cut-diff against the source: fidelity 0-1, matched/missing/extra cuts, mean drift."
                },
                "audio_track": {
                  "type": "string",
                  "enum": [
                    "generated",
                    "original",
                    "replace",
                    "none"
                  ],
                  "description": "Which soundtrack shipped on this variant."
                },
                "thumbnail_url": {
                  "type": "string"
                },
                "cards": {
                  "type": "object",
                  "description": "Picker cards made from THIS output: { creator?, outfit?, location? } → image URL. The card is what rendered."
                },
                "chain_from": {
                  "type": "string",
                  "description": "The variant this one was rendered on top of — an earlier variant it accumulates on, or the intermediate leg the server inserted when this variant mixed words-only changes with image-backed ones."
                },
                "creator_reference_url": {
                  "type": "string",
                  "description": "The face the caller picked for the creator change — described, never sent to the engine."
                },
                "library_video_id": {
                  "type": "string"
                },
                "error": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    {
      "id": "creative_pack",
      "object": "workflow",
      "name": "Creative Pack",
      "description": "Build a product-aware creative pack with analysis, angles, hooks, and a monetizable script.",
      "status": "available",
      "input_schema": {
        "type": "object",
        "properties": {
          "prompt": {
            "type": "string"
          },
          "product_url": {
            "type": "string",
            "format": "uri"
          },
          "product_name": {
            "type": "string"
          },
          "product_description": {
            "type": "string"
          },
          "category": {
            "type": "string"
          },
          "audience": {
            "type": "string"
          },
          "tone": {
            "type": "string",
            "enum": [
              "casual",
              "professional",
              "humorous",
              "educational",
              "persuasive",
              "emotional"
            ]
          },
          "length": {
            "type": "string",
            "enum": [
              "short",
              "medium",
              "long"
            ]
          },
          "image_urls": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uri"
            }
          },
          "additional_requirements": {
            "type": "string"
          }
        }
      },
      "output_schema": {
        "type": "object",
        "properties": {
          "product": {
            "type": "object"
          },
          "analysis": {
            "type": "object"
          },
          "hooks": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "body": {
            "type": "string"
          },
          "call_to_action": {
            "type": "string"
          },
          "full_script": {
            "type": "string"
          }
        }
      }
    },
    {
      "id": "product_ad_variants",
      "object": "workflow",
      "name": "Product Ad Variants",
      "description": "Generate multiple UGC-style ad script variants for the same product or offer.",
      "status": "available",
      "input_schema": {
        "type": "object",
        "properties": {
          "prompt": {
            "type": "string"
          },
          "product_name": {
            "type": "string"
          },
          "product_description": {
            "type": "string"
          },
          "audience": {
            "type": "string"
          },
          "tone": {
            "type": "string",
            "enum": [
              "casual",
              "professional",
              "humorous",
              "educational",
              "persuasive",
              "emotional"
            ]
          },
          "length": {
            "type": "string",
            "enum": [
              "short",
              "medium",
              "long"
            ]
          },
          "variant_count": {
            "type": "number",
            "minimum": 1,
            "maximum": 5
          },
          "additional_requirements": {
            "type": "string"
          }
        }
      },
      "output_schema": {
        "type": "object",
        "properties": {
          "variant_count": {
            "type": "number"
          },
          "variants": {
            "type": "array",
            "items": {
              "type": "object"
            }
          }
        }
      }
    }
  ]
}
GET /workflows/{workflowKey}
workflows:read

Get one workflow definition

Returns the input and output schema for a specific workflow.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Parameters

workflowKey path required

A workflow id such as `hook_pack` or `creative_pack`.

Body Fields

No body fields for this endpoint.

curl Example

curl https://api.genfire.ai/v1/workflows/{workflowKey} \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "id": "hook_pack",
  "object": "workflow",
  "name": "Hook Pack",
  "description": "Generate three monetizable UGC-style hooks plus a supporting body and CTA.",
  "status": "available",
  "input_schema": {
    "type": "object",
    "required": [
      "prompt"
    ],
    "properties": {
      "prompt": {
        "type": "string"
      },
      "audience": {
        "type": "string"
      },
      "tone": {
        "type": "string",
        "enum": [
          "casual",
          "professional",
          "humorous",
          "educational",
          "persuasive",
          "emotional"
        ]
      },
      "length": {
        "type": "string",
        "enum": [
          "short",
          "medium",
          "long"
        ]
      },
      "target_duration": {
        "type": "number"
      },
      "keywords": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "additional_requirements": {
        "type": "string"
      }
    }
  },
  "output_schema": {
    "type": "object",
    "properties": {
      "hooks": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "body": {
        "type": "string"
      },
      "call_to_action": {
        "type": "string"
      },
      "full_script": {
        "type": "string"
      }
    }
  }
}
POST /workflows/{workflowKey}/runs
workflows:write

Execute a workflow

Creates a run for the requested workflow. The request body depends on the workflow you choose.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Required

Parameters

workflowKey path required

A workflow id such as `hook_pack`, `ugc_ad`, or `creative_pack`.

Body Fields

workflow-specific fields object required

Use the schema from `GET /workflows/{workflowKey}` or the workflow catalog below.

curl Example

curl https://api.genfire.ai/v1/workflows/{workflowKey}/runs \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Idempotency-Key: unique_request_key" \
  -H "Content-Type: application/json" \
  -d '{
  "prompt": "Portable blender for busy professionals",
  "audience": "Remote workers who skip breakfast",
  "tone": "persuasive",
  "length": "short",
  "target_duration": 20,
  "keywords": [
    "protein shake",
    "commute",
    "healthy"
  ],
  "additional_requirements": "Lead with convenience and save time."
}'

Response Example

{
  "id": "run_workflow_123",
  "object": "run",
  "status": "completed",
  "capability": "workflow.hook_pack",
  "endpoint": "workflows.hook_pack.run",
  "model": null,
  "request_id": "run_img_123",
  "input_summary": {
    "workflow": "hook_pack",
    "prompt": "Portable blender for busy professionals",
    "audience": "Remote workers who skip breakfast",
    "tone": "persuasive",
    "length": "short",
    "target_duration": 20,
    "keywords": [
      "protein shake",
      "commute",
      "healthy"
    ],
    "additional_requirements": "Lead with convenience and save time."
  },
  "output": {
    "workflow": "hook_pack",
    "topic": "Portable blender for busy professionals",
    "hooks": [
      "If breakfast keeps losing to your calendar, this fixes it.",
      "I stopped skipping protein the day I threw this in my bag.",
      "This is how I make a full shake before my first meeting."
    ],
    "body": "Portable, fast, and easy to clean for daily use.",
    "call_to_action": "Try it before your next busy week.",
    "full_script": "If breakfast keeps losing to your calendar...",
    "word_count": 96,
    "estimated_duration": 22
  },
  "usage": {
    "credits": 8
  },
  "error": null,
  "resource_id": null,
  "provider_request_id": null,
  "created_at": "2026-03-25T12:00:00.000Z",
  "updated_at": "2026-03-25T12:00:02.000Z",
  "completed_at": "2026-03-25T12:00:02.000Z"
}

Request Example Body

{
  "prompt": "Portable blender for busy professionals",
  "audience": "Remote workers who skip breakfast",
  "tone": "persuasive",
  "length": "short",
  "target_duration": 20,
  "keywords": [
    "protein shake",
    "commute",
    "healthy"
  ],
  "additional_requirements": "Lead with convenience and save time."
}

Notes

  • The workflow catalog below includes example payloads for every supported workflow.

Reference

User Workflows

GET /user-workflows
workflows:read

List your editor workflows

Lists the node-graph workflows the authenticated account owns or can access through team sharing — the same workflows shown in the dashboard workflow editor. Use the returned `id` to trigger runs via `POST /user-workflows/{workflowId}/runs`.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Body Fields

No body fields for this endpoint.

curl Example

curl https://api.genfire.ai/v1/user-workflows \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "object": "list",
  "data": [
    {
      "id": "wf_abc123",
      "object": "user_workflow",
      "title": "Product shot pipeline",
      "nodeCount": 6,
      "updatedAt": "2026-07-01T12:00:00.000Z",
      "teamId": null
    }
  ]
}
POST /user-workflows/{workflowId}/runs
workflows:write

Run one of your editor workflows

Starts a run of a user-created workflow graph — the same execution path as the editor’s Run button. Execution is asynchronous: this returns `202 Accepted` immediately with a run id; poll `GET /user-workflows/{workflowId}/runs/{runId}` for progress and per-node outputs. Credits are charged to the authenticated account per node as the graph executes (runner pays).

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Parameters

workflowId path required

A workflow id from `GET /user-workflows`.

Body Fields

pageId string optional

Which page of the workflow to run. Defaults to the first page.

selectedNodeIds array optional

Node ids to run — their upstream dependencies run automatically. Defaults to the editor behavior: the page’s Export nodes if it has any, otherwise every generation leaf node (image/video/audio/text nodes with no outgoing edges).

paramOverrides object optional

Per-run parameter overrides shaped as `{ nodeId: { paramKey: value } }`. Values must be primitives (string, number, boolean, or null) and the object must serialize to at most 50KB. Overrides apply to this run only — the stored workflow is never modified.

curl Example

curl https://api.genfire.ai/v1/user-workflows/{workflowId}/runs \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "pageId": "page_1",
  "paramOverrides": {
    "node_prompt_1": {
      "text": "A red sneaker on a marble table"
    }
  }
}'

Response Example

{
  "runId": "wfrun_abc123",
  "totalCostCredits": 42,
  "pageId": "page_1",
  "selectedNodeIds": [
    "node_export_1"
  ]
}

Request Example Body

{
  "pageId": "page_1",
  "paramOverrides": {
    "node_prompt_1": {
      "text": "A red sneaker on a marble table"
    }
  }
}

Notes

  • Requires owner or editor access to the workflow; team viewers receive a 403.
  • `totalCostCredits` is the up-front estimate for the nodes that will execute; per-node charges settle against your credit balance as the run progresses.
  • Snake_case body keys (`page_id`, `selected_node_ids`, `param_overrides`) are accepted as aliases.
GET /user-workflows/{workflowId}/runs/{runId}
workflows:read

Get the status and outputs of a workflow run

Returns run-level status plus one entry per executed node with its output media URL or text. Poll until `status` is `completed`, `failed`, or `cancelled`.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Parameters

workflowId path required

A workflow id from `GET /user-workflows`.

runId path required

The run id returned by `POST /user-workflows/{workflowId}/runs`.

Body Fields

No body fields for this endpoint.

curl Example

curl https://api.genfire.ai/v1/user-workflows/{workflowId}/runs/{runId} \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "runId": "wfrun_abc123",
  "workflowId": "wf_abc123",
  "pageId": "page_1",
  "status": "completed",
  "totalCostCredits": 42,
  "startedAt": "2026-07-01T12:00:01.000Z",
  "completedAt": "2026-07-01T12:02:40.000Z",
  "error": null,
  "nodes": [
    {
      "nodeId": "node_image_1",
      "status": "completed",
      "output": {
        "type": "image",
        "url": "https://firebasestorage.googleapis.com/.../shot.png"
      }
    },
    {
      "nodeId": "node_export_1",
      "status": "completed",
      "output": {
        "type": "file",
        "url": "https://firebasestorage.googleapis.com/.../export.png"
      }
    }
  ]
}

Reference

Batches

GET /batches
batches:read

List recent batches

Lists batch jobs created by the authenticated account.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Parameters

status query optional

Optional status filter such as `queued`, `processing`, `completed`, `failed`, or `partial`.

mode query optional

Optional batch mode filter: `workflow` or `operation`.

target query optional

Optional target filter such as `hook_pack` or `images.generations.create`.

limit query optional

Maximum number of batches to return.

Default: 25

Body Fields

No body fields for this endpoint.

curl Example

curl https://api.genfire.ai/v1/batches \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "object": "list",
  "data": [
    {
      "id": "batch_123",
      "object": "batch",
      "mode": "workflow",
      "target": "hook_pack",
      "status": "queued",
      "total_items": 2,
      "completed_items": 0,
      "failed_items": 0,
      "concurrency": 2,
      "input_summary": {
        "mode": "workflow",
        "target": "hook_pack",
        "item_count": 2
      },
      "output": null,
      "error": null,
      "created_at": "2026-03-25T12:00:00.000Z",
      "updated_at": "2026-03-25T12:00:00.000Z",
      "completed_at": null
    }
  ]
}
GET /batches/{batchId}
batches:read

Get a batch by id

Returns batch-level status, counts, and summary output.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Parameters

batchId path required

The batch id returned by `POST /batches`.

Body Fields

No body fields for this endpoint.

curl Example

curl https://api.genfire.ai/v1/batches/{batchId} \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "id": "batch_123",
  "object": "batch",
  "mode": "workflow",
  "target": "hook_pack",
  "status": "queued",
  "total_items": 2,
  "completed_items": 0,
  "failed_items": 0,
  "concurrency": 2,
  "input_summary": {
    "mode": "workflow",
    "target": "hook_pack",
    "item_count": 2
  },
  "output": null,
  "error": null,
  "created_at": "2026-03-25T12:00:00.000Z",
  "updated_at": "2026-03-25T12:00:00.000Z",
  "completed_at": null
}
GET /batches/{batchId}/items
batches:read

List items in a batch

Returns one row per batch item so you can inspect per-item progress and run ids.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Parameters

batchId path required

The batch id returned by `POST /batches`.

Body Fields

No body fields for this endpoint.

curl Example

curl https://api.genfire.ai/v1/batches/{batchId}/items \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "object": "list",
  "data": [
    {
      "id": "batch_item_123",
      "object": "batch_item",
      "batch_id": "batch_123",
      "index": 0,
      "target": "hook_pack",
      "status": "queued",
      "run_id": null,
      "input_summary": {
        "prompt": "Portable blender for busy professionals"
      },
      "output": null,
      "error": null,
      "created_at": "2026-03-25T12:00:00.000Z",
      "updated_at": "2026-03-25T12:00:00.000Z",
      "completed_at": null
    }
  ]
}
POST /batches
batches:write

Create a batch

Create a batch over workflows or selected generation operations. Each item becomes its own run when processed.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Required

Body Fields

mode string required

Use `workflow` for workflow batches or `operation` for supported primitive operations.

target string required

Workflow key or supported operation target such as `images.generations.create`.

concurrency number optional

How many items to process concurrently.

Default: 2

items array required

Array of batch items. Each item must have an `input` object.

curl Example

curl https://api.genfire.ai/v1/batches \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Idempotency-Key: unique_request_key" \
  -H "Content-Type: application/json" \
  -d '{
  "mode": "workflow",
  "target": "hook_pack",
  "concurrency": 2,
  "items": [
    {
      "input": {
        "prompt": "Portable blender for busy professionals"
      }
    },
    {
      "input": {
        "prompt": "Portable blender for college students"
      }
    }
  ]
}'

Response Example

{
  "id": "batch_123",
  "object": "batch",
  "mode": "workflow",
  "target": "hook_pack",
  "status": "queued",
  "total_items": 2,
  "completed_items": 0,
  "failed_items": 0,
  "concurrency": 2,
  "input_summary": {
    "mode": "workflow",
    "target": "hook_pack",
    "item_count": 2
  },
  "output": null,
  "error": null,
  "created_at": "2026-03-25T12:00:00.000Z",
  "updated_at": "2026-03-25T12:00:00.000Z",
  "completed_at": null,
  "items": [
    {
      "id": "batch_item_123",
      "object": "batch_item",
      "batch_id": "batch_123",
      "index": 0,
      "target": "hook_pack",
      "status": "queued",
      "run_id": null,
      "input_summary": {
        "prompt": "Portable blender for busy professionals"
      },
      "output": null,
      "error": null,
      "created_at": "2026-03-25T12:00:00.000Z",
      "updated_at": "2026-03-25T12:00:00.000Z",
      "completed_at": null
    },
    {
      "id": "batch_item_124",
      "object": "batch_item",
      "batch_id": "batch_123",
      "index": 1,
      "target": "hook_pack",
      "status": "queued",
      "run_id": null,
      "input_summary": {
        "prompt": "Portable blender for college students"
      },
      "output": null,
      "error": null,
      "created_at": "2026-03-25T12:00:00.000Z",
      "updated_at": "2026-03-25T12:00:00.000Z",
      "completed_at": null
    }
  ]
}

Request Example Body

{
  "mode": "workflow",
  "target": "hook_pack",
  "concurrency": 2,
  "items": [
    {
      "input": {
        "prompt": "Portable blender for busy professionals"
      }
    },
    {
      "input": {
        "prompt": "Portable blender for college students"
      }
    }
  ]
}

Notes

  • Current operation batches support `images.generations.create` and `videos.generations.create`.
  • Workflow batches support any workflow listed by `GET /workflows`.
  • Items in `operation`-mode batches accept the same body fields as the operation `target` — e.g. `quality` and `resolution` are honored when batching `images.generations.create`.

Reference

Webhooks

GET /webhooks
webhooks:read

List webhook endpoints

Returns webhook destinations registered for the authenticated account.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Body Fields

No body fields for this endpoint.

curl Example

curl https://api.genfire.ai/v1/webhooks \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "object": "list",
  "data": [
    {
      "id": "wh_123",
      "object": "webhook_endpoint",
      "url": "https://example.com/webhooks/genfire",
      "description": "Agency production endpoint",
      "status": "active",
      "events": [
        "run.completed",
        "run.failed"
      ],
      "signing_secret_preview": "gfwsec_1234...abcd",
      "created_at": "2026-03-25T12:00:00.000Z",
      "updated_at": "2026-03-25T12:00:00.000Z",
      "last_delivery_at": null
    }
  ]
}
GET /webhooks/deliveries
webhooks:read

List webhook deliveries

Returns delivery attempts for the authenticated account.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Parameters

endpoint_id query optional

Optional webhook endpoint id to filter deliveries.

limit query optional

Maximum number of deliveries to return.

Default: 25

Body Fields

No body fields for this endpoint.

curl Example

curl https://api.genfire.ai/v1/webhooks/deliveries \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "object": "list",
  "data": [
    {
      "id": "delivery_123",
      "object": "webhook_delivery",
      "endpoint_id": "wh_123",
      "event_type": "run.completed",
      "run_id": "run_img_123",
      "batch_id": null,
      "status": "success",
      "attempt_count": 1,
      "max_attempts": 6,
      "response_status": 200,
      "response_body": "ok",
      "last_error": null,
      "request_headers": {
        "X-Genfire-Signature": "sha256=..."
      },
      "created_at": "2026-03-25T12:00:05.000Z",
      "updated_at": "2026-03-25T12:00:05.000Z",
      "last_attempt_at": "2026-03-25T12:00:05.000Z",
      "next_attempt_at": null,
      "delivered_at": "2026-03-25T12:00:05.000Z"
    }
  ]
}
POST /webhooks
webhooks:write

Create a webhook endpoint

Registers a webhook destination and returns the signing secret once.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Body Fields

url string required

Public HTTPS endpoint that will receive webhook POST requests.

description string optional

Optional human-readable label for the endpoint.

events array optional

Optional list of event types to subscribe to.

Default: ["run.completed","run.failed"]

curl Example

curl https://api.genfire.ai/v1/webhooks \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "url": "https://example.com/webhooks/genfire",
  "description": "Agency production endpoint",
  "events": [
    "run.completed",
    "run.failed"
  ]
}'

Response Example

{
  "id": "wh_123",
  "object": "webhook_endpoint",
  "url": "https://example.com/webhooks/genfire",
  "description": "Agency production endpoint",
  "status": "active",
  "events": [
    "run.completed",
    "run.failed"
  ],
  "signing_secret_preview": "gfwsec_1234...abcd",
  "created_at": "2026-03-25T12:00:00.000Z",
  "updated_at": "2026-03-25T12:00:00.000Z",
  "last_delivery_at": null,
  "signing_secret": "gfwsec_live_example_secret"
}

Request Example Body

{
  "url": "https://example.com/webhooks/genfire",
  "description": "Agency production endpoint",
  "events": [
    "run.completed",
    "run.failed"
  ]
}

Notes

  • Store the signing secret immediately. It is only returned when the endpoint is created.
POST /webhooks/deliveries/{deliveryId}/replay
webhooks:write

Replay a webhook delivery

Queues a new delivery attempt for an existing webhook delivery record.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Parameters

deliveryId path required

The webhook delivery id.

Body Fields

No body fields for this endpoint.

curl Example

curl https://api.genfire.ai/v1/webhooks/deliveries/{deliveryId}/replay \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "id": "delivery_456",
  "object": "webhook_delivery",
  "endpoint_id": "wh_123",
  "event_type": "run.completed",
  "run_id": "run_img_123",
  "batch_id": null,
  "status": "pending",
  "attempt_count": 0,
  "max_attempts": 6,
  "response_status": null,
  "response_body": null,
  "last_error": null,
  "request_headers": {
    "X-Genfire-Signature": "sha256=..."
  },
  "created_at": "2026-03-25T12:00:05.000Z",
  "updated_at": "2026-03-25T12:00:05.000Z",
  "last_attempt_at": null,
  "next_attempt_at": null,
  "delivered_at": null
}
PATCH /webhooks/{endpointId}
webhooks:write

Update a webhook endpoint

Update a webhook URL, description, status, or subscribed events.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Parameters

endpointId path required

The webhook endpoint id.

Body Fields

url string optional

New destination URL.

description string | null optional

New description or `null` to clear it.

status string optional

Use `active` or `disabled`.

events array optional

Replacement list of subscribed event types.

curl Example

curl https://api.genfire.ai/v1/webhooks/{endpointId} \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "status": "disabled"
}'

Response Example

{
  "id": "wh_123",
  "object": "webhook_endpoint",
  "url": "https://example.com/webhooks/genfire",
  "description": "Agency production endpoint",
  "status": "disabled",
  "events": [
    "run.completed",
    "run.failed"
  ],
  "signing_secret_preview": "gfwsec_1234...abcd",
  "created_at": "2026-03-25T12:00:00.000Z",
  "updated_at": "2026-03-25T12:05:00.000Z",
  "last_delivery_at": null
}

Request Example Body

{
  "status": "disabled"
}
DELETE /webhooks/{endpointId}
webhooks:write

Delete a webhook endpoint

Deletes the webhook endpoint. The endpoint id is no longer usable after deletion.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Parameters

endpointId path required

The webhook endpoint id.

Body Fields

No body fields for this endpoint.

curl Example

curl https://api.genfire.ai/v1/webhooks/{endpointId} \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

204 No Content

Reference

Picture Books

POST /picture-books/generations
images:write

Generate an illustrated picture book

Creates a print-ready children’s book: a style anchor, a reference sheet per cast member and recurring place, then every page painted from those references so the characters stay the same, and finally the covers (which render LAST, from a finished interior page). Async — returns a run in `processing`; poll `GET /v1/runs/{runId}` (in-flight runs carry `progress`, and `resource_id` is the book id), then read `GET /v1/picture-books/{id}` for the pages. Pass `plan` to have your own words rendered exactly as written; pass `idea` or `script` to have Genfire write the story first.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Required

Body Fields

plan object optional

An authored book: `{ title, cast:[{name, description}], places?:[{name, description}], pages:[{ text, visual, cast?, place?, kind? }] }`. Rendered exactly as written — no planner runs. `kind` is `page` | `spread` (one picture across two facing pages, one render, one page credit, must start on an even slot) | `text-page` (words only, free). Overrides `idea`/`script`/`pages`.

idea string optional

One line to write the story from, when you are not supplying `plan` or `script`.

script string optional

Your full story text (≤ 20000 chars). Split across pages by the planner; the words themselves are never rewritten.

title string optional

Book title. Defaults to the planner’s.

cast array optional

Up to 4 characters as `{name, description}` — one fixed physical description each, which becomes that character’s reference sheet.

age_band string optional

`board` | `picture` (default) | `early-reader`. Sets the word budget and the page-count options.

pages number optional

Interior page count within the band’s options (board 12/16/20, picture 16/24/32/40, early-reader 24/32/40/48).

style_id string optional

Art style from `GET /v1/picture-books/styles`. Defaults to `storybook`.

format_id string optional

Trim/aspect preset (KDP trims, other print sizes, or digital aspects). Defaults to `kdp-8.5x8.5`.

quality string optional

`low` (default) or `medium`. Medium costs several times more per unit — confirm before choosing it.

lettering string optional

`typeset` (default) — Genfire sets the words in post, so they stay editable and correctly spelled — or `lettered`, where the model paints them into the art. The FRONT COVER is always lettered.

team_id string optional

Bill the team pool (requires a billable role on that team).

curl Example

curl https://api.genfire.ai/v1/picture-books/generations \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Idempotency-Key: unique_request_key" \
  -H "Content-Type: application/json" \
  -d '{
  "idea": "a shy hedgehog who is afraid of the dark and finds a firefly friend",
  "age_band": "picture",
  "pages": 24,
  "style_id": "storybook",
  "quality": "low"
}'

Response Example

{
  "id": "run_123",
  "object": "run",
  "status": "processing",
  "capability": "picture_book_generation",
  "output": {
    "book_id": "bk_123",
    "url": "https://genfire.ai/dashboard/books/bk_123"
  }
}

Request Example Body

{
  "idea": "a shy hedgehog who is afraid of the dark and finds a firefly friend",
  "age_band": "picture",
  "pages": 24,
  "style_id": "storybook",
  "quality": "low"
}

Notes

  • Call `POST /v1/picture-books/estimate-cost` first — the whole book is checked for affordability up front and a short balance is a 402 before anything renders.
  • Every page is billed as one unit; a spread is ONE render and one page credit; a `text-page` is free.
  • Covers render last so they match the finished interior.
POST /picture-books/estimate-cost
account:read

Estimate picture-book credit cost

Prices a prospective book without generating anything: the style anchor, one sheet per cast member and place, every art page and the two covers. Also returns the plan Genfire would build (title, cast, page count) so you can confirm it first.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Body Fields

idea string optional

Same body as the generation call — `idea`, `script` or `plan`, plus the config fields.

age_band string optional

Sets the page-count options and the word budget.

pages number optional

Interior page count.

quality string optional

`low` or `medium`.

curl Example

curl https://api.genfire.ai/v1/picture-books/estimate-cost \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "idea": "a shy hedgehog who is afraid of the dark",
  "age_band": "picture",
  "pages": 24,
  "quality": "low"
}'

Response Example

{
  "object": "picture_book_cost_estimate",
  "estimated_credits": 84,
  "current_credits": 1200,
  "affordable": true,
  "plan": {
    "title": "Pip and the Little Light",
    "pages": 24,
    "art_pages": 24,
    "cast": [
      {
        "name": "PIP",
        "description": "a small round hedgehog with a rust-red scarf"
      }
    ]
  }
}

Request Example Body

{
  "idea": "a shy hedgehog who is afraid of the dark",
  "age_band": "picture",
  "pages": 24,
  "quality": "low"
}
GET /picture-books/{id}
account:read

Read one picture book

The book: status, progress, cast and places, every page with its art URL and text, the exports produced so far, and a deep link into the studio.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Body Fields

No body fields for this endpoint.

curl Example

curl https://api.genfire.ai/v1/picture-books/{id} \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "object": "picture_book",
  "id": "bk_123",
  "title": "Pip and the Little Light",
  "status": "ready",
  "pages": [
    {
      "id": "pg_1",
      "page_number": 1,
      "kind": "page",
      "text": "Pip was small.",
      "image_url": "https://…/page-1.png",
      "status": "ready"
    }
  ]
}
GET /picture-books/styles
account:read

List picture-book art styles

The sixteen art styles that can be passed as `style_id`, plus the trim/aspect presets for `format_id`.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Body Fields

No body fields for this endpoint.

curl Example

curl https://api.genfire.ai/v1/picture-books/styles \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "object": "list",
  "data": [
    {
      "id": "storybook",
      "label": "Classic Storybook",
      "group": "Painterly"
    }
  ]
}

Reference

Faceless Reels

POST /faceless-reels/generations
reels:write

Generate a faceless reel

Generates a vertical (9:16) short end-to-end: LLM script → voiceover → style-locked images → music → captioned video. Async — returns a run in `processing`; poll `GET /v1/runs/{runId}` until it is `completed`, then read the `video_url` from `output`.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Required

Body Fields

topic string required

The subject / seed for the reel. Use a phrase like "the disappearance of the Sodder children" or "Surprise me with a fresh idea".

preset_id string optional

Niche preset id from `GET /v1/faceless-reels/presets` (drives topic + tone). Defaults to a creepy-story preset.

style_id string optional

Visual style id from `GET /v1/faceless-reels/styles`. Defaults to the preset’s recommended style.

target_duration_sec number optional

Target length in seconds (10–600, up to 10 minutes). Drives script + scene count. Defaults to the niche’s natural length.

caption_preset_id string optional

Caption font/animation preset from `GET /v1/faceless-reels/caption-presets`.

Default: hormozi

caption_animation string optional

Override the caption animation (highlight | pop | typewriter | classic | background).

caption_position string optional

Vertical caption placement: "top" | "middle" | "bottom". Default middle (the classic centered render).

Default: middle

voice_id string optional

TTS voice id (ElevenLabs or Qwen). Defaults to a built-in narrator voice.

motion_vibe string optional

Camera-motion feel for the image slideshow: "auto" (per-niche, default) | "calm" (slow pans, subtle zoom) | "dynamic" (mixed pans + zooms) | "energetic" (corner punch-ins + shake).

Default: auto

animation_mode string optional

How much of the reel is real video: "stills" (Ken-Burns slideshow, default) | "hook" (premium — the FIRST scene is a real omni image-to-video clip) | "full" (ultra — EVERY scene is a real omni clip, one i2v clip cost per scene). Wins over animated_hook.

Default: stills

animated_hook boolean optional

LEGACY: true ≈ animation_mode "hook". Prefer animation_mode.

Default: false

video_model string optional

i2v model for animated clips. Every value resolves to "omni" (gemini-omni-flash); "grok"/"seedance-mini" are accepted legacy aliases.

Default: omni

direction string optional

Extra creative direction passed to the script model.

custom_story object optional

{ prompt, scene_hint? } to author a fully custom story instead of using a niche preset.

music object optional

Background music: { source: "none"|"preset"|"ai"|"library", preset_id?, prompt?, track_id? }.

curl Example

curl https://api.genfire.ai/v1/faceless-reels/generations \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Idempotency-Key: unique_request_key" \
  -H "Content-Type: application/json" \
  -d '{
  "topic": "The unsolved mystery of the Mary Celeste",
  "preset_id": "mystery",
  "target_duration_sec": 45,
  "caption_preset_id": "hormozi",
  "music": {
    "source": "preset",
    "preset_id": "unsolved-mystery"
  }
}'

Response Example

{
  "id": "run_8f3c4a2b1d6e7f9a0b1c2d3e",
  "object": "run",
  "status": "processing",
  "capability": "faceless_reel_generation",
  "endpoint": "faceless_reels.generations.create",
  "model": "reel.faceless",
  "resource_id": "reel_abc123",
  "created_at": "2026-06-08T12:00:00.000Z"
}

Request Example Body

{
  "topic": "The unsolved mystery of the Mary Celeste",
  "preset_id": "mystery",
  "target_duration_sec": 45,
  "caption_preset_id": "hormozi",
  "music": {
    "source": "preset",
    "preset_id": "unsolved-mystery"
  }
}

Notes

  • A reel renders in minutes. Poll `GET /v1/runs/{runId}` until `completed`; the output carries `{ reel_id, video_url, script, scenes, duration_seconds }`.
  • Cost varies with duration and music. Call `POST /v1/faceless-reels/estimate-cost` first for a per-config credit estimate.
  • The same `Idempotency-Key` returns the same run instead of generating (and billing) twice.
POST /faceless-reels/estimate-cost
reels:read

Estimate reel credit cost

Returns a per-config credit breakdown (images + voiceover + music) for a prospective reel, without generating anything.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Body Fields

preset_id string optional

Niche preset id (affects default scene count).

target_duration_sec number optional

Target length in seconds (10–600, up to 10 minutes).

music object optional

Music config; only `source: "ai"` adds a music fee.

curl Example

curl https://api.genfire.ai/v1/faceless-reels/estimate-cost \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "preset_id": "mystery",
  "target_duration_sec": 45,
  "music": {
    "source": "preset"
  }
}'

Response Example

{
  "object": "reel_cost_estimate",
  "images": 18,
  "voiceover": 6,
  "music": 0,
  "total": 24,
  "sceneCount": 7
}

Request Example Body

{
  "preset_id": "mystery",
  "target_duration_sec": 45,
  "music": {
    "source": "preset"
  }
}
GET /faceless-reels/presets
reels:read

List niche presets

Lists the available niche presets (topic + tone) that can be passed as `preset_id`.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Body Fields

No body fields for this endpoint.

curl Example

curl https://api.genfire.ai/v1/faceless-reels/presets \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "object": "list",
  "data": [
    {
      "id": "mystery",
      "label": "Unsolved Mystery",
      "emoji": "🔍",
      "tone": "mystery",
      "recommendedStyleId": "cinematic"
    }
  ]
}
GET /faceless-reels/styles
reels:read

List visual styles

Lists the available visual styles (art mediums) that can be passed as `style_id`.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Body Fields

No body fields for this endpoint.

curl Example

curl https://api.genfire.ai/v1/faceless-reels/styles \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "object": "list",
  "data": [
    {
      "id": "cinematic",
      "label": "Cinematic",
      "emoji": "🎬",
      "group": "Realistic"
    }
  ]
}
GET /faceless-reels/music-presets
reels:read

List background-music presets

Lists curated background-music tracks usable with `music.source = "preset"`.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Body Fields

No body fields for this endpoint.

curl Example

curl https://api.genfire.ai/v1/faceless-reels/music-presets \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "object": "list",
  "data": [
    {
      "id": "unsolved-mystery",
      "label": "Unsolved Mystery",
      "mood": "mystery"
    }
  ]
}
GET /faceless-reels/caption-presets
reels:read

List caption presets

Lists caption font/animation presets usable as `caption_preset_id`.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Body Fields

No body fields for this endpoint.

curl Example

curl https://api.genfire.ai/v1/faceless-reels/caption-presets \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "object": "list",
  "data": [
    {
      "id": "hormozi",
      "label": "Hormozi",
      "animation": "highlight"
    }
  ]
}
GET /faceless-reels/subscriptions
reels:read

List reel subscriptions

Lists the account owner’s recurring reel subscriptions ("Stories"). Each defines a niche + schedule that auto-generates reels.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Body Fields

No body fields for this endpoint.

curl Example

curl https://api.genfire.ai/v1/faceless-reels/subscriptions \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "object": "list",
  "data": [
    {
      "id": "sub_abc123",
      "enabled": true,
      "presetId": "mystery",
      "cadencePerDay": 1,
      "slots": [
        "18:00"
      ],
      "timezone": "America/New_York"
    }
  ]
}
POST /faceless-reels/subscriptions
reels:write

Create a reel subscription

Creates a faceless CHANNEL — a named recurring series that auto-produces episodes on a daily schedule. This is the same object the Faceless Studio shows; the path says "subscriptions" for backwards compatibility. Accepts the same creative fields as one-off generation, plus the channel identity, scheduling and topic-rotation fields. Pass enabled:false for a channel with no schedule yet.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Body Fields

label string optional

The channel name.

avatar_url string optional

CHANNEL identity: square avatar image URL.

tagline string optional

CHANNEL identity: one-line pitch shown under the channel name.

description string optional

CHANNEL identity: longer channel description.

niche string optional

CHANNEL identity: niche id (education, history, kids, storytelling, true-crime, finance, motivation, science, mystery, horror, animals, mythology, psychology).

format string optional

CHANNEL identity: "shorts" (9:16 reels) or "longform" (16:9 explainer episodes) — picks which engine renders each episode.

Default: shorts

episode_defaults object optional

CHANNEL identity: defaults every new episode inherits — { aspect_ratio: "16:9"|"9:16", target_duration_sec: 8-600, motion_style: "seamless"|"scenes"|"stills" }.

preset_id string optional

Niche preset id.

style_id string optional

Visual style id.

caption_preset_id string optional

Caption preset id.

caption_position string optional

Vertical caption placement: "top" | "middle" | "bottom".

Default: middle

voice_id string optional

TTS voice id.

motion_vibe string optional

Camera-motion feel: "auto" | "calm" | "dynamic" | "energetic".

Default: auto

animation_mode string optional

Animation tier: "stills" | "hook" (first scene animated) | "full" (every scene a real omni clip).

Default: stills

animated_hook boolean optional

LEGACY: true ≈ animation_mode "hook".

Default: false

video_model string optional

i2v model for animated clips (every value resolves to "omni").

Default: omni

target_duration_sec number optional

Target length (10–600, up to 10 minutes).

music object optional

Background music config.

topic_source string optional

"ai-auto" (fresh ideas) or "user-list" (rotate `topic_seeds`).

Default: ai-auto

topic_seeds array optional

Topics to rotate through when `topic_source` is "user-list".

cadence_per_day number optional

Reels per day (1–6).

Default: 1

slots array optional

Local "HH:mm" times; length must equal `cadence_per_day`.

Default: ["18:00"]

timezone string optional

IANA timezone for the slots.

Default: America/New_York

direction string optional

STANDING creative direction every episode inherits — tone, pacing, what to avoid.

custom_story object optional

{ prompt, scene_hint? } — a fixed recurring premise every episode is written from.

reference_images array optional

The channel’s RECURRING CAST: [{ url, label }] up to 8 https images every episode inherits.

reference_url string optional

A reference channel this one is modelled on.

caption_animation string optional

highlight | pop | typewriter | classic | background.

caption_words_per_line number optional

Caption line length (1-12).

ideas array optional

Episode titles queued for this channel (up to 24).

targets array optional

Connected accounts every finished episode AUTO-PUBLISHES to, as "platform:account_id" (see GET /social/accounts). Omit to keep episodes private.

enabled boolean optional

Whether the schedule is active.

Default: true

curl Example

curl https://api.genfire.ai/v1/faceless-reels/subscriptions \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "label": "Daily mysteries",
  "preset_id": "mystery",
  "cadence_per_day": 1,
  "slots": [
    "18:00"
  ],
  "timezone": "America/New_York",
  "topic_source": "ai-auto"
}'

Response Example

{
  "object": "reel_subscription",
  "id": "sub_abc123",
  "enabled": true,
  "presetId": "mystery",
  "cadencePerDay": 1,
  "slots": [
    "18:00"
  ],
  "timezone": "America/New_York"
}

Request Example Body

{
  "label": "Daily mysteries",
  "preset_id": "mystery",
  "cadence_per_day": 1,
  "slots": [
    "18:00"
  ],
  "timezone": "America/New_York",
  "topic_source": "ai-auto"
}
PATCH /faceless-reels/subscriptions/{id}
reels:write

Update a reel subscription

Updates a faceless channel. Accepts every field the create endpoint does — including the channel identity (avatar_url, tagline, description, niche, format, episode_defaults). Changing cadence/slots/timezone recomputes the schedule; enabled:false pauses it without deleting it.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Parameters

id path required

Subscription id.

Body Fields

No body fields for this endpoint.

curl Example

curl https://api.genfire.ai/v1/faceless-reels/subscriptions/{id} \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "enabled": false
}'

Response Example

{
  "object": "reel_subscription",
  "id": "sub_abc123",
  "enabled": false
}

Request Example Body

{
  "enabled": false
}
DELETE /faceless-reels/subscriptions/{id}
reels:write

Delete a reel subscription

Deletes a reel subscription. Already-generated reels are unaffected.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Parameters

id path required

Subscription id.

Body Fields

No body fields for this endpoint.

curl Example

curl https://api.genfire.ai/v1/faceless-reels/subscriptions/{id} \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "object": "reel_subscription",
  "id": "sub_abc123",
  "deleted": true
}
POST /faceless-reels/subscriptions/{id}/estimate-episode
reels:read

Quote one channel episode

Resolves an episode against the channel and returns the PLAN plus a credit estimate, without generating anything. The plan is what will actually be made: which engine won (a `longform` channel, a 16:9 aspect_ratio, or a custom_script all force the explainer), the clamped duration, and the style, voice and reference images that applied. Quote before POST /episodes and confirm the spend.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Parameters

id path required

Channel id.

Body Fields

topic string optional

Episode title or subject.

aspect_ratio string optional

"16:9" | "9:16". Overrides the channel default; 16:9 forces the explainer engine.

target_duration_sec number optional

Explainer 20-600, reel 10-120. Clamped to the winning engine.

motion_style string optional

"seamless" | "scenes" | "stills".

curl Example

curl https://api.genfire.ai/v1/faceless-reels/subscriptions/{id}/estimate-episode \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "topic": "How Carthage fell",
  "aspect_ratio": "16:9",
  "target_duration_sec": 300,
  "motion_style": "seamless"
}'

Response Example

{
  "object": "episode_estimate",
  "plan": {
    "engine": "explainer",
    "aspect_ratio": "16:9",
    "target_duration_sec": 300,
    "motion_style": "seamless",
    "style_id": "pixel-art",
    "voice_id": "onwK4e9ZLuTAKqWW03F9",
    "caption_preset_id": "none",
    "reference_images": []
  },
  "estimate": {
    "total": 812
  }
}

Request Example Body

{
  "topic": "How Carthage fell",
  "aspect_ratio": "16:9",
  "target_duration_sec": 300,
  "motion_style": "seamless"
}
GET /faceless-reels/subscriptions/{id}/episodes
reels:read

List a channel’s episodes

Episodes filed under this channel, newest first — reels AND long-form explainer episodes, whichever engine produced them.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Parameters

id path required

Channel id.

limit query optional

1-100, default 30.

Body Fields

No body fields for this endpoint.

curl Example

curl https://api.genfire.ai/v1/faceless-reels/subscriptions/{id}/episodes \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "object": "list",
  "data": [
    {
      "id": "reel_9x1",
      "object": "episode",
      "topic": "How Carthage fell",
      "status": "completed",
      "kind": "explainer",
      "aspect_ratio": "16:9",
      "video_url": "https://storage.googleapis.com/genfire/episodes/9x1.mp4",
      "thumbnail_url": null,
      "created_at": "2026-08-27T09:00:00.000Z"
    }
  ]
}
POST /faceless-reels/subscriptions/{id}/episodes
reels:write

Produce one channel episode

Produces ONE episode of a channel with per-episode overrides — the editorial call, as opposed to run-now which fires the channel’s next episode on its own settings. The channel’s `format` picks the engine (shorts → 9:16 faceless reel, longform → 16:9 explainer) and the episode inherits the channel’s creative lock (style, voice, standing direction, recurring cast, captions, music) unless overridden here. Async and billable — quote with estimate-episode first. Returns 409 if the same title is already generating on this channel.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Required

Parameters

id path required

Channel id.

Body Fields

topic string required

Episode title or subject.

aspect_ratio string optional

"16:9" | "9:16".

target_duration_sec number optional

Explainer 20-600, reel 10-120.

motion_style string optional

"seamless" chains each beat off the last frame within a sequence; "scenes" is one shot per beat; "stills" is no motion.

style_id string optional

Override the channel style for this episode.

voice_id string optional

Override the channel narrator for this episode.

reference_images array optional

[{ url, label }] up to 8 — added on top of the channel’s recurring cast.

custom_script string optional

Your own narration instead of the writer’s. Forces the explainer engine and sets the runtime.

custom_style_prompt string optional

Describe the look instead of picking a style_id.

style_anchor_url string optional

An image that becomes frame 0 (the style anchor). Not a reference image.

captions_on boolean optional

Burn captions. Default: on for shorts, off for long-form.

music object optional

{ source: none|preset|ai|library, preset_id?, prompt?, track_id? }.

engine string optional

"reel" | "explainer" — force the engine instead of deriving it.

curl Example

curl https://api.genfire.ai/v1/faceless-reels/subscriptions/{id}/episodes \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Idempotency-Key: unique_request_key" \
  -H "Content-Type: application/json" \
  -d '{
  "topic": "How Carthage fell",
  "aspect_ratio": "16:9",
  "target_duration_sec": 300,
  "motion_style": "seamless"
}'

Response Example

{
  "id": "run_8f3c4a2b1d6e7f9a0b1c2d3e",
  "object": "run",
  "status": "processing",
  "capability": "explainer_generation"
}

Request Example Body

{
  "topic": "How Carthage fell",
  "aspect_ratio": "16:9",
  "target_duration_sec": 300,
  "motion_style": "seamless"
}
POST /faceless-reels/subscriptions/{id}/run-now
reels:write

Generate a reel now for a subscription

Manually triggers one reel for a subscription right now (async run), using the subscription’s settings. Returns 409 if a reel is already generating for that subscription.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Required

Parameters

id path required

Subscription id.

Body Fields

topic string optional

Optional topic override for this run; otherwise resolved from the subscription.

curl Example

curl https://api.genfire.ai/v1/faceless-reels/subscriptions/{id}/run-now \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Idempotency-Key: unique_request_key" \
  -H "Content-Type: application/json" \
  -d '{
  "topic": "The vanishing of Flight 19"
}'

Response Example

{
  "id": "run_8f3c4a2b1d6e7f9a0b1c2d3e",
  "object": "run",
  "status": "processing",
  "capability": "faceless_reel_generation",
  "endpoint": "faceless_reels.subscriptions.run_now",
  "model": "reel.faceless",
  "resource_id": "reel_abc123",
  "created_at": "2026-06-08T12:00:00.000Z"
}

Request Example Body

{
  "topic": "The vanishing of Flight 19"
}

Notes

  • Poll `GET /v1/runs/{runId}` for the finished video, same as one-off generation.

Reference

Scheduled Tasks

GET /tasks
tasks:read

List scheduled tasks

Lists the account owner’s scheduled tasks — standing briefs Genfire’s agent runs on its own cadence, headlessly, filing each result for review.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Body Fields

No body fields for this endpoint.

curl Example

curl https://api.genfire.ai/v1/tasks \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "object": "list",
  "data": [
    {
      "object": "scheduled_task",
      "id": "task_abc123",
      "title": "Daily affiliate report",
      "cadence": "daily",
      "active": true,
      "next_run_at": "2026-08-27T19:40:00.000Z",
      "max_credits_per_run": 100,
      "auto_approve": false,
      "delivery": {
        "email": true,
        "slack": false
      }
    }
  ]
}
POST /tasks
tasks:write

Create a scheduled task

Schedules a brief the agent runs automatically. Creating one is free; each RUN spends credits, capped by max_credits_per_run. The brief must be self-contained — a scheduled run has no conversation to read. Give the start time either as `time` + `timezone` (a local wall clock) or `first_run_at` (an exact instant); an unreadable value is a 400 rather than a silent default, because a report firing at the wrong hour every day is worse than one that refused to be created.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Body Fields

prompt string required

The full standing brief the run executes.

title string optional

Short name for the schedule list.

cadence string optional

once | daily | weekly | monthly.

Default: daily

time string optional

Local start on a 24-HOUR clock, "HH:mm" — 3:40pm is "15:40". Requires timezone.

timezone string optional

IANA zone for `time`, e.g. "America/New_York".

first_run_at string optional

Alternative to time+timezone: an ISO 8601 instant with offset. Must be in the future.

max_credits_per_run integer optional

Credit ceiling ONE run may spend (1-2000).

Default: 100

auto_approve boolean optional

Autopilot — runs publish within budget instead of waiting for the owner’s sign-off.

Default: false

persona_id string optional

AI Employee to run the task as.

delivery object optional

{ email, slack } — where a finished run reports. Both default false.

curl Example

curl https://api.genfire.ai/v1/tasks \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "object": "scheduled_task",
  "id": "task_abc123",
  "title": "Daily affiliate report",
  "cadence": "daily",
  "active": true,
  "next_run_at": "2026-08-27T19:40:00.000Z",
  "runs_at": "3:40pm America/New_York"
}
PATCH /tasks/{id}
tasks:write

Pause, resume or re-route a scheduled task

Pausing (active:false) is the reversible way to stop a task. A `delivery` patch merges onto the stored channels, so naming one does not switch the other off. The brief, cadence and start time are not editable — delete and recreate to change those.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Body Fields

active boolean optional

false pauses, true resumes (also clears an automatic failure pause).

delivery object optional

{ email, slack } — only the channels you name change.

curl Example

curl https://api.genfire.ai/v1/tasks/{id} \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "object": "scheduled_task",
  "id": "task_abc123",
  "active": false
}
DELETE /tasks/{id}
tasks:write

Delete a scheduled task

Permanently deletes the task. Not reversible — to stop it temporarily, PATCH active:false instead. Runs it already produced are unaffected.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Body Fields

No body fields for this endpoint.

curl Example

curl https://api.genfire.ai/v1/tasks/{id} \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "object": "scheduled_task",
  "id": "task_abc123",
  "deleted": true
}

Reference

Explainers

POST /explainers/generations
reels:write

Generate an explainer video

Generates a long-form narrated explainer/documentary (20s–10min, 16:9 or 9:16): script → expressive voiceover → style-locked frames → Gemini Omni Flash video clips per scene → composed film with optional captions. Pass a structured `script` to author the ENTIRE creative contract with your own model (agents: write the beats yourself — narration, shot-specs, motion notes, render modes, reference routing, emphasis words, recurring cast) and Genfire only renders; or pass just `topic` and Genfire writes the script. Async — returns a run in `processing`; poll `GET /v1/runs/{runId}`.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Required

Body Fields

topic string required

What the explainer is about. Also used as the video title. Required even with a `script` (labels the run + video).

script object optional

Structured agent-authored script: { cast?: [{ name, description }] (≤3, UPPERCASE names, one fixed visual identity each), beats: [{ narration (spoken words, may carry ElevenLabs v3 [audio tags]), visual (concrete storyboard shot-spec with quoted on-screen labels), motion? (camera/animation director note), render? ("anchored"|"direct"), continues? (bool — continue previous shot via last-frame chaining; prefer true on most beats so the film flows as continuous footage, breaking only at deliberate scene changes; never where a cast member enters/returns — their introduction needs an anchored shot), refs? ([1-based reference_images indices]), emphasis? (≤3 verbatim narration substrings for keyword captions), cast? ([declared names]) }] (3–100 beats). Bypasses EVERY internal LLM call; narration length sets the duration (target_duration_sec is ignored). Validation errors return 400 `invalid_script` with the exact fix.

custom_script string optional

Plain word-for-word narration (no beat structure). Genfire still storyboards the visuals for you. Ignored when `script` is present.

allow_duplicate boolean optional

Authored scripts (`script` / `custom_script`) that re-tell an episode this account already rendered are refused with 409 duplicate_script (the match is named). Pass true to render anyway.

Default: false

style_id string optional

Visual style preset from `GET /v1/explainers/styles` (41 looks: pixel-art, claymation, whiteboard-doodle…). Defaults to a 2D-illustration look.

aspect_ratio string optional

"16:9" (default) or "9:16".

Default: 16:9

target_duration_sec number optional

Target runtime in seconds (20–600). Ignored when `script` is present — the narration length sets the duration.

Default: 60

voice_id string optional

Narration voice id (ElevenLabs; renders on eleven_v3 with expressive [audio tags]). Defaults to a documentary narrator.

motion_level string optional

How many scenes render as real omni video clips: "full" (every scene, default) | "mixed" (every 5th) | "stills" (Ken-Burns only, cheapest). Draft-run lever for agents.

Default: full

continuity string optional

How animated scenes join: "seamless" (default — each clip seeds from the previous clip's last frame; continuous footage) | "cuts" (every scene is its own shot, hard cuts — "scene by scene"). Stills ignore it.

Default: seamless

music object optional

Background music bed: { source: "none"|"preset"|"ai"|"library", preset_id?, prompt?, track_id? }.

caption_preset_id string optional

Captions are OPT-IN — omit for none. Any caption preset id from `GET /v1/faceless-reels/caption-presets` enables burned captions.

Default: none

caption_position string optional

Vertical caption placement: "top" | "middle" | "bottom" (default when captions are on).

caption_mode string optional

"full" burns the transcript; "keywords" pops only each beat's emphasis words at their spoken timestamps.

Default: full

caption_animation string optional

Override the caption animation (highlight | pop | typewriter | classic | background).

reference_images array optional

Up to 8 { url (https), label? (≤60 chars) } — products/characters/brands that must appear. Beats reference them via `refs` (1-based); those scenes render via omni reference-to-video. Put `refs: [1]` on the FIRST beat — the opening frame is generated as an image EDIT from the refs, locking the subject's real identity into the style anchor every later scene inherits.

curl Example

curl https://api.genfire.ai/v1/explainers/generations \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Idempotency-Key: unique_request_key" \
  -H "Content-Type: application/json" \
  -d '{
  "topic": "How quantum computers actually work",
  "script": {
    "cast": [
      {
        "name": "QUBIT",
        "description": "a glowing translucent blue sphere with orbiting light rings, softly pulsing"
      }
    ],
    "beats": [
      {
        "narration": "Your laptop thinks in bits — tiny switches that are either on, or off.",
        "visual": "Clean diagram: a row of light switches on a circuit board, each labeled \"0\" or \"1\", one flipping",
        "motion": "Slow push-in as one switch flips",
        "emphasis": [
          "bits"
        ]
      },
      {
        "narration": "[curious] A quantum computer thinks in qubits — and a qubit can be both at once.",
        "visual": "QUBIT hovering between two glowing labels \"0\" and \"1\", overlapping into a blended glow labeled \"BOTH\"",
        "motion": "QUBIT drifts between the labels, rings spinning up",
        "cast": [
          "QUBIT"
        ],
        "emphasis": [
          "qubits",
          "both at once"
        ]
      },
      {
        "narration": "That superposition lets it explore millions of answers at the same time.",
        "visual": "Wide shot: QUBIT at the center of a branching tree of thousands of faint answer-paths lighting up simultaneously, label \"1,000,000 paths\"",
        "motion": "Camera pulls back as the tree ignites outward",
        "cast": [
          "QUBIT"
        ],
        "emphasis": [
          "superposition"
        ]
      }
    ]
  },
  "aspect_ratio": "16:9",
  "style_id": "2d-illustrator",
  "caption_preset_id": "minimal",
  "caption_mode": "keywords"
}'

Response Example

{
  "id": "run_8f3c4a2b1d6e7f9a0b1c2d3e",
  "object": "run",
  "status": "processing",
  "capability": "explainer_generation",
  "endpoint": "explainers.generations.create",
  "model": "explainer.omni",
  "resource_id": "reel_abc123",
  "created_at": "2026-07-06T12:00:00.000Z"
}

Request Example Body

{
  "topic": "How quantum computers actually work",
  "script": {
    "cast": [
      {
        "name": "QUBIT",
        "description": "a glowing translucent blue sphere with orbiting light rings, softly pulsing"
      }
    ],
    "beats": [
      {
        "narration": "Your laptop thinks in bits — tiny switches that are either on, or off.",
        "visual": "Clean diagram: a row of light switches on a circuit board, each labeled \"0\" or \"1\", one flipping",
        "motion": "Slow push-in as one switch flips",
        "emphasis": [
          "bits"
        ]
      },
      {
        "narration": "[curious] A quantum computer thinks in qubits — and a qubit can be both at once.",
        "visual": "QUBIT hovering between two glowing labels \"0\" and \"1\", overlapping into a blended glow labeled \"BOTH\"",
        "motion": "QUBIT drifts between the labels, rings spinning up",
        "cast": [
          "QUBIT"
        ],
        "emphasis": [
          "qubits",
          "both at once"
        ]
      },
      {
        "narration": "That superposition lets it explore millions of answers at the same time.",
        "visual": "Wide shot: QUBIT at the center of a branching tree of thousands of faint answer-paths lighting up simultaneously, label \"1,000,000 paths\"",
        "motion": "Camera pulls back as the tree ignites outward",
        "cast": [
          "QUBIT"
        ],
        "emphasis": [
          "superposition"
        ]
      }
    ]
  },
  "aspect_ratio": "16:9",
  "style_id": "2d-illustrator",
  "caption_preset_id": "minimal",
  "caption_mode": "keywords"
}

Notes

  • Explainers render in minutes to tens of minutes (a 10-minute film ≈ 30 min). Poll `GET /v1/runs/{runId}` — in-flight runs carry a `progress` stage card; completed output is `{ reel_id, video_url, script, scenes: [{ index, video_url, poster_url, prompt, narration, duration_sec, animated }], duration_seconds }` (per-scene clips included).
  • Cost scales with duration — call `POST /v1/explainers/estimate-cost` first (same body; with a `script` the quote derives from the narration length).
  • Structured-script authoring rules: `emphasis` phrases must quote the beat's spoken narration VERBATIM; `refs` must point at supplied reference_images; `cast` names must be declared in script.cast; a beat's visual is a concrete storyboard shot (subjects + composition + quoted on-screen text), never a metaphor.
  • The same `Idempotency-Key` returns the same run instead of generating (and billing) twice.
POST /explainers/estimate-cost
reels:read

Estimate explainer credit cost

Returns a per-config credit breakdown (frames + voiceover + music + video clips) for a prospective explainer, without generating anything. Accepts the same body as generate; with a `script` the duration derives from the narration length.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Body Fields

target_duration_sec number optional

Target runtime in seconds (20–600). Ignored when `script` is present.

script object optional

Structured script (same shape as generate) — the quote derives from its narration length.

motion_level string optional

"full" | "mixed" | "stills" — how many scenes render as real video clips (the dominant cost lever).

Default: full

music object optional

Music config; only `source: "ai"` adds a music fee.

voice_id string optional

Narration voice (a Seed Audio preset switches the TTS credit key).

aspect_ratio string optional

"16:9" | "9:16" (no cost impact today; accepted for parity).

curl Example

curl https://api.genfire.ai/v1/explainers/estimate-cost \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "target_duration_sec": 120,
  "motion_level": "full",
  "music": {
    "source": "preset"
  }
}'

Response Example

{
  "object": "explainer_cost_estimate",
  "effective_duration_sec": 120,
  "images": 42,
  "voiceover": 18,
  "music": 0,
  "videoClips": 220,
  "total": 280,
  "sceneCount": 20,
  "animatedScenes": 20
}

Request Example Body

{
  "target_duration_sec": 120,
  "motion_level": "full",
  "music": {
    "source": "preset"
  }
}
GET /explainers/styles
reels:read

List explainer visual styles

Lists the explainer visual style presets that can be passed as `style_id`.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Body Fields

No body fields for this endpoint.

curl Example

curl https://api.genfire.ai/v1/explainers/styles \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "object": "list",
  "data": [
    {
      "id": "pixel-art",
      "label": "Pixel Art"
    },
    {
      "id": "claymation",
      "label": "Claymation"
    }
  ]
}

Reference

Music Videos

POST /music-videos/generations
reels:write

Generate a music video

Produces an auto-directed AI music video (9:16 or 16:9) from a song: song → beat/section analysis → style-locked anchor frame → per-scene Gemini Omni Flash video clips cut to the music → composed video with optional karaoke lyric captions. Bring your own track via `song_url` (with optional lyrics/sections/word timestamps), or pass an inline `song` prompt and Genfire generates the track first (ElevenLabs music_v2, billed as its own step). Async — returns a run in `processing`; poll `GET /v1/runs/{runId}`.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Required

Body Fields

concept string required

The creative concept / narrative direction for the video (e.g. "a lonely astronaut drifting through neon ruins, longing for home"). Steers the shot-list and styling.

song_url string optional

https URL of the song to score the video to. Provide THIS or an inline `song` (not both). Optionally pair with `song_title`, `song_lyrics`, `song_sections`, `song_word_timestamps`.

song object optional

Inline song generation (instead of `song_url`): { prompt (what the track should sound like), duration_ms (10000–600000), instrumental? }. Genfire generates the track first via ElevenLabs music_v2 with word timestamps, bills it separately, then produces the video.

song_title string optional

Title for a bring-your-own `song_url` track (labels the output). Ignored with an inline `song`.

song_lyrics string optional

Full lyrics for a bring-your-own track — improves lyric-aware pacing and captions.

song_sections array optional

Optional pre-computed sections for a bring-your-own track: [{ label, start_sec, end_sec }]. Skips section analysis.

song_word_timestamps array optional

Optional word timings for karaoke captions on a bring-your-own track: [{ word, start_sec, end_sec }].

transcribe_lyrics boolean optional

For a bring-your-own `song_url` only: transcribe the track to derive lyrics + word timestamps (unlocks lyric_captions and lyric-aware scenes). Runs as its own step, billed per second (Whisper). No-op when `song_word_timestamps` were supplied or an inline `song` is used (those get timings natively); an instrumental track proceeds without lyrics. Default false.

Default: false

style_preset_id string required

Visual style preset id from `GET /v1/music-videos/styles` (cinematic-performance, anime, neon-city…).

aspect_ratio string optional

"9:16" (default) or "16:9".

Default: 9:16

scene_density string optional

How many scenes the song is cut into: "low" (~10s/scene) | "medium" (~7s) | "high" (~5s). More scenes = more clips = higher cost.

Default: medium

lyric_captions boolean optional

Burn karaoke-style lyric captions (uses word timestamps from the song). Default false.

Default: false

reference_images array optional

Up to 8 { url (https), label? (≤60 chars) } — characters/products/looks that should appear and anchor the style.

curl Example

curl https://api.genfire.ai/v1/music-videos/generations \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Idempotency-Key: unique_request_key" \
  -H "Content-Type: application/json" \
  -d '{
  "concept": "a lonely astronaut drifting through neon-lit ruins, longing for home",
  "song": {
    "prompt": "melancholic synthwave, slow build, emotional female vocal",
    "duration_ms": 90000
  },
  "style_preset_id": "neon-city",
  "aspect_ratio": "9:16",
  "scene_density": "medium",
  "lyric_captions": true
}'

Response Example

{
  "id": "run_9a2b3c4d5e6f7a8b9c0d1e2f",
  "object": "run",
  "status": "processing",
  "capability": "music_video_generation",
  "endpoint": "music_videos.generations.create",
  "model": "music-video.omni",
  "resource_id": "reel_abc123",
  "created_at": "2026-07-21T12:00:00.000Z"
}

Request Example Body

{
  "concept": "a lonely astronaut drifting through neon-lit ruins, longing for home",
  "song": {
    "prompt": "melancholic synthwave, slow build, emotional female vocal",
    "duration_ms": 90000
  },
  "style_preset_id": "neon-city",
  "aspect_ratio": "9:16",
  "scene_density": "medium",
  "lyric_captions": true
}

Notes

  • Music videos render in minutes to tens of minutes. Poll `GET /v1/runs/{runId}` — in-flight runs carry a `progress` stage card; completed output is `{ reel_id, video_url, script, scenes, duration_seconds }`.
  • Pass EXACTLY ONE of `song_url` or inline `song`. With an inline `song`, the track is generated and billed BEFORE the video-production stage (a separate ElevenLabs music_v2 charge). The song duration is always probed server-side and capped (default 300s).
  • Cost scales with song length and scene_density — call `POST /v1/music-videos/estimate-cost` first (that quote covers the video-production stage only, not the song).
  • The same `Idempotency-Key` returns the same run instead of generating (and billing) twice.
POST /music-videos/estimate-cost
reels:read

Estimate music-video credit cost

Returns a per-config credit breakdown (style anchor frame + per-scene AI clips) for the VIDEO-PRODUCTION stage of a prospective music video, without generating anything. The song's own cost is not included (the song is produced/uploaded before this stage as its own billed step).

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Body Fields

song_duration_sec number required

Length of the song in seconds (the dominant driver of scene count).

aspect_ratio string optional

"9:16" (default) or "16:9".

Default: 9:16

scene_density string optional

"low" | "medium" | "high" — scenes per second of song (the main cost lever).

Default: medium

lyric_captions boolean optional

Whether karaoke lyric captions are burned in (no material cost impact today; accepted for parity).

Default: false

curl Example

curl https://api.genfire.ai/v1/music-videos/estimate-cost \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "song_duration_sec": 90,
  "aspect_ratio": "9:16",
  "scene_density": "medium"
}'

Response Example

{
  "object": "music_video_cost_estimate",
  "totalCredits": 220,
  "sceneCount": 13,
  "breakdown": [
    {
      "label": "Style anchor image (1× gpt-image-2)",
      "credits": 20
    },
    {
      "label": "AI clips (9 of 13 scenes; ~30% chorus-reuse assumed for songs over 90s, 7s each)",
      "credits": 200
    }
  ]
}

Request Example Body

{
  "song_duration_sec": 90,
  "aspect_ratio": "9:16",
  "scene_density": "medium"
}
GET /music-videos/styles
reels:read

List music-video visual styles

Lists the music-video visual style presets that can be passed as `style_preset_id`.

Auth: Bearer API key or OAuth access token
Idempotency-Key: Not required

Body Fields

No body fields for this endpoint.

curl Example

curl https://api.genfire.ai/v1/music-videos/styles \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "object": "list",
  "data": [
    {
      "id": "cinematic-performance",
      "name": "Cinematic Performance",
      "description": "Filmic, anamorphic performance footage — moody key light, shallow depth of field, real-camera energy."
    },
    {
      "id": "anime",
      "name": "Anime",
      "description": "Vibrant modern anime — expressive characters, dynamic skies, sakuga-grade motion."
    }
  ]
}
Copied to clipboard