Kalpana Docs
Resources

Create a batch

Fill pages with up to 1,000 rows of values, one file per row and page. Nothing renders until you run it, unless you ask.

A batch renders every row on every page it names, so 100 rows on 2 pages make 200 files. It never waits: the call answers at once and the files render in the background. For a handful of files you want back in the same call, use Create jobs.

POST /api/batches

Requires batches:create, plus renders:create when run is true. Returns 201.

Request body

{
  "workspace": "acme",
  "name": "September products",
  "pages": ["k7fq2m8a", "p3rtv9we"],
  "rows": [
    {
      "modifications": {
        "Headline": "Weekend offer",
        "Photo": "shoe.png",
        "p3rtv9we@Headline": "Weekend offer, in stories"
      },
      "output": { "format": "png", "fileName": "weekend-offer" }
    },
    {
      "modifications": {
        "Headline": "New arrivals",
        "Photo": { "asset": "0b0f5a3e-5b1c-4d65-9a5e-3f7d2f2f6c11", "fit": "contain" },
        "Badge": { "visible": false },
        "Subline": null
      }
    }
  ],
  "collection": "0c8f7e2a-6b31-4d95-a0e4-1f5b9c3d7a62",
  "run": false,
  "webhookUrl": "https://example.com/hooks/kalpana"
}
FieldRequiredDescription
workspaceYesWorkspace slug or id.
nameYesThe batch's name, up to 200 characters.
pagesOne of pages, templates or flowPage ids, from any templates. Up to 20.
templatesOne of pages, templates or flowTemplate ids. Every page of each is rendered, in page order. Up to 20.
flowOne of pages, templates or flowOne flow id. Each row makes the flow's video.
rowsYes1 to 1,000 rows. See below.
collectionNoThe creative folder the files go into.
runNofalse (default) saves a draft and spends nothing. true publishes the batch and starts rendering.
webhookUrlNoSends each job's result to your URL. See Callback URLs. API keys only.

Give exactly one of pages, templates and flow. Fields the API does not know are refused.

A row

FieldRequiredDescription
modificationsNoLayer to value, filled on every page the batch names. See Modifications.
outputNoformat, fileName and stillTime, as in Create jobs. format defaults to png; a flow batch needs a video format.

Rows carry their own modifications and output; there is no batch-level copy.

A plain key fills every named page that has a layer of that name. <pageId>@<layer> fills one page only, and wins. A key that no named page has is refused. With several pages, a row's fileName gets the page's name added so the files stay distinct (weekend-offer Feed, weekend-offer Story).

Credits

Creating a batch spends nothing. With run: true, the cost of the whole batch is checked first and the call fails with 402 if there are not enough credits; nothing is created. Each job's cost is charged once, only when it renders.

run: true publishes the batch as it starts it. A batch saved with run: false is a draft: review it in the Studio, change it with Update a batch, and start it with Run a batch. When a batch with run: true cannot start (not enough credits, say), it is still saved, as a draft.

Response

{
  "id": "9a2e6f31-5c7d-4b08-8e1a-d4f2c6b0a937",
  "status": "draft",
  "rowCount": 2,
  "jobCount": 4,
  "creditCost": 4
}
FieldDescription
idThe batch's id (a UUID).
statusdraft, or published when run was true.
rowCountThe rows you sent.
jobCountThe files it will make: rows times pages.
creditCostWhat rendering the whole batch costs.

Follow a running batch with Get a batch, list its files with List a batch's jobs, or take its webhooks.

Refused: 400 with several issues

Every issue across every row comes back in one answer, each with the row's index, so you fix the sheet in one pass. Nothing is saved. Validate a batch gives the same check without creating anything.

{
  "defined": true,
  "code": "BAD_REQUEST",
  "status": 400,
  "message": "Invalid rows. rows[1].Headlin: No layer \"Headlin\" in this template. Its layers: Headline, Photo, Badge. rows[1].Photo: No image \"missing.png\" in this workspace. rows[7].output.format: A flow is a video: use mp4 or gif.",
  "data": {
    "issues": [
      { "row": 1, "field": "Headlin", "code": "unknown_layer", "message": "No layer \"Headlin\" in this template. Its layers: Headline, Photo, Badge." },
      { "row": 1, "field": "Photo", "code": "asset_not_found", "message": "No image \"missing.png\" in this workspace." },
      { "row": 7, "field": "output.format", "code": "bad_value", "message": "A flow is a video: use mp4 or gif." }
    ]
  }
}

Errors

StatusCause
400Not exactly one of pages, templates and flow, no rows or more than 1,000, an unknown field, or any row issue above. data.issues lists them.
402run is true and the organization cannot afford the batch, or webhookUrl is set and it has no active subscription. data holds cost and remaining.
403Your role or key lacks batches:create, or lacks renders:create when run is true.
404A page, template or flow is not in this workspace. The message names it.
413The body is larger than 4 MiB. A full batch of 1,000 rows is about 1.2 MiB at its largest.
Was this page helpful?

Updated 10 Nov 2026

On this page