Turn failed Stripe payments into Close recovery tasks

By General Input

When a Stripe charge or invoice fails, open a same-day recovery task on the matching Close lead and ping your revenue channel in Slack.

Integrations

  • Stripe
  • Close
  • Slack Bot

Type

Deterministic Code

Categories

  • Sales
  • Finance

Build a code workflow that turns every failed Stripe payment into a same-day recovery task on the matching Close lead, plus a Slack alert in our revenue-recovery channel.

Trigger: a Stripe webhook listening for charge.failed and invoice.payment_failed events. Verify the Stripe signature on every incoming request.

On each event, extract the customer email, the failure reason (decline code or failure message), the amount in dollars, the Stripe customer id, and the invoice id when present. For invoice.payment_failed, also capture the subscription id if it exists.

Use Stripe Retrieve Subscription to pull the current plan name and monthly recurring revenue when a subscription id is available, so we can include them in the task body. Skip this step gracefully for one-off charges with no subscription.

Use Close List Leads to find the lead whose primary contact email matches the Stripe customer's email (filter by query like email_address:"{email}"). If exactly one lead matches, use it. If zero match, treat it as unmatched and skip the Close step. If more than one match, pick the most recently updated lead and note the ambiguity in the Slack alert.

When a Close lead is found, use Close Create Task on that lead with: due date = today (in the Close org's timezone), assignee = lead owner by default (with a workflow option to override to a fixed user id), text title "Recover failed payment: ${amount} from {customer name or email}", and a body that includes the Stripe failure reason, the Stripe invoice id (or charge id), the plan and MRR if we fetched them, and a deep link to the Stripe payment in the dashboard.

Then use Slack Bot Send a Message to post in a configurable revenue-recovery channel. The message should include: the customer name and email, the dollar amount and currency, the failure reason, a link to the Stripe payment, and a link to the Close lead if matched. If no Close lead was matched, prefix the message with ":warning: Unmatched customer" so a human can triage. If multiple Close leads matched, mention that too.

Configurable inputs the workflow should expose: the Slack channel id for revenue-recovery alerts, the Close task assignee strategy (lead owner vs a fixed user id), and a toggle to include plan and MRR in the task body.

Deduplicate by Stripe invoice id (for invoice.payment_failed) and charge id (for charge.failed) so retries on the same invoice do not create duplicate Close tasks or duplicate Slack alerts. If a task already exists for that invoice or charge id, update the existing Slack alert or no-op instead of opening a second one.

Always return a 2xx to Stripe quickly so the webhook is not retried unnecessarily. Log the customer email, the event type, the matched Close lead id, the created Close task id, and the Slack message timestamp for every run.

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