> For clean Markdown of any page, append .md to the page URL. > For a complete documentation index, see https://docs.paymentkit.com/guides/billing/dunning-recovery/automatic-retries-emails/llms.txt. > For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.paymentkit.com/_mcp/server. # Automatic retries & emails # How dunning works Dunning is composed of three coordinated actions: #### Payment retries Automatic attempts to charge the customer. #### Email notifications Up to 5 emails per dunning cycle (capped at one every 24 hours), each containing a secure payment method update link. Emails are sent at the retry steps configured in the profile's email map — not necessarily after every attempt. #### Failure handling Controls what happens if all payment attempts ultimately fail: * **Subscription status:** Cancel subscription / pause subscription / leave subscription active (past due) * **Invoice status:** Mark invoice as uncollectible / leave invoice open ```mermaid flowchart TD A[Payment fails] --> B[Retry schedule triggered] B --> C[Send dunning email with payment update link] C --> D{Hard decline?} D -->|Yes| E[Try next payment method] E --> F{Method left to try?} F -->|Yes| B F -->|No| G[Apply failure handling → Notify customer to update method] D -->|No| H{Retries exhausted?} H -->|Yes| I[Apply subscription & invoice failure handling] H -->|No| B ``` --- # Retry schedules PaymentKit automatically retries failed payments according to the **subscription billing cycle**. The schedule varies by cycle length. * **Retry interval:** Time between retry attempts * **Final retry:** Last retry before applying failure handling * **Retry attempts:** `floor(final_retry / retry_interval) + 1`, then capped by the profile's max retries (adaptive defaults: 3 daily, 4 short, 8 standard, 10 long) ## Cycle lengths & parameters | Cycle length | Retry interval | Final retry (offset from the invoice due date) | | -------------------- | ----------------- | -------------------------------------------------------------------------------------------------------- | | Daily (1 day) | 23 hours | `min(23h, payment_terms*24h - 1h, next_invoice_date - invoice_due_date - 1h)` | | Short (2–6 days) | 2 days (48 hours) | `min(cycle_length - 1, payment_terms - 1, next_invoice_date - invoice_due_date - 1)` | | Standard (7–29 days) | 4 days (96 hours) | `min(cycle_length - 1, max_dunning_window, payment_terms - 1, next_invoice_date - invoice_due_date - 1)` | | Long (≥30 days) | 4 days (96 hours) | `min(cycle_length - 1, max_dunning_window, payment_terms - 1, next_invoice_date - invoice_due_date - 1)` | `max_dunning_window` defaults to 30 days. Standard and long cycles share the same interval and final-retry formula; they differ only in the adaptive profile's default max retries (8 vs 10). Emails are sent at the retry steps configured in the profile's email map — typically the first at the initial failure and the last at the final retry, with additional steps for longer cycles — capped at 5 per cycle and no more than one every 24 hours. The timeline below is illustrative; emails do not necessarily follow every retry. ```mermaid gantt dateFormat YYYY-MM-DD axisFormat %b %d title Retry & Email Timeline section Retry & Email Retry 1 :a1, 2026-01-01, 1d Email 1 :a2, after a1, 1d Retry 2 :a3, after a2, 1d Email 2 :a4, after a3, 1d Retry 3 :a5, after a4, 1d Email 3 :a6, after a5, 1d Final Retry :a7, 2026-01-21, 1d Final Email :a8, after a7, 1d ``` Intervals adjust for cycle type; Short and daily cycles would compress accordingly. --- # Retry behavior by profile type How retries are scheduled depends on whether you're using an adaptive (system default) or custom dunning profile. ## Adaptive profiles: Intelligent retries Adaptive profiles inject additional retry attempts based on the decline reason: | Decline Type | Extra Retries | Timing | | ------------------------------------------------ | ----------------- | ------------------------------------ | | **TECHNICAL** (network timeout, processor error) | Technical retries | T+1h and T+2h after failure | | **SOFT** (insufficient funds) | Liquidity retries | 1st/15th of month or Fridays at 9 AM | > **Tip** > > Liquidity retries target paydays when customers are most likely to have funds available. This significantly improves recovery rates for insufficient funds declines. These intelligent retries don't run alongside the standard schedule — they're reconciled with it through a 24-hour deduplication window. When more than one retry falls in the same window, the highest-priority one fires (priority order: final > technical > liquidity > standard). ## Custom profiles: Fixed intervals Custom profiles use your configured `retry_interval_hours` for every retriable decline, with no decline-type-specific timing: * TECHNICAL declines → fixed interval (no T+1h/T+2h fast-path) * SOFT declines → fixed interval (no liquidity/payday targeting) * HARD declines → payment-method update, the same as adaptive profiles (the fallback-card cascade is not profile-specific) Retries occur at predictable, fixed intervals. > **Note** > > Choose custom profiles when you need deterministic retry schedules, have compliance requirements for fixed timing, or want full control over every retry attempt. ## The renewal wall applies to both The **renewal wall** — 1 hour before the current billing period ends — is not an adaptive behavior. It is a system constraint that profile configuration cannot override, and it binds custom profiles exactly as it binds adaptive ones: * No retry is scheduled at or after the wall. * If your fixed interval would place the next retry past the wall, that attempt is pulled back onto the wall and runs there as the **final retry**. Choosing a custom profile does not forfeit the last attempt of the cycle. * Once the wall has passed, dunning ends and your configured failure handling is applied. The wall clamps your schedule rather than extending it. If your configured retries run out before the wall, dunning ends there — no extra attempt is added beyond your `max_retries`. > **Warning** > > A `retry_interval_hours` close to or longer than the billing cycle means most of your configured retries never run: the cycle hits the wall first and the attempt that would have crossed it becomes the final one. Keep the interval well under the cycle length to use the full retry budget. One-time invoices have no next billing period and therefore no renewal wall; their retries are bounded by the one-time retry window instead. --- # Failure handling settings When retries are off or exhausted, PaymentKit applies these rules: | Type | Option | Description | | ----------------------- | ----------------------------------- | --------------------------------------------------------- | | **Subscription status** | Cancel subscription | Cancel the subscription when all retries fail | | | Pause subscription | Pause the subscription when all retries fail | | | Keep subscription active (past-due) | Leave the subscription active even if all payments fail | | **Invoice status** | Mark as uncollectible | Treat the invoice as uncollectible after all retries fail | | | Leave invoice open | Keep the invoice open for future collection attempts | > **Note** > > The invoice status choice takes effect only when the subscription is **paused**. When the subscription is cancelled or left active (past-due), the invoice is always marked uncollectible. For most businesses, cancelling the subscription and marking the invoice uncollectible will give you the cleanest reporting. --- # Hard decline handling When a payment method returns a hard decline (expired card, closed account, invalid card number, stolen/lost card), PaymentKit: 1. **Marks the payment method as declined** for this specific invoice 2. **Attempts the next payment method** in the customer's payment method list 3. **Repeats until success** or all payment methods have hard declined If all payment methods hard decline, the invoice moves to "Update payment method" status and: * Automatic retries stop — no usable payment method remains to charge * The customer is notified to update their payment method * Adding a valid payment method resumes collection; if the dunning cycle has already ended, the new method starts a fresh cycle > **Note** > > Hard decline tracking is per-invoice. A payment method that fails on one invoice may still work for other invoices. --- # Edge cases during dunning PaymentKit gracefully handles scenarios where external changes occur during active dunning: ## Invoice manually paid If an invoice is marked as paid outside the normal payment flow (e.g., manual payment recorded, payment via alternative channel), dunning stops immediately: * No further automatic retries are scheduled * Dunning status transitions to "Completed" * Subscription state updates based on remaining unpaid invoices ## Invoice voided When an invoice is voided during dunning: * Dunning ends with the terminal status "Invoice voided" (distinct from "Completed") * The subscription continues if other invoices are still active * No end behavior is applied (voiding is explicit cancellation of the debt) ## Subscription cancelled externally If a subscription is cancelled while in dunning (e.g., via API, admin action, or customer request): * Scheduled payment retries are skipped * Outstanding invoices remain in their current state * End behavior for existing invoices follows your failure handling settings ## Payment method changes During active dunning: * **Method deleted**: Next retry uses remaining methods; if none available, transitions to "Update payment method" * **Method added**: New method is included in the next retry attempt * **Default method changed**: New default is prioritized in the retry order > PaymentKit’s dunning system automatically recovers failed payments through retries and emails while giving you control over subscription and invoice outcomes when all payment attempts fail.