Skip to main content

Bulk Rendering

Bulk rendering submits one template + many variable sets in a single request — Zvid fans it out into individual render jobs, each with its own credits, status, and output. It's the scale half of templates: personalized videos from a CRM export, one video per product, per city, per employee.

Submitting a batch

curl -X POST https://api.zvid.io/api/render/bulk/api-key \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"template": "tpl_xxxxxxxxxxxxxxxxxxxx",
"name": "spring-campaign",
"items": [
{ "variables": { "firstName": "Amira", "city": "Cairo" }, "name": "spring-amira" },
{ "variables": { "firstName": "Omar", "city": "Alexandria" } },
{ "variables": { "firstName": "Lina", "city": "Giza" } }
],
"webhookUrl": "https://example.com/hooks/bulk-done"
}'

Envelope fields:

FieldRequiredNotes
template or payloadone of themA stored tpl_… id, or a full inline project (with variables defaults).
itemsyes1–500 entries; each is { variables, name? }. Your plan's maxBulkItems may be lower — validation errors report it.
variablesnoBatch-level values merged under every item's variables.
overridesnoOutput knobs applied to every job (name, dimensions, format, …).
namenoBatch name shown in the dashboard.
webhookUrlnoPer-request webhook — called per job completion.

Best-effort validation

Items are validated individually. Valid items become jobs immediately; invalid ones are returned in errors — each entry carries the item's original request index as item (0-based) plus field-level details — and the batch is only rejected outright when the envelope is malformed or every item fails:

{
"bulkId": "blk_…",
"queued": true,
"totalJobs": 2,
"rejectedItems": 1,
"errors": [
{
"item": 1,
"error": "Validation failed",
"details": [
{
"field": "payload.duration",
"message": "Duration must be at least 0.1 seconds"
}
]
}
],
"failedToQueue": 0,
"creditsReserved": 12,
"clientRoom": "api:42:7",
"queueAhead": 0,
"jobs": [
{
"jobId": "550e8400-…",
"index": 0,
"name": "spring-amira",
"creditsReserved": 6
},
{ "jobId": "6ba7b810-…", "index": 2, "name": null, "creditsReserved": 6 }
]
}

jobs[].index is each queued job's original position in items, so you can line results back up with your source rows even when some items were rejected.

Fix the failed rows and resubmit just those — the dashboard's bulk page has a fix-and-resubmit flow and CSV export for exactly this.

Credits

Each job reserves its own credits when it starts and refunds on failure — there is no batch-level charge. See Credits, Plans & Limits.

Tracking a batch

EndpointAuthPurpose
GET /api/render/bulkJWTList your bulk batches
GET /api/render/bulk/{id}JWT or API keyBatch status with per-item job states and results

Individual jobs are also visible through the normal GET /api/jobs/{id} endpoint, and each fires webhook events on completion.

Bulk images

POST /api/render/image/bulk (and /image/bulk/api-key) is the same contract with type: "image" enforced — useful for thumbnail sets and social-card batches. Image credit pricing (1 credit per 10 images) makes large image batches cheap: 25 images ≈ 3 credits.