Skip to content
Get started

Errors & limits

Every error response has the same shape:

{
"error": {
"code": "validation_failed",
"message": "Invalid input",
"details": [{ "field": "/customer/name", "reason": "Required property 'name' is missing" }]
},
"meta": { "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736" }
}

Branch on code, which is stable, not on message, which is meant for people. details is present for some codes, described below. Quote meta.trace_id when you contact support about a failed request.

Status code Meaning
400 validation_failed The request or the render data is invalid. details lists each field. See Data & JSON Schema.
400 invalid_json The body isn’t valid JSON.
401 unauthorized The API key is missing, wrong or deleted.
402 plan_limit_exceeded A plan quota is used up, such as monthly renders or the number of templates.
403 forbidden The API key lacks the permission this call needs, such as render.
404 not_found The template, version, file or job doesn’t exist in this workspace. A template with no published version also returns 404 for its latest version.
406 not_acceptable The Accept header asks for an unsupported format.
409 conflict The change conflicts with the current state, such as a duplicate asset alias.
410 workspace_scheduled_for_deletion The workspace is being deleted and is read-only.
412 conflict The If-Match header no longer matches. Reload and retry.
422 render_failed The template failed while rendering. See below.
429 rate_limit_exceeded Too many requests. See Rate limits.
5xx internal_error, storage_error Something went wrong on our side. Retry with backoff.

A 422 render_failed means the data was valid but the template couldn’t render it. details points at the failing spot:

{
"error": {
"code": "render_failed",
"message": "Template error in main.html at line 2: wrong type for value; expected float64; got string",
"details": [
{
"file": "main.html",
"line": 2,
"column": 30,
"field": ".total",
"reason": "wrong type for value; expected float64; got string"
}
]
}
}

Here the data sent "total": "12,50", a string, to a function that needs a number. A schema typing total as number would have caught it earlier, as a 400 naming the field.

Render errors caused by the template are deterministic, so retrying won’t help. Render jobs retry only temporary failures; see Retries.

Render calls are rate limited per workspace and per minute, with higher limits on higher plans. See Pricing for each plan’s limits and monthly render quota.

Every rate-limited response carries:

Header
X-RateLimit-Limit Requests allowed in the current window
X-RateLimit-Remaining Requests left in the current window
X-RateLimit-Reset When the window resets, in Unix seconds

Over the limit, the API answers 429 rate_limit_exceeded with a Retry-After header in seconds. Wait that long before retrying. The limit is shared by all of the workspace’s API keys, and covers both POST /v1/render and POST /v1/render/jobs.

Limit
Render time 45 seconds per document
Asset size 10 MB per file
Page size 200 inches on either side
Tags per file 10, up to 128 characters each
Webhook endpoints 10 per workspace