Concurrency Limits by Plan
Your plan’s rate limit determines how many requests you can issue per minute. For batch workloads, translate that into a practical concurrency ceiling:Rate limits count requests, while your monthly allowance is metered in render units (a text render costs 1 unit; image-heavy renders cost more, up to 16). Plan for both: requests/min bound your throughput, render units bound your monthly volume.
These concurrency figures are conservative estimates that keep you safely below the rate limit ceiling while accounting for variable render times. You can tune the concurrency value up or down based on observed throughput in your environment.
Python: Async Batch with asyncio and aiohttp
The most efficient Python approach uses asyncio with aiohttp to issue multiple render requests in parallel, capped by a semaphore set to your concurrency limit.
Node.js: Concurrent Batch with Promise.all and a Concurrency Pool
Node.js’s Promise.all runs tasks concurrently, but without a concurrency cap it will fire all requests simultaneously and overwhelm the rate limit. The renderBatch function below implements a simple pool that keeps exactly MAX_CONCURRENCY requests in flight at any time.
Handling Rate Limit Errors
When you exceed your plan’s rate limit, the API returnsHTTP 429 Too Many Requests. Both examples above implement exponential backoff — they wait 1 second after the first 429, 2 seconds after the second, 4 seconds after the third, and so on.
Key principles for robust batch jobs:
- Never retry immediately on 429. Back off before each retry attempt.
- Cap your retries (4–5 attempts is usually sufficient). After that, log the failure and move on so the rest of the batch can complete.
- Log failures with document IDs so you can re-run just the failed subset without re-processing the whole batch.
- Monitor
X-Render-StatusandX-Render-Diagnosticsacross your batch run — a rising share ofdegradedrenders or error-severity diagnostic codes can flag documents with missing glyphs, image fetch failures, or other issues. When you need a strict match to the source Markdown, also checkX-Render-Rendered-As-Requested. LogX-Request-Idfor any failures so support can trace them.
Shared Images: Stage Once, Reference Everywhere
Batch jobs often reuse the same logo or letterhead across every document. Instead of inlining that image as a largedata: URL in every request — which counts toward your input-size limit and bloats each payload — stage it once and reference it by handle:
- Stage it through the MCP
upload_imagetool — one call for a small image (or ordered parts for a larger one) that takes the image bytes (base64) and returns theblink://asset/<sha256>handle directly (identical bytes dedupe and return adupflag). The server hashes the bytes for you, so no client-side SHA-256 step and no presignedPUTare involved. - Reference it in every render as
.
upload_image handles one image at a time, so if a batch mixes several logos, stage each distinct image before referencing it.
Staged assets are fetched at render time and do not count toward the request input-size limit, they are content-addressed (identical bytes are stored once), and they are scoped per credential — so a handle staged with your batch key resolves in every POST /v1/render call that key makes. Assets live up to 24 hours, so one staging step covers a full batch run.
For image-only outputs — digitizing scans or assembling photo batches — use the imageSequence field to lay staged assets out as pages (one per page or a grid) without hand-writing Markdown. See Document Options.
Sizing Your Plan for Batch Workloads
Use this formula to estimate the minimum plan you need:Pro Plan — $9/mo
120 req/min · 30k render units/mo — Good for nightly batch jobs of a few hundred documents or on-demand runs of up to ~1,000 text documents.
Business Plan — $79/mo
600 req/min · 1M render units/mo — Suitable for large month-end batch runs, bulk document digitization, and high-frequency automated pipelines.
The Enterprise plan offers dedicated capacity with custom rate limits and no per-render metering — designed for workloads that require sustained high-volume generation. Contact sales to discuss capacity planning.