Limited offer · Save $800 on the snapshot · Closing in 00d 00h 00m 00s Claim now →
Free guide for SaaS founders

Set up dunning and failed-payment recovery in GHL

Step-by-step guide to configuring the SaaS Snapshot's four-touch dunning workflow — including billing provider webhooks, sequence timing, and recovery measurement.

Published May 16, 2026 · Takes PT2H

Step-by-step

The 7-step walkthrough

1

Configure your billing provider webhook

Connect Stripe, Paddle, or Chargebee to your GHL snapshot by adding the webhook endpoint URL to your billing provider's developer settings and selecting the required payment failure and recovery events.

2

Map webhook fields to GHL custom fields

In GHL, verify that incoming webhook data maps correctly to the pre-configured custom fields: payment_failed_date, payment_failure_reason, payment_recovery_date, and subscription_status.

3

Set your dunning window

Configure how many days from failed payment to access suspension (default 14 days). This setting drives the timing of all four dunning touches — adjust it for your billing model and customer contract terms.

4

Customize email and SMS templates

Personalize the four dunning message templates with your product name, brand voice, and direct billing portal URL. Verify each message includes a working update-payment link.

5

Configure the success branch

Verify that the payment-recovered webhook (Stripe: invoice.payment_succeeded) correctly suppresses remaining dunning touches, removes the in-app banner, and triggers the recovery confirmation email.

6

Run a test failed-payment simulation

Use your billing provider's test mode to trigger a payment failure on a test contact. Confirm all four touches fire on schedule and the success branch fires when payment is recovered.

7

Go live and monitor first 30 days

Enable the dunning workflow on your live account contacts. Check the recovery rate dashboard weekly for the first month and tune subject lines or timing based on which touch drives the most card updates.

Free download · No credit card

Get the full Set up dunning and failed-payment recovery in GHL as a PDF

Read this guide right here on the page — or send the full PDF straight to your inbox along with our weekly SaaS automation playbooks. Includes the checklist, real-world examples, and our "what to automate next" decision tree.

  • The complete 7-step walkthrough as a printable PDF
  • A bonus "what to automate next" checklist for your firm
  • Weekly playbook emails — unsubscribe anytime
  • Zero spam · zero phone calls unless you ask
Loading question…

No credit card. We respect your inbox.

Why dunning needs to be configured carefully

Failed-payment recovery is one of the highest-ROI automations in the SaaS lifecycle — but it only works if the technical connections between your billing provider and GHL are set up correctly. A dunning workflow that fires on the wrong event, sends to the wrong contact, or fails to suppress when payment recovers creates a worse experience than no dunning at all.

This guide walks through every configuration step with enough detail to get it right on the first attempt.

Step 1 — Billing provider webhook configuration

Stripe

In your Stripe Dashboard, navigate to Developers → Webhooks → Add endpoint.

Endpoint URL: https://[your-ghl-subdomain].gohighlevel.com/webhook/dunning (exact URL provided in your snapshot onboarding).

Events to send:

  • invoice.payment_failed — triggers the dunning sequence start.
  • invoice.payment_succeeded — triggers the success branch and suppresses remaining touches.
  • customer.subscription.deleted — logs voluntary cancellation and excludes the contact from dunning (they cancelled intentionally — don’t chase a payment they don’t want to make).
  • customer.subscription.updated — catches plan downgrades that may affect access levels.

Paddle

In your Paddle seller dashboard, navigate to Developer Tools → Notifications → New Destination.

Notification URL: your GHL webhook endpoint (provided in onboarding).

Events to send:

  • subscription.payment.failed
  • subscription.payment.succeeded
  • subscription.cancelled
  • subscription.updated

Chargebee

In Chargebee, navigate to Settings → Configure Chargebee → Webhooks → Add Webhook.

Events to send:

  • payment_failed
  • payment_succeeded
  • subscription_cancelled
  • subscription_changed

Step 2 — Field mapping verification

The SaaS Snapshot ships with pre-configured custom fields for dunning data. After setting up your billing webhook, trigger a test event from your billing provider’s test mode and verify that the following fields populate correctly on a test contact in GHL:

FieldExpected value
payment_failed_dateDate of failure (ISO 8601)
payment_failure_reason”card_declined”, “insufficient_funds”, “expired_card”, or provider code
subscription_status”past_due” or equivalent
dunning_touch_countIncrements with each message sent (0 → 1 → 2 → 3 → 4)
payment_recovery_datePopulated when recovery event fires (empty until then)

