Reference

API quickstart

Two endpoints — /v1/pdf and /v1/screenshot. Send HTML or a URL, get a document or an image back. Authenticate with a bearer token.

Authentication

Pass your key in the Authorization header. The on-site playground uses a public, rate-limited demo key.

Authorization: Bearer sk_live_your_key

Generate a PDF

POST /api/v1/pdf
Content-Type: application/json

{
  "html": "<h1>Hello, PDF</h1>",
  "options": { "format": "A4", "printBackground": true }
}

Or render a live URL:

curl https://rendral.com/api/v1/pdf \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{ "url": "https://example.com" }' \
  --output page.pdf

Headers, footers & page numbers

Set pageNumbers: truefor a centered “N / total” footer, or supply your own header/footer HTML using Puppeteer's injected classes — pageNumber, totalPages, date, title.

{
  "html": "<h1>Report</h1>",
  "options": {
    "pageNumbers": true,
    "headerTemplate": "<div style='font-size:9px;width:100%;text-align:right;padding:0 12px'>Acme Inc.</div>",
    "displayHeaderFooter": true,
    "margin": { "top": "0.8in", "bottom": "0.8in" }
  }
}

Waiting for content

For pages that render asynchronously (charts, fonts, client-side data), control when capture happens.

{
  "url": "https://dashboard.example.com/report",
  "options": {
    "waitUntil": "networkidle0",
    "waitForSelector": "#chart.ready",
    "delay": 500
  }
}

PDF options

FieldTypeDefault
formatstringA4
width / heightstring— (overrides format)
landscapebooleanfalse
printBackgroundbooleantrue
scalenumber1
marginobject0.4in all sides
pageNumbersbooleanfalse
headerTemplate / footerTemplatestring (HTML)
pageRangesstringe.g. "1-3, 5"
preferCSSPageSizebooleanfalse
waitUntilstringnetworkidle0
waitForSelectorstring
delaynumber (ms)0
emulateMediaType"screen" | "print"print
cachebooleantrue

Screenshots

Same inputs, an image back — PNG, JPEG or WebP. Capture the full page, the viewport, or a single element.

POST /api/v1/screenshot

{
  "url": "https://example.com",
  "options": {
    "type": "png",
    "fullPage": true,
    "viewport": { "width": 1280, "height": 800 }
  }
}

Capture one element and keep transparency:

{
  "html": "<div id='card'>…</div>",
  "options": { "type": "png", "selector": "#card", "omitBackground": true }
}
FieldTypeDefault
type"png" | "jpeg" | "webp"png
fullPagebooleanfalse
selectorstring— (whole page)
qualitynumber (jpeg/webp)80
omitBackgroundbooleanfalse
clip{ x, y, width, height }
viewport{ width, height }800 × 600
deviceScaleFactornumber1

Open Graph images

POST /api/v1/og renders a 1200×630 social image. Pass a few fields for the built-in template, or your own html for full control.

{
  "title": "Ship PDFs without a browser",
  "description": "One API call. Real Chrome rendering.",
  "eyebrow": "Rendral",
  "theme": "dark"
}

Merge & watermark

Combine PDFs or stamp a watermark — pure and fast, no browser involved. Send PDFs as base64.

POST /api/v1/merge
{ "files": ["<base64 pdf>", "<base64 pdf>"] }

POST /api/v1/watermark
{ "file": "<base64 pdf>", "text": "CONFIDENTIAL",
  "options": { "opacity": 0.15, "rotate": 45 } }

Caching

Identical requests are cached for an hour and served instantly — responses carry an X-Cache: HIT or MISS header. Pass "cache": false in options to force a fresh render.

Client libraries

Official SDKs wrap every endpoint and return the raw bytes.

// Node — npm install @rendral/sdk
import { RenderClient } from "@rendral/sdk";
const client = new RenderClient(process.env.RENDER_API_KEY);
const pdf = await client.pdf({ html, options: { pageNumbers: true } });
# Python — pip install rendral
from rendral import RenderClient
client = RenderClient(os.environ["RENDER_API_KEY"])
pdf = client.pdf(html=html, options={"pageNumbers": True})

Idempotency

Send an Idempotency-Key header to make retries safe — a repeated request returns the original response (with Idempotency-Replayed: true) and doesn't count against your quota. Keys are remembered for 24 hours.

curl https://rendral.com/api/v1/pdf \
  -H "Authorization: Bearer sk_live_..." \
  -H "Idempotency-Key: order-1042-invoice" \
  -H "Content-Type: application/json" \
  -d '{ "html": "<h1>Invoice</h1>" }'

OpenAPI & agents

The full machine-readable spec lives at /openapi.json— point Postman, a client generator, or an AI coding assistant at it. There's also an /llms.txt summary written for agents.

Errors

Errors return JSON with a machine-readable code and a request_id (also in the X-Request-Id header — quote it when asking for support).

{ "error": "Invalid API key.", "code": "invalid_key", "request_id": "a1ab9015-…" }

Codes: missing_auth / invalid_key (401), invalid_request (400), blocked_url (400), rate_limited (429), quota_exceeded (402), render_failed (500).

Rendering runs on headless Chrome. URL rendering refuses internal / private hosts.