Batches
Render one template for many items with POST /v1/batches, from JSON and CSV items and the combined ZIP or merged PDF to progress, cancel and retry, webhooks, billing and limits.
A batch renders one published template version for many items in a single request. Each item has its own data and becomes an ordinary render with its own files. The batch tracks the items together, reports progress and can package the results as one ZIP file or one merged PDF. Batches are included from the Starter plan.
Batches are asynchronous: POST /v1/batches answers 202 Accepted at once, and the items render in the background. Follow them with GET /v1/batches/{id} or the batch.progress and batch.completed webhook events.
When to use a batch
Use a batch when you render the same template for a list of records, such as certificates for every participant of a course, monthly statements or name badges:
- One request covers up to your plan's item limit instead of one request per document. The items start in turn, as many at a time as your plan's bulk concurrency allows.
- One batch object shows the progress of all items, and two webhook events replace one event per document.
- The results can be packaged as one ZIP file or one merged PDF.
- Failed items can be rendered again with one call.
- The items can come from a CSV file.
Send single renders with POST /v1/renders instead when you need the file in the response (sync mode, binary or base64 delivery), when the documents use different templates, or for HTML, URL or Markdown input. A batch renders one stored template, and its items can't use data_url.
In the dashboard, Batches → New batch walks through the same steps: pick a published template, upload a CSV file or paste JSON, map the columns, check a few sample renders and start the batch.
Create a batch
curl https://api-eu.dynamicdocumentapi.com/v1/batches \
-H "Authorization: Bearer $DYNAMIC_DOCUMENT_API_KEY" \
-H "Idempotency-Key: certificates-course-2026-09" \
-H "Content-Type: application/json" \
-d '{
"template_id": "tpl_01J9ZK3M7Q8V5W2X4Y6Z8A0B1C",
"items": [
{ "data": { "name": "Ann Example", "course": "Safety 101" }, "reference": "cert_001", "filename": "ann-example.pdf" },
{ "data": { "name": "Bob Example", "course": "Safety 101" }, "reference": "cert_002" }
],
"output": { "format": "pdf", "filename": "certificate-{{ data.name }}.pdf" },
"combine": { "zip": true, "zip_filename": "certificates.zip" },
"reference": "course_2026_09",
"metadata": { "course": "safety-101" }
}'The API checks the whole batch before anything renders: the template, the options and every item. If something is invalid, no batch is created, and the error's errors[] lists each problem with a JSON pointer, such as /items/1/data or /csv/row/5. A valid batch is answered with 202 Accepted, a Location header and the batch object:
HTTP/1.1 202 Accepted
Location: /v1/batches/bat_01J9ZN4T6V8X0Z2B4D6F8H0K2M
Content-Type: application/json
{"id": "bat_01J9ZN4T6V8X0Z2B4D6F8H0K2M", "object": "batch", "status": "queued", "total": 2, "succeeded": 0, "failed": 0, "pending": 2, "progress": 0.0}The response body above is shortened.
Request body
| Field | Type | Default | Description |
|---|---|---|---|
template_id | string | required | The template to render (tpl_…) |
version | string or integer | "live" | "live" for the published version, or a version number such as 7. Drafts can't be rendered in a batch, not even with a test key. |
items | array | — | The items as JSON. See items. |
csv_upload_id | string | — | A CSV file uploaded with POST /v1/uploads (upl_…), instead of items. See CSV input. |
csv_mapping | object | every column | Which CSV column fills which template variable |
output | object | the template's options | Format, file name and format options, as in a render request. Applies to every item. |
delivery | object | url delivery, or none without hosted copies | As in a render request, except binary and base64. Applies to every item. |
combine | object | none | A ZIP file and a merged PDF of the results. See combined files. |
webhook | object | none | A webhook for this batch's events. See webhooks. |
reference | string | none | Your identifier for the batch, up to 255 characters. Usable as a list filter. |
metadata | object | none | Key-value pairs for the batch. They are copied to every item's render. |
engine | string | template or workspace default | Engine channel for every item |
test | boolean | false | Marks a test batch. See test batches. |
Send exactly one of items and csv_upload_id. Fields of a render request that aren't listed here, such as mode, data_url or priority, are rejected with 400 validation_error. The API reference has the full schemas.
Items
Each entry in items is one document:
| Field | Description |
|---|---|
data | The item's data for the template, up to 1 MB. Keys become template variables, as in a render request. |
reference | Your identifier for the item, up to 255 characters. It becomes the reference of the item's render. |
filename | File name for this item, up to 255 characters. It replaces output.filename, and the file gets the extension of the output format. |
metadata | Key-value pairs added to the batch's metadata on this item's render. The item's value wins when a key is in both. Batch and item together allow 50 keys. |
output.filename is evaluated for each item with that item's data, so certificate-{{ data.name }}.pdf gives every file its own name.
CSV input
A batch can also read its items from a CSV file. Upload the file with POST /v1/uploads first:
curl https://api-eu.dynamicdocumentapi.com/v1/uploads \
-H "Authorization: Bearer $DYNAMIC_DOCUMENT_API_KEY" \
-F "file=@participants.csv"The response contains the upload's id (upl_…). Uploads can be up to 50 MB and are kept for 24 hours; the batch reads the file when you create it. Then pass the ID as csv_upload_id:
curl https://api-eu.dynamicdocumentapi.com/v1/batches \
-H "Authorization: Bearer $DYNAMIC_DOCUMENT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"template_id": "tpl_01J9ZK3M7Q8V5W2X4Y6Z8A0B1C",
"csv_upload_id": "upl_01J9ZM1X3F7R8K2C4V6B8N0P2Q",
"csv_mapping": { "name": "Full Name", "course": "Course" },
"combine": { "merged_pdf": true }
}'With this file, the first item gets the data {"name": "Ann Example", "course": "Safety 101"}, the reference cert_001 and the file name ann-example.pdf:
Full Name,Course,_reference,_filename
Ann Example,Safety 101,cert_001,ann-example
Bob Example,Safety 101,cert_002,bob-example- The file is UTF-8 (a byte order mark is ignored) and comma-separated as in RFC 4180, with the column names in the first row. Give it a
.csvname when you upload it. csv_mappingmaps template variables to column names, and only the mapped columns are used. A dotted variable such ascustomer.namebecomes a nested object.- Without
csv_mapping, every column is used under its own name, and a dotted column name such ascustomer.namebecomes a nested object. - Values are always strings, and an empty cell is
"". For numbers, booleans, lists (such as an e-invoice'slines) or per-itemmetadata, send JSONitems. - The optional columns
_referenceand_filenameset each item'sreferenceandfilename, up to 255 characters. They aren't part of the data. - Rows whose cells are all empty are skipped. Every other row needs as many fields as the header.
- Rows are numbered as in a spreadsheet: the header is row 1 and the first item is row 2. Errors point at rows as
/csv/row/<n>and at the mapping as/csv_mapping/<variable>.
Options for all items
output and delivery work as in a render request: the template's stored options apply, and what you send overrides them. Some rules are specific to batches:
- Async only.
delivery.typeisurlornone. Without it, the items geturlwhen they keep a hosted copy andnonewhen they don't, see Hosted copy.binaryandbase64need a sync render and are rejected. - Data schema. If the template enforces a JSON Schema for its data, every item is checked when you create the batch. One mismatch rejects the whole batch with
422 data_schema_mismatch, with pointers such as/items/3/data/nameor/csv/row/5/data/name. - E-invoices. A literal
output.einvoice.invoiceapplies to every item.invoice_path, and a template's default e-invoice, are resolved in each item's own data. See E-invoicing. - Storage. Each item's files are uploaded to the destinations in
delivery.storage, or to your workspace's default destinations, like a single render's. In path templates,render.referenceis the item's reference. See Storage. - Emails. Email rules apply to every item. See emails.
Combined files
Set combine to package the results once every item has finished:
| Field | Default | Description |
|---|---|---|
zip | false | One ZIP file with the file of every succeeded item |
merged_pdf | false | One PDF with the pages of every succeeded item. Needs output.format: "pdf". |
zip_filename | the batch ID | File name of the ZIP, up to 200 characters. The merged PDF gets the same name with .pdf. Without it, the files are named after the batch, such as bat_….zip. |
- The combined files are built when every item has a final status and at least one item succeeded. They use the hosted files of the succeeded items, in item order; failed and canceled items are left out.
- ZIP entries are named after the items' files. A file without a name of its own is named after its render ID and stored as
<index>-rnd_….<ext>. Repeated names get(2),(3)and so on before the extension, ignoring case. - The merged PDF has one bookmark per item, titled with the item's file name. It counts against your plan's pages per PDF: a batch with more items than that limit can't request a merged PDF, and a merged PDF that comes out longer fails.
- The files appear in the batch's
fileswith a signedurlthat lastsdelivery.expires_inseconds. EveryGET /v1/batches/{id}returns fresh URLs. The files are kept for the same retention period as the items. - The combined files hold every succeeded item or none. If a combined file can't be built, the batch ends as
failed, and itserrorsays why. The item files stay available on their renders as long as their retention lasts. - An item's files can be gone by the time the last item finishes: their retention ended while the batch waited for renders or ran for a long time (test batches keep files for a day), or
DELETE /v1/renders/{id}/filespurged them. Then neither the ZIP nor the merged PDF is built, anderroris{"code": "item_files_expired", "message": "…", "items": […]}, whereitemslists the indexes of those items (at most 100). - A canceled batch isn't combined.
combineneeds items that keep their hosted copy. It is rejected with400 validation_errorat/combinefor zero-retention batches (codezero_retention) and for batches whose items keep no hosted copy (codenot_hosted):delivery.hosted: false, or nohostedwhile every storage destination of the batch haskeep_hosted_copy: false, see Hosted copy. To combine with such destinations, senddelivery.hosted: true. In the dashboard, tick Keep hosted copies in the Options step of New batch; until you do, the ZIP file and the merged PDF can't be selected.
Track a batch
GET /v1/batches/{id} returns the batch object with its counters, its progress and, once they are built, signed URLs for the ZIP file and the merged PDF. Webhooks tell you when a batch has finished, without polling.
The batch object
{
"id": "bat_01J9ZN4T6V8X0Z2B4D6F8H0K2M",
"object": "batch",
"status": "completed",
"test": false,
"template_id": "tpl_01J9ZK3M7Q8V5W2X4Y6Z8A0B1C",
"template_version": 7,
"total": 1200,
"succeeded": 1198,
"failed": 2,
"canceled": 0,
"pending": 0,
"progress": 1.0,
"paused": null,
"error": null,
"files": [
{
"kind": "zip",
"file_id": "file_01J9ZP0A2C4E6G8J0K2N4Q6S8V",
"filename": "certificates.zip",
"content_type": "application/zip",
"bytes": 41873920,
"url": "https://files-eu.dynamicdocumentapi.com/f/…",
"url_expires_at": "2026-09-17T16:21:08Z",
"expires_at": "2026-10-17T15:21:08Z"
}
],
"combine": { "zip": true, "merged_pdf": false, "zip_filename": "certificates.zip" },
"emails": { "sent": 0, "failed": 0, "unknown": 0, "pending": 0, "skipped": 0, "canceled": 0 },
"reference": "course_2026_09",
"metadata": { "course": "safety-101" },
"created_at": "2026-09-17T15:06:33Z",
"completed_at": "2026-09-17T15:21:08Z"
}| Field | Description |
|---|---|
id | Batch ID (bat_…) |
object | Always batch |
status | See status values |
test | true for test batches |
template_id, template_version | The template and the version number every item renders |
total | Number of items |
succeeded, failed, canceled | Items that ended with that status |
pending | Items without a final status yet, started or not |
progress | Finished items divided by total, from 0 to 1 |
paused | null, or the reason and start time while a live batch waits for renders. See paused batches. |
error | null, unless the batch failed because a requested combined file couldn't be built: then that file's error (the ZIP's first), with code and message, and items for item_files_expired. See combined files. |
files | The ZIP file and the merged PDF, once built |
combine | The combine options of the request |
emails | The items' emails by status. See emails. |
reference, metadata | Values from your request |
created_at, completed_at | When the batch was created, and when it reached a final status |
Each entry in files has:
| Field | Description |
|---|---|
kind | zip or merged_pdf |
file_id | File ID (file_…) |
filename, content_type, bytes | File name, media type and size in bytes |
pages | Number of pages, for the merged PDF |
url, url_expires_at | Signed download URL and when it stops working. Omitted when no hosted copy is available. |
expires_at | When the file will be deleted, or null if it's kept |
Status values
| Status | Meaning |
|---|---|
queued | Accepted; no item has started yet |
processing | Items are rendering, or the combined files are being built |
completed | Every item has a final status, at least one succeeded, and every requested combined file was built. Items that didn't succeed are counted in failed and canceled. |
failed | No item succeeded, or a requested combined file couldn't be built; error then says why |
canceled | Canceled with POST /v1/batches/{id}/cancel |
Paused batches
If your workspace runs out of renders while a live batch is running, the batch pauses instead of failing:
- Items that haven't started wait. Items that are already rendering finish normally.
- The batch stays
processing,pausedshows{"reason": "render_limit_reached", "since": "…"}, and onebatch.progressevent is sent. - About once a minute the batch checks again. It resumes on its own once renders are available, for example after you raise the monthly top-up limit or change your plan, or when the next billing cycle starts.
- Canceling works while a batch is paused.
A live batch created while no renders are left at all fails at once with 402 render_limit_reached. See Plans and limits for top-ups and the monthly top-up limit.
Items
GET /v1/batches/{id}/items lists the items in their original order, with cursor pagination. Filter by status, for example to see what retry-failed would render again:
curl -G https://api-eu.dynamicdocumentapi.com/v1/batches/bat_01J9ZN4T6V8X0Z2B4D6F8H0K2M/items \
-H "Authorization: Bearer $DYNAMIC_DOCUMENT_API_KEY" \
--data-urlencode "status=failed"{
"object": "list",
"data": [
{
"index": 17,
"status": "failed",
"render_id": "rnd_01J9ZN5B7D9F1H3K5M7P9R1T3V",
"reference": "cert_018",
"filename": null,
"error": { "code": "template_runtime_error", "message": "'dict object' has no attribute 'course'" }
}
],
"has_more": false,
"next_cursor": null
}| Field | Description |
|---|---|
index | The item's position, counting from 0: its place in items, or among the CSV's data rows |
status | See the table below |
render_id | The item's render (rnd_…) once it has started, otherwise null |
reference, filename | The item's values |
error | Why the item failed: code and message, plus line, column and excerpt for template errors. While a retried item waits for its new render, previous_render_id names the failed one. |
| Item status | Meaning |
|---|---|
pending | Not started yet |
queued | Started: its render is queued or rendering |
succeeded | Its render succeeded |
failed | Its render failed |
canceled | Canceled before it finished |
Renders of a batch
Every item is an ordinary render with source: "batch", mode: "async" and the batch's ID in batch_id. Its reference is the item's, not the batch's, and its metadata combines the batch's and the item's.
Get an item's files with GET /v1/renders/{id}, using the render_id from the items list, or list every render of the batch with GET /v1/renders?batch_id=bat_…. That list also contains the renders that built the ZIP file and the merged PDF (input_type: "pdf_tool") and the earlier attempts of retried items; add input_type=template to leave out the combined files. See Renders for the render object and the other list filters.
Cancel a batch
POST /v1/batches/{id}/cancel stops a batch that hasn't finished:
curl -X POST https://api-eu.dynamicdocumentapi.com/v1/batches/bat_01J9ZN4T6V8X0Z2B4D6F8H0K2M/cancel \
-H "Authorization: Bearer $DYNAMIC_DOCUMENT_API_KEY"- Items that haven't started are canceled at once and never billed.
- Items that have started are canceled when a renderer picks them up. An item that is already rendering may still finish; it then counts as succeeded or failed, and is billed if it succeeds.
- The batch becomes
canceledimmediately,batch.completedis sent, and no combined files are built.
The response is the batch object. Canceling a batch that has already finished fails with 409 conflict, and the problem details include its batch_status.
Retry failed items
POST /v1/batches/{id}/retry-failed renders the failed items of a finished batch again:
curl -X POST https://api-eu.dynamicdocumentapi.com/v1/batches/bat_01J9ZN4T6V8X0Z2B4D6F8H0K2M/retry-failed \
-H "Authorization: Bearer $DYNAMIC_DOCUMENT_API_KEY"- Each failed item goes back to
pendingand renders as a new render, with the template version, data and options the batch was created with. Retrying helps when items failed for a temporary reason. To fix a template or data error, create a new batch with the failed items. - The batch returns to
processing,completed_atis cleared,errorgoes back tonullandfilesis emptied. The ZIP file and the merged PDF are built again, andbatch.completedis sent again, when the batch finishes. - Retrying works for
completed,failedandcanceledbatches with at least one failed item. Canceled items stay canceled.
The response is the batch object with 202 Accepted. A batch that is still running or has no failed items answers 409 conflict. A zero-retention batch answers 409 zero_retention, because its items no longer have their data. A batch with combine whose succeeded items' files are already gone answers 409 item_files_expired, with their indexes in items, before anything is rendered again: the new combined files couldn't hold those items. Submit the failed items in a new batch instead.
Endpoints
| Endpoint | Scope | Description |
|---|---|---|
POST /v1/batches | render:write | Create a batch |
GET /v1/batches | renders:read | List batches, newest first. Filters: status, template_id, reference. |
GET /v1/batches/{id} | renders:read | Retrieve a batch, with fresh signed URLs for its combined files |
GET /v1/batches/{id}/items | renders:read | List the items in order. Filter: status. |
POST /v1/batches/{id}/cancel | render:write | Cancel a batch that hasn't finished |
POST /v1/batches/{id}/retry-failed | render:write | Render the failed items again |
POST /v1/batches/{id}/resend-emails | render:write | Resend the items' failed emails. See emails. |
Both lists use cursor pagination like GET /v1/renders: limit (up to 100, 50 by default) and cursor. Test keys only see test batches.
Webhooks
A batch sends two events instead of one event per item:
| Event | Sent when |
|---|---|
batch.progress | Another 10 % of the items has finished (at 10 %, 20 % and so on up to 90 %, each at most once), or a live batch paused because the render limit was reached |
batch.completed | The batch reached a final status: completed, failed or canceled |
The item that finishes a batch sends no progress event: the batch builds its combined files, if any, and then sends batch.completed. data.object is the full batch object, including signed URLs for the combined files unless your workspace has file URLs in webhooks turned off.
There are two ways to receive the events:
- Webhook endpoints subscribed to
batch.progressorbatch.completed. An endpoint with atemplate_idsfilter receives a batch's events only when the filter lists the batch's template. - A webhook for one batch, set in the request:
{
"template_id": "tpl_01J9ZK3M7Q8V5W2X4Y6Z8A0B1C",
"items": [{ "data": { "name": "Ann Example", "course": "Safety 101" } }],
"webhook": { "url": "https://example.com/webhooks/batches", "events": ["batch.completed"] }
}| Field | Description |
|---|---|
url | Where the events go. HTTPS is required, except for test batches. Private and local addresses are rejected with 422 url_not_allowed. |
events | batch.progress, batch.completed or both (the default) |
Like per-request render webhooks, these deliveries are signed with the secret of your workspace's default webhook endpoint, so the workspace needs one. Without it, the batch is rejected with 400 validation_error at /webhook.
A delivery looks like this (the object is shortened):
{
"id": "evt_01J9ZP2C4E6G8J0K2M4P6R8T0V",
"type": "batch.completed",
"created_at": "2026-09-17T15:21:08Z",
"workspace_id": "ws_01J9ZK0P2R4T6V8X0Z2B4D6F8H",
"region": "eu",
"data": {
"object": {
"id": "bat_01J9ZN4T6V8X0Z2B4D6F8H0K2M",
"object": "batch",
"status": "completed",
"total": 1200,
"succeeded": 1198,
"failed": 2,
"files": [{ "kind": "zip", "filename": "certificates.zip", "url": "https://files-eu.dynamicdocumentapi.com/f/…" }]
}
}
}Batch events are signed, retried and logged like every other event; see Webhooks to verify them. Test batches send them too, with "test": true on the batch. The endpoint test, POST /v1/webhook-endpoints/{id}/test, only sends render and template events, so run a small test batch to try batch events.
No render events for batch items
Item renders don't send render.succeeded, render.failed or render.expired, not even to endpoints subscribed to them: the batch events cover them. Read the outcome of each item from GET /v1/batches/{id}/items. Email events of items are sent as usual.
Emails
With email delivery, on Growth and higher plans, every item sends the template's email rules like a single render does. delivery.email works as in a render request: leave it out for the template's enabled rules, set false for none, or list the rules to use. The rules are read once, when the batch is created.
The batch object's emails counts the newest email of each item and rule by status. To send the failed ones again:
curl https://api-eu.dynamicdocumentapi.com/v1/batches/bat_01J9ZN4T6V8X0Z2B4D6F8H0K2M/resend-emails \
-H "Authorization: Bearer $DYNAMIC_DOCUMENT_API_KEY" \
-H "Content-Type: application/json" \
-d '{"statuses": ["failed"]}'{ "resent": 12, "skipped": [{ "send_id": "ems_01J9ZM1X3F7R8K2C4V6B8N0P2T", "code": "email_file_expired" }] }statuses defaults to ["failed"]. Add "unknown" to resend emails whose outcome is unknown as well, but check your provider's logs first: the provider may already have delivered them. skipped lists up to 100 emails that couldn't be resent, with the reason.
Zero retention
A batch can use zero-retention delivery when the files go to your own storage. Set delivery.retention to "none" (or turn zero retention on in your workspace settings), and send the files to a storage destination, in delivery.storage or through your workspace's default destinations:
{
"template_id": "tpl_01J9ZK3M7Q8V5W2X4Y6Z8A0B1C",
"items": [{ "data": { "employee": { "name": "Alex Example" }, "salary": 5400 } }],
"delivery": {
"retention": "none",
"storage": [{ "destination_id": "dst_01J9ZK7R9T1V3X5Z7B9D1F3H5K" }]
}
}In a zero-retention batch:
- each item's files go to your storage only, so there are no hosted copies and no download URLs
delivery.typeisnone, the only type such a batch can use, so you can leave it outcombineis rejected, because there are no hosted files to combine- an item's data is deleted as soon as the item finishes, so
retry-failedanswers409 zero_retention; submit the failed items in a new batch - email rules don't apply
Test batches
A batch created with a test key is a test batch, with "test": true. Sending "test": true with a live key fails with 403 test_key_required.
The items of a test batch are test renders: free and watermarked "TEST". A test batch counts as one render towards your plan's test renders per minute, whatever its size, and sends webhook events like a live batch.
Billing
Every item is a render and is billed like one, following the render table: a PDF of up to 50 pages is 1 render, each further 50 pages add 1, and an image is 1 render. Each item's render shows its cost in billed_renders.
| Part of a batch | Billed renders |
|---|---|
| Item that succeeds | The same as a single render of that output |
| Item that fails or is canceled | 0 |
| ZIP file | 0 (the renders inside are already billed) |
| Merged PDF | 1 |
| Retried item | Billed like any item when its new render succeeds |
| Test batch, including its combined files | 0 |
For example, a batch of 1,000 two-page invoices with a ZIP file and a merged PDF costs 1,001 renders when every item succeeds.
Items are billed as they finish. A live batch that runs out of renders pauses until renders are available again.
Limits
Batches are available from the Starter plan. On Free, POST /v1/batches answers 402 plan_feature_unavailable.
| Limit | Free | Starter | Growth | Pro | Scale | Enterprise |
|---|---|---|---|---|---|---|
| Items per batch | — | 500 | 2,000 | 10,000 | 50,000 | custom |
| Bulk concurrency | — | 2 | 10 | 20 | 50 | custom |
Bulk concurrency is the number of batch items of your workspace that render at the same time, across all its batches. Running batches take turns, oldest first, and a new item starts when one finishes. Your current value is limits.bulk_concurrency in GET /v1/account.
A batch with more items than your plan allows is rejected with 400 validation_error (too_many_items); split it into several batches.
| Limit on every plan | Value |
|---|---|
Request body of POST /v1/batches | 25 MB |
| Data per item | 1 MB |
| CSV upload | 50 MB, kept for 24 hours |
metadata | 50 keys for batch and item together, values up to 500 characters |
reference and item filename | 255 characters |
combine.zip_filename | 200 characters |
csv_mapping | 500 entries |
Each item also renders within your plan's limits for a single render, such as the async maximum duration and the pages per PDF. See Plans and limits.
Idempotency
POST /v1/batches accepts an Idempotency-Key header, as POST /v1/renders does. Reuse the key when you retry after a network error or a timeout:
- The same key with the same body within 24 hours returns the original
202response, and no second batch is created. - While the first request is still being processed, a retry fails with
409 idempotency_in_progress. - The same key with a different body fails with
422 idempotency_key_reused.
The cancel, retry-failed and resend-emails endpoints accept the header too.
Errors
| Status | Code | When |
|---|---|---|
400 | validation_error | The request or an item is invalid. errors[] points at each problem, such as /items/3/metadata, /csv/row/5 or /combine/merged_pdf. /combine with the code zero_retention or not_hosted means the items keep no hosted files to combine. |
402 | plan_feature_unavailable | Your plan doesn't include batches, or a feature the batch uses, such as e-invoices below Growth |
402 | render_limit_reached | A live batch was created while your workspace had no renders left |
403 | test_key_required | "test": true with a live key |
404 | template_not_found, version_not_found | The template or the version doesn't exist, or the template has no published version |
404 | upload_not_found | The CSV upload doesn't exist or has expired |
404 | not_found | The batch doesn't exist. Test keys only see test batches. |
409 | conflict | Cancel on a finished batch, or retry-failed on a running batch or one without failed items |
409 | zero_retention | Retry-failed on a zero-retention batch |
409 | item_files_expired | Retry-failed on a batch with combine whose succeeded items' files are gone; items lists their indexes |
410 | template_deleted | The template was deleted |
413 | payload_too_large | The request body is over 25 MB, or an item's data is over 1 MB |
422 | data_schema_mismatch | An item's data doesn't match the template's JSON Schema |
422 | url_not_allowed | The batch's webhook.url isn't allowed |
See Errors for the problem details format and every other code.
Related pages
- Renders for the render request, delivery options and the render object
- Webhooks for endpoints, signatures and retries
- Storage for uploading files to your own buckets
- Email delivery for email rules and sends
- E-invoicing for e-invoices in batches
- PDF tools for merging, splitting and converting existing PDFs
- Plans and limits for the render table and every limit
- Errors for every error code
Renders
Create PDFs and images with POST /v1/renders, from the request body and sync or async modes to delivery, idempotency, listing and rate limits.
PDF options
Paper sizes, margins, scaling, print behaviour, metadata, accessibility and PDF/UA, PDF/A archiving, attachments, protection and wait strategies for PDF output.