If any field doesn’t populate, check the field mapping in GHL’s webhook configuration (Settings → Integrations → Webhooks) and verify the incoming payload key names match your billing provider’s documentation.

Step 3 — Dunning window configuration

The dunning window (default: 14 days from failed payment to access suspension) needs to match your business model:

Monthly subscriptions, low-touch self-serve: 14 days is appropriate. Long enough that customers have time to notice and fix the issue; short enough that you’re not extending credit indefinitely.

Annual contracts or enterprise accounts: Consider 21-30 days. A finance team may need a billing cycle to reissue a corporate card. Suspending an enterprise account at 14 days can damage the relationship.

Free + paid tiers: If customers can continue on a limited free tier when payment fails, the “suspension” event becomes a downgrade. Configure the workflow’s suspension branch to trigger a downgrade action rather than a full access block.

To change the dunning window: in GHL Workflows, find the Dunning - Day 14 - Final Warning workflow and update the delay between Touch 3 and Touch 4 (and the access suspension trigger) to match your window.

Step 4 — Template customization

Each of the four dunning email templates ships with placeholder text using [Product] and [billing portal URL] markers. Before going live, update every template:

Replace:

  • [Product] → your product name.
  • [billing portal URL] → your direct billing portal URL (Stripe Customer Portal, Paddle billing page, or Chargebee self-serve portal). This must be a direct deep link that takes the customer immediately to the card update screen — not a login page they need to navigate from.

Verify:

  • Each email renders correctly in both dark mode and light mode (test in Gmail, Outlook, and Apple Mail).
  • The SMS messages are under 160 characters (or 320 for two concatenated segments).
  • Your sender name on the email matches the name in your email signature template.

Step 5 — The success branch

The success branch is what prevents a customer who updates their card from continuing to receive dunning emails. Verify it does the following:

  1. Suppresses remaining touches: when the invoice.payment_succeeded or subscription.payment.succeeded event fires, all scheduled dunning workflow steps for that contact are cancelled.
  2. Removes the in-app banner: if you’ve implemented the in-app banner through a GHL custom field flag, the success branch must set that field back to false.
  3. Sends the recovery confirmation: a short, warm “all sorted” email confirming payment is resolved. Subject: “All sorted — your [Product] access continues.” Body: 3 sentences max. No CTAs.
  4. Logs the recovery: the payment_recovery_date field gets populated, and the dunning_touch_count at recovery is logged. This data powers your recovery rate reporting.

Step 6 — Test simulation

Before going live, run a complete test simulation:

  1. Create a test contact in GHL with a valid email address you control.
  2. In your billing provider’s test mode, trigger a payment_failed event for that contact’s subscription ID.
  3. Verify Touch 1 fires (immediate email + in-app banner flag set).
  4. Fast-forward the workflow delays in GHL’s test mode to verify Touch 2 and Touch 3 fire in sequence.
  5. Trigger a payment_succeeded event. Verify Touch 4 is cancelled and the recovery confirmation email fires.
  6. Check that payment_recovery_date is populated on the contact.

If anything doesn’t fire correctly, check the workflow’s contact enrollment conditions — a common issue is the enrollment condition filtering on a contact tag that your test contact doesn’t have.

Measuring recovery rate

The SaaS Snapshot includes a dunning recovery dashboard in GHL. After your first 30 days live, you should be able to see:

  • Failed payment volume: number of contacts that entered the dunning workflow.
  • Recovery rate by touch: which touch (1, 2, 3, or 4) drove the card update.
  • Unrecovered (churned): contacts who didn’t update and whose access was suspended.
  • Monthly recovery revenue: estimated MRR recovered from the dunning sequence.

A well-configured dunning sequence should recover 30-50% of failed payments. If your rate is below 25% in the first 30 days, check: (a) is your billing portal URL a direct deep link or a generic homepage? (b) are your SMS messages actually delivering (check GHL’s SMS delivery logs)? (c) is Touch 2 firing correctly — the Day 3 SMS is often the highest-recovering single touch and missing it leaves significant recovery on the table.

Want this done for you?

The Snapshot Ships With Everything In This Guide

Skip the build — installed in your GHL account in 24 hours for $1,200 one-time.

Book Demo Get Snapshot