Daily failed payment recovery from MySQL to HubSpot and Slack
Every morning at 9am, turn yesterday's failed and declined charges in your billing database into HubSpot follow-ups for account owners and a single tidy Slack digest for the billing team.
Build me an agent workflow that recovers failed payments from my MySQL billing database every morning. Trigger: cron, daily at 9:00 AM in my local time zone.
Step 1. Pull the failures. Use MySQL Custom Query against my payments/transactions table to select every charge with a failed or declined status in the last 24 hours. Join to the customers table so each row also has: customer email, company name, plan name, monthly recurring revenue (MRR), date of the most recent successful charge, the failure code and human-readable reason, the HubSpot contact id if we already store one, and the account owner's name and email. Order by MRR descending. If the result set is empty, stop here and post nothing to Slack.
Step 2. For each failed payment, create a HubSpot follow-up. First use HubSpot Get Contact with idProperty=email to look up the contact by the customer's email address (skip this lookup if my database already stores the HubSpot contact id). Then use HubSpot Create Task with: subject in the form "Recover $<amount> from <company name>", a 2-3 sentence body that summarizes the situation (customer, amount, failure code and reason, plan, MRR, days since last successful charge, link back to the customer in our admin if I provide a URL pattern), due date = tomorrow at 9am local, status = NOT_STARTED, priority = HIGH when MRR is above a threshold I can tune (default $500/mo) and MEDIUM otherwise, assigned to the HubSpot owner whose email matches the account owner from the database (fall back to a default owner if no match), and associated with the matching HubSpot contact. Capture the returned task id and a deep link to the task in HubSpot for the Slack summary.
Step 3. Avoid duplicates. Before creating a new task, check whether the same contact already has an open task with a subject starting with "Recover $" created in the last 3 days. If yes, update that task instead (refresh the body and bump the due date) rather than stacking a second one.
Step 4. Post the daily summary. Use Slack Send a Message to post one message to #billing (let me change the channel). Open with a one-line header like "Failed payments overnight: N customers, $X at risk." Then a sorted list (highest MRR first) where each line shows: company name, plan tier, dollar amount, failure code in plain English, and a link to the HubSpot task. Keep it scannable, use Slack mrkdwn, and group enterprise-tier customers at the top with a small flag. If step 1 returned zero rows, do not post anything to Slack at all.
Inputs I should be able to configure at setup time: the MySQL table and column names for payments and customers, the MRR threshold for HIGH priority, the Slack channel, the default HubSpot owner email, the time zone, and an optional URL pattern for linking to the customer in our internal admin.
Quality bar: parameterize every MySQL query (use ? placeholders, never string-concatenate values), handle the empty-result case gracefully (silent on clean days), and write the Slack message and HubSpot task bodies in plain English a non-technical billing or CS teammate can act on in under a minute.
Additional information
What does this prompt do?
- Pulls every failed or declined payment from the last 24 hours out of your MySQL billing database, with customer, plan, MRR, last successful charge, and the failure reason.
- Creates a HubSpot task on the matching contact, assigned to the named account owner, with a clear subject like Recover $X from Acme and a due date of tomorrow.
- Marks tasks high priority when the customer's MRR is above a threshold you set so your team works the biggest dollars first.
- Posts one daily summary to a billing channel in Slack, sorted by MRR, with each customer, amount, failure reason, and a link to its HubSpot task. Stays silent on days with no failures.
What do I need to use this?
- A MySQL database that stores your payment attempts and customer records (works with your own billing tables or a Stripe webhook mirror).
- A HubSpot login with permission to view contacts and create tasks, plus the account owner names that map to your customers.
- A Slack workspace and a channel where the daily digest should land, such as #billing or #revenue-ops.
How can I customize it?
- Change the time, time zone, or cadence. Run it twice a day, only on weekdays, or right after your nightly billing job.
- Tune the MRR threshold that flips a task to high priority, or add tiers like enterprise, mid market, and self serve.
- Pick a different Slack channel, or send a private DM to the head of billing instead of posting publicly.
- Adjust the lookback window, the failure codes you care about, or skip customers who already churned.
Frequently asked questions
What if my payment data lives in Stripe, not MySQL?
Do I need a paid HubSpot plan?
How does it know who to assign each task to?
What happens on days with no failed payments?
Can I avoid duplicate tasks for the same customer?
Stop letting failed payments sit unnoticed for days.
Connect your MySQL database, HubSpot, and Slack once, and your billing team gets a sorted recovery list in their inbox every morning at 9.