Errors
Errors return the matching HTTP status and a JSON body of the shape { "error": { "code", "message" } }. Branch on the stable code rather than the human-readable message.
| Status | Code | Meaning |
|---|---|---|
401 | missing_api_key | No API key was provided. |
401 | invalid_api_key | The key is invalid or revoked. |
402 | quota_exceeded | Monthly PDF quota reached — upgrade your plan. |
404 | template_not_found | No template with that id exists for your account. |
429 | rate_limited | Too many requests — retry after the Retry-After delay. |
422 | invalid_json | The request body was not valid JSON. |
422 | missing_template_id | The 'template_id' field is required. |
422 | data_too_large | The 'data' payload exceeds 256 KB. |
422 | template_compile_error | The template has a syntax error. |
422 | template_render_error | The template failed to render with this data. |
502 | render_failed | The render service returned an error. |
504 | render_timeout | Rendering took longer than 20 seconds. |
402, 429, 502 and 504 are safe to retry with backoff — for 429, wait for the Retry-After header; 4xx validation errors are not — fix the request first.
Every /v1/generate response includes X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset so you can pace requests before hitting a 429.