Skip to main content
POST

Overview

Cinematic Studio writes a short film from a brief. Hooked turns the brief into a storyboard (scenes, cast and dialogue), draws a portrait of each character, draws a start frame for each scene, films every scene with the video model you pick (the characters speak with the model’s own audio), then adds subtitles and music and renders the video. It is the same pipeline as Automatic mode in the dashboard’s Cinematic Studio. Send storyBrief, durationSeconds (10 to 120) and model. Everything else is optional: storyTone, presetId (the visual style), imageModel, characterIds (your characters, from List Characters), preserveExactStoryText, aspectRatio, language (en or es), musicId, name, webhook and metadata.
The request answers in a few seconds with a projectId and status processing. The storyboard, the portraits, the scenes, the final cut and the render all happen after that. What can be refused up front (an invalid body, a brief about a real person, missing keys, too few credits for the whole run) is still answered with a 400, 402 or 404 and nothing is created. If a later step fails, the project becomes failed with the reason in message and your webhook gets the failure.

More request bodies

To cast characters you saved in the dashboard (Studio → Characters), get their ids with List Characters (GET /v1/character/list), add "characterIds": ["<characterId>"] (up to 6) and mention them in the brief as @Name. They keep their look, voice and photos; a character without a photo gets a portrait drawn like any other.

Options

Every value these fields accept is listed by Get Catalog with name=cinematic (one item per field, with each model’s durations, resolutions and aspect ratios), read from the same lists this endpoint validates against. Seedance models can’t film the photorealistic styles (realistic, cinematic): their face filter refuses realistic people, so that pair answers 400. Pick another model or style. In GET /v1/catalog/cinematic, the presetId item lists those styles with the models each one refuses (excludedModels).

What happens next

  1. During the request: the body is checked, the whole run is priced and the brief is checked (no real, identifiable or famous people, no minors). The project is created with status processing and the request answers.
  2. In the background: the storyboard is written and a portrait is drawn for each character; then a start frame is drawn for each scene, one after the other; then every scene is filmed, the subtitles and the music are added and the video is rendered. While the storyboard is being written, the project is processing with no scenes and no video yet.
  3. Follow the project with GET /v1/project/{projectId} until video.status is COMPLETED (or the project status is failed), or wait for your webhook.
The webhook is called once when the video is ready ("status": "COMPLETED" with data.url), or once if the project fails ("status": "FAILED", videoId: null). See Webhooks for every payload.

Credits and your own keys

Teams on Hooked’s keys (managed):
  • Checked up front. Before anything is paid, the whole run is priced: a portrait for each library character without a photo, plus one start frame and one clip for each 6 seconds of durationSeconds (filmed at 1080p, the same estimate the dashboard shows). If the balance does not cover it, the request answers 402 INSUFFICIENT_CREDITS with creditsNeeded and creditsAvailable, and nothing is created or charged. Once the storyboard is written (in the background), the run is priced again with its real scenes and characters; if the balance no longer covers it, the project becomes failed (“Not enough credits…” in message) before anything is charged, and your webhook gets the failure.
  • Charged in stages, as each one starts: the portraits once the storyboard is written, the scene start frames right after them, the clips once every frame is ready, and the subtitles once every clip is done (if the balance can’t cover the subtitles then, the video completes without them).
  • Refunds on failure. A portrait, start frame or clip that fails is refunded, and so is every frame or clip that was paid for but never started when the run stops. A portrait that was drawn is a delivered asset: it stays in your media library and is not refunded, even if the video fails later (for example, when the scene frames can’t be paid for or queued). Once the frames have started, what was already made (frames, finished clips) stays in your media library and is not refunded.
  • On the project. usedCredits in Get Project is what the run has cost so far: every stage charged, minus what was refunded. It grows as the stages start. On a failed project it is what you kept paying for (the portraits that were drawn).
Teams on their own keys (BYOK): no credits are charged. The team needs OpenRouter in Settings → AI keys (story, portraits, frames and clips), and Gemini when model is gemini_omni_flash. A missing key answers 402 missing_credentials with the list in missingProviders, before anything is created.

Errors

Send an Idempotency-Key header to retry safely: if a request times out or answers 5xx, sending it again with the same key and body returns the first answer instead of creating (and charging) the project twice.

Writing a brief

Say what happens, who is in it and the mood: “A lighthouse keeper finds a message in a bottle during a storm and decides to answer it” gives the storyboard a character, a place and a turn. Write the dialogue in quotes and set preserveExactStoryText: true to keep it word for word. Briefs about real, identifiable or famous people are refused; use original characters.

Next Steps

Get Project

Follow the project until the video is ready

Webhooks

Payloads and delivery rules

Cinematic example

A full request, from brief to video

List Music

Pick a background track

Authorizations

x-api-key
string
header
required

Headers

Idempotency-Key
string

Makes the request safe to retry. 1-255 printable ASCII characters, one per operation (your job id, or a UUID you store), reused on every retry. Within 24 hours the same key with the same body answers with the first response and the header Idempotent-Replayed: true, without running or charging again. Keys are scoped to your team and the endpoint. 5xx answers and refusals before anything ran (401, 402, 403, 409, 429) are not kept. See Idempotency.

