Recover failed Stripe payments with Supabase context and personalized retry emails

By General Input

When a Stripe payment fails, pull the customer's history from Supabase, log the failure, alert revenue ops in Slack, and send a retry email matched to the customer's tier.

Integrations

  • Stripe
  • Supabase
  • Slack Bot
  • Resend

Type

Agentic Task

Categories

  • Finance
  • Customer Support
  • Operations

Build an agent workflow that turns every failed Stripe payment into a fully contextualized, personalized recovery action across Stripe, Supabase, Slack, and Resend.

Trigger: a Stripe webhook. The workflow should fire whenever Stripe emits charge.failed or invoice.payment_failed. The incoming webhook payload contains the charge or invoice object — use it as the entry point.

When the webhook fires, the agent should:

1) Hydrate the Stripe context. Call Stripe Retrieve Charge with the charge id from the webhook (or Retrieve Invoice if it's an invoice.payment_failed event, then pull the customer id from the invoice). Then call Stripe Retrieve Customer to get the full customer object. Capture the failure reason, amount (remember Stripe amounts are in the smallest currency unit), currency, and customer email.

2) Pull internal customer history from Supabase. Use Supabase Get Row on the customers table filtered by the Stripe customer id (or email) to retrieve plan tier, account owner, and lifetime value. Then use Supabase Get Many Rows on the subscriptions table filtered by that customer to read subscription history: how long they've been a customer, current plan, MRR, prior renewal events, and any prior payment failures. If the customer is not found in Supabase, fall back gracefully to the Stripe data and note the gap in the alert.

3) Log the failure to Supabase. Use Supabase Create Row on a payment_failures table with at minimum: stripe_customer_id, stripe_charge_id (or invoice id), failure_reason, amount, currency, customer_email, account_tier, and a timestamp. This becomes the durable record of what happened.

4) Decide a recommendation. Based on the customer's history, the agent should pick one of: "automatic retry" (low-value or newly failed account, likely transient), "downgrade or pause" (recurring failures on a higher plan that may warrant offering a cheaper tier), or "churn risk — escalate" (high-LTV or long-tenured customer whose card has now failed). Write the recommendation as a single short line.

5) Post a Slack alert. Use the Slack Bot Send a Message operation to post in #revenue-ops. Include: customer name and email, plan tier and MRR, lifetime value, failure reason and amount, time since the customer joined, count of any prior failures, and the one-line recommendation. Keep it scannable — a short header line, a few bullet-style fields, and the recommendation at the bottom.

6) Send a personalized retry email through Resend. Use Resend Send Email to message the customer. The tone and content must be matched to their history, not a generic dunning template:

• Trial or low-tenure customer → friendly, low-pressure nudge with a clear retry link and a quick reassurance that it's usually a card issue.

• Established paying customer (mid LTV, several months tenure) → warmer, more direct ask, acknowledge their history, give them the retry path and an offer to chat.

• High-LTV or long-tenure customer → account-manager style, mention their tenure or specific plan, offer a direct line to the account owner, and treat the retry as a courtesy rather than a demand.

The email should have a real subject line, a clear update-your-card call to action, and a sign-off that matches the recommended tone. Send it from a verified Resend domain (do not hardcode a domain — let the user configure it).

Constraints: do not send a retry email if the failure_reason indicates fraud or a disputed charge — only alert Slack in that case. If the same customer has had more than two failures in the last 14 days (visible from the payment_failures table), skip the email and explicitly flag the Slack alert as "churn risk — escalate" instead. The agent should pick the recommendation and the email tone — not run a fixed template.

Auth and config to expect: Stripe secret key, Supabase project URL and secret key (Supabase tables involved: customers, subscriptions, payment_failures, all in the public schema), Slack bot OAuth, Resend API key with a verified sending domain. The Slack channel (#revenue-ops) and the from-address for Resend should be configurable inputs.

Related prompts

Explore more prompts
Let support send one-off Loops emails without an engineerA brand asset library your marketing team actually searchesTurn Mailjet email clicks into ranked HubSpot follow-upsClean out the Looker dashboards and Looks nobody opensLiveKit live operations console for room moderationWake up dormant Keap leads with a researched reasonCustomer lifecycle inspector for Loops, Stripe and PostHogLiveChat coverage board for planning next week's shiftsPhone routing control panel for LiveKit voice agentsLinkedIn Ads budget pacing dashboard for every client account