Most document APIs give you one endpoint that renders one file, and leave the other 999 as your problem. That is where the timeouts, the retry loops and the half-finished statement runs come from.
The usual approach is a loop around a synchronous endpoint. It breaks in three predictable ways. The HTTP request outlives its gateway timeout. The provider starts refusing you partway through, so you write retry logic and now you have two problems. And a failure at document 700 leaves you with no way to answer the only question that matters — which ones actually got made.
Send the whole run in one call. You get a job ID immediately, the work fans out across the render fleet in parallel, and you poll the job for status. When it finishes, the manifest tells you the outcome of every single item — not a count, a list.
POST /v1/render/batch
{ "template_id": "statement", "items": [ … 1,000 payloads … ] }
→ { "job_id": "job_8f2a…", "accepted": 1000 }
GET /v1/render/batch/job_8f2a…
→ { "status": "completed", "succeeded": 1000, "failed": 0 } Every plan has a parallel-render figure, and it is a limit rather than a reservation. Requests above it are held briefly in memory and then queued. They are not rejected, so there is no 429 to handle and no backoff to write. Your documents take a little longer under load; they do not fail.
This is deliberate. A rate limit that returns an error moves the problem into your code, where it becomes a retry loop that makes the overload worse.
On Growth and Enterprise, each finished PDF is written directly into cloud storage you own — your S3 bucket or Azure container — as it completes. A thousand-document run does not need a thousand downloads, and we keep no copy of any of it.
Accounts are by invitation while we onboard a few teams at a time. Tell us where to reach you and roughly what you render.
Request an invitation on the home page, or write to info@paperomat.com.