How to Send Receipt & Invoice Emails
Send transactional receipt and invoice emails after a payment — HTML you own, delivery via Notify.
Receipt and invoice emails are transactional: a user paid (or an invoice is due), your backend knows the amount and line items, and you need that record in their inbox. Build the HTML in your app; Notify sends it with SPF/DKIM, logs, and webhooks. Prefer html. Pro is $10 for 10,000 emails. Stripe recipe: Stripe payment → receipt.
Prerequisites
- Payment provider webhook or server-side confirmation (e.g. Stripe
checkout.session.completed) - API key from Credentials
- Verified domain for production
fromaddresses (SPF/DKIM/DMARC) - Optional:
notifycxfor typed sends
Flow
- Confirm payment in your backend (never trust the client alone)
- Load order / invoice details (amount, currency, items, customer email)
- Render a receipt or invoice as HTML
- Send with
notifycxorPOST https://notify.cx/api/email/send - Optionally store the Notify message id next to the order for support
Example: receipt send
async function sendReceiptEmail(order: {
email: string;
id: string;
totalFormatted: string;
itemsHtml: string;
}) {
const response = await fetch('https://notify.cx/api/email/send', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': process.env.NOTIFY_API_KEY!
},
body: JSON.stringify({
to: order.email,
subject: `Receipt for order ${order.id}`,
from: 'billing@your-verified-domain.com',
html: `
<h1>Thanks for your purchase</h1>
<p>Order <strong>${order.id}</strong></p>
<p>Total: <strong>${order.totalFormatted}</strong></p>
${order.itemsHtml}
<p>Questions? Reply to this email.</p>
`
})
});
if (!response.ok) {
throw new Error(await response.text());
}
return response.json();
}
Invoices vs receipts
| Receipt | Invoice | |
|---|---|---|
| When | After successful payment | Often before/with payment terms |
| Content | What was paid | What is owed / was billed |
| Notify role | Same — deliver html | Same |
If you generate PDF invoices, attach them in your own stack or link to a signed download URL in the HTML. Prefer html in the send body; keep file attachments in your app if you need them.
Idempotency
Payment webhooks can fire more than once. Gate the send on “receipt not yet sent” for that order.id so customers do not get duplicates.
Observe
- Dashboard logs for delivery
- Webhooks for bounce/complaint on Pro/Scale
- Correlate failures with the order id you put in the subject or body