Skip to main content
Errors are RFC 7807 Problem Details documents (application/problem+json). The shape:
{
  "title": "Human-readable summary",
  "status": 422,
  "detail": "More specific detail, usually the first error's message",
  "errors": [
    { "code": "template.too_complex", "message": "…" }
  ]
}
Branch on status and on the code inside errors. The code strings are stable; title/detail/message are for humans and may be reworded. (Responses also carry a type URI, per the RFC 7807 default for the status code.)

Status codes at a glance

StatusMeaningcode(s)errors array?
400Malformed or incomplete requestno
401Authentication failedno
402Monthly quota reachedquota.exceededyes
413Request body too largeno
422Template unusabletemplate.*yes
429Rate limit / playground caprate_limit.exceededyes
500Unexpected server errorno

400 Bad Request

Two cases, distinguished by title: The body isn’t valid JSON, or can’t be parsed into a template. Malformed JSON, wrong field types, or a missing/unknown node type — an unknown type is rejected here by the parser, before validation. detail carries the parser’s message.
{ "title": "Invalid request body", "status": 400, "detail": "Unknown node type: 'foo'." }
The body is valid JSON but omits the template field.
{ "title": "Invalid request", "status": 400, "detail": "Request body must include 'template' and 'data'." }
Neither carries an errors array. Fix the request shape and retry.
A missing data is not a 400 — data defaults to empty, so the request proceeds and any unfilled {{tokens}} surface as a 422 missing-data (or it renders, if the template has no tokens).

401 Unauthorized

The API key is missing, malformed, or revoked. The response carries a WWW-Authenticate: Bearer header; the body is a Problem Details document without an errors array, so branch on the status code. The request never reaches the renderer, so no quota or rate budget is spent. See Authentication.

402 Payment Required

Your plan’s monthly document quota is used up. The request is blocked, not billed — Tipar never charges overage you didn’t choose.
{
  "title": "Monthly quota exceeded",
  "status": 402,
  "detail": "Monthly document quota reached for your plan. Upgrade to keep generating.",
  "errors": [
    { "code": "quota.exceeded", "message": "Monthly document quota reached for your plan. Upgrade to keep generating." }
  ]
}
Upgrade your plan in the dashboard, or wait for the quota to reset at the start of the month. Quota sizes are on the pricing page.

413 Payload Too Large

The request body exceeded the cap — 4 MB for /generate, 256 KB for the playground. Almost always an oversized base64 image; downscale it before encoding.

422 Unprocessable Entity

The body was valid JSON and well-formed, but the template couldn’t produce a document. This is the error you’ll meet while building templates. Every problem is reported at once, so one response shows everything to fix. The code tells you which kind:
A {{path}} in the template has no matching value in data. One entry per missing path; the path is in message.
{
  "title": "Template references missing data",
  "status": 422,
  "errors": [
    { "code": "template.missing_data", "message": "invoice.total" },
    { "code": "template.missing_data", "message": "customer.name" }
  ]
}
Fix: add the missing fields to data, or correct the path in the template.
Render failures surface as 422, not 500. A genuine 500 from /generate is rare and should be treated as a bug — please report it.

429 Too Many Requests

You exceeded a rate limit. The response carries a Retry-After header (seconds).
{
  "type": "https://tools.ietf.org/html/rfc6585#section-4",
  "title": "Too Many Requests",
  "status": 429,
  "detail": "Rate limit exceeded. Slow down and retry after the Retry-After period.",
  "errors": [
    { "code": "rate_limit.exceeded", "message": "Rate limit exceeded." }
  ]
}
On the playground, the same status carries a message about the daily cap instead. Wait Retry-After seconds and retry.

500 Internal Server Error

An unexpected server-side failure. Recoverable template and render problems are reported as 4xx (mostly 422), so a 500 is unusual — retry, and if it persists, check status or report it.

Handling errors well

Branch on code, show message

Switch on status and errors[].code in code; surface message/title to humans.

Respect Retry-After

On 429, wait the header’s seconds before retrying rather than hammering.

Treat 422 as a dev-time signal

Missing-data and structural 422s mean a template/data mismatch — fix the template, not the runtime.

Don't retry 4xx blindly

400/401/402/422 won’t succeed on retry without a change. Only 429 (and transient 500) are worth retrying as-is.