Failed payment save play: alert CS with account context before a missed payment turns into churn
Stripe + HubSpot + Slack
Who it's for
CS teams at companies that bill through Stripe, who want to know when a subscription falls behind on payment, with the account's owner, renewal and recent history, before the customer quietly churns. Everything in Stripe stays read-only. HubSpot can be swapped for Salesforce, Attio or Pipedrive, and Slack for a Gmail draft.
What you get
Past-due subscriptions with account context, and one Slack alert drafted. Sample output: every company and person in it is fictional.
Stripe subscriptions behind on payment: 3. Open invoices past their due date: 4. Nothing has been changed in Stripe or HubSpot. | Customer | Subscription | Unpaid invoice | Amount | Due | Days late | HubSpot owner | Renews | Open tickets | |---|---|---|---|---|---|---|---|---| | Fernhill Software (fictional) | Business, monthly | INV-1187 | $2,400 | Oct 1 | 15 | Priya Raman | Jan 30 | 2 (billing, login) | | Mossgate Labs (fictional) | Team, annual | INV-1162 | $9,600 | Sep 24 | 22 | Sam Whitlock | Sep 24 (this invoice) | 0 | | Larkspur Freightworks (fictional) | Business, monthly | INV-1191 | $3,100 | Oct 5 | 11 | Jordan | Mar 12 | 0. Note Oct 8: "new card coming from AP" | | Quarry Lane Analytics (fictional) | n/a | INV-1170 | $750 | Sep 30 | 16 | No match on domain quarrylane.example | ? | ? | Skipped: Larkspur (a note says a new card is on the way). Quarry Lane has no HubSpot match, so check it yourself. Draft Slack alert to #cs-saves (not posted): :warning: Payment behind: Fernhill Software (fictional) Owner: @priya. Business plan, monthly. INV-1187 for $2,400 is 15 days past due. Context: 2 open tickets, one about billing (Oct 9). Renews Jan 30. Champion: Dana Okafor, [email protected]. Suggested move: Priya checks in with Dana today about the billing ticket before finance sends a second notice. Reply 'post 1' or 'post all' to approve.
Time and cost
Estimate About 10–15 minutes a week, most of it reading the alerts.
Assumptions: One weekly run over about 5 past-due subscriptions or invoices, with 3 alerts approved.
- Stripe: Reads only: subscriptions, open invoices and their customers. No writes. Credit use not confirmed by Stripe.
- HubSpot: A company, owner, ticket and recent-notes lookup per customer. No writes. Credit use not confirmed by HubSpot.
- Slack: A user lookup per owner, plus one channel message or direct message per account after you approve it. Credit use not confirmed by Slack.
Exact credit costs depend on your plan with each vendor. Check the tool pages before a large run.
MCP servers
Every server is confirmed in: Claude
-
ClaudeChatGPTClaude CodeCursorRead + writeCredits not confirmed
https://mcp.stripe.com -
ClaudeChatGPTRead + writeCredits not confirmedNeeds admin or IT
https://mcp.hubspot.com -
ClaudeClaude CodeCursorRead + writeCredits not confirmedNeeds admin or IT
https://mcp.slack.com/mcp
Set up in a chat app
Every server in this recipe is confirmed for Claude. Connect each one, then paste the prompts below into one conversation.
- Connect Stripe without code (Claude, ChatGPT)
- Connect HubSpot without code (Claude, ChatGPT)
- Connect Slack without code (Claude)
Developer setup
Auth setup and mcp.json for Claude Code and Cursor
- Stripe: Sign in with OAuth, or pass an API key as a Bearer token for headless use.
- HubSpot: Sign in with OAuth in your client (run
/mcpin Claude Code). Do it once interactively, and the client stores and refreshes the token. - Slack: Sign in with OAuth in your client (run
/mcpin Claude Code). Do it once interactively, and the client stores and refreshes the token.
Put this in .mcp.json (Claude Code, project root) or ~/.cursor/mcp.json (Cursor). Swap the example keys for your own, and don't commit real ones. Remove the // comment lines if your client requires strict JSON.
{
"mcpServers": {
"stripe": {
"url": "https://mcp.stripe.com"
// headless alternative: "headers": { "Authorization": "Bearer YOUR_STRIPE_API_KEY" }
},
"hubspot": {
"url": "https://mcp.hubspot.com"
},
"slack": {
"url": "https://mcp.slack.com/mcp"
}
}
}
Step-by-step prompts
- In Stripe, list subscriptions that are past due or unpaid, and open invoices more than {days} days past their due date: customer, customer email, plan, invoice number, amount, status, due date and days late. Leave out draft and voided invoices. Read only. Don't change anything in Stripe.
- For each customer, find the matching company in HubSpot by email domain. Show the owner, the renewal date from {renewal_field}, open tickets and any note from the last 14 days. List customers with no match separately. Don't change any records.
- Skip any account where a recent note says payment is on its way. For the rest, look up each owner in Slack by email, and draft one short alert per account for {channel}: who owns it, what's late, the account context, and one suggested save move. List owners you can't match. Show me the drafts.
- Post each alert only after I approve it. Then give me a one-line summary: how many accounts are behind and the total amount late.
Run it on a schedule (optional)
- Run it weekly, or twice a week if most of your customers pay monthly.
- In a scheduled run, stop at the table and the draft alerts, and send the drafts to yourself. Post to the CS channel only after you approve.
- For a headless run, Stripe accepts an agent API key. From December 2026 it rejects full-access secret keys and restricted keys without the Agent tag, so use a restricted Agent key with read access only.
Where this goes wrong
- Alerting on a customer who already paid. The customer may have paid another way, or told the owner a new card is coming. Check the HubSpot notes from the last 14 days for a payment or card comment, and skip anything with one.
- Draft or voided invoices counted as late. An invoice that was never finalized never reached the customer. Ask for open invoices only, and show each invoice's status and due date so you can spot drafts.
- Wrong owner pinged in Slack. The HubSpot owner's email may not match a Slack user. Match on email, list any owner without an exact match, and skip them instead of guessing.
- An accidental change in Stripe. Stripe's MCP server can void and finalize invoices, cancel subscriptions and issue refunds. Tell it up front the run is read-only, and stop it if it proposes any Stripe write.
Gotchas
- Stripe's listed tools cover customers, invoices and subscriptions. Payment intents, charges and decline reasons aren't among them, so this recipe works from past-due subscriptions and open invoices past their due date, not from individual failed payment attempts. It can tell you a customer is behind, not why the card was declined.
- Stripe's MCP server can write: it creates, finalizes and voids invoices, cancels subscriptions and issues refunds with human confirmation. Connect with an account or restricted key that only has the read access this recipe needs.
- In Claude Team and Enterprise, an owner must add the Stripe connector to the workspace before you can connect it.
- HubSpot and Slack both need admin setup. HubSpot non-admin users need a Super Admin to approve the connector, and Slack needs a workspace admin to approve the integration before anyone can connect.
- Using Salesforce instead? Use the read-only platform/sobject-reads server, since this recipe never writes to the CRM. Salesforce needs Enterprise Edition or above and an admin-created External Client App, and each tool call counts against your org's daily API quota.
Download
Get the prompts, guardrails and expected output as one Markdown file. Paste it into a Claude Project or ChatGPT project's instructions, or save it as CLAUDE.md for Claude Code.
Download failed-payment-save.md
New recipe and breakage notes every week
Vendor sites: HubSpot · Slack. If we join an affiliate program, these links will be labeled as affiliate links.