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.
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
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.pdfJavaScript (fetch / Node.js)
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)
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.
| Header | Example | Meaning |
|---|---|---|
Content-Type | application/pdf | Type of binary returned. |
X-Render-Ms | 11 | Render time in milliseconds (native engine). |
X-Render-Bytes | 18234 | File size in bytes. |
X-Render-Engine | native | Engine used: native or chromium. |
X-Renderly-Document-Hash | a1b2… | SHA-256 of the bytes delivered. |
X-Renderly-Verify-Url | .../verify/… | Public verification page. |
X-Renderly-Verify-Id | uuid | Id 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.
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.pdfhtml or template. If you send a template that does not exist in your organization, you get 404 template_not_found. See Templates.Production checklist
| Item | Why |
|---|---|
| Key in an environment variable | Never commit it, never on the front-end. |
| Handle status != 200 | Errors come as JSON { error: { code, message } }. |
| 60s client timeout | Heavy documents can get close to the limit. |
| Store the X-Renderly-Verify-Id | Lets you link the document to the verification page later. |
| Monitor your quota | Avoid the 402 quota_exceeded at the end of the month. |
Renderly