PaymentRescue sends webhook events to your endpoint when payment recovery events occur. Use these to trigger actions in your email platform, CRM, or custom system.
Webhooks allow your application to receive real-time HTTP POST notifications when recovery events happen. Each event includes a JSON payload with customer details and payment information.
Configure your webhook endpoint in the PaymentRescuedashboard under Settings → Webhooks. You can subscribe to specific event types or receive all events.
| Method | POST |
| Content-Type | application/json |
| Timeout | 10 seconds — respond within this window |
| Expected Response | 2xx status code |
| Max Payload Size | ~4 KB per event |
| Header | Description |
|---|---|
| X-PaymentRescue-Signature | HMAC-SHA256 signature of the payload for verification |
| X-PaymentRescue-Event | The event type (e.g., payment.failed) |
| X-PaymentRescue-Delivery | Unique delivery ID for deduplication |
Fired immediately when a subscription payment fails. Includes customer details, failure reason, and the amount at risk.
{
"id": "evt_abc123def456",
"type": "payment.failed",
"created_at": "2026-04-14T10:30:00Z",
"data": {
"customer_email": "jane@example.com",
"customer_name": "Jane Smith",
"amount": 9900,
"currency": "usd",
"invoice_id": "in_1234567890",
"failure_reason": "card_declined",
"recovery_step": 0
}
}Fired when a previously failed payment is successfully collected. This means the customer updated their payment method or a retry succeeded.
{
"id": "evt_xyz789ghi012",
"type": "payment.recovered",
"created_at": "2026-04-15T14:22:00Z",
"data": {
"customer_email": "jane@example.com",
"customer_name": "Jane Smith",
"amount": 9900,
"currency": "usd",
"invoice_id": "in_1234567890",
"failure_reason": "card_declined",
"recovery_step": 2
}
}Fired when a customer clicks the recovery link and successfully updates their payment method via the Stripe-hosted portal.
{
"id": "evt_mno345pqr678",
"type": "payment_method.updated",
"created_at": "2026-04-15T14:20:00Z",
"data": {
"customer_email": "jane@example.com",
"customer_name": "Jane Smith",
"amount": 9900,
"currency": "usd",
"invoice_id": "in_1234567890",
"failure_reason": "card_declined",
"recovery_step": 2
}
}| Field | Type | Description |
|---|---|---|
| id | string | Unique event identifier |
| type | string | Event type: payment.failed, payment.recovered, or payment_method.updated |
| created_at | string (ISO 8601) | When the event was created |
| data.customer_email | string | Customer's email address |
| data.customer_name | string | Customer's display name |
| data.amount | number | Amount in cents (e.g., 9900 = $99.00) |
| data.currency | string | Three-letter ISO currency code |
| data.invoice_id | string | Stripe invoice ID |
| data.failure_reason | string | Reason for failure: card_declined, insufficient_funds, expired_card, etc. |
| data.recovery_step | number | Current dunning step (0 = just failed, 1-3 = email sequence step) |
Every webhook request includes an X-PaymentRescue-Signature header. Verify this to ensure the request is authentically from PaymentRescue.
// Node.js verification example
import crypto from "crypto";
function verifyWebhookSignature(
payload: string,
signature: string,
secret: string
): boolean {
const expected = crypto
.createHmac("sha256", secret)
.update(payload)
.digest("hex");
return signature === `sha256=${expected}`;
}
// In your webhook handler:
app.post("/webhooks/paymentrescue", (req, res) => {
const signature = req.headers["x-paymentrescue-signature"];
const isValid = verifyWebhookSignature(
JSON.stringify(req.body),
signature,
process.env.PAYMENTRESCUE_WEBHOOK_SECRET
);
if (!isValid) {
return res.status(401).json({ error: "Invalid signature" });
}
// Process the event
const event = req.body;
switch (event.type) {
case "payment.failed":
// Add to email recovery campaign
break;
case "payment.recovered":
// Send celebration email, update CRM
break;
case "payment_method.updated":
// Log the update, notify team
break;
}
res.json({ received: true });
});If your endpoint returns a non-2xx status code or times out, PaymentRescue will retry the delivery with exponential backoff:
| Attempt | Delay | Total Elapsed |
|---|---|---|
| 1st retry | 1 minute | 1 minute |
| 2nd retry | 5 minutes | 6 minutes |
| 3rd retry | 30 minutes | 36 minutes |
| 4th retry | 2 hours | ~2.5 hours |
| 5th retry (final) | 24 hours | ~26.5 hours |
After 5 failed delivery attempts, the webhook is marked as failed. You can view failed deliveries and manually retry them from the dashboard.
Use webhooks to connect PaymentRescue with your favorite tools:
On payment.failed, add customer to a recovery email campaign. On payment.recovered, remove from campaign.
Send real-time notifications to a channel when payments fail or recover. Include amount and customer details for context.
Update customer records with payment status. Create tasks for account managers when high-value payments fail.
Track recovery metrics in your own data warehouse. Calculate real-time recovery rates and revenue saved.
Set up webhooks in your PaymentRescue dashboard. Start receiving real-time recovery events in minutes.