rows, one object per video (up to 20,000 per request). For a single video, pass a rows list with one item.
Use it for a single generation triggered by a user action in your own app, or with a list of people or items — customers, leads, students — to generate one personalized video per row, all from the same template.
Why rows, not a CSV
Generation takes rows — a JSON array of objects — directly in the request body. There’s no CSV to format and no file to host anywhere first: if your data already lives in a database, spreadsheet export, or CRM, you serialize it straight into the request.
Correlating results back to your own data
Add anexternal_id to any row — your own identifier (a user ID, order ID, anything) — and it comes back unchanged in the CSV export once the batch is done, or immediately via Get single video status while it’s still processing. This is the reliable way to match a result to the input that produced it, since it doesn’t depend on remembering the original order you sent rows in:
external_id is a reserved key — it’s stripped out before the rest of the row is used to fill in the template’s variables, so it never conflicts with a variable of the same name.
Submitting a batch
Response
The template’s scenes are snapshotted at submission time — the whole batch renders consistently against that snapshot even if the template is edited in the editor while the batch is still processing.
Tracking progress
Response — while processing
summary is the headline most integrations poll for while a batch is still running. This endpoint doesn’t return per-row detail — to check on a specific row before the batch finishes, use Get single video status.
Once status is done, csv_ready flips to true — at that point, download every row in one file via Download CSV export:
Cost
A batch coststemplate.estimated_credits × row_count, deducted upfront when the batch is accepted. If the workspace doesn’t have enough balance, the whole batch is rejected with 402 before anything is created — no partial batches.