Recover failed Stripe payments with Postgres context and Resend

When a Stripe payment fails, look up the customer in your Postgres database, mark the account past due, and send a personalized recovery email from Resend.

Agentic Task
StripePostgreSQLResendFinanceEmail AutomationNotifications & Alerts
PromptCreate

Build me an agent workflow that recovers failed Stripe payments by enriching them with customer context from my Postgres database and sending a personalized recovery email through Resend.

Trigger: a Stripe webhook listening for invoice.payment_failed and charge.failed events.

When the webhook fires, the agent should:

1. Pull the Stripe customer ID, invoice or charge amount, currency, failure reason, and next retry date out of the event payload.

2. Use PostgreSQL Find Row to look up the matching account in my customers table by stripe_customer_id. The lookup should return the customer's name, primary contact email, plan tier, signup date, and last successful payment date.

3. Use PostgreSQL Update Row on that same row to set account_status to 'past_due' and stamp payment_failed_at with the current timestamp. Keep the update idempotent so re-deliveries of the same Stripe event don't churn the row or trigger duplicate emails.

4. If the event includes a subscription ID, optionally call Stripe Retrieve Subscription to get the current period end and next billing date so the email can reference real dates instead of vague language.

5. Compose the dunning email. Tone and personalization is where the agent earns its keep over a static template. Shape the copy by plan tier (self-serve trial gets a light touch, paid customer gets warmth, enterprise gets a more formal note), tenure (a brand-new account vs. a multi-year customer), and the specific failure reason from Stripe (declined card, expired card, insufficient funds, do_not_honor, etc.). The email should acknowledge the failure plainly, explain when Stripe will retry, link to the billing portal so the customer can update their card, and sign off from the billing or success team.

6. Send the email via Resend Send Email to the contact email from the Postgres row, falling back to the email on the Stripe customer object if the database lookup missed.

Edge cases: if the Postgres lookup finds no matching row, still send the recovery email using the Stripe customer name and email, and return the mismatch in the workflow output so we can reconcile later. If the row is already marked past_due with a payment_failed_at within the last 24 hours, skip the email and just log the additional failure so we don't spam the customer through Stripe's retry cycle.

Output: a structured summary with the customer ID, plan tier, failure reason, whether the database lookup hit or missed, whether the email was sent or skipped, and the Resend message ID.

What does this prompt do?

  • Fires the instant a Stripe charge or invoice payment fails, so dunning never waits on a manual export.
  • Looks up the matching account in your Postgres customer table and marks it past due with a timestamp, so the rest of your product knows the customer is at risk.
  • Pulls the customer's name, plan, and last successful payment date from your database to write an email that actually sounds like it knows them.
  • Sends a warm, on-brand recovery email through Resend with the retry schedule and a link to update their card, with tone shaped by plan tier and tenure.

What do I need to use this?

  • A Stripe account in live or test mode
  • A Postgres database with a customers or accounts table that includes the Stripe customer ID, plan, and a status column the workflow can update
  • A Resend account with a verified sending domain
  • A billing portal or update-card URL to include in the email

How can I customize it?

  • Change which columns get stamped on failure, for example past_due, delinquent, or a numeric grace counter.
  • Edit the email tone, signoff, and which billing portal link is included for each plan tier.
  • Add a higher-touch path for paid or enterprise customers, like skipping the email and opening a CSM task instead.
  • Scope the trigger to only the final Smart Retry instead of every failed attempt if you'd rather email less often.

FAQs

Does this fire on every failed attempt or only after Stripe gives up retrying?
By default it fires on each failed payment event from Stripe, so customers get a tone-matched email through the whole Smart Retries cycle. You can also scope it to only the final retry if you prefer fewer emails per customer.
What if the customer isn't in my Postgres database?
The agent falls back to the name and email on the Stripe customer record and still sends the recovery email. The mismatch is logged in the workflow output so you can clean up your database later.
Will it overwrite a customer who's already marked past due?
No. The update is idempotent, so re-runs against the same customer are safe. You won't accidentally double-email someone if Stripe re-delivers the same event.
Can I send from a different provider than Resend?
Yes. The same workflow works with SendGrid, Postmark, AWS SES, or Gmail. Just swap the send-email step when you generate the workflow.
Does this work for one-time charges or only for subscriptions?
Both. The trigger handles one-time charge failures and recurring subscription invoice failures, and the agent writes the email accordingly.

Related templates

Rank your Intercom queue by what each customer pays you

See every open conversation next to that customer's plan, monthly value and unpaid invoices, so the expensive account never sits waiting all morning.

Intercom
Stripe
App
Catch the trials quietly dying before the card gets charged

Open one desk each morning to see every account still in a trial, ranked by how much money is at stake against how little they have actually used.

Intercom
Stripe
General Input Database
App
Work every open Stripe dispute from one chargeback war room

See every dispute ranked by how little time is left, get a rebuttal drafted from real fraud signals, and submit only what you approve.

Stripe
IPQualityScore
General Input Database
App
Look up any customer's support, billing and CRM in one page

Type a customer email before a renewal call and get their whole support history next to their plan, their invoices and their open deals.

Help Scout
Stripe
HubSpot
App
Investor update studio that builds your board deck monthly

Open one screen each month to see your real numbers, write the commentary yourself, and generate a board deck you can send to investors.

Gamma
Stripe
HubSpot
+1
App
Sell and invoice Ghost newsletter sponsor slots in one board

Replace the sponsorship spreadsheet with a live board of upcoming issues, sold and open slots, real subscriber counts, and paid or unpaid status from Stripe.

Ghost
Stripe
App

Stop losing revenue to silent card failures.

Connect Stripe, Postgres, and Resend once, and Geni handles every failed payment with a personalized recovery email and a clean record in your database.