Getting started

Quickstart

In just a few minutes you go from signing up to a PDF saved on disk. This page walks through each step and shows the same request in curl, JavaScript (fetch) and Python (requests).

1. Create your account and generate the API key

Open the Dashboard and generate a key. Every production key has the rndr_live_ prefix. For security, the full key is shown only once — copy it and store it in a secrets vault (environment variable, secret manager). Internally we keep only its SHA-256 hash.

Never expose the key on the front-end
The rndr_live_ grants full access to your organization. Use it only on the server. If it leaks, revoke it right away from the Dashboard and generate a new one — revocation is instant.

2. Make your first call

The endpoint is POST /v1/render. Send a JSON body with html (raw HTML) and, optionally, data to fill the {{...}} variables. The example below generates a simple invoice.

curl

bash
curl -X POST https://api.renderly.dev/v1/render \
  -H "Authorization: Bearer rndr_live_SEU_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "html": "<h1 style=\"font-family:sans-serif\">Invoice #{{number}}</h1><p>Customer: {{customer}}</p><p>Total: <strong>{{total}}</strong></p>",
    "data": { "number": "001", "customer": "Acme Inc.", "total": "$1,480.00" },
    "format": "pdf"
  }' --output invoice.pdf

JavaScript (fetch / Node.js)

node
const res = await fetch("https://api.renderly.dev/v1/render", {
  method: "POST",
  headers: {
    "Authorization": "Bearer rndr_live_SEU_TOKEN",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    html: "<h1>Invoice #{{number}}</h1><p>Total: {{total}}</p>",
    data: { number: "001", total: "$1,480.00" },
    format: "pdf",
  }),
})

if (!res.ok) {
  const { error } = await res.json()
  throw new Error(`${error.code}: ${error.message}`)
}

// The response IS the PDF. Read it as bytes.
const buffer = Buffer.from(await res.arrayBuffer())
await require("node:fs/promises").writeFile("invoice.pdf", buffer)

console.log("hash:", res.headers.get("X-Renderly-Document-Hash"))
console.log("verify at:", res.headers.get("X-Renderly-Verify-Url"))

Python (requests)

python
import requests

res = requests.post(
    "https://api.renderly.dev/v1/render",
    headers={"Authorization": "Bearer rndr_live_SEU_TOKEN"},
    json={
        "html": "<h1>Invoice #{{number}}</h1><p>Total: {{total}}</p>",
        "data": {"number": "001", "total": "$1,480.00"},
        "format": "pdf",
    },
    timeout=60,
)
res.raise_for_status()

with open("invoice.pdf", "wb") as f:
    f.write(res.content)

print("hash:", res.headers["X-Renderly-Document-Hash"])
print("verify at:", res.headers["X-Renderly-Verify-Url"])

3. Understand the response

On success the response is not JSON: the body is the binary of the file (PDF by default). The metadata comes in the headers — including the render time, the size, the engine used and the verification data.

HeaderExampleMeaning
Content-Typeapplication/pdfType of binary returned.
X-Render-Ms11Render time in milliseconds (native engine).
X-Render-Bytes18234File size in bytes.
X-Render-EnginenativeEngine used: native or chromium.
X-Renderly-Document-Hasha1b2…SHA-256 of the bytes delivered.
X-Renderly-Verify-Url.../verify/…Public verification page.
X-Renderly-Verify-IduuidId of the recorded issuance.

See the full response contract and every body parameter on the Render endpoint page.

4. Next level: use a saved template

Sending raw HTML every time works, but the recommended way for recurring documents is to save a template in the visual editor and call it by its slug. The slug is live the moment you save in the editor — there is no publish step. From then on you only send the data — tables, QR codes and charts are resolved on the server.

POST /v1/render — via template
curl -X POST https://api.renderly.dev/v1/render \
  -H "X-API-Key: rndr_live_SEU_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "template": "invoice",
    "data": { "customer": "Acme Inc.", "items": [
      { "description": "Pro Plan", "amount": "$99.00" }
    ] }
  }' --output invoice.pdf
html OR template, never both required
Every request needs html or template. If you send a template that does not exist in your organization, you get 404 template_not_found. See Templates.

Production checklist

ItemWhy
Key in an environment variableNever commit it, never on the front-end.
Handle status != 200Errors come as JSON { error: { code, message } }.
60s client timeoutHeavy documents can get close to the limit.
Store the X-Renderly-Verify-IdLets you link the document to the verification page later.
Monitor your quotaAvoid the 402 quota_exceeded at the end of the month.
Next
Authentication
API keys, accepted headers, security and key rotation.