Batch generation
Nightly notice runs and bulk mailings don't need 200 HTTP calls.
POST /v1/templates/{templateId}/generate-batch accepts up to 200 items
(each a data object and optional output name) and renders them
asynchronously as one job:
curl -s "https://api.pdfs.ecourtdate.com/v1/templates/$TEMPLATE_ID/generate-batch" \
-H "x-api-key: $API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: notices-2026-08-15" \
-d '{
"items": [
{ "data": { "client_name": "Jordan Smith", "hearing_date": "2026-08-15" }, "name": "notice-smith" },
{ "data": { "client_name": "Alex Rivera", "hearing_date": "2026-08-15" }, "name": "notice-rivera" }
]
}'
{ "job_id": "9d2c6a71-…", "status": "queued", "total": 2 }
The 202 response's Location header points at the job. Two guarantees are
worth designing around:
- Validation happens up front. Every item's
datais validated against the version's merge-tag schema before anything is enqueued. A bad batch fails whole with422BATCH_ITEMS_INVALIDand per-item errors: you never get 180 rendered documents and 20 silent holes. - The version is pinned at submit. Publishing a new version mid-job never
splits a batch: every item renders with the version resolved when the job
was accepted. You can also pin explicitly with
"version": N.
Polling the job
curl -s "https://api.pdfs.ecourtdate.com/v1/jobs/9d2c6a71-…" \
-H "x-api-key: $API_KEY"
{
"job_id": "9d2c6a71-…",
"status": "completed",
"template_id": "5f0c2a4e-…",
"version": 1,
"total": 2, "pending": 0, "succeeded": 2, "failed": 0,
"items": [
{ "index": 0, "status": "succeeded", "output_id": "0f6a1c9d-…" },
{ "index": 1, "status": "succeeded", "output_id": "6b1e8f30-…" }
],
"files": [
{ "index": 0, "output_id": "0f6a1c9d-…", "url": "https://…signed…",
"name": "notice-smith.pdf", "bytes": 24831, "sha256": "6f3f2b…", "expires_in": 3600 }
],
"next_cursor": null
}
- Job status:
queued→running→completed,completed_with_errors, orcancelled. Item status:queued,running,succeeded,failed(with anerrormessage), orcancelled. - Download URLs are re-signed on every read, so polling always returns usable links. There is no "the URL expired while I was polling" failure mode.
- Poll on a backoff (a few seconds growing to ~30 s). The API is polling-only by design: it works from restricted networks that can't receive inbound HTTP.
Jobs expire 48 hours after submission; outputs follow the standard retention window. Collect files promptly.
Cancelling
curl -s -X DELETE "https://api.pdfs.ecourtdate.com/v1/jobs/9d2c6a71-…" \
-H "x-api-key: $API_KEY"
Cancellation stops items that haven't rendered yet; already-rendered items keep their outputs. Cancelling is idempotent.
Practices
- Send an
Idempotency-Keyon every submit: a retried submission then can't double-render a whole batch. - Validate rows ahead of time with
dry_runduring data preparation, so batch submission failures become rare. - Use per-item
names that match your filing convention (notice-<case-number>), and store each file'ssha256with the case record.