Error response format
Every error response includes at least:error: A plain-language sentence describing the problem.hint: Optional actionable suggestion. Present on many (but not all) errors.
resetAt can be:
- millisecond Unix timestamp (rate limits)
- ISO timestamp string (renewing quotas)
null(non-renewing free-tier quotas)
used:
HTTP status codes
| Status | Meaning |
|---|---|
200 | Success |
202 | Job accepted (async only) |
307 | Redirect to download URL |
400 | Bad request: fix your request body |
401 | Unauthorized: check your API key |
403 | Forbidden: feature not available on your plan |
404 | Not found: check IDs and account ownership |
409 | Conflict: action not possible in current state |
413 | Payload too large: reduce request size |
422 | Validation error: template or data violates a limit |
429 | Too many requests: rate limited or quota exhausted |
500 | Internal server error: unexpected failure |
502 | Bad gateway: PDF generation service unreachable |
504 | Gateway timeout: generation took too long |
Errors by status
HTTP 400: Bad request
Something about the request body is malformed or missing.| Scenario | Error message |
|---|---|
| Request body is not valid JSON | Request body must be valid JSON. |
data is an array instead of an object | The data field must be a JSON object, not an array or primitive. |
jsonData does not parse to an object | The jsonData field must be a valid JSON object, not an array or primitive. |
webhookUrl is provided without webhookSecret | webhookSecret is required when webhookUrl is provided. |
webhookUrl is not a valid public HTTPS URL | Webhook URL must be a valid public HTTPS URL. |
error field first, then hint when present.
HTTP 401: Unauthorized
HTTP 403: Forbidden
A feature you are trying to use is not available on your current plan. The response body includes anerror and hint field.
Fix: Upgrade your plan in the dashboard if the hint refers to a paid feature.
HTTP 404: Not found
| Scenario | Error message |
|---|---|
| Template ID is wrong or belongs to another account | Template not found. It may not exist or may belong to a different account. |
| Job ID is wrong or belongs to another account | Job not found. It may not exist, may have expired, or may belong to a different account. |
| Completed job file was deleted or expired | Could not generate a download URL. The file may have been deleted or expired. |
HTTP 409: Conflict
Returned when you try to download a job that has not yet completed.GET /api/v1/jobs/:jobId until status is "completed", then download.
HTTP 413: Payload too large
The request or one of its parts is too large.| What exceeded the limit | Error message |
|---|---|
| Total request body (512 KB) | Request body exceeds 524288 bytes. |
| HTML template (200 KB) | HTML template exceeds 204800 bytes. |
| Custom CSS (100 KB) | Custom CSS exceeds 102400 bytes. |
| Data JSON (256 KB) | Data JSON exceeds 262144 bytes. |
HTTP 422: Validation error
The request is well-formed but violates a structural or complexity limit.| Scenario | Error message |
|---|---|
| Data nested more than 12 levels | Data depth exceeds 12. |
| An array has more than 1 000 items | At least one array exceeds 1000 items. |
| Template has more than 2 000 Liquid tokens | Liquid token count exceeds 2000. |
| Inline base64 images exceed 5 MB | Inline base64 image payload exceeds 5242880 bytes. |
| More than 100 external asset URLs | External asset URL count exceeds 100. |
| Header/footer field longer than 512 chars | Header/Footer fields must be 512 characters or fewer. |
| Rendered PDF is larger than 20 MB | Rendered PDF exceeds 20971520 bytes. |
| Rendered PDF has more than 200 pages | Rendered PDF exceeds 200 pages. |
HTTP 429: Too many requests
Common scenarios that use 429:Rate limit (per-minute window)
You sent too many requests in a short period.resetAt (millisecond Unix timestamp) before retrying.
Monthly quota exhausted
Your account has used its monthly page allowance.resetAt, or upgrade your plan.
Active job limit
Too many async jobs are in progress at the same time.Render queue saturation (rare)
If the render service is temporarily saturated, sync generation can return:HTTP 500: Internal server error
An unexpected error occurred on the server.x-request-id response header if present.