Skip to content

More than one document / POST /v1/pdf/batch

Render many PDFs in one API call

Up to several hundred documents in one request, each stored and returned as a link, with per-item success or failure rather than one all-or-nothing result.

What it is for

For the moment a billing run closes and four hundred invoices have to exist. Sending four hundred separate requests works and spends four hundred round trips on it. A batch sends one request and gets back a result for every item saying what happened to it. Up to ten items are answered in the call; a larger batch is accepted at once with a batch id and rendered in the background, with the results at GET /v1/pdf/batch/:id and on the webhook.

The request

Sent to POST /v1/pdf/batch. Everything else on this page is what happens around it.

bash

curl -X POST https://api.pdfpipe.xyz/v1/pdf/batch \
  -H "Authorization: Bearer $PDFPIPE_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "options": { "format": "A4", "margin": "16mm" },
    "requests": [
      { "html": "<h1>Invoice 1</h1>", "filename": "inv-1.pdf" },
      { "html": "<h1>Invoice 2</h1>", "filename": "inv-2.pdf" }
    ],
    "webhook_url": "https://your-app.example/hooks/batch",
    "webhook_secret": "a-secret-of-at-least-16-chars"
  }'

The actual limits

Read from the implementation rather than remembered, so these are the numbers the API enforces rather than the ones a roadmap intends.

  • Items per call depend on the plan: 10 on Starter, 50 on Growth, 100 on Scale, 250 on Business.
  • Up to 10 items answer in the call with 200. More than 10, or "async": true, answers 202 with a batch_id and renders in the background at roughly 2 to 4 seconds per document, two at a time.
  • Shared options apply to every item and per-item options override them.
  • Every item is stored, so batch requires document storage and inherits your plan's retention.
  • A webhook_secret must be 16 to 256 characters (whsec_ plus base64 is the Standard Webhooks form), and the webhook_url is checked against the same private-address guard as a URL render.
  • Each item consumes one document from your quota. A batch of fifty is fifty documents.

What failure looks like

A batch answered in the call returns 200 even when some items fail, and the failures are in the results array with an error code; a background batch reports them the same way when it completes. That is deliberate: a batch where item 37 has a broken template should not throw away the other items. It does mean a caller that checks only the HTTP status will miss failed documents, so the results array has to be read. Failed items are not charged.

Plan availability

Not available on the free plan. Attempting it returns 403 with plan_required and a message naming the smallest plan that includes it.

When this is the wrong tool

When the documents are produced one at a time by user actions rather than by a scheduled run. Batching a queue that arrives continuously means holding documents back to group them, which adds latency to every one of them to save round trips nobody was counting.

Frequently asked

Is batch rendering available on the free plan?

Not available on the free plan. Attempting it returns 403 with plan_required and a message naming the smallest plan that includes it.

Where do these numbers come from?

The running implementation. Every figure on this page, from payload ceilings to per-plan limits, is what the API enforces today rather than what a specification says it should. If one of them is wrong, the API is the thing to believe.

Related capabilities

Options that come up in the same request, and one from each of the other groups.

100 free documents a month, and a playground that runs a real render without a key.