Generate PDF Invoices
Create professional PDF invoices from templates and attach them to emails automatically.
Overview
FormaMail allows you to generate PDF documents dynamically from templates and attach them to emails. This tutorial covers:
- Creating an attachment template for PDF generation (via AI, gallery, or manually)
- Designing a professional invoice layout
- Sending emails with dynamically generated PDF attachments
- Generating standalone PDFs via the API
This is perfect for invoices, receipts, reports, contracts, and any document you need to send as an attachment.
Prerequisites
Before starting, make sure you have:
- An active FormaMail account
- An API key with attachment permissions
- (Optional) Company logo for branding
How PDF Generation Works
FormaMail uses attachment templates to generate PDFs:
- Create an Attachment Template - Design your PDF layout in the visual editor
- Send Email with Attachment - Reference the template and pass variables
- Automatic Generation - FormaMail renders the PDF with your data
- Delivery - The PDF is attached to your email
Email Template + Attachment Template + Variables β Email with PDF AttachmentSame Designer Technology: FormaMail uses the same visual editor for creating email and PDF templates. Each template is created separately using the same drag-and-drop interface.
Choose Your Approach
FormaMail offers three ways to create PDF templates:
| Approach | Best For | Time |
|---|---|---|
| AI Generation | Quick start, standard invoices/reports | ~1 minute |
| Template Gallery | Professional designs, common documents | ~2 minutes |
| Manual Design | Full customization, complex layouts | ~15-20 minutes |
Option A: Generate with AI (Fastest)
Let AI create your invoice template in seconds:
Step 1: Start AI Generation
- Log in to your FormaMail Dashboard
- Go to Templates β Create Template
- Select Attachment Template
- Click Generate with AI
Step 2: Describe Your Invoice
Enter a natural language description. Be specific:
Example prompts:
βProfessional invoice PDF with company logo, invoice number, date, bill-to section, line items table with description, quantity, unit price and amount, subtotal, tax, and total. Include payment terms and bank details at the bottom.β
βSimple receipt with company header, receipt number, date, list of items purchased, total amount, and thank you messageβ
βDetailed quote/estimate PDF with company branding, customer information, itemized services with pricing, terms and conditions, and signature lineβ
Step 3: Review and Customize
- AI generates a complete PDF template with:
- Professional A4/Letter layout
- Properly formatted tables
- Pre-configured variables (e.g.,
{{invoiceNumber}},{{items}},{{total}})
- Review the template in the designer
- Make any adjustments:
- Add your company logo
- Update colors to match your brand
- Modify text content and sections
Step 4: Publish
- Click Preview to test with sample data
- Click Save and Publish
- Copy the Template ID for use in your code
Option B: Import from Template Gallery
Use professionally designed invoice templates:
Step 1: Open the Template Gallery
- Log in to your FormaMail Dashboard
- Go to Templates β Template Gallery
- Filter by Attachment templates
Step 2: Find an Invoice Template
Browse categories:
- Invoices: Professional invoices, simple invoices, detailed invoices
- Receipts: Purchase receipts, payment confirmations
- Reports: Monthly reports, statements, summaries
- Contracts: Agreements, proposals, quotes
Step 3: Import and Customize
- Click on a template to preview
- Click Import to add it to your templates
- Customize the template:
- Replace placeholder logo
- Update company details
- Adjust colors and fonts
- Modify sections as needed
Step 4: Publish
- Click Preview to test
- Click Save and Publish
- Copy the Template ID
Option C: Build Manually (Full Control)
For complete customization, build your invoice template from scratch.
Tutorial: Create a Professional Invoice PDF
Step 1: Create an Attachment Template
- Log in to your FormaMail Dashboard
- Navigate to Templates β Create Template
- Select Attachment Template
- Choose PDF as the output format
Set the template details:
- Name:
Invoice Template - Slug:
invoice-template - Description:
Professional invoice for customers
Step 2: Configure Page Settings
Before designing, set up the PDF page:
- Click Page Settings in the toolbar
- Configure:
- Page Size: A4 (or Letter for US)
- Orientation: Portrait
- Margins: 40px all sides
- Header Height: 0 (weβll add our own header)
- Footer Height: 60px
Step 3: Design the Invoice Header
Create a professional header with your company branding:
-
Drag a Columns component (2 columns) onto the canvas
-
Left Column - Company Info:
- Add Image component for your logo
- Width:
150px
- Width:
- Add Text for company name:
- Content:
{{companyName}} - Font Size:
20px - Font Weight:
Bold
- Content:
- Add Text for address:
- Content:
{{companyAddress}} - Font Size:
12px - Color:
#666666
- Content:
- Add Image component for your logo
-
Right Column - Invoice Details (right-aligned):
- Add Heading:
- Content:
INVOICE - Level:
H1 - Font Size:
32px - Color:
#1a1a2e
- Content:
- Add Text for invoice number:
- Content:
Invoice #: {{invoiceNumber}} - Font Size:
14px
- Content:
- Add Text for dates:
- Content:
Date: {{invoiceDate}} - Content:
Due Date: {{dueDate}}
- Content:
- Add Heading:
Step 4: Add Bill To Section
Below the header:
-
Add a Divider component
- Margin:
24px 0
- Margin:
-
Add a Columns component (2 columns)
-
Left Column - Bill To:
- Add Heading:
Bill To- Level:
H4 - Margin Bottom:
8px
- Level:
- Add Text:
{{customer.name}} {{customer.address}} {{customer.city}}, {{customer.state}} {{customer.zip}} {{customer.email}}
- Add Heading:
-
Right Column - Payment Info (optional):
- Add Heading:
Payment Details - Add Text:
{{paymentMethod}}
- Add Heading:
Step 5: Create the Line Items Table
This is the core of the invoice:
-
Add a Container with:
- Background:
#f8f9fa - Border Radius:
8px - Margin Top:
24px - Padding:
0
- Background:
-
Add a Table component inside with:
- Header Row: Description | Quantity | Unit Price | Amount
- Header background:
#1a1a2e - Header text color:
#ffffff
-
For the table body, use a Loop component:
- Data Source:
{{items}}
- Data Source:
-
Inside the loop, add table cells:
- Description:
{{item.description}} - Quantity:
{{item.quantity}} - Unit Price:
{{item.unitPrice}} - Amount:
{{item.amount}}
- Description:
Table Styling: Use alternating row colors for readability. Set even rows to #ffffff and odd rows to #f8f9fa.
Step 6: Add Totals Section
Below the items table:
-
Add a Container for totals:
- Width:
300px - Float:
Right - Margin Top:
24px
- Width:
-
Add rows for each total line using Columns (2 columns):
Subtotal Row:
- Left:
Subtotal: - Right:
{{subtotal}}(right-aligned)
Tax Row:
- Left:
Tax ({{taxRate}}%): - Right:
{{taxAmount}}
Discount Row (conditional):
- Wrap in Conditional with condition
{{hasDiscount}} - Left:
Discount: - Right:
-{{discountAmount}}
Divider
Total Row:
- Left:
Total Due:(bold, larger) - Right:
{{total}}(bold, larger, primary color)
- Left:
Step 7: Add Payment Terms
Below the totals:
-
Add a Container:
- Margin Top:
40px - Padding:
16px - Background:
#f0f9ff(light blue) - Border Radius:
8px
- Margin Top:
-
Add Heading:
Payment Terms- Level:
H4
- Level:
-
Add Text:
{{paymentTerms}} Please make payment to: Bank: {{bankName}} Account: {{accountNumber}} Reference: {{invoiceNumber}}
Step 8: Add Notes Section (Optional)
-
Add a Conditional component:
- Condition:
{{notes}}
- Condition:
-
Inside, add:
- Heading:
Notes - Text:
{{notes}}
- Heading:
Step 9: Design the Footer
-
Add a Container at the bottom:
- Background:
#1a1a2e - Padding:
16px - Text Color:
#ffffff - Text Align:
Center
- Background:
-
Add Text:
- Content:
Thank you for your business! - Font Size:
14px
- Content:
-
Add Text:
- Content:
{{companyName}} | {{companyPhone}} | {{companyEmail}} - Font Size:
12px - Color:
#aaaaaa
- Content:
Step 10: Review and Publish
- Click Variables tab to review all variables:
| Variable | Type | Description |
|---|---|---|
invoiceNumber | String | Invoice identifier |
invoiceDate | String | Invoice date |
dueDate | String | Payment due date |
companyName | String | Your company name |
companyAddress | String | Company address |
companyPhone | String | Company phone |
companyEmail | String | Company email |
customer | Object | Customer details |
items | Array | Line items |
subtotal | String | Subtotal amount |
taxRate | Number | Tax percentage |
taxAmount | String | Tax amount |
hasDiscount | Boolean | Has discount? |
discountAmount | String | Discount amount |
total | String | Total due |
paymentTerms | String | Payment terms |
notes | String | Additional notes |
- Click Preview to test with sample data
- Click Save and Publish
- Copy the Template ID
Sending Emails with PDF Attachments
Now use your invoice template to send emails with PDF attachments:
Basic Example
const axios = require('axios');
const API_KEY = process.env.FORMAMAIL_API_KEY;
const API_URL = 'https://api.formamail.com/api';
async function sendInvoiceEmail() {
const response = await axios.post(
`${API_URL}/emails/send`,
{
// Email template
templateId: 'invoice-email-template',
to: [
{
email: 'customer@example.com',
name: 'John Doe'
}
],
// Email variables
variables: {
customerName: 'John',
invoiceNumber: 'INV-2024-001'
},
// PDF attachment
attachments: [
{
filename: 'invoice-{{invoiceNumber}}.pdf',
attachmentTemplateId: 'invoice-template',
outputFormats: ['pdf'],
variables: {
invoiceNumber: 'INV-2024-001',
invoiceDate: 'December 7, 2025',
dueDate: 'December 21, 2025',
companyName: 'Acme Corp',
companyAddress: '123 Business St, Suite 100',
companyPhone: '+1 (555) 123-4567',
companyEmail: 'billing@acme.com',
customer: {
name: 'John Doe',
address: '456 Customer Lane',
city: 'New York',
state: 'NY',
zip: '10001',
email: 'john@example.com'
},
items: [
{
description: 'Professional Services - November',
quantity: 40,
unitPrice: '$150.00',
amount: '$6,000.00'
},
{
description: 'Software License - Annual',
quantity: 1,
unitPrice: '$1,200.00',
amount: '$1,200.00'
},
{
description: 'Support Package - Premium',
quantity: 1,
unitPrice: '$500.00',
amount: '$500.00'
}
],
subtotal: '$7,700.00',
taxRate: 8.5,
taxAmount: '$654.50',
hasDiscount: true,
discountAmount: '$200.00',
total: '$8,154.50',
paymentTerms: 'Net 14 - Payment due within 14 days of invoice date.',
bankName: 'First National Bank',
accountNumber: '****4567',
notes: 'Thank you for being a valued customer!'
}
}
]
},
{
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json'
}
}
);
console.log('Invoice email sent!');
console.log('Email ID:', response.data.id);
return response.data;
}
sendInvoiceEmail();Dynamic Filename
The filename supports variables:
attachments: [
{
filename: 'invoice-{{invoiceNumber}}-{{customerName}}.pdf',
// Generates: invoice-INV-2024-001-John.pdf
attachmentTemplateId: 'invoice-template',
outputFormats: ['pdf'],
variables: { /* ... */ }
}
]Multiple Output Formats
Generate both PDF and Excel from the same template:
attachments: [
{
filename: 'invoice-{{invoiceNumber}}',
attachmentTemplateId: 'invoice-template',
outputFormats: ['pdf', 'xlsx'], // Both formats
variables: { /* ... */ }
}
]This creates two attachments: invoice-INV-001.pdf and invoice-INV-001.xlsx.
Standalone PDF Generation
Generate PDFs without sending an email:
async function generatePDF() {
const response = await axios.post(
`${API_URL}/attachments/generate`,
{
templateId: 'invoice-template',
outputFormat: 'pdf',
variables: {
invoiceNumber: 'INV-2024-001',
// ... all other variables
}
},
{
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json'
}
}
);
console.log('PDF generated!');
console.log('Download URL:', response.data.url);
console.log('Expires:', response.data.expiresAt);
return response.data;
}Response:
{
"id": "att_abc123",
"url": "https://cdn.formamail.com/attachments/att_abc123.pdf",
"filename": "invoice-INV-2024-001.pdf",
"size": 125432,
"contentType": "application/pdf",
"expiresAt": "2024-12-08T12:00:00.000Z"
}Real-World Example: Order Invoice System
Hereβs a complete example integrating with your order system:
const axios = require('axios');
class InvoiceService {
constructor(apiKey) {
this.client = axios.create({
baseURL: 'https://api.formamail.com/api',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
}
});
}
async sendInvoice(order, customer) {
// Calculate totals
const subtotal = order.items.reduce(
(sum, item) => sum + (item.quantity * item.price), 0
);
const taxAmount = subtotal * (order.taxRate / 100);
const total = subtotal + taxAmount - (order.discount || 0);
// Format items for template
const formattedItems = order.items.map(item => ({
description: item.name,
quantity: item.quantity,
unitPrice: this.formatCurrency(item.price),
amount: this.formatCurrency(item.quantity * item.price)
}));
// Send email with PDF invoice
const response = await this.client.post('/emails/send', {
templateId: 'invoice-notification',
to: [{ email: customer.email, name: customer.name }],
variables: {
customerName: customer.name.split(' ')[0],
invoiceNumber: order.invoiceNumber,
viewUrl: `https://yoursite.com/invoices/${order.invoiceNumber}`
},
attachments: [{
filename: `invoice-${order.invoiceNumber}.pdf`,
attachmentTemplateId: 'invoice-template',
outputFormats: ['pdf'],
variables: {
invoiceNumber: order.invoiceNumber,
invoiceDate: this.formatDate(order.createdAt),
dueDate: this.formatDate(order.dueDate),
companyName: 'Your Company',
companyAddress: '123 Business St, City, ST 12345',
companyPhone: '+1 (555) 123-4567',
companyEmail: 'billing@yourcompany.com',
customer: {
name: customer.name,
address: customer.address.line1,
city: customer.address.city,
state: customer.address.state,
zip: customer.address.zip,
email: customer.email
},
items: formattedItems,
subtotal: this.formatCurrency(subtotal),
taxRate: order.taxRate,
taxAmount: this.formatCurrency(taxAmount),
hasDiscount: order.discount > 0,
discountAmount: this.formatCurrency(order.discount || 0),
total: this.formatCurrency(total),
paymentTerms: 'Payment due within 30 days.',
bankName: 'Your Bank',
accountNumber: '****1234'
}
}],
tags: ['invoice', 'billing'],
metadata: {
orderId: order.id,
customerId: customer.id
}
});
return response.data;
}
formatCurrency(amount) {
return new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD'
}).format(amount);
}
formatDate(date) {
return new Date(date).toLocaleDateString('en-US', {
year: 'numeric',
month: 'long',
day: 'numeric'
});
}
}
// Usage
const invoiceService = new InvoiceService(process.env.FORMAMAIL_API_KEY);
const order = {
id: 'order-123',
invoiceNumber: 'INV-2024-001',
createdAt: new Date(),
dueDate: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000),
taxRate: 8.5,
discount: 50,
items: [
{ name: 'Product A', quantity: 2, price: 99.99 },
{ name: 'Product B', quantity: 1, price: 149.99 }
]
};
const customer = {
id: 'cust-456',
name: 'John Doe',
email: 'john@example.com',
address: {
line1: '456 Customer Lane',
city: 'New York',
state: 'NY',
zip: '10001'
}
};
invoiceService.sendInvoice(order, customer)
.then(result => console.log('Invoice sent:', result.id))
.catch(err => console.error('Error:', err));PDF Design Best Practices
Layout
- Use standard page sizes - A4 for international, Letter for US
- Set appropriate margins - 40-60px for printing
- Keep it single page - When possible, fit content on one page
- Use visual hierarchy - Clear headings, grouped sections
Typography
- Professional fonts - Arial, Helvetica, Georgia work best
- Readable sizes - 10-12pt for body, 14-18pt for headings
- Consistent alignment - Right-align numbers for easy scanning
- Adequate spacing - White space improves readability
Branding
- Include your logo - Top-left is traditional for invoices
- Use brand colors - Sparingly for headers and accents
- Consistent styling - Match your email templates
- Professional footer - Contact info and company details
Data Tables
- Clear headers - Bold, contrasting background
- Alternating rows - Improves readability
- Right-align numbers - Currency, quantities
- Adequate column width - Donβt crowd data
Troubleshooting
PDF Not Generating
Solutions:
- β Verify attachment template exists and is published
- β Check all required variables are provided
- β
Ensure
outputFormatsincludespdf - β Check API key has attachment permissions
Layout Issues in PDF
Solutions:
- β Preview the template in PDF mode before sending
- β Use fixed widths for columns in tables
- β Avoid very long unbroken text
- β Test with maximum expected data length
Missing Data in PDF
Solutions:
- β Check variable names match exactly (case-sensitive)
- β Verify nested object structure matches template
- β Ensure array data is properly formatted
- β Check the Variables tab in template editor
PDF Too Large
Solutions:
- β Compress images before uploading
- β Use web-optimized images
- β Reduce image dimensions if possible
- β Limit number of pages/items
Next Steps
Now that you can generate PDF invoices:
- Send Bulk Personalized Emails - Send invoices to multiple customers
- Create Email Templates - Design the invoice notification email
- Webhooks - Get notified when PDFs are generated
- API Reference - Full attachment API documentation