Errors
Errors come back as RFC 9457 problem+json. Every response carries a correlationId; quote it when you contact support.
| Status | Meaning | What to do |
|---|---|---|
401 | Key missing or invalid | Check the X-PDFgine-Key header and that the key has not been revoked. |
402 | Quota exhausted | Upgrade the plan or wait for the period to renew. |
404 | Template or document not found | Verify the template code and that it has a published revision. |
429 | Rate limit exceeded | Wait the number of seconds in the Retry-After header, then retry. |
Rate limits come with the plan
The per-minute and hourly ceilings on the generation endpoints are per TENANT and come from your plan; the table below lists them. Because the ceiling counts per tenant rather than per key, adding a second API key does not raise it. A 429 response names the window you hit in the X-PDFgine-RateLimit-Scope header: tenant-api, tenant-render-minute or tenant-render-hour. For bulk work, send up to 100 documents in one /document-batches request instead of one document per request.
HTTP/1.1 402 Payment Required
X-PDFgine-Quota-Remaining: 0
X-PDFgine-Metering-Basis: pdf-equivalent
{
"title": "Page quota exceeded",
"status": 402,
"detail": "Your plan has used up its available page quota.",
"correlationId": "114249cb1dbc52a29026ab2eca5c4b72"
}
Retry-After and the window
Two ceilings apply, one after the other. The first protects the service and counts per credential: 30 requests per window without a key, 120 with one, over a 60 second window. The second comes from your plan and counts per tenant.
| Plan | Documents / minute | Documents / hour |
|---|---|---|
| Free | 15 | 150 |
| Go | 30 | 300 |
| Pro | 60 | 600 |
| Max | 300 | 3,000 |
HTTP/1.1 429 Too Many Requests
Retry-After: 60
X-PDFgine-RateLimit-Scope: tenant-render-minute
{
"title": "Too many requests",
"status": 429,
"detail": "The request limit was exceeded. Please try again later.",
"correlationId": "505aac87e234a7b4669e6203ac7ffcd5"
}
The window is fixed, not sliding: it opens on the first request and every request inside it counts against the same allowance, then the count resets. Retry-After is the number of seconds left in that window - waiting exactly that long is enough, and retrying sooner only spends another refusal.
What usually goes wrong
- A 4xx repeated unchanged fails again. These say the request is wrong, not that the service is busy; only 429 and 5xx are worth retrying.
- On 429 the answer already carries Retry-After. Backing off by your own guess either wastes time or walks straight into the next refusal.
- 402 is not a fault to page someone about at three in the morning. It means the month is spent; watch X-PDFgine-Quota-Remaining and raise the plan before it happens.
- 410 on a download is not a lost file. Retention ended: the document was produced, counted and then removed on the schedule your plan sets.
- Logging only the status code makes a support request a guessing game. Log correlationId with it; that one value finds the request.