Anjin Design
Docs navigation

Docs

Batch rendering

One request, many images — a campaign's worth of variants, a spreadsheet of names, a catalogue of products. Each row succeeds or fails on its own.

The request#

POST/v1/renders/batch

shell
curl -X POST https://api.anjin.design/v1/renders/batch \
  -H "Authorization: Bearer $ANJIN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "format": "png",
    "renders": [
      { "template": "acme_quote_1080x1080",
        "modifications": [{"name": "quote", "text": "Ship it."}] },
      { "template": "acme_quote_1080x1080",
        "modifications": [{"name": "quote", "text": "Then fix it."}],
        "scale": 2 }
    ]
  }'

format, scale and webhook_url can be set at the batch level and overridden per row — a row-level value wins. An invalid batch-level format or scale would poison every row identically, so it fails the whole request with a 400 before anything is created.

Per-row isolation#

The response is { "results": [...] } in the same order you sent. Each entry is either a render envelope (with its own id to poll) or a structured error for that row alone:

202 — mixed outcome
{
  "results": [
    { "id": "6f1c…", "status": "pending", "output_url": null },
    { "error": { "code": "unknown_slot", "message": "Unknown slot: quotee" } }
  ]
}

A bad addressing key, a missing slot or insufficient credits on one row never blocks the others. Failed rows charge nothing.

Waiting vs polling#

Prefer: wait works here too: rows render concurrently and the response is a 200 with each completed row’s URLs populated. For larger batches, prefer the asynchronous flow — take the 202, then poll each row’s GET /v1/renders/:id, or attach a webhook and be told.

Limits#

  • Up to 50 rows per request.
  • Rows draw from the per-account rate budget by credit cost — see rate limits.