Recover failed Stripe payments with smart Loops dunning emails

By General Input

When a Stripe payment fails, send the right Loops recovery email based on how many times the customer has already failed, and brief your revenue team in Slack.

Integrations

  • Stripe
  • Loops.so
  • Slack Bot

Type

Agentic Task

Categories

  • Finance
  • Customer Support

Build me an agent workflow that recovers revenue from failed Stripe payments without spamming the customer. It should pick the right Loops dunning email based on how deep into the failure cycle the customer is, and loop my revenue team in via Slack.

Trigger: Stripe webhook on invoice.payment_failed.

When the event fires, the agent should:

1. Pull full context. Call Stripe Retrieve Customer for the customer on the failed invoice. Then call Stripe List Invoices filtered to that customer to count how many invoices have status open or uncollectible (or were marked payment_failed) in the last 30 days. This is the failure depth.

2. Skip noise. If the Stripe customer is a test customer (livemode is false, or metadata flags it as test) or the invoice amount_due is under $5, stop and do nothing.

3. Enrich from Loops. Call Loops Find Contact by the customer's email so the agent can read prior contact properties like plan tier (planTier) and lifecycle stage (lifecycleStage). If no contact exists in Loops, proceed using only Stripe fields.

4. Pick the template. Based on the failure count in the last 30 days, choose the matching published Loops transactional template:

- 1 failure -> gentle first nudge template

- 2 or 3 failures -> firmer urgent reminder template

- 4 or more failures -> churn-warning template

Make these three transactionalId values configurable at the top of the workflow so I can swap them without editing logic. Also leave a clear hook for branching by planTier or lifecycleStage if I want a white-glove variant later.

5. Send the email. Call Loops Send Transactional Email to the customer's email with the chosen transactionalId and dataVariables for: firstName (from the Loops contact, else parse from Stripe customer name), amountDue (formatted as currency from invoice.amount_due in cents), retryDate (from invoice.next_payment_attempt, formatted as a friendly date), and invoiceUrl (the invoice.hosted_invoice_url). Send an Idempotency-Key header derived from the Stripe invoice id + attempt_count so a retried webhook does not re-send.

6. Brief the team. Call Slack Bot Send a Message to a configurable revenue channel (default #revenue-alerts) with a short structured summary:

- Customer name and email

- Plan tier (from Loops, if present)

- Dollar amount at risk

- Number of prior failures in the last 30 days

- Which Loops template was sent (gentle / urgent / churn-warning)

- Link to the hosted Stripe invoice

Use slackbot (not the user OAuth slack integration) so the alert is attributed to the bot, not me.

Configuration to expose at the top of the workflow: the three Loops transactionalId values, the Slack channel, the minimum dollar amount (default $5), and the failure-count thresholds (defaults 1, 2-3, 4+).

Error handling: if Loops returns 404 on transactionalId, post a warning to the Slack channel naming the missing template instead of silently failing. If Stripe Retrieve Customer or List Invoices fails, still try to post a degraded Slack alert with whatever fields are available so nothing is missed.

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