One receipt per event id
Use event.id, or a stable invoice or payment id, as the retry key. A repeated webhook returns the first send instead of sending another email.
Stripe retries a webhook until your endpoint returns 200, so a naive receipt job can email the customer twice. Key the NoticeAPI send on the Stripe event id, and those retries collapse into one message you can trace from accepted to delivered.
import { NoticeAPI } from "noticeapi";
const notice = new NoticeAPI(process.env.NOTICEAPI_API_KEY!);
export async function sendReceiptFromStripeEvent(event: {
id: string;
type: string;
data: { object: { customer_email?: string; number?: string } };
}) {
const invoice = event.data.object;
if (!invoice.customer_email) return;
return notice.emails.send(
{
from: "Acme Billing <[email protected]>",
to: invoice.customer_email,
subject: `Invoice ${invoice.number ?? "receipt"}`,
html: "<p>Your billing receipt is ready.</p>",
},
{ idempotencyKey: event.id }, // Stripe retries reuse the id -> one email
);
}Check the Stripe-Signature header in your handler before it decides to send anything. The webhook hits your app, not NoticeAPI.
Route invoice.paid, invoice.payment_failed, and subscription events to the template and recipient each one deserves.
Call notice.emails.send with event.id as the retry key so Stripe's retries cannot stack up duplicate receipts.
Search the stored message and recipient timeline, or replay the delivery from a signed webhook, when someone says the receipt never came.
Use event.id, or a stable invoice or payment id, as the retry key. A repeated webhook returns the first send instead of sending another email.
Render each billing notice from a stored template. Attach the invoice PDF through the REST send API on a paid plan.
Fire the success and failure sends at simulator recipients from a sandbox sender before a real card is ever charged.
Signed webhooks report delivered, bounced, or suppressed, so a missing receipt surfaces in your systems instead of a support ticket.
A Stripe-triggered receipt, invoice, or payment failure is transactional email your customer expects. Send product news, offers, and newsletters through audience broadcasts, where one-click unsubscribe and List-Unsubscribe are handled for you.
No. Stripe stays your billing system. NoticeAPI sends the email your product decides to send once it has verified a Stripe event.
The Stripe event id covers webhook retries. For a job built around one object, a stable invoice or payment id works too.
Yes, on a paid plan. Pass the PDF bytes to the REST send API's attachment field once your app has generated them.
Simulator outcomes are free. Move to a verified domain when the path is ready.