Skip to main content

Failed Payment Recovery

Windback detects failed payments from your billing provider and runs a smart dunning sequence to recover the revenue automatically.

How Dunning Works

1

Detect

Windback receives a webhook from your payment provider when a payment fails (e.g., invoice.payment_failed from Stripe).
2

Create Record

A payment failure record is created for the customer, capturing the amount, currency, failure reason, and attempt count.
3

Dunning Sequence

Windback begins a configurable retry sequence. Each retry is spaced according to your retry_interval_hours setting.
4

AI Emails

Between retries, Windback sends AI-generated emails to the customer encouraging them to update their payment method. The tone escalates across the sequence based on your tone_sequence setting.
5

Resolution

The process ends when the payment succeeds (status: recovered), or all retries are exhausted (status: abandoned).

Supported Webhook Events

Windback listens for the following events from your payment provider:
ProviderFailure EventSuccess Event
Stripeinvoice.payment_failedinvoice.payment_succeeded
Razorpaypayment.failedinvoice.payment_succeeded
When Windback receives a success event for a customer with an active dunning sequence, the sequence is stopped automatically and the record is marked as recovered.

Payment Failure Statuses

StatusDescription
failingThe payment has failed and a dunning sequence is in progress
recoveredThe payment was successfully collected after one or more retries
abandonedAll retries have been exhausted without a successful payment

Dashboard Overview

The Failed Payments page in your project dashboard shows:

Recovery Stats

Total failed payments, recovery rate, and revenue recovered over the selected time range.

Active Sequences

Customers currently in a dunning sequence with their status, retry count, and next retry time.

Failure Breakdown

Common failure reasons (card declined, insufficient funds, expired card) with counts.

Email Performance

Open rates and click-through rates for dunning emails, broken down by sequence step.

API Endpoints

List Payment Failures

curl https://api.windbackai.com/api/v1/projects/:slug/payment-failures \
  -H "Authorization: Bearer <token>"
Response:
{
  "failures": [
    {
      "id": "pf_abc123",
      "customer_email": "jane@example.com",
      "amount": 4900,
      "currency": "usd",
      "status": "failing",
      "failure_reason": "card_declined",
      "attempts": 2,
      "max_retries": 4,
      "next_retry_at": "2026-04-05T14:00:00Z",
      "created_at": "2026-04-02T10:00:00Z"
    }
  ],
  "total": 1
}

Get Failure Detail

curl https://api.windbackai.com/api/v1/projects/:slug/payment-failures/:id \
  -H "Authorization: Bearer <token>"

Retry a Payment Manually

curl -X POST https://api.windbackai.com/api/v1/projects/:slug/payment-failures/:id/retry \
  -H "Authorization: Bearer <token>"
Manual retries count toward the max_retries limit. If the limit has already been reached, the request will return a 409 Conflict.

Get Recovery Stats

curl https://api.windbackai.com/api/v1/projects/:slug/payment-failures/stats \
  -H "Authorization: Bearer <token>"
Response:
{
  "total_failures": 142,
  "recovered": 98,
  "abandoned": 31,
  "active": 13,
  "recovery_rate": 0.69,
  "revenue_recovered": 487500,
  "currency": "usd"
}

Dunning Configuration

Get Current Config

curl https://api.windbackai.com/api/v1/projects/:slug/dunning-config \
  -H "Authorization: Bearer <token>"
Response:
{
  "enabled": true,
  "max_retries": 4,
  "retry_interval_hours": 72,
  "tone_sequence": ["friendly", "professional", "urgent", "final"],
  "send_emails": true,
  "sender_name": "Billing Team"
}

Update Config

curl -X PUT https://api.windbackai.com/api/v1/projects/:slug/dunning-config \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "max_retries": 4,
    "retry_interval_hours": 72,
    "tone_sequence": ["friendly", "professional", "urgent", "final"],
    "send_emails": true
  }'

Configuration Fields

FieldTypeDefaultDescription
enabledbooleantrueWhether dunning is active
max_retriesinteger4Maximum number of payment retry attempts
retry_interval_hoursinteger72Hours between each retry attempt
tone_sequencestring[]["friendly","professional","urgent","final"]Email tone for each step in the sequence
send_emailsbooleantrueWhether to send dunning emails to the customer
sender_namestring"Billing Team"Display name on dunning emails
A retry_interval_hours of 72 (3 days) works well for most SaaS products. Shorter intervals can feel aggressive; longer intervals risk the customer forgetting about the issue.

Setup Instructions

1

Connect Your Payment Provider

Add the Windback webhook URL to your payment provider. See Quickstart for the full URL format.
2

Verify Sender Domain

Dunning emails require a verified sender domain. Go to Settings > Email in your project dashboard to configure one.
3

Configure Dunning Settings

Navigate to Settings > Failed Payments or use the API above to set your retry count, interval, and tone sequence.
4

Test with a Failing Payment

Use your payment provider’s test mode to trigger a payment_failed event and confirm the dunning sequence starts.
Windback never initiates actual payment charges. Retries are triggered through your payment provider’s API, so all charges follow your existing billing rules and PCI compliance setup.