---
title: "Render up to 10 images in one call"
method: POST
path: "/render/batch"
---

# Render up to 10 images in one call

`POST /render/batch`

## Request

- Base URL: `https://rendry.io/api/v1`
- URL: `https://rendry.io/api/v1/render/batch`
- Auth: one of:
  - HTTP bearer
  - HTTP bearer
  - HTTP bearer
  - HTTP bearer

One template x many data sets. Each item is charged as one render (1-3 credits by canvas area; pdf/html 2 a page) and the run stops at the first item the balance cannot pay for. For hundreds of rows use POST /batch-tasks (a table, one archive); for thousands loop this endpoint or queue /render/async with a webhook.

## Headers

- `X-Rendry-Account` string

## Request body

- object
  - `preset_id` string, required
  - `items` object[], required
    - `dynamic_data` object
    - `filename` string
    - `rows` object: This item's rows for its repeat groups and tables (rows_key)
  - `format` 'png' | 'jpeg' | 'webp' | 'pdf' | 'html': For the whole batch. pdf and html render the document profile at 2 credits a page
  - `quality` integer
  - `max_width` integer

## Response `200`

Batch finished, per-item status inside. An item that was refused carries the same refusal object a single render answers (`error`, `message`, `diagnostics`, …) beside its `index` and `status` (error, insufficient_credits, quota_exceeded). When the credits run out the batch stops, and every item it did not attempt is listed with `status` not_attempted and a `reason`.

- BatchRenderResponse: The reply of POST /render/batch: every item's outcome. The run stops at the first item the balance cannot pay for.
  - `rendered` integer, required: Items that finished
  - `total` integer, required
  - `items` BatchRenderItem[], required
    - `index` integer, required
    - `job_id` string: Poll-able through GET /render/status/{id}
    - `status` string, required: success, error, insufficient_credits or quota_exceeded
    - `result_url` string: Absolute URL of the file (https://rendry.io/api/v1/files/…): the tool-bridge doors return full links, the native REST doors return paths.
    - `error` string
    - `warnings` string[]
  - `hint` string
  - `cost` CreditCost: What this call took and what is left.
    - `credits_charged` number
    - `balance` number
  - `needs_attention` integer[]: Item indexes with warnings; sent when there are any

## Other responses

- `400`: Refusal before anything is charged: `unknown_field` (a key the tool does not read, items included; a near miss is renamed instead and reported in `autofixed_fields`), `invalid_request`, or `invalid_input`.
- `401`: Missing/invalid API key
- `402`: Not enough credits: the body carries error, balance, required and packages_url.
- `404`: `preset_not_found`: the whole call is refused before any item is rendered.
- `429`: Too many renders at once — concurrency limit, not a monthly quota. Retry in a moment.

---

[API](https://skmtc.dev/rendry/apis/rendry-api.md) · [All operations](https://skmtc.dev/rendry/apis/rendry-api/llms.txt) · [OpenAPI document](https://skmtc.dev/rendry/apis/rendry-api/revisions/c4fb572c26c9?raw)