Required string length: 1 - 255
Pattern: ^[\x20-\x7E]+$

Body

application/json
storyBrief
string
required

What the film is about (1–4,000 characters): the story, who is in it, the mood. Mention a library character with @Name. A brief that recreates a real, identifiable or famous person (or a minor) answers 400.

Required string length: 1 - 4000
durationSeconds
integer
required

Target length in seconds (10–120). The storyboard picks the real scene count; credits are checked up front for one 6-second scene per 6 seconds.

Required range: 10 <= x <= 120
model
enum<string>
required

Video model that films every scene, with its own audio (the cast speaks). Seedance models can't film the photorealistic styles (realistic, cinematic): that pair answers 400. gemini_omni_flash runs on Gemini.

Available options:
veo_3_fast,
veo_3,
gemini_omni_flash,
grok_imagine_video,
kling_3_0,
seedance_2_0,
seedance_2_0_fast,
veo_3_1_lite,
seedance_2_0_mini
storyTone
enum<string>
default:drama

Genre and pacing of the story. Default: drama.

Available options:
drama,
comedy,
action,
romance,
thriller,
documentary,
music_video,
fantasy,
anime
presetId
enum<string>
default:realistic

Visual style of every scene and of the cast portraits: one of the style ids (realistic, cinematic, anime, pixar, ghibli-studio…, the same list as presetSettings.preset in Script to Video), or custom-<id> for one of your team's custom styles. Default: realistic. An unknown id answers 400 (presetId: Invalid preset "…". Allowed values are: …).

Available options:
realistic,
cinematic,
anime,
real-anime,
retro-anime,
cyberpunk-anime,
ghibli-studio,
pixar,
cartoon,
comic-book,
claymation,
fantasy,
80s-fantasy-movie,
creative,
art-style,
sketch-black-and-white,
sketch-color,
japanese-ink,
ink-style,
haunted-linework,
neon-futuristic,
pixel-art,
collage,
lego,
technical-blueprints,
stickman,
nursery-rhyme,
south-park,
skeleton-3d,
fruit-people,
talking-fruit,
talking-objects,
talking-organs,
minecraft,
gta-v,
free-fire,
fortnite,
roblox,
pubg,
bitlife,
space-marines-40k,
bombardiro-crocodilo,
tralalero-tralala,
demon-slayer,
dragon-ball,
one-piece,
pokemon,
naruto,
attack-on-titan,
final-fantasy,
mecha-break,
alien-stage,
marvel,
dc,
star-wars,
star-trek,
harry-potter,
lord-of-the-rings,
game-of-thrones,
doctor-who,
sherlock-holmes,
stranger-things,
squid-game,
wednesday,
zelda,
genshin-impact,
dungeons-and-dragons,
rick-and-morty,
amazing-digital-circus
imageModel
enum<string>
default:gpt_image_2

Image model that draws each scene's start frame. Default: gpt_image_2.

Available options:
gpt_image_2,
nano_banana_pro,
nano_banana_2,
nano_banana,
grok_imagine_image,
seedream_5_0,
seedream_4_5
characterIds
string[]

Up to 6 characters saved in your team's dashboard (Studio → Characters) to cast: their look, voice and photos are kept; mention them in the brief as @Name. Without it the storyboard invents the cast. An id that is not your team's answers 400 (characterIds: Character "…" not found.).

Maximum array length: 6
preserveExactStoryText
boolean
default:false

Keep the brief's own dialogue and narration word for word instead of rewriting it.

aspectRatio
enum<string>
default:ratio_16_9

Default: horizontal. ratio_1_1 only with Kling and Seedance; a ratio the model does not film answers 400.

Available options:
ratio_16_9,
ratio_9_16,
ratio_1_1
language
enum<string>
default:en

Language the story and its dialogue are written in.

Available options:
en,
es
musicId
string

Background music under the whole film: a track from /v1/music/list or your team's own uploaded music. No music when omitted. An ID that is neither answers 400 (musicId: Music "<id>" not found.).

Maximum string length: 30
name
string

Project name (max 100 characters). The storyboard's title when omitted.

Maximum string length: 100
webhook
string<uri>

HTTPS URL on a public host, called when the video is ready or the project fails (max 500 characters). Requests are signed: verify the Hooked-Signature header (HMAC-SHA256 of ".") with the signing secret from Settings → Webhooks; Hooked-Event and Hooked-Delivery headers name the event and the delivery. No redirects are followed; 10 s timeout; 3 immediate attempts. See the Webhooks guide for the payload.

Maximum string length: 500
metadata
object

Any JSON object of your own (max 5 KB). Stored on the project and sent back in the webhook payload. The key automationId is reserved for dashboard automations and is removed.

Response

Project created. Follow it with GET /v1/project/{projectId} or wait for the webhook.

success
enum<boolean>
required
Available options:
true
data
object
required
message
string
required