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_keyGenerate 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.pdfHeaders, 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
| Field | Type | Default |
|---|---|---|
| format | string | A4 |
| width / height | string | — (overrides format) |
| landscape | boolean | false |
| printBackground | boolean | true |
| scale | number | 1 |
| margin | object | 0.4in all sides |
| pageNumbers | boolean | false |
| headerTemplate / footerTemplate | string (HTML) | — |
| pageRanges | string | e.g. "1-3, 5" |
| preferCSSPageSize | boolean | false |
| waitUntil | string | networkidle0 |
| waitForSelector | string | — |
| delay | number (ms) | 0 |
| emulateMediaType | "screen" | "print" | |
| cache | boolean | true |
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 }
}| Field | Type | Default |
|---|---|---|
| type | "png" | "jpeg" | "webp" | png |
| fullPage | boolean | false |
| selector | string | — (whole page) |
| quality | number (jpeg/webp) | 80 |
| omitBackground | boolean | false |
| clip | { x, y, width, height } | — |
| viewport | { width, height } | 800 × 600 |
| deviceScaleFactor | number | 1 |
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.