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 free plan.
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. Free plan, no credit card required.