Rendex
Use Case

One Template + Data → Invoices, Reports & Certificates

Send an HTML or Markdown template with {{placeholders}} and a JSON data object. Rendex fills it with logic-less Mustache — loops, nested fields, HTML-escaped by default — and renders the result to an image or PDF. Design the layout once, generate thousands of personalized documents.

The Problem

Generating a personalized invoice, certificate, or report per record usually means string-concatenating HTML in application code, escaping customer data by hand (one miss is an injection bug), and redeploying every time someone tweaks the layout. The template ends up buried in your codebase instead of living where content belongs.

The Solution

Rendex renders the template for you. Keep your invoice or certificate as an HTML or Markdown template with {{placeholders}}, pass a row of data as a JSON object, and Rendex fills it with Mustache before capture — {{#items}} loops for line items, {{a.b}} for nested fields, and HTML-escaping by default so customer data can't break your layout. It works across every output format and the JSON endpoint.

See it in action

A Mustache HTML template with placeholders plus a JSON data object on the left, rendered by Rendex into a filled-in invoice document on the right.

Get Started in Minutes

invoice-from-template.sh
curl -X POST https://api.rendex.dev/v1/screenshot \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "markdown": "# Invoice {{number}}\n\n**Billed to:** {{client}}\n\n| Item | Qty | Amount |\n| --- | --- | --- |\n{{#items}}| {{name}} | {{qty}} | {{amount}} |\n{{/items}}\n\n**Total: {{total}}**",
    "data": {
      "number": "INV-2026-0042",
      "client": "Northwind Traders",
      "items": [
        { "name": "API calls (100k)", "qty": 1, "amount": "$49.00" },
        { "name": "Priority support", "qty": 2, "amount": "$8.00" }
      ],
      "total": "$57.00"
    },
    "format": "pdf",
    "pdfFormat": "A4"
  }' --output invoice.pdf
certificate-from-template.js
import Rendex from "@copperline/rendex";
import { writeFileSync } from "fs";

const rendex = new Rendex("YOUR_API_KEY");

// Store this template once; render one image per recipient.
const template = `
<div style="width:1200px;height:630px;display:flex;flex-direction:column;
  align-items:center;justify-content:center;gap:14px;font-family:Georgia,serif;
  background:#fffaf3;border:14px solid #d97706;color:#1c1917">
  <div style="letter-spacing:3px;color:#92400e">CERTIFICATE OF COMPLETION</div>
  <div style="font-size:56px;font-weight:700">{{name}}</div>
  <div style="font-size:22px">completed <strong>{{course}}</strong></div>
  <div style="color:#78716c">{{date}}</div>
</div>`;

const { image } = await rendex.screenshot({
  html: template,
  data: { name: "Dana Okafor", course: "Edge Rendering 101", date: "May 26, 2026" },
  format: "png",
  width: 1200,
  height: 630,
});
writeFileSync("certificate.png", Buffer.from(image));
reports_from_template.py
from rendex import Rendex
from pathlib import Path

rendex = Rendex("YOUR_API_KEY")

# One template, one render per customer record.
template = """
<div style="font-family:system-ui;padding:48px;max-width:760px">
  <h1>Usage report — {{month}}</h1>
  <p>Hi {{contact.name}}, here is {{company}}'s activity.</p>
  <ul>
    {{#metrics}}<li><strong>{{label}}:</strong> {{value}}</li>{{/metrics}}
  </ul>
</div>
"""

records = [
    {
        "month": "May 2026",
        "company": "Acme",
        "contact": {"name": "Lee"},
        "metrics": [
            {"label": "Renders", "value": "12,408"},
            {"label": "p95 latency", "value": "84 ms"},
        ],
    },
    # ...one dict per customer
]

for r in records:
    result = rendex.screenshot(html=template, data=r, format="pdf", pdf_format="A4")
    Path(f"report-{r['company']}.pdf").write_bytes(result.image)

100 free API calls/month — no credit card required. Get your API key and start building.

Built for This Use Case

Mustache Placeholders

Fill {{var}} with HTML-escaped values, or {{{var}}} for trusted raw HTML. Logic-less by design — your data shapes the document, not code.

Loops & Lists

{{#items}}…{{/items}} repeats a block per array element — invoice line items, table rows, bullet lists — and {{^empty}} handles the empty case.

HTML or Markdown Templates

Author the template in whichever you prefer. Both fill from the same data object, so a Markdown invoice and an HTML certificate share one workflow.

Escaped by Default

{{var}} is HTML-escaped, so customer names, notes, and amounts can't break your layout or inject markup. Opt into raw output explicitly with {{{var}}}.

One Template, Many Documents

Invoices, receipts, certificates, reports, badges, OG cards — change the data, not the template. Store the layout once and render per record.

Every Output Format

Render templated output to PNG, JPEG, WebP, or PDF, plus the /v1/screenshot/json endpoint for base64 + metadata.

Start Free, Scale as You Grow

100 calls/month free. Starter at $69/mo for 10K calls (or $58/mo billed annually — 2 months free). Pro at $179/mo for 100K calls.

Frequently Asked Questions

Related Resources