Get PaymentRescue up and running in under 2 minutes. No code changes required.
┌─────────────┐ invoice.payment_failed ┌──────────────────┐
│ │ ──────────────────────────────> │ │
│ Stripe │ │ PaymentRescue │
│ │ <───────────────────────────── │ │
└─────────────┘ billing_portal.session └────────┬─────────┘
│ │
│ payment_intent.succeeded │ Dunning Emails
│ │ (3-step sequence)
▼ ▼
┌─────────────┐ ┌──────────────────┐
│ Customer │ <────────────────────────────── │ Email Inbox │
│ pays with │ "Update Payment" link │ (Resend API) │
│ new card │ └──────────────────┘
└─────────────┘
│
│ Webhook: payment succeeded
▼
┌─────────────────────────────────────────────────────────────────┐
│ PaymentRescue marks invoice as RECOVERED, stops email sequence │
└─────────────────────────────────────────────────────────────────┘
Sign up for PaymentRescue with your email. No credit card required for the 14-day trial.
Click "Connect Stripe" in the dashboard. You'll be redirected to Stripe's OAuth flow where you authorize PaymentRescue to access your account.
Once connected, Stripe automatically sends us invoice.payment_failed events. Here's what the webhook payload looks like:
// Stripe webhook event: invoice.payment_failed
{
"id": "evt_1234567890",
"type": "invoice.payment_failed",
"data": {
"object": {
"id": "in_1234567890",
"customer": "cus_ABC123",
"amount_due": 9900,
"currency": "usd",
"attempt_count": 1,
"next_payment_attempt": 1711324800,
"customer_email": "customer@example.com",
"customer_name": "Jane Smith"
}
}
}We store the failed payment, create a secure payment update link via Stripe, and queue the first dunning email.
// Internal flow (simplified)
async function handleFailedPayment(event) {
// 1. Store the failed invoice
await db.failedPayments.create({
invoiceId: event.data.object.id,
customerId: event.data.object.customer,
amount: event.data.object.amount_due,
email: event.data.object.customer_email,
});
// 2. Create Stripe billing portal session
const session = await stripe.billingPortal.sessions
.create({
customer: event.data.object.customer,
return_url: "https://yourapp.com/billing",
});
// 3. Queue first dunning email
await emailQueue.add("send-dunning", {
step: 1,
to: event.data.object.customer_email,
updateUrl: session.url,
amount: event.data.object.amount_due,
});
}The 3-step email sequence fires on days 0, 3, and 7. Each email includes a one-click payment update link. If the customer pays at any step, the sequence stops automatically.
// Dunning schedule
const DUNNING_SEQUENCE = [
{ step: 1, delay: "0 days", tone: "friendly" },
{ step: 2, delay: "3 days", tone: "urgent" },
{ step: 3, delay: "7 days", tone: "final" },
];
// Email is automatically skipped if:
// - Payment was recovered
// - Customer updated payment method
// - Invoice was voided or marked uncollectibleTrack recovery rates, email performance, and revenue saved in real-time. Export data to CSV for reporting.
PaymentRescue automatically processes these Stripe webhook events:
| Event | Action |
|---|---|
| invoice.payment_failed | Start dunning sequence, create recovery link |
| invoice.payment_succeeded | Mark as recovered, stop email sequence |
| customer.subscription.deleted | Mark as churned, log final status |
| payment_method.attached | Trigger immediate retry of failed invoice |
| invoice.voided | Cancel dunning sequence |
Set up in 2 minutes. 14-day free trial. No credit card required.