> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dodopayments.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Subscription Dunning

> Send email sequences automatically to recover lapsed or cancelled subscriptions, and prompt customers to update their payment method or re-purchase.

<Info>
  Subscription Dunning emails customers whose subscription lapsed after a failed payment, or who cancelled it, and asks them to update their payment method or re-purchase. It runs automatically once you turn it on.
</Info>

## What Is Subscription Dunning?

Dunning detects when a subscription enters a recoverable state and sends a sequence of emails that ask the customer to act. Three states start a sequence:

* **On Hold subscriptions**: A renewal payment failed, for example because of insufficient funds or an expired card.
* **Past Due subscriptions**: A renewal payment failed while a [grace period](/features/subscription#grace-period) is open.
* **Cancelled subscriptions**: The customer cancelled from the Customer Portal.

## How Dunning Works

<Steps>
  <Step title="Trigger">
    A subscription enters one of the three states:

    * **On Hold**: A renewal payment failed.
    * **Past Due**: A renewal payment failed while a [grace period](/features/subscription#grace-period) is open.
    * **Cancelled**: The customer cancelled their subscription from the Customer Portal.

    Dodo Payments then creates a dunning attempt and sends the `dunning.started` webhook. No attempt starts when the matching sequence has no enabled emails, and a subscription has at most one active attempt at a time.
  </Step>

  <Step title="Grace Period">
    If you set a [grace period](/features/subscription#grace-period), a failed renewal moves the subscription to `past_due` instead of `on_hold`.

    The on-hold email sequence runs during that window, so the customer is asked to pay while they still have access.

    One failed payment starts one sequence. The end of the window doesn't start a second sequence. If the window ends with the subscription on hold, the remaining emails in the sequence still go out. If it ends with the subscription cancelled, the attempt is marked `exhausted`.

    The dunning attempt records a `past_due` trigger state. When you read dunning analytics, filter on `past_due` as well as on `on_hold`.
  </Step>

  <Step title="Email Sequence">
    Based on the trigger state, Dodo Payments sends up to 4 dunning emails at the delays you configure. Each email links to the Customer Portal, where the customer can update their payment method, or to a checkout where they can re-purchase a cancelled subscription.
  </Step>

  <Step title="Recovery">
    When the customer updates their payment method in the Customer Portal, Dodo Payments automatically charges the remaining dues. If the payment succeeds, the subscription is reactivated and the dunning attempt is marked `recovered`.
  </Step>
</Steps>

## Status Lifecycle

Each dunning attempt has one of these statuses:

| Status | Description |
| - | - |
| `recovering` | The dunning attempt is active, and emails are being sent |
| `recovered` | The customer updated their payment method or re-purchased, and the payment succeeded |
| `exhausted` | All emails were sent and seven days passed with no recovery, or the subscription state changed unexpectedly |

<Info>
  When a dunning attempt is marked `exhausted`, Dodo Payments doesn't change the subscription. It stays in its current state (past due, on hold, or cancelled).
</Info>

## Configuring Dunning

Turn on and configure Dunning in **Settings → Recovery** in your dashboard. Dunning is off by default.

<Frame caption="Dunning settings in the dashboard showing enable toggle, on-hold sequence, and cancelled sequence">
  <img src="https://mintcdn.com/dodopayments/tvJ2MmXYymW0IZ3R/images/recovery/dunning-settings.png?fit=max&auto=format&n=tvJ2MmXYymW0IZ3R&q=85&s=7389a9413d6008800e7ca8a5c4cd1ee5" alt="Dunning settings page with enable toggle, four on-hold emails at 1, 3, 5, and 7 day intervals, and four cancelled emails at the same intervals" style={{ maxHeight: '500px', width: 'auto' }} width="2250" height="1628" data-path="images/recovery/dunning-settings.png" />
</Frame>

### Email Sequences

Dunning has two email sequences, **On Hold** and **Cancelled**, each with up to 4 emails. The dashboard lists them as **Emails sent to customer when subscription is on hold** and **Emails sent to customer when subscription is cancelled**. A `past_due` attempt uses the On Hold sequence.

Each email has these settings:

| Setting | Description |
| - | - |
| **Enable this email** | Turns the email on or off without deleting it |
| **Send after** | How long after dunning starts to send this email, in days and hours |
| **Subject Line** | The email subject. It supports the placeholders listed after this table. |
| **Email Body Text** | Plain text shown inside the standard dunning email layout. Line breaks are kept. HTML and placeholders are not rendered. |
| **Reply-to email** | The address that receives customer replies. If you leave it empty, your store contact email is used. |

In **Subject Line**, Dodo Payments replaces these placeholders: `{store_name}`, `{store_owner_name}`, `{store_contact_email}`, `{subscription_id}`, `{failure_reason}`, and `{payment_form_link}`.

The default delays are:

| Sequence | Email # | Default Delay |
| - | - | - |
| On Hold | 1 | 1 day |
| On Hold | 2 | 3 days |
| On Hold | 3 | 5 days |
| On Hold | 4 | 7 days |
| Cancelled | 1 | 1 day |
| Cancelled | 2 | 3 days |
| Cancelled | 3 | 5 days |
| Cancelled | 4 | 7 days |

### Example Dunning Emails

Dunning sends a different email for each subscription state. These examples show what the customer sees.

<Tabs>
  <Tab title="On Hold">
    <Frame caption="Dunning email sent when a renewal payment fails and the subscription is on hold">
      <img src="https://mintcdn.com/dodopayments/tvJ2MmXYymW0IZ3R/images/recovery/dunning-on-hold-email.png?fit=max&auto=format&n=tvJ2MmXYymW0IZ3R&q=85&s=5e46040ed49a4da84569afdeeb87c813" alt="Dunning email for an on-hold subscription showing store name, message about failed payment, subscription details with plan and amount, and an Update Payment Method button" style={{ maxHeight: '500px', width: 'auto' }} width="1070" height="1502" data-path="images/recovery/dunning-on-hold-email.png" />
    </Frame>
  </Tab>

  <Tab title="Cancelled">
    <Frame caption="Dunning email sent when a customer cancels their subscription">
      <img src="https://mintcdn.com/dodopayments/tvJ2MmXYymW0IZ3R/images/recovery/dunning-cancelled-email.png?fit=max&auto=format&n=tvJ2MmXYymW0IZ3R&q=85&s=f404fbf9415df4e4bd01562a90bd2456" alt="Dunning email for a cancelled subscription showing store name, message about cancellation, subscription details with plan and amount, and a Re-purchase Subscription button" style={{ maxHeight: '500px', width: 'auto' }} width="1070" height="1502" data-path="images/recovery/dunning-cancelled-email.png" />
    </Frame>
  </Tab>
</Tabs>

## Customer Recovery Experience

When a customer clicks the link in an on-hold dunning email, the Customer Portal opens on their subscription. There they can see the subscription status and update their payment method.

<Frame caption="Customer portal showing an on-hold subscription with option to update payment method">
  <img src="https://mintcdn.com/dodopayments/tvJ2MmXYymW0IZ3R/images/recovery/customer-recovery-page.png?fit=max&auto=format&n=tvJ2MmXYymW0IZ3R&q=85&s=f498d3654afd3d70447b7b8ce7bf3767" alt="Customer portal showing an on-hold subscription for Pro Plan at $95.00/year with an Update payment method button and a warning banner about the failed payment" style={{ maxHeight: '500px', width: 'auto' }} width="2144" height="734" data-path="images/recovery/customer-recovery-page.png" />
</Frame>

After the customer updates their payment method, Dodo Payments charges any outstanding dues. If the payment succeeds, the subscription returns to `active`.

For a cancelled subscription, the link opens a checkout page with the subscription's product already in the cart.

## Analytics

Track Dunning performance under **Analytics → Recovery** in your dashboard.

<Frame caption="Recovery analytics dashboard showing ACR and dunning metrics">
  <img src="https://mintcdn.com/dodopayments/B3-0kuKcZDP1TiJD/images/recovery/recovery-analytics.png?fit=max&auto=format&n=B3-0kuKcZDP1TiJD&q=85&s=d3bf0c7474818bc4584b75654423e14c" alt="Recovery analytics dashboard showing dunning entry counts, success rates, recovered revenue, and per-email performance breakdown" style={{ maxHeight: '500px', width: 'auto' }} width="2548" height="2190" data-path="images/recovery/recovery-analytics.png" />
</Frame>

The Dunning section shows these metrics:

| Metric | Description |
| - | - |
| **Dunning entries** | Total number of dunning attempts created |
| **Recovery rate** | Percentage of dunning attempts that led to recovery |
| **Recovered revenue** | Total revenue recovered through dunning |
| **Emails sent** | Total number of dunning emails sent |
| **Avg. time to recover** | Average time from the start of dunning to recovery |
| **Recovery rate by email** | Breakdown of which email in the sequence drove the recovery |

## Webhook Events

Dunning sends two webhook events:

| Event | Description |
| - | - |
| `dunning.started` | A dunning attempt has started for a subscription |
| `dunning.recovered` | A subscription has been recovered through dunning |

<Card title="Recovery Webhook Payloads" icon="code" href="/developer-resources/webhooks/intents/recovery">
  View the full webhook payload schemas for dunning events.
</Card>

## Edge Cases

Dunning handles these cases automatically:

| Scenario | Behavior |
| - | - |
| Customer pays before the first email | The subscription is reactivated, and the dunning attempt is marked `exhausted` instead of `recovered`. No `dunning.recovered` event is sent. |
| Customer has, or buys, another active subscription with your business | The dunning attempt is marked `exhausted` before the next email |
| All dunning emails sent | Seven days after the last email, the dunning attempt is marked `exhausted`. The subscription state doesn't change. |
| Subscription changes to an unexpected state, for example cancellation at the end of a grace period | The dunning attempt is marked `exhausted` |
| The subscription's [BYOP](/features/byop) connector is disabled | No dunning attempt starts. A running attempt sends no emails until the connector is enabled again. |

## Best Practices

* **Start with defaults**: The default delays (1, 3, 5, and 7 days) spread the emails over a week, so customers aren't flooded but still see a steady reminder.
* **Monitor recovery rates**: Check **Recovery rate by email** to see which email drives the most recoveries. If later emails recover almost nothing, turn them off.
* **Coordinate with support**: Tell your support team that dunning emails are going out, so they can help customers who reply.
* **Review subscription states**: Pair dunning with the `subscription.on_hold` and `subscription.cancelled` webhooks to track the full subscription lifecycle.

<Info>
  Dunning works alongside the existing on-hold and reactivation flows in the Customer Portal. Once you turn it on, it runs automatically with no integration work.
</Info>

## Related

<CardGroup cols={2}>
  <Card title="Recovery Webhooks" icon="webhook" href="/developer-resources/webhooks/intents/recovery">
    React to `dunning.started` and `dunning.recovered` events.
  </Card>

  <Card title="Abandoned Cart Recovery" icon="cart-shopping" href="/features/recovery/abandoned-cart-recovery">
    Recover abandoned or failed checkouts with recovery emails.
  </Card>

  <Card title="Customer Portal" icon="id-card" href="/features/customer-portal">
    Customers update their payment methods in the Customer Portal.
  </Card>

  <Card title="Subscriptions" icon="repeat" href="/features/subscription">
    The subscription states that trigger dunning.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.