Renduo

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

  1. Sign in to the Renduo dashboard with Google or GitHub. Your first login automatically creates an organization and a production environment — no setup step needed.
  2. Go to Keys and create a new API key. For this guide, give it the generate and templates:write scopes (you'll register a template and generate a PDF).
  3. Copy the key immediately — it's shown once, in the form rnd_live_XXXXXXXXXXXX (or rnd_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_here

All requests to Renduo — via curl or the CLI — authenticate with:

Authorization: Bearer rnd_live_your_key_here

3. 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:

BasicDocument.tsx
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-document
Response
Template ID: 5f0c2e3a-...
Version:     1
Slug:        basic-document

Save 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.pdf

That'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.

On this page