Skip to main content

Dunning

When an invoice payment fails, Subscribd automatically retries the charge according to a configurable dunning schedule. Subscriptions that exhaust all retries without a successful payment are marked expired and access is revoked.

Default retry schedule

Out of the box, Subscribd retries failed payments at:
  • 24 hours after initial failure
  • 72 hours after initial failure
  • 168 hours (7 days) after initial failure
If all three retries fail, the subscription moves to expired and the SubscriptionExpired event is fired.

Configuration

The retry_after array defines when retries are attempted, in hours after the first failure. You can add or remove entries to suit your billing cycle. For example, a weekly billing cycle might use [24, 96, 240].

How dunning works

  1. Payment fails — gateway fires invoice.payment_failed (or equivalent). The subscription moves to past_due.
  2. Retry job scheduled — a RetryInvoice job is queued for each interval in retry_after.
  3. Retry succeeds — the invoice is marked paid, the subscription returns to active, and InvoicePaid is fired.
  4. Retry failsPaymentRetryFailed is fired if the current hour matches a notify_at threshold.
  5. All retries exhausted — if cancel_on_fail is true (default), the subscription is marked expired and SubscriptionExpired is fired.

Custom dunning strategy

Implement Pixelworxio\Subscribd\Contracts\DunningStrategy to replace the built-in schedule with custom logic:
Register your strategy in config/subscribd.php:

Notifying customers during dunning

Listen to PaymentRetryFailed to send reminder emails or in-app notifications:
Register your listener in AppServiceProvider::boot():

Manually retrying an invoice

Retry a specific invoice immediately, bypassing the dunning schedule:
This attempts a charge on the customer’s default payment method and returns the updated Invoice model. If the charge succeeds, the subscription returns to active.

Grace period

When a subscription enters past_due, the billable retains access for grace_days (default: 3) before the subscription is expired. Configure this globally or per plan:
Or in config/subscribd.php:

Updating payment methods

When a customer updates their payment method during a past_due period, trigger an immediate retry:

Checking dunning status

Next steps

  • Hooks and Events — Events fired during the dunning cycle
  • Webhooks — Receiving payment failure events from gateways