API reference

Batches

Use with your agent

Give this prompt to your AI agent. The agent does the task for you.

Read https://thirds.ai/docs/api-reference/batches and help me choose the right thirds.ai endpoint and write a request. Check the fields and credentials in this reference.

Render one saved template version once per data row, poll each row, retry failed rows, and download a ZIP of the files that succeeded.

See all API resources or read API keys and requests.

Endpoints

createBatch

POST /v1/batches

Create a render batch

Render one saved template version once per data row as PDF, PNG, JPEG, or WebP. The account plan sets how many rows one run accepts: 10 on Free and a pack-only account, 50 on Starter, 100 on Growth, and 200 on Scale. A run over that limit answers 400 batch_row_limit with error.plan_limit. Validates every row against the version's schema before any job exists. Creates one normal render job per row as account and key concurrency allow. Remaining rows stay pending until a later retry or the background drain. The ledger reserves one credit per admitted job, settles it on success, and releases it on failure or cancellation. quoted_credits is the row count, not a discount.

Authentication: bearer API key. See authentication.

ParameterLocationRequiredRule
Idempotency-KeyheaderYes{"type":"string","minLength":1,"maxLength":255,"pattern":"^[ -~]+$"}

Request body: application/json, BatchCreate.

StatusMeaningBody
201The batch was created, or an earlier request with the same idempotency key and body is replayed.application/json: Batch
400The one error envelope every backend response uses.application/json: ErrorEnvelope
401The one error envelope every backend response uses.application/json: ErrorEnvelope
403The authenticated account is suspended. The code is account_suspended.application/json: ErrorEnvelope
404The one error envelope every backend response uses.application/json: ErrorEnvelope
405The method is not allowed on this route.application/json: ErrorEnvelope
409The one error envelope every backend response uses.application/json: ErrorEnvelope
413The one error envelope every backend response uses.application/json: ErrorEnvelope
415The one error envelope every backend response uses.application/json: ErrorEnvelope
429The one error envelope every backend response uses.application/json: ErrorEnvelope
431The request has more than 64 headers or more than 32 KiB of header names and values.application/json: ErrorEnvelope
500The one error envelope every backend response uses.application/json: ErrorEnvelope
503The one error envelope every backend response uses.application/json: ErrorEnvelope

getBatch

GET /v1/batches/{id}

Get a render batch's status

Returns the batch with each row's own state and, once any row has succeeded, a signed archive_url for the ZIP of every succeeded file. GET never starts billed work.

Authentication: bearer API key. See authentication.

ParameterLocationRequiredRule
idpathYes{"type":"string","pattern":"^batch_[0-9a-f]{32}$"}
StatusMeaningBody
200The batch's current status.application/json: Batch
401The one error envelope every backend response uses.application/json: ErrorEnvelope
403The authenticated account is suspended. The code is account_suspended.application/json: ErrorEnvelope
404The one error envelope every backend response uses.application/json: ErrorEnvelope
405The method is not allowed on this route.application/json: ErrorEnvelope
431The request has more than 64 headers or more than 32 KiB of header names and values.application/json: ErrorEnvelope
500The one error envelope every backend response uses.application/json: ErrorEnvelope

retryBatch

POST /v1/batches/{id}/retry

Retry a batch's failed, cancelled, or pending rows

Creates one new job for every row whose last attempt failed or was cancelled, and admits still-pending rows as concurrency allows. A queued, running, or already succeeded row is left untouched. Retry never bills a row that already succeeded.

Authentication: bearer API key. See authentication.

ParameterLocationRequiredRule
idpathYes{"type":"string","pattern":"^batch_[0-9a-f]{32}$"}
StatusMeaningBody
200The batch after retry, with a new job for each row that was retried.application/json: BatchRetry
401The one error envelope every backend response uses.application/json: ErrorEnvelope
403The authenticated account is suspended. The code is account_suspended.application/json: ErrorEnvelope
404The one error envelope every backend response uses.application/json: ErrorEnvelope
405The method is not allowed on this route.application/json: ErrorEnvelope
429The one error envelope every backend response uses.application/json: ErrorEnvelope
431The request has more than 64 headers or more than 32 KiB of header names and values.application/json: ErrorEnvelope
500The one error envelope every backend response uses.application/json: ErrorEnvelope

