Quickstart
Get an API key, push a React component, and generate your first PDF in a few minutes.
Renduo generates production-quality PDFs — invoices, receipts, contracts — from component-first templates: a real React component you register once, executed in an isolated browser sandbox on each request. You write the component and compile it locally; Renduo bakes it into a self-contained HTML shell and, per request, injects only the data.
This guide takes you from zero to your first generated PDF.
1. Create an API key
- Sign in to the Renduo dashboard with Google
or GitHub. Your first login automatically creates an organization and a
productionenvironment — no setup step needed. - Go to Keys and create a new API key. For this guide, give it the
generateandtemplates:writescopes (you'll register a template and generate a PDF). - Copy the key immediately — it's shown once, in the form
rnd_live_XXXXXXXXXXXX(orrnd_test_...for a test-mode key).
Keep it somewhere safe — treat it like a password. If you ever need a new one, revoke the old key from the dashboard and create another.
2. Set your API key as an environment variable
export RENDUO_API_KEY=rnd_live_your_key_hereAll requests to Renduo — via curl or the CLI — authenticate with:
Authorization: Bearer rnd_live_your_key_here3. Write and push a component
A template is a React component that reads its props from
window.__RENDUO_PROPS__. Here's a minimal invoice — a title, a customer
line, an itemized table, and a total:
const props = JSON.parse(window.__RENDUO_PROPS__)
export default function BasicDocument() {
return (
<div style={{ fontFamily: 'sans-serif', padding: 40 }}>
<h1 style={{ fontSize: 28, marginBottom: 24 }}>{props.title}</h1>
<p style={{ fontSize: 14, color: '#555' }}>Customer: {props.customer.name}</p>
<table style={{ width: '100%', borderCollapse: 'collapse' }}>
<tr>
<th style={{ textAlign: 'left', padding: 8 }}>Description</th>
<th style={{ textAlign: 'right', padding: 8 }}>Total</th>
</tr>
{props.items.map((item, i) => (
<tr key={i}>
<td style={{ padding: 8 }}>{item.description}</td>
<td style={{ textAlign: 'right', padding: 8 }}>{item.amount}</td>
</tr>
))}
</table>
<p style={{ marginTop: 24, fontSize: 16, fontWeight: 600 }}>Total: {props.total}</p>
</div>
)
}Register it with the CLI (which bundles locally with esbuild and uploads):
npm install -g @renduo/cli
renduo push BasicDocument.tsx --slug basic-documentTemplate ID: 5f0c2e3a-...
Version: 1
Slug: basic-documentSave the templateId — you'll need it to generate documents.
Or, with a direct POST to /v1/templates (multipart: slug, name, and the
IIFE bundle compiled with esbuild).
4. Generate your first PDF
TEMPLATE_ID="5f0c2e3a-..." # from step 3
curl -X POST https://api.renduo.dev/v1/generate \
-H "Authorization: Bearer $RENDUO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"templateId": "'"$TEMPLATE_ID"'",
"mode": "sync",
"payload": {
"title": "Invoice 2026-001",
"customer": { "name": "Acme Corp" },
"items": [
{ "description": "Starter Plan", "amount": 19000 },
{ "description": "Tax (19%)", "amount": 3610 }
],
"total": 22610
}
}' | python3 -c "
import sys, json, base64
data = json.load(sys.stdin)
open('output.pdf', 'wb').write(base64.b64decode(data['pdf']))
print(f'Saved output.pdf ({data[\"durationMs\"]}ms)')
"mode: "sync" waits for the PDF and returns it as base64 directly — ideal for
on-demand generation where a user is waiting on screen. For high-volume or
background generation, see async, retention & webhooks.
Or, with the CLI:
renduo generate "$TEMPLATE_ID" \
--props '{"title":"Invoice 2026-001","customer":{"name":"Acme Corp"},"items":[{"description":"Starter Plan","amount":19000},{"description":"Tax (19%)","amount":3610}],"total":22610}' \
--output invoice.pdfThat's it — you've registered a real React template and generated a PDF end to end.
Prefer Node.js? The SDK cuts this down to a few lines
If your backend is TypeScript or Node.js, the official
@renduo/sdk does the base64 decoding, error
parsing, and polling for you — no need for the curl + python3 pipe above:
import { Renduo } from '@renduo/sdk'
import { writeFile } from 'node:fs/promises'
const renduo = new Renduo({ apiKey: process.env.RENDUO_API_KEY! })
const { pdf } = await renduo.generate({ templateId: TEMPLATE_ID, payload: { /* same payload */ } })
await writeFile('invoice.pdf', pdf)It's optional — the API works the same with plain curl. Think of it as a
shortcut, not a requirement: if you're not on Node.js, ignore it.
Next steps
- Read the CLI reference for the full command surface.
- Explore concepts to understand the component-first model, versions, environments & keys, and plans.
- Follow the guides for deeper workflows — CLI iteration, async + webhooks, custom fonts, the Node.js SDK, and backend examples.
- See the API reference for every endpoint, request and response shape.