---
title: "Render up to 50 documents"
method: POST
path: "/v1/render/batch"
tags: ["Renders"]
---

# Render up to 50 documents

`POST /v1/render/batch`

## Request

- Base URL: `https://api.galleyrender.com`
- URL: `https://api.galleyrender.com/v1/render/batch`
- Auth: HTTP bearer

Every item is queued. Items that hit the cache come back finished. A failed item does not fail the batch: its entry in `renders` is an error envelope with the same `index`.

## Request body

- BatchRequest
  - `renders` RenderRequest[], required
    - `template` string, required: `invoice` for the latest version, or `invoice@3` to pin one. Pin it in anything you ship.
    - `version` union: Version number, if you would rather not put `@3` in `template`.
      - integer
      - string
    - `data` object: The payload, validated against the template's JSON Schema. `lang` and `labels` at the root of `data` are read by the language engine only where the template's schema declares a root property of that name, as a direct property (a `$ref` or `allOf` declaration does not count). The starter library's templates declare them for new accounts and for existing accounts once the library refresh has been run; on a template that does not, they are ordinary unknown fields (an `unknown_field` warning on an open schema, a 422 on a closed one), and the template's own schema decides what they may hold. Fields the template does not use are never an error; they come back in `warnings`.
      - `lang` string: Only where the template's schema declares `lang`. Language of the document's fixed text — titles, labels, headings, default sentences — and the locale dates and money are formatted in, as a BCP 47 tag (the languages with translated text are listed at /docs/templates/languages). The library's schemas accept a tag of up to 35 characters matching the pattern below, and refuse anything else with a 422 at `data.lang`; the engine itself reads up to 100. A tag that passes the pattern but that `Intl` cannot canonicalise (for example `en-a`) is not an error: it is ignored, as if `lang` had not been sent, with no warning. A tag with no translated text formats dates and money for that locale, keeps the English text, and adds an `unsupported_language` warning. Omit it and nothing changes.
      - `labels` object: Your own wording for any of the document's fixed strings, by key. Wins over `lang`. Use it for a house term ("Quotation" instead of "Estimate"), or for a language we do not ship.
    - `format` 'pdf' | 'png' | 'jpg' | 'jpeg': Defaults to `pdf` for chromium templates and `png` for satori ones. `webp` is not in v1.
    - `options` RenderOptions: Merged over the template's own defaults. Options are part of the cache key, so two calls that differ only here are two different renders.
      - `page_size` string: PDF page size: `Letter`, `A4`, `Legal`, or `210mm x 297mm`.
      - `landscape` boolean: PDF only.
      - `margin` union: PDF margins as a CSS length, or per side. Each value is a non-negative number with an optional unit (in, px, cm, mm) — these four and no others, because they are the four Chromium takes. A bare number is pixels: 48, "48", "48px" and "0.5in" are the same margin. A value that is not a length, or a negative one, is refused with 400 invalid_request before the render starts, as are margins larger than the sheet — the one named by page_size, or the largest Chromium knows when there is none, since the page then comes from the template's own CSS. Margins too large for the page a template actually prints on come back as render_failed 422 with cause template.
        - string
        - number
        - object
          - `top` union
            - string
            - number
          - `right` union
            - string
            - number
          - `bottom` union
            - string
            - number
          - `left` union
            - string
            - number
      - `width` integer: Viewport width in px for png/jpg. Default 1200.
      - `height` integer: Viewport height in px for png/jpg. Default 630.
      - `scale` number: Device pixel ratio for png/jpg; a CSS zoom on PDF, where it is capped at 2. Values above the cap are clamped, not rejected, and the cap is 3 on both engines.
      - `full_page` boolean: png/jpg: capture the whole document, not just the viewport. The capture is limited to 16,384 device pixels on either side, measured after `scale`; a larger page is refused with render_failed 422 and cause `template`.
      - `quality` integer: jpg only. Default 90.
      - `background` string: CSS colour painted under the document.
      - `print_background` boolean: PDF: print background colours and images. Default true.
      - `css` string: Extra CSS appended after the template's own styles.
      - `on_blocked_asset` 'fail' | 'skip': What to do when an image, font or other subresource is refused by the egress policy or fails to fetch. `fail` fails the render with `asset_blocked` naming the URL; `skip` drops the asset and renders without it. Both engines behave identically.
    - `webhook_url` string, uri: Absolute https URL to POST on completion. Supplying one forces the queued path. The body is signed with `X-Galley-Signature` (HMAC-SHA256 over the raw body, using the secret from `GET /v1/account`), and delivery is retried up to five times with exponential backoff over about a quarter of an hour.
    - `async` boolean: Force the queued path even for a small job.
  - `webhook_url` string, uri: Applied to every item that does not carry its own.

## Response `202`

Accepted.

- Batch
  - `object` 'batch', required
  - `id` string, required
  - `count` integer, required
  - `queued` integer, required
  - `cached` integer, required
  - `renders` unknown[], required: One entry per item, in order, each carrying its `index`. A render item is a `Render` with its `warnings`; a failed item is an error envelope.
    - unknown

## Other responses

- `400`: `invalid_request` — empty batch, or more than 50 items.
- `401`: `authentication_error`.
- `429`: `rate_limited`. A batch spends one unit of the per-minute limit per item, so 50 renders count as 50.

---

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