Skip to main content
Blink PDF enforces rate limits to keep rendering quality consistent and fair for every customer. Limits are applied per API key and reset on a rolling basis. This page explains what each limit means, how to stay within it, and what to do when you hit one.

Limits by Plan

There is no daily cap on any plan — usage is metered monthly in units. Fill and render share that allowance. Stored-template object caps (10 / 50 / 250) live on Pricing. They are not this page’s rate bucket and they are not the persistent-PDF cap.

Understanding Each Limit

Sustained Rate

The sustained rate is the maximum number of metered PDF requests you can make in any 60-second window. POST /v1/fill, POST /v1/render, and POST /v1/templates/*/render share this bucket. Short bursts slightly above this rate may succeed, but requests that consistently exceed it will receive 429 Too Many Requests responses.

Concurrency

Concurrency controls how many metered PDF jobs can be in-flight simultaneously on your account (shared across POST /v1/fill, POST /v1/render, and sandwich template routes). A request occupies a concurrency slot from the moment the server accepts it until the PDF response is returned. If you hit the concurrency ceiling, new requests block until a slot frees up or return 429 depending on your client configuration.
If you need to render many PDFs quickly, pipeline your requests up to your concurrency limit rather than sending them sequentially. For example, a Pro account can keep 10 renders running at once, which is far more efficient than waiting for each one to finish before starting the next.

Validate has its own rate-limit bucket

POST /v1/render/validate is rate-limited per plan tier in its own bucket, kept independent from POST /v1/render. A burst of validation calls never spends your render throughput, and a burst of renders never throttles your validation — each can return 429 independently of the other. Validation still consumes no units.

Max input size (bodyBytes)

Plan bodyBytes caps a Markdown render body and a fill-by-bytes body (JSON or multipart pdf on POST /v1/fill): 128 KiB / 2 MiB / 5 MiB. Oversize is 413 payload_too_large and names bodyBytes. Fill-by-id does not re-check the stored PDF against bodyBytes. On Free, a real form does not fit in 128 KiB — store the blank, then fill by id. Inspect and validate-fill do not apply bodyBytes to live pdf bytes.
For Markdown renders, this limit applies to the request body, not the final PDF file size. Images staged out of band and referenced with blink://asset/<id> handles are fetched at render time and do not count toward this limit — only inline data: images and Markdown text do.

Template upload (maxTemplateBytes)

A stored template is not a render JSON body. Store and replace use maxTemplateBytes: 5 / 10 / 20 MiB. Oversize is 413 payload_too_large and names maxTemplateBytes. A 20 MiB form is the Business upload cap — a named limit, not a mystery 413. Enterprise can raise this byte cap. Do not expect a 20 MiB form to pass as fill-by-bytes. That path still uses bodyBytes (5 MiB on Business). Store it, then fill by id.

What Counts Toward Your Usage

Only successful fills and renders consume units. A call is counted only when the API returns a valid PDF response (HTTP 200) and its X-BlinkPDF-Billing header is counted — that includes POST /v1/fill, POST /v1/render, and POST /v1/templates/*/render. A fill is 1 unit on the same allowance as render. Cache and idempotent replays on /v1/render (deduped-cache / deduped-idempotent) are not billed. Fill honors x-idempotency-key (counted / deduped-idempotent) and does not use the render LRU (deduped-cache does not apply).

What Does NOT Count

The following never consume units:
  • GET /health and any health-check endpoints
  • POST /v1/render/validate (though it has its own rate-limit bucket, above)
  • POST /v1/inspect and POST /v1/validate-fill
  • Storing, listing, getting, updating, or deleting a blank template
  • Font, theme, and style-target catalog listings
  • MCP persist_pdf, list_pdfs, delete_pdf, and template-library tools
  • Requests that return any error status (400, 401, 402, 405, 413, 422, 429, 5xx)
  • Retried requests that ultimately fail

Handling HTTP 429 Too Many Requests

When you exceed your rate limit, the API responds with:

Retry Strategy

Use exponential backoff with jitter when retrying after a 429. A simple recipe:
For example, in Python:
Always respect the Retry-After header value. Retrying immediately after a 429 will not succeed and may result in your key being temporarily throttled further.

Monthly Spending Cap

On Pro and Business plans, you can set a configurable monthly spending cap in your account dashboard. Each paid plan also has a fixed hard cap at 2× its included volume. When your usage reaches the cap:
  • The API returns a clear 402 error with the reason spend_cap_reached
  • No further charges are incurred for that billing period
  • The cap resets automatically at the start of your next billing cycle
The spending cap is optional. If you don’t set one, your account follows soft overage billing — you’re never cut off, but overage charges apply beyond your included quota.

Upgrading for Higher Limits

If you consistently hit rate or concurrency limits, the most effective solution is to upgrade your plan. Limits increase significantly with each tier. Need limits beyond the Business plan? Contact our team to discuss an Enterprise arrangement with dedicated capacity and custom throughput agreements.