Docs

Errors

Every failure is structured JSON with error.code. Branch on the code, not the HTTP status text. Failed operations, 429s, and 402s are never billed.

Every failure returns { "error": { "code", "message" } } plus optional details. SDKs throw RelayPDFError with status, code, message, and retryAfter when present.

Shape

Same envelope on all endpoints.

Error JSON
{
  "error": {
    "code": "invalid_request",
    "message": "Provide exactly one of `html`, `url`, `markdown`, or `templateId`."
  }
}

Codes

Use error.code for branching. HTTP status is the transport; the code is the cause.

codeTypical HTTPWhat to do
invalid_request400Check field names, types, and exclusive sources
unauthorized401Missing or unknown API key
account_suspended403Keys cannot be created or used
url_not_allowed400Private, loopback, or metadata host; or callbackUrl is not https
payload_too_large413Reduce HTML, files, or zip entries
not_found404Unknown job, file, or template
rate_limited429Honor Retry-After. Never billed
payment_required402Wallet empty — top up or enable auto-reload
quota_exceeded402/429Account limits; unbilled
render_failed502Chromium could not print the page; unbilled
processing_failed502PDF tool or job failed; unbilled
convert_unavailable503Document worker cold or unreachable; unbilled
ai_unavailable503Template generate backend unavailable; unbilled
storage_unavailable503Temporary file storage unavailable; unbilled
internal_error500Retry with backoff; unbilled

Billing

Failed operations, 429s, and 402s are never billed. Only a successful generation or conversion debits the wallet.