By the end of this guide, three revenue-critical emails send automatically from Stripe events: a payment-failed notice when a charge fails, a win-back when a subscription is canceled, and a trial-ending reminder before a trial lapses — each from a dashboard template you can rewrite without a deploy. Stripe already emails receipts and invoices, so don’t rebuild those. What Stripe doesn’t send well is the branded, copy-sensitive lifecycle mail: a multi-step dunning nudge, a “we’d love you back” after cancellation, or a trial reminder on your own schedule. That copy changes constantly — exactly what belongs in a template, not a redeploy.Documentation Index
Fetch the complete documentation index at: https://docs.senderkit.com/llms.txt
Use this file to discover all available pages before exploring further.
You’ll need: a SenderKit account with an API key, a Stripe
account with subscriptions or Checkout live, and a Next.js app. Use an
sk_test_
SenderKit key and Stripe test mode while you build.Author the three templates
Create three
Write the copy for each — these are the messages you’ll iterate on most, so lean on
AI authoring for a first draft and publish when ready.
email templates in the dashboard. Suggested
slugs and variables:| Slug | When it sends | Variables |
|---|---|---|
payment-failed | A renewal charge fails | attempt, update_payment_url |
subscription-canceled | A subscription ends | comeback_url |
trial-ending | A trial is about to lapse | trial_end, final |
Stand up the Stripe webhook route
Stripe signs every webhook, and you must verify the signature against the raw
request body. In the Next.js App Router,
await req.text() gives you the untouched
body — there’s no bodyParser config to disable (that was the Pages Router).app/api/webhooks/stripe/route.ts
Send on a failed payment (dunning)
The Keying on
invoice.payment_failed event carries everything you need directly on the
invoice — including customer_email, so no extra lookup is needed.${invoice.id}:${invoice.attempt_count} means each retry attempt gets its
own email, but a duplicate delivery of the same attempt does not.Win back a canceled subscription
A subscription object doesn’t carry the email, so look up the customer.
Remind before a trial ends — as a scheduled sequence
customer.subscription.trial_will_end fires roughly three days out. Send the reminder
now, and use scheduledAt to queue a final nudge
for the day before the trial lapses — one event, a two-touch sequence.final variable lets the one template render two ways — use a
show-if block ({{#final}}…{{/final}})
to sharpen the copy on the last reminder.Verify it works
Forward events to your local route and trigger one with the
Stripe CLI:With your
sk_test_ key, watch the message move through its
lifecycle in the SenderKit dashboard — no real email sent.What’s next
Welcome on signup
The other end of the lifecycle — greet new users automatically.
Scheduling sends
How
scheduledAt defers delivery up to 30 days out.Idempotency
Why every webhook handler needs a stable key.
Messages
Filter by
metadata to find a customer’s sends.