How to reduce subscription churn on Polar
How Polar handles cancellation at period end vs revoke, failed payment retries, the customer portal, discounts, cancellation reasons and webhooks.
Polar gives you more churn tooling than you might expect from a young billing platform: cancellation at period end that the customer can undo, recorded cancellation reasons, a pause option, and automatic retries on failed renewals. This guide explains how each piece works and how to add a retention step and win-back on top.
It sticks to Polar’s own documentation: managing subscriptions, recovering failed payments, customer portal, discounts, update subscription, webhook events, analytics, fees and the changelog (all accessed November 2026). Polar’s docs move quickly, so check the version of the API you use.
Polar is the merchant of record
Polar sells to your customers as merchant of record, handling tax, payments and disputes. Its fees page says each dispute costs $15, won or lost, deducted from your balance. Its account reviews page explains that Polar watches chargeback rates and, for orders below a certain value, may refund automatically when it gets an early signal from the card networks. You do not answer disputes yourself, but the way you handle cancellations has a direct effect on how many you get.
Two ways a subscription ends
Polar’s managing subscriptions page describes two paths.
| Cancel at period end | Revoke | |
|---|---|---|
| How | PATCH /v1/subscriptions/{id} with cancel_at_period_end: true, or the dashboard toggle |
DELETE /v1/subscriptions/{id} |
| Access | Kept until current_period_end |
Ends immediately, benefits revoked |
| Refund | Not applicable | None issued |
| Reversible | Yes, until the end date (uncancel) | No |
For a customer who asks to cancel, cancel at period end is the right default: they keep what they paid for, and they can change their mind. Polar says so itself: use cancel at period end if you want the option to reverse the decision. Uncancelling sets cancel_at_period_end back to false and clears ends_at and canceled_at.
Record the reason
When you cancel at period end through the API, Polar accepts an optional reason and comment. The eight reason codes are too_expensive, missing_features, switched_service, unused, customer_service, low_quality, too_complex and other. Polar asks you to set them only when the customer actually gave them, for example in a survey, and warns that the comment is visible to the customer in their purchase history, so internal notes do not belong there.
Polar’s analytics show cancellation reasons in charts you can click through to the subscriptions and comments behind them. It also separates “canceled” (the customer asked to cancel during the period) from “churned” (paid access actually ended), which is a useful distinction when you measure a cancel flow.
Pause
Per Polar’s changelog, a pause is scheduled for the end of the billing period. At that point billing stops and benefits are revoked, but the subscription and payment method stay on file. You can let customers pause from the customer portal, and the subscription.paused and subscription.resumed webhooks tell you when the state changes.
The customer portal
Polar’s hosted customer portal lets customers cancel (at period end by default) and update their default payment method. Plan changes, seat changes and pause or resume depend on toggles in your portal settings. Updating the payment method is only available in the hosted portal, which keeps card details off your servers; the Customer Portal API you can use for your own portal does not cover it.
If customers cancel from the hosted portal, they go straight to the cancellation. If you want a retention step first, send the “Cancel” button in your app to your own flow, and keep the hosted portal for payment details.
Discounts
Polar discounts apply once, for a fixed number of months, or forever. To give a discount to an existing subscriber, set discount_id with the update subscription endpoint; Polar applies the change on the next billing cycle, and null removes it. Polar’s docs do not say whether swapping a repeating discount resets its remaining months, so test that in the sandbox before you rely on it.
What Polar does on failed payments
Polar documents its behavior on recovering failed payments:
- When a renewal charge fails, the subscription becomes
past_dueandsubscription.past_duefires. - Polar retries four times: 2, 5, 7 and 7 days after the previous attempt, which is 2, 7, 14 and 21 days after the first failure.
- If the customer updates their payment method in the portal, Polar retries the charge immediately.
- If all retries fail, or the decline means the payment method will never work, Polar stops retrying, the subscription ends and benefits are revoked, and
subscription.revokedfires. - An organization-level grace period can delay benefit revocation. It does not change the retry schedule.
Usage-based meter orders follow a different schedule and do not affect the subscription itself; see Polar’s billing page. The retry timing is fixed by Polar; what you can add is clear communication with the customer while the subscription is past due, pointing them to the portal to update their card.
Webhooks to listen to
From Polar’s webhook events:
| Event | Meaning |
|---|---|
subscription.updated |
Fires for every change, including the ones below |
subscription.canceled |
Cancellation requested; the subscription may still be active until period end |
subscription.uncanceled |
The customer undid a pending cancellation |
subscription.revoked |
Access ends: period end reached after cancellation, or retries exhausted |
subscription.past_due |
A renewal payment failed and can still be recovered |
subscription.paused / subscription.resumed |
Pause state changed |
subscription.cycled |
A renewal |
For a cancellation at period end, Polar sends subscription.updated and subscription.canceled immediately (status still active, cancel_at_period_end true), then subscription.updated and subscription.revoked when the period ends. Polar’s guidance is not to remove access on subscription.canceled, but to wait for the end of the period or subscription.revoked.
A cancel flow on Polar, step by step
- Route “Cancel” in your app to your flow, not to an immediate API call.
- Ask why, using Polar’s eight reason codes so the answers line up with Polar’s analytics, plus a free-text field.
- Show one offer that fits the reason.
too_expensive: a discount for a few months.unused: a pause.missing_featuresortoo_complex: a reply from a person. - Keep “Cancel now” visible on every step, finishing in one click.
- Apply the result. Discount:
PATCHwithdiscount_id. Cancel:PATCHwithcancel_at_period_end: true, the reason and, if the customer wrote one, the comment. Avoid revoking unless the customer asked for an immediate end, since it cannot be undone and issues no refund. - Confirm the end date from
current_period_end, and offer a “keep my subscription” button until then.
Win-back
Start from subscription.revoked. Keep the reason the customer gave, wait, then contact them with something that answers that reason, and send them to a new checkout, with a discount if that fits.
Doing this with NoChurn
NoChurn reads your Polar subscriptions and webhooks and adds a cancel flow with reasons, offers and a one-click cancel that is always visible, hosted or headless through the API, plus win-back emails at day 30, 60 and 90 based on the cancel reason and a churn score from 0 to 100. Polar stays the merchant of record: checkout, payments, payment recovery, refunds and disputes stay with Polar, and disputes appear in NoChurn read only. NoChurn is free under $300 MRR, with every feature on every plan. See NoChurn + Polar.