Send the text itself. You do not need to upload anything first, create a
project first, or find an id for your lesson in some catalogue.
story is the
input.The call
story carries up to 40,000 characters — a long
lecture fits comfortably. Everything else is optional:
Collect the file
status: "queued" is acceptance, not completion. Rendering takes minutes. Poll:
job.artifacts.video is your video. Fetch it directly — it points at the
origin holding the bytes, not back through this API, which is why a multi-gigabyte
render downloads at the origin’s speed rather than a gateway’s. Captions come
with it, as both SubRip and WebVTT.
Branch on status, never on phase: status is a closed set, phase is the
pipeline’s own stage word and changes between releases. done and failed are
the terminal ones. Polling every 15–30 seconds is plenty.
Cut shorts from it
Once the render isdone, its job id is the input to the derivative pass:
projectId files the render and its clips in one container you
can read back with a single GET /v1/projects/{projectId}.
If the document is not written yet
video.render narrates prose you already have. When you have a subject rather
than a manuscript, write it first and render the result:
Text capabilities
text.research for a brief, text.paraphrase to restyle something long,
text.script when you are working from a seed video.Jobs & polling
The full status table, and why
awaiting_review never advances on its own.Retrying without paying twice
TheIdempotency-Key above is not decoration on a 300-credit call. A retry with
the same key and the same body replays the stored response instead of starting a
second render, so a client timeout cannot become two charges. The same key with a
different body answers 409 conflict rather than a wrong result.
A render that fails after being accepted is refunded against the key it was
billed under. You are never charged for a video that does not exist.