All workflows

Recover failed payments before the subscription cancels

Catch past-due subscriptions early, send a friendly link to fix the card, and hand the biggest accounts to a person.

View on GitHub

failed-payment-recovery.md

Recover failed payments before the subscription cancels

Set up the tools below, then run the steps in order for the user, carrying each step's results into the next.

Inputs

Ask the user for these before you start.

  • sender: the address to send from, on a domain verified in Resend, e.g. billing@acme.example
  • stripe_emails_on: whether Stripe already emails customers about failed payments, e.g. no; if yes, this workflow only escalates
  • escalate_amount: the amount due that deserves a personal call, with its currency, e.g. 1,000 USD (Stripe's 100000 in cents)
  • cs_channel: the Slack channel for escalations, e.g. #customer-success

Set up

Stripe (tool:stripe/list-subscriptions, tool:stripe/list-invoices)

Use the first option your agent supports.

MCP (official, remote)

Add this server to your agent's MCP settings, then sign in when asked.

{ "mcpServers": { "stripe": { "url": "https://mcp.stripe.com" } } }
  • List subscriptions: call the MCP tool stripe_api_read with GET /v1/subscriptions
  • List invoices: call the MCP tool stripe_api_read with GET /v1/invoices
CLI (official)

Install the command and sign in with it, then confirm it runs.

npm install -g @stripe/cli
stripe --version
  • List subscriptions: run stripe subscriptions list
  • List invoices: run stripe invoices list

Send an email (Resend, tool:resend/send-email)

Use the first option your agent supports.

Note: Pass an Idempotency-Key header (--idempotency-key on the CLI) so a retry never sends it twice; keys expire after 24 hours.

MCP (official, remote)

Add this server to your agent's MCP settings, then sign in when asked.

{ "mcpServers": { "resend": { "url": "https://mcp.resend.com/mcp" } } }

Call the MCP tool send-email.

CLI (official)

Install the command, then confirm it runs.

npm install -g resend-cli
resend --version

Run resend emails send.

Set $RESEND_API_KEY in your environment first (get a key: https://resend.com/api-keys).

Post a message (Slack, tool:slack/post-message)

Use the first option your agent supports.

Note: Needs the chat:write scope. Over MCP it posts as the signed-in user; the API and CLI post as the app's bot.

MCP (official, remote)

Add this server to your agent's MCP settings, then sign in when asked.

{ "mcpServers": { "slack": { "url": "https://mcp.slack.com/mcp" } } }

Call the MCP tool slack_send_message.

CLI (official)

Install the command, then confirm it runs.

curl -fsSL https://downloads.slack-edge.com/slack-cli/install.sh | bash
slack --version

Run slack api chat.postMessage.

Set $SLACK_BOT_TOKEN in your environment first (get a key: https://api.slack.com/apps).

Before step 1, confirm access to each service with its cheapest read-only call, like a list or a search. Never send or change anything to test access.

Steps

  1. Find past-due subscriptions with List subscriptions (Stripe). List subscriptions with status past_due. Keep each subscription ID and customer ID.
  2. Get the unpaid invoices with List invoices (Stripe). For each subscription, list its open invoices. Keep, per customer, customer_name, customer_email, and each invoice's amount_due and currency (in the currency's smallest unit), next_payment_attempt and hosted_invoice_url.
  3. Write the nudges yourself. Skip this step and the next when stripe_emails_on is yes, so no one gets two emails. Otherwise draft one short, friendly email per customer, with a subject and a plain-text body: the payment did not go through, each hosted_invoice_url to pay or update the card, and the next retry date, or that no retries are left when next_payment_attempt is empty. Show the drafts to the user.
  4. Send with Send an email (Resend). After the user approves, send each email from sender to its customer_email, one recipient per email. Keep each email's ID.
  5. Escalate the big ones with Post a message (Slack). Post one message per customer who owes escalate_amount or more to cs_channel, with customer_name, the amount and the next retry date.

Done when

  • Every customer with a past-due subscription got an email, or has a note saying why not.
  • cs_channel has one post per large account, and the user has the total amount due by currency.

Rules

  • Use only the services set up above. The read-only calls they need, like listing ids or polling for results, are fine.
  • Ask the user before anything that sends messages, costs money, or changes data, and say how many records it touches. One approval covers a batch the user has seen.
  • Never print API keys.