DOCS · CANCELLATION RECOVERY
LIVE

Cancellation Recovery

Intercept cancel clicks, capture reasons, and fire save offers automatically. Works on Starter, Growth, and Pro.

Before installing: you'll need a chsk_live_ API key. Generate one in Integrations › Cancellation Recovery. You'll also need to point your cancel button at our mint-token endpoint before redirecting. Need help? Talk to the founder.

How it works

  1. STEP 1

    Your customer clicks cancel

    Your cancel button calls our mint-token endpoint server-side to get a short-lived signed token, then redirects the customer to cancel.chaser.cash/<workspaceId>?token=<token>.

  2. STEP 2

    The cancel page intercepts

    The customer sees a branded cancel page with your logo. They select a reason, optionally leave a comment, and see a save offer if one of your rules matches their reason and MRR.

  3. STEP 3

    Chaser writes back to Stripe

    If the customer accepts an offer, Chaser applies the coupon or pause to their Stripe subscription. If they confirm cancellation, Chaser sets cancel_at_period_end: true. Everything is logged to your Cancellation Insights dashboard.

Step 1: Enable and configure

Enable in Integrations

Go to Integrations › Cancellation Recovery and enable the toggle. Select "Via a cancel button in my app" as your setup path.

Add save rules (optional)

Under Save Rules, add rules to intercept cancellations with a matching offer. Rules are evaluated in priority order, first match wins. You can match on cancellation reason, minimum MRR, or both.

Brand your cancel page

Open the Branding accordion in the Cancellation Recovery tab to configure:

Theme:        Dark or Light
Logo:         PNG, JPG, WEBP, or SVG up to 2MB
Accent color: #RRGGBB hex, buttons and selections
Background:   #RRGGBB hex, page background
Card color:   #RRGGBB hex, form card background

Use Generate with AI to write a branded headline and subheadline in your tone. Four tones available: Founder-Style, Standard Corporate, Direct & Urgent, Concierge.

Full branding guide

Add custom cancellation reasons

Open the Cancellation reasons accordion to add reasons specific to your product. Custom reasons appear after the seven default reasons. Click Suggest with AI to get product-specific suggestions. Max 20 custom reasons.

Set up a custom domain (optional)

Host your cancel page on your own subdomain instead of chaser.cash. Requires a DNS CNAME record.

Custom domain setup guide

Step 2: Mint a token

Server-side token minting

When your customer clicks cancel, call this endpoint from your backend:

POST https://chaser.cash/api/public/cancel/mint-token
Authorization: Bearer chsk_live_YOUR_KEY
Content-Type: application/json

{ "customerId": "cus_stripe_customer_id" }

Response:
{
  "token": "eyJ...",
  "publicWorkspaceId": "ws_xxx",
  "expiresAt": "2026-06-21T21:00:00Z",
  "ttlSeconds": 1800
}

Redirect the customer

Redirect your customer to:

https://cancel.chaser.cash/<publicWorkspaceId>?token=<token>

The token expires in 30 minutes and is single-workspace scoped. Never expose your API key client-side.

Step 3: Preview your cancel page

Use the live preview

The Cancellation Recovery tab has a live preview panel on the right. It updates instantly as you change branding, reasons, and copy. Toggle between Mobile and Desktop views using the device switcher at the top of the preview panel.

Open test page with a real token

If you have a verified custom domain, click Open test page next to the Verified badge. This mints a real HMAC token and opens your cancel page in a new tab with your actual rules active.

Preview URL (no custom domain)

Without a custom domain, use the preview URL to see the cancel page without a real customer token:

https://chaser.cash/cancel/{workspaceId}?token=preview

The preview token loads your real branding, logo, and custom reasons but does not process a real cancellation.

Cancellation Insights

What gets logged

Every cancellation attempt is logged to Cancellation Insights regardless of which flow fired: branded cancel page or Stripe Billing Portal. Each event records:

source:         branded_page | stripe_portal
reason_code:    normalized reason (too_expensive,
                missing_features, switched_competitor,
                technical_issues, unused,
                temporary_pause, other, unknown)
reason_raw:     original reason string
save_attempted: whether an offer was shown
outcome:        no_offer | offered | accepted |
                declined | canceled
mrr_cents:      subscription value at cancellation

Save rate

Save rate is calculated as accepted divided by accepted plus canceled across all cancellation attempts. MRR kept tracks the subscription value of saved customers. MRR lost tracks the value of customers who canceled despite an offer or with no offer shown.

Stripe Billing Portal

When using the Stripe Billing Portal path, Chaser captures cancellation reasons via webhook automatically. No cancel page is shown. Reasons are mapped from Stripe's feedback enum to the normalized reason_code taxonomy.

Troubleshooting

Token expired or invalid

Tokens expire after 30 minutes. If a customer lands on an expired token they see a "This link has expired" message. Mint a fresh token and redirect again.

Customer has no active subscription

If the Stripe customer ID has no active subscription, the cancel page returns a 404. Check that you are passing the correct stripe_customer_id, not an internal user ID.

Save offer not showing

Check that your save rule is enabled and that the customer's reason and MRR match the rule conditions. Use the Cancellation Insights dashboard to see what outcome was logged for the attempt.