Failed-Payment Rescue: recover churning subscribers with a kind email, not a scary invoice
An n8n workflow that catches Stripe's failed subscription payments, waits for the retry to fail too, then has Claude write a warm personal email with a one-click update-card link — recovering revenue that default dunning emails lose to their robotic tone.
- 1
Catch the failure event
A
Webhooknode registered in Stripe forinvoice.payment_failed, with signature verification (same pattern as the payment notifier recipe). AnIFnode passes only events whereattempt_count >= 2— let Stripe's silent retry do its job first. - 2
Generate the fix-it link
An
HTTP Requestto Stripe's/v1/billing_portal/sessionswith the customer ID returns a secure, personal update-card URL. No custom pages to build, nothing to maintain. - 3
Claude writes the note
Claude gets the customer's first name, plan name, and amount, and writes 3 sentences: normalize the failure (cards expire), the link, and a genuine 'reply if anything's off'. Banned words: 'failed', 'declined', 'overdue', 'suspend'. Requested tone: the way you'd text a customer you like.
- 4
Send and track
A
Gmailnode sends from your founder/support address (never no-reply), and aGoogle Sheetsrow logs customer, amount at risk, and date so you can measure recovery rate. A follow-up variant 4 days later is included in the workflow, disabled by default.
Frequently asked questions
Why does tone matter this much for dunning?
Because most failed payments are innocent — expired cards, new bank, spending limit. A cold 'YOUR PAYMENT FAILED' template makes an innocent customer feel like a debtor and nudges them toward cancelling. A note that sounds like a human ('cards expire, it happens — here's a 10-second fix') keeps the relationship warm and the fix friction-free.
Where does the update-card link come from?
The workflow calls Stripe's API to generate a Customer Portal session link scoped to that customer — the official, secure way to let them update their card without logging in. The link is unique per customer and expires; nothing sensitive travels in the email.
When should this send relative to Stripe's own retries?
The workflow triggers on invoice.payment_failed but waits until attempt_count ≥ 2 before emailing — Stripe's automatic first retry silently fixes a chunk of failures, and you don't want to email someone whose payment already went through on retry. The email lands when human action is genuinely needed.