Invoice generator template
- Node.js
- Express
Turn a form into a PDF invoice with line items, sales tax, a discount and payment terms.
A Node.js and Express app that turns a form into a PDF invoice. Fill in who it’s from and who it’s for, add line items, sales tax, a discount and payment terms, and download a PDF ready to send. Use it to bill by hand, or call its route when an order is paid.

What it does
- A real PDF
- Returns a download link to a finished invoice PDF with your line items and totals.
- Tax and discounts
- Applies a sales tax percentage and a discount, and shows payment terms and the job name.
- Only the right fields
- The server passes on only invoice fields and caps their lengths, so a deployed copy can’t be misused.
- Keeps your key private
- The page calls your own server, which holds the key and limits each visitor to 10 invoices a minute.
How it works
The route that checks the form and creates the invoice.
const DATE = /^\d{4}-\d{2}-\d{2}$/;
const num = (v, min, max) => {
const n = Number(v);
return Number.isFinite(n) ? Math.min(max, Math.max(min, n)) : undefined;
};
const party = (p, b) => ({
[`${p}_name`]: str(b[`${p}_name`], 100),
[`${p}_street`]: str(b[`${p}_street`], 100),
[`${p}_city`]: str(b[`${p}_city`], 60),
[`${p}_state`]: str(b[`${p}_state`], 2).toUpperCase(),
[`${p}_zip`]: str(b[`${p}_zip`], 10)
});
// POST /api/generate: only the fields the Invoice Generator accepts are passed on.
app.post('/api/generate', async (req, res) => {
const b = req.body || {};
const items = (Array.isArray(b.items) ? b.items : []).slice(0, 25)
.map((i) => ({ description: str(i.description, 120), qty: num(i.qty, 1, 100000) ?? 1, unit_price: num(i.unit_price, 0, 10_000_000) ?? 0 }))
.filter((i) => i.description && i.unit_price > 0);
if (!items.length) return res.status(400).json({ error: 'Add at least one line item with a price.' });
const invoice = {
invoiceNumber: str(b.invoiceNumber, 40) || 'INV-001',
...(DATE.test(b.date) && { date: b.date }),
...(DATE.test(b.dueDate) && { dueDate: b.dueDate }),
...party('from', b),
...party('to', b),
...(str(b.job, 100) && { job: str(b.job, 100) }),
...(str(b.paymentTerms, 100) && { paymentTerms: str(b.paymentTerms, 100) }),
...(num(b.salesTax, 0, 100) && { salesTax: num(b.salesTax, 0, 100) }),
...(num(b.discount, 0, 10_000_000) && { discount: num(b.discount, 0, 10_000_000) }),
currency: /^[A-Z]{3}$/.test(b.currency) ? b.currency : 'USD',
items
};
try {
const data = await callApi('invoicegenerator', { body: invoice });
res.json({ success: true, pdfUrl: data.downloadURL, invoiceNumber: invoice.invoiceNumber });
} catch (err) {
res.status(err.status || 502).json({ error: err.message });
}
});Deploy it
- Get a free API key
The free plan includes 200 credits a month, no card needed. Create your key.
- Deploy it
Click Deploy to Vercel. Vercel copies the repo to your GitHub account and asks for
APIVERVE_API_KEY: paste your key there. - Open your app
Vercel builds it and gives you a live URL, usually in about a minute. Every push to the repo redeploys it.
Try the Invoice Generator API — the call this template makes
No key required to try it. Get a key to use it in your app.
{
"status": "ok",
"error": null,
"data": {
"pdfName": "fc17c4bd-e660-4078-94ae-f46be56c9006.pdf",
"expires": 1766096689189,
"downloadURL": "https://storage.googleapis.com/apiverve-helpers.appspot.com/htmltopdf/fc17c4bd-e660-4078-94ae-f46be56c9006.pdf?GoogleAccessId=1089020767582-compute%40developer.gserviceaccount.com&Expires=1766096689&Signature=zZYB17Rj1yfbfhM3Epmjc9PEfmsVpgsCATX5%2Bx2yAo%2FV45xUatVzkAjUkPC48PkR4m%2BF7uIJBToUY2QAZMzNIOre4T0Md2eToXtcYF%2F%2FefS3sZocODRdiC%2BmEuMZjsAPMfkhbCMQZT4lZczQn9sfaWJlWJi%2FGWXKVUwZby3yn06Ed7OqianYbxQj87ENoqYudZFe5qFpI0hmwh4lBrnIM40hb4eZwwbGEvZL2WejNdBgD0cKb3C%2BHwJHkPvd2PAzFfNvuJolBxMN4jE3QCx9DN2MdHGUqb7t3vlP0Kder8m0lMpac%2BPbwZsDVmlF595cFzkKaE928uxzA1Mzkenffg%3D%3D"
}
}