cancelBatch

POST /v1/batches/{id}/cancel

Cancel a batch's pending and queued rows

Stops rows that have no job yet and cancels queued jobs. Running jobs finish. Succeeded files stay downloadable. Cancelled and failed rows cost nothing.

Authentication: bearer API key. See authentication.

ParameterLocationRequiredRule
idpathYes{"type":"string","pattern":"^batch_[0-9a-f]{32}$"}
StatusMeaningBody
200The batch after cancel.application/json: Batch
401The one error envelope every backend response uses.application/json: ErrorEnvelope
403The authenticated account is suspended. The code is account_suspended.application/json: ErrorEnvelope
404The one error envelope every backend response uses.application/json: ErrorEnvelope
405The method is not allowed on this route.application/json: ErrorEnvelope
431The request has more than 64 headers or more than 32 KiB of header names and values.application/json: ErrorEnvelope
500The one error envelope every backend response uses.application/json: ErrorEnvelope

getBatchArchive

GET /v1/batches/archive/{token}

Download a batch's ZIP archive

Stream a ZIP of one batch's succeeded rows, in requested order with numbered filenames such as 001.pdf, plus manifest.json recording that order and any failed or cancelled rows. The link carries its own authority, so no other credential is read. The manifest never includes customer data.

Authentication: no credential required.

ParameterLocationRequiredRule
tokenpathYesThe signed archive link. {"type":"string"}
StatusMeaningBody
200The ZIP archive of succeeded rows plus manifest.json.application/zip: {"type":"string","format":"binary"}
403The link is genuine but its time is over.application/json: ErrorEnvelope
404The link is not valid, or the batch has no succeeded row to archive.application/json: ErrorEnvelope
405The method is not allowed on this route.application/json: ErrorEnvelope
431The request has more than 64 headers or more than 32 KiB of header names and values.application/json: ErrorEnvelope
500An internal error occurred.application/json: ErrorEnvelope

Schemas

BatchCreate

FieldRequiredDescription and type
template_idYesTemplateId
versionNoOmitted to use the template's latest version at creation time. The batch pins that exact version. {"type":"integer","minimum":1}
formatYes{"type":"string","enum":["pdf","png","jpeg","webp"]}
rowsYes1 to 200 JSON objects. Each object is one render. 200 is the system cap; the account plan can allow fewer. The CSV parser lives in the studio; this API accepts rows only. {"type":"array","items":{"type":"object"},"minItems":1,"maxItems":200}

Schema rules: {"type":"object","additionalProperties":false}.

BatchRow

FieldRequiredDescription and type
positionYes{"type":"integer","minimum":0}
stateYes{"type":"string","enum":["queued","running","succeeded","failed","cancelled"]}
errorYes{"type":["object","null"],"properties":{"code":{"type":"string"}},"required":["code"],"additionalProperties":false}
download_urlYes{"type":["string","null"]}

Schema rules: {"type":"object","additionalProperties":false}.

Batch

FieldRequiredDescription and type
idYes{"type":"string","pattern":"^batch_[0-9a-f]{32}$"}
template_idYesTemplateId
versionYes{"type":"integer","minimum":1}
formatYes{"type":"string","enum":["pdf","png","jpeg","webp"]}
created_atYes{"type":"string","format":"date-time"}
stateYes{"type":"string","enum":["queued","running","complete","partial","failed","cancelled"]}
quoted_creditsYesThe row count. Each successful file settles one credit. Failed and cancelled rows cost nothing. There is no bulk discount. {"type":"integer","minimum":1,"maximum":200}
rowsYes{"type":"array","items":{"$ref":"#/components/schemas/BatchRow"}}BatchRow
archive_urlYesA signed ZIP download link, present once any row has succeeded. {"type":["string","null"]}

Schema rules: {"type":"object","additionalProperties":false}.

BatchRetry

Schema rules: Batch.

Shared errors, headers, and authentication schemes are in shared types and security.

Ready to make your first file?

Start in the playground with a gallery template, or get an API key and send your first request from your own terminal.