CANCEL FLOWSPOLAR

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.

Published 5 min read

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:

  1. When a renewal charge fails, the subscription becomes past_due and subscription.past_due fires.
  2. 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.
  3. If the customer updates their payment method in the portal, Polar retries the charge immediately.
  4. 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.revoked fires.
  5. 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

  1. Route “Cancel” in your app to your flow, not to an immediate API call.
  2. Ask why, using Polar’s eight reason codes so the answers line up with Polar’s analytics, plus a free-text field.
  3. Show one offer that fits the reason. too_expensive: a discount for a few months. unused: a pause. missing_features or too_complex: a reply from a person.
  4. Keep “Cancel now” visible on every step, finishing in one click.
  5. Apply the result. Discount: PATCH with discount_id. Cancel: PATCH with cancel_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.
  6. 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.

PROMPT

Read https://www.nochurn.sh/llms.txt,
then follow https://www.nochurn.sh/docs/quickstart/
to add NoChurn to this app. Use a test key
(nc_test_…) until I say we go live.

Stop leaking revenue.

  • Free until $300 MRR
  • No card needed
  • Live in 10 minutes
  • Never a cut of what we recover