Email customers about failed payments and log them in Sheets
When a Stripe charge fails, send the customer a retry email matched to the reason their card was declined and log the row for finance.
Build me a code workflow that runs failed-payment dunning end to end whenever Stripe reports a payment failure.
Trigger: a Stripe webhook on the charge.failed event. Also accept invoice.payment_failed for subscription invoices so both one-off charges and recurring invoices flow through the same path.
When the webhook fires, pull these fields out of the Stripe event payload: customer email, customer name, failed amount and currency, failure code (for example card_declined, insufficient_funds, expired_card), the human-readable failure message, and the Stripe customer portal or hosted invoice URL so the customer has a place to retry.
Step 1: call AgentMail Send Email from a billing@ inbox to the customer. Pick subject and body from a small lookup table keyed off the Stripe failure code. card_declined gets one short template (your bank declined the charge, here is the retry link), insufficient_funds gets another (the charge could not go through due to insufficient funds), expired_card gets another (your card on file appears to have expired, update it here), and any unrecognized code falls back to a generic retry template. Every template includes the customer's first name, the amount and currency formatted for humans, and a clear retry CTA pointing at the Stripe link from the event. Keep the templates short and avoid heavy personalization, this is intentionally a code workflow not an agent.
Step 2: call Google Sheets Append Values to append one row to a Failed Payments sheet (let me pick the spreadsheet and tab during setup). Columns in order: timestamp (ISO 8601 from the Stripe event created field), customer email, customer name, amount, currency, failure code, failure message, retry link, and the AgentMail message_id returned by Send Email so finance can reconcile which email was sent for which failure.
Every step is deterministic: one webhook in, one templated email out, one row appended. No judgement calls, no LLM in the loop, no extra branches. If the AgentMail send fails, still append the audit row but leave the message_id column blank and put the AgentMail error in the failure_message column so finance can see what happened.
Additional information
What does this prompt do?
- Watches Stripe for failed payments and reacts the moment one happens.
- Sends the customer a clear retry email written for the specific failure reason, like a declined card versus an expired card.
- Appends a row to your Failed Payments sheet with the timestamp, customer, amount, failure code, and the email message id so finance has a full audit trail.
- Runs deterministically so every failure gets the same treatment and nothing slips through the cracks.
What do I need to use this?
- A Stripe account with permission to manage webhooks.
- An AgentMail inbox you can send from, such as billing@yourcompany.
- A Google account with edit access to a Failed Payments spreadsheet.
How can I customize it?
- Swap in your own email copy for each failure reason, like card declined, insufficient funds, or expired card.
- Change which sender address the email goes from, or point the customer to a different retry link.
- Pick a different sheet, tab, or column order for the audit log, or add columns like invoice id or plan name.
Frequently asked questions
Does this handle subscription payment failures too?
Can I personalize the retry email per customer?
Will this send a duplicate email if Stripe retries the same charge?
Do I need to write any code to set this up?
What does finance actually see in the sheet?
Stop chasing failed payments by hand.
Connect Stripe, AgentMail, and Google Sheets once, and every failed charge gets a tailored retry email and a clean audit row.