Generate PDFs with pdfn and send them as email attachments using Resend . Works with invoices, receipts, order confirmations, and reports.
Setup
Install Resend alongside your existing pdfn setup:
Add your Resend API key:
PDFN_API_KEY = pdfn_live_...
RESEND_API_KEY = re_...
API route
Generate a PDF and send it as an attachment:
app/api/send-invoice/route.tsx
import { Resend } from 'resend' ;
import { pdfn } from '@pdfn/react' ;
import Invoice from '@/pdfn-templates/invoice' ;
import { InvoiceEmail } from '@/emails/invoice-email' ;
const resend = new Resend ( process . env . RESEND_API_KEY );
const client = pdfn ();
export async function POST ( req : Request ) {
const { invoiceNumber , customerName , customerEmail , total } = await req . json ();
// Generate PDF
const { data : pdf , error : pdfError } = await client . generate ({
react: < Invoice number = { invoiceNumber } customer = { customerName } total = { total } /> ,
});
if ( pdfError ) {
return Response . json ({ error: pdfError . message }, { status: 500 });
}
// Send email with attachment
const { data : email , error : emailError } = await resend . emails . send ({
from: 'Billing <billing@yourdomain.com>' ,
to: customerEmail ,
subject: `Invoice ${ invoiceNumber } ` ,
react: < InvoiceEmail customerName = { customerName } invoiceNumber = { invoiceNumber } /> ,
attachments: [
{
filename: `invoice- ${ invoiceNumber } .pdf` ,
content: pdf . buffer ,
},
],
});
if ( emailError ) {
return Response . json ({ error: emailError . message }, { status: 500 });
}
return Response . json ({ id: email . id });
}
pages/api/send-invoice.tsx
import type { NextApiRequest , NextApiResponse } from 'next' ;
import { Resend } from 'resend' ;
import { pdfn } from '@pdfn/react' ;
import Invoice from '@/pdfn-templates/invoice' ;
import { InvoiceEmail } from '@/emails/invoice-email' ;
const resend = new Resend ( process . env . RESEND_API_KEY );
const client = pdfn ();
export default async function handler ( req : NextApiRequest , res : NextApiResponse ) {
const { invoiceNumber , customerName , customerEmail , total } = req . body ;
// Generate PDF
const { data : pdf , error : pdfError } = await client . generate ({
react: < Invoice number = { invoiceNumber } customer = { customerName } total = { total } /> ,
});
if ( pdfError ) {
return res . status ( 500 ). json ({ error: pdfError . message });
}
// Send email with attachment
const { data : email , error : emailError } = await resend . emails . send ({
from: 'Billing <billing@yourdomain.com>' ,
to: customerEmail ,
subject: `Invoice ${ invoiceNumber } ` ,
react: < InvoiceEmail customerName = { customerName } invoiceNumber = { invoiceNumber } /> ,
attachments: [
{
filename: `invoice- ${ invoiceNumber } .pdf` ,
content: pdf . buffer ,
},
],
});
if ( emailError ) {
return res . status ( 500 ). json ({ error: emailError . message });
}
return res . json ({ id: email . id });
}
The example uses two React components:
Invoice — pdfn template for the PDF attachment
InvoiceEmail — email template for the email body
You can also use html or text instead of react for the email body if you don’t need a React component.
Multiple attachments
Generate and attach multiple PDFs:
const [ invoice , receipt ] = await Promise . all ([
client . generate ({ react: < Invoice { ... invoiceData } /> }),
client . generate ({ react: < Receipt { ... receiptData } /> }),
]);
await resend . emails . send ({
from: 'Billing <billing@yourdomain.com>' ,
to: customerEmail ,
subject: 'Your order documents' ,
react: < OrderEmail customerName = { customerName } /> ,
attachments: [
{ filename: 'invoice.pdf' , content: invoice . data . buffer },
{ filename: 'receipt.pdf' , content: receipt . data . buffer },
],
});
Resend has a 40MB limit per email. For large PDFs, send download links instead.
Next steps
Generate & Render Client setup, generate() and render() parameters
Components Document, Page, and layout components