Auto-Generate Invoice PDFs from Stripe in n8n
Turn every Stripe payment into a branded, print-ready PDF invoice with one n8n workflow. Stripe fires, n8n maps the line items, Rendex renders the HTML template to PDF, and the customer gets their receipt — automatically.
Last updated 2026-07-21
The Problem
Stripe sends a payment confirmation, but its built-in invoices are rigid — you can't fully control the layout, branding, or the fields, and customers often ask for a proper PDF you can't easily produce on the fly. Rolling your own means hosting Puppeteer or wrestling with wkhtmltopdf inside an n8n worker, which breaks fonts, drops modern CSS, and adds infrastructure you have to babysit.
The Solution
Design the invoice once as an HTML template with {{customerName}}, {{invoiceNumber}}, {{lineItems}}, and {{total}} placeholders. On each Stripe payment, n8n maps the event into a data object and posts it to Rendex, which renders the template to a print-ready A4 PDF with full modern CSS — Flexbox, Grid, web fonts, print backgrounds. Email the PDF directly, or request a hosted signed link to drop into the email body. All on Rendex's free tier.
How the Workflow Runs
Stripe Trigger
Fires on checkout.session.completed / invoice.paid
Set / Function
Build customer, invoice number, and line-item data from the event
Rendex
Render the HTML invoice template to a print-ready PDF (and/or a hosted link)
Gmail / SMTP
Email the PDF to the customer (+ archive to Drive or S3)
Input → Rendered Output

Rendered by Rendex
What You Need
- A Rendex API key — the free tier gives you 100 renders/month with no card required
- n8n (cloud or self-hosted) with the Rendex community node installed and Stripe credentials connected
- An invoice HTML template with {{customerName}}, {{invoiceNumber}}, {{lineItems}}, and {{total}} placeholders (line items rendered as table rows)
- An email node (Gmail, SMTP, or your provider) and optionally a Drive/S3 node to archive the PDF
What This Recipe Uses
HTML to PDF
Render your invoice template to a print-ready A4 PDF with full modern CSS — Flexbox, Grid, custom fonts, and print backgrounds. No headless browser to host.
Mustache data{} templating
Send one reusable HTML template plus a data object. {{customerName}}, {{invoiceNumber}}, and {{lineItems}} are filled in server-side per payment.
Hosted invoice links
Call /v1/render/link to get a signed URL for the invoice and email a short link instead of an attachment — first crawl renders and caches, repeats are free.
Free-tier ready
PDF output, data templating, and hosted links are all available on the free plan. 100 renders/month covers most small-business billing volume.
Build It
{
"parameters": {
"resource": "screenshot",
"operation": "capture",
"source": "html",
"html": "<!doctype html><html><head><meta charset=\"utf-8\"><style>body{font-family:system-ui,Segoe UI,Roboto,sans-serif;color:#0f172a;margin:0;padding:48px;}h1{color:#ea580c;font-size:24px;margin:0 0 4px;}table{width:100%;border-collapse:collapse;margin-top:28px;}th,td{padding:10px 12px;text-align:left;}thead th{border-bottom:2px solid #e2e8f0;font-size:12px;text-transform:uppercase;color:#64748b;}tbody td{border-bottom:1px solid #f1f5f9;}td.amt,th.amt{text-align:right;}tfoot td{font-weight:700;font-size:16px;padding-top:16px;}</style></head><body><h1>Invoice {{invoiceNumber}}</h1><p>Billed to {{customerName}}</p><table><thead><tr><th>Description</th><th class=\"amt\">Amount</th></tr></thead><tbody>{{#lineItems}}<tr><td>{{description}}</td><td class=\"amt\">{{amount}}</td></tr>{{/lineItems}}</tbody><tfoot><tr><td>Total</td><td class=\"amt\">{{total}}</td></tr></tfoot></table></body></html>",
"templateData": {
"customerName": "={{ $json.customer_details.name }}",
"invoiceNumber": "={{ 'INV-' + $json.id.slice(-8).toUpperCase() }}",
"total": "={{ '$' + ($json.amount_total / 100).toFixed(2) }}",
"lineItems": "={{ $json.line_items.map(li => ({ description: li.description, amount: '$' + (li.amount_total / 100).toFixed(2) })) }}"
},
"format": "pdf",
"pdfFormat": "A4",
"pdfPrintBackground": true,
"pdfMargin": { "top": "24px", "right": "24px", "bottom": "24px", "left": "24px" }
},
"name": "Rendex — Render Invoice PDF",
"type": "n8n-nodes-rendex.rendex",
"typeVersion": 1
}curl -X POST https://api.rendex.dev/v1/screenshot \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
--output invoice-INV-9X2K7Q.pdf \
-d '{
"html": "<!doctype html><html><head><style>body{font-family:system-ui,sans-serif;color:#0f172a;padding:48px;}h1{color:#ea580c;margin:0 0 4px;}table{width:100%;border-collapse:collapse;margin-top:28px;}th,td{padding:10px 12px;}td.amt,th.amt{text-align:right;}thead th{border-bottom:2px solid #e2e8f0;}tbody td{border-bottom:1px solid #f1f5f9;}tfoot td{font-weight:700;padding-top:16px;}</style></head><body><h1>Invoice {{invoiceNumber}}</h1><p>Billed to {{customerName}}</p><table><thead><tr><th>Description</th><th class=\"amt\">Amount</th></tr></thead><tbody>{{#lineItems}}<tr><td>{{description}}</td><td class=\"amt\">{{amount}}</td></tr>{{/lineItems}}</tbody><tfoot><tr><td>Total</td><td class=\"amt\">{{total}}</td></tr></tfoot></table></body></html>",
"data": {
"customerName": "Acme Robotics, Inc.",
"invoiceNumber": "INV-9X2K7Q",
"lineItems": [
{ "description": "Rendex Pro — May 2026", "amount": "$49.00" },
{ "description": "Priority support", "amount": "$6.00" }
],
"total": "$55.00"
},
"format": "pdf",
"pdfFormat": "A4",
"pdfPrintBackground": true,
"pdfMargin": { "top": "24px", "right": "24px", "bottom": "24px", "left": "24px" }
}'import Rendex from "@copperline/rendex"
const rendex = new Rendex(process.env.RENDEX_API_KEY)
// Same template + data — but ask for a hosted, signed URL instead of bytes.
// Email this short link to the customer; the first crawl renders and caches.
const { url, expiresAt } = await rendex.renderLink({
html: INVOICE_TEMPLATE, // your HTML with {{customerName}} {{invoiceNumber}} {{lineItems}} {{total}}
data: {
customerName: session.customer_details.name,
invoiceNumber: "INV-" + session.id.slice(-8).toUpperCase(),
lineItems: session.line_items.map((li) => ({
description: li.description,
amount: "$" + (li.amount_total / 100).toFixed(2),
})),
total: "$" + (session.amount_total / 100).toFixed(2),
},
format: "pdf",
pdfFormat: "A4",
pdfPrintBackground: true,
expiresIn: 2592000, // 30 days
})
console.log("Invoice ready:", url, "expires", expiresAt)
// -> send `url` in your Gmail/SMTP node as the "Download your invoice" link100 free API calls/month — no credit card required. Get your API key and start building.
Reach for this workflow when you sell through Stripe Checkout or Stripe-hosted invoices but need a branded PDF that matches your own template — not Stripe's default receipt. It is the right fit for solo founders, agencies billing clients, and SaaS teams who want every successful payment to produce a clean, archivable document without standing up a PDF microservice. Because the invoice is just an HTML template with Mustache placeholders, your designer can iterate on it in the browser, and n8n only has to map the Stripe event into a flat data object. You get deterministic layout, real fonts, and a print-ready A4 file on each payment. Use the direct PDF render when you want to attach the file to an email or archive it to Drive or S3; use a hosted render link when you would rather email a short URL the customer can open or re-download. Both paths run on the free 100 renders per month, no card required.