stripebilling portalcancellation reasonscancellation flow

Stripe Billing Portal Can Finally Ask Custom Cancellation Reasons — It Still Can't Route the Offer

Stripe shipped a Billing.FeedbackOption API on August 26 letting merchants customize cancellation reasons in the hosted portal. Here's the catch.

XY
29 August 2026 · 7 min read

For as long as Stripe's Billing Portal has supported cancellation reasons, it's supported exactly eight of them, and they were Stripe's eight, not yours. On August 26, 2026, that changed. A new Billing.FeedbackOption resource landed in the API, and it's the first time the hosted portal has let you define the reasons customers see when they cancel, instead of picking from a list Stripe wrote.

Key stat
23%
Average cancellation deflection rate from reason-matched retention offers, versus 17% for a single generic discount
Source: Chargebee Retention, subscription cancellation data (2024–2026)

That gap is the whole reason this release matters, and it's also the reason it's easy to overrate. Better reason data is genuinely useful — it feeds your product roadmap and your churn reporting either way. But the deflection lift in that stat doesn't come from asking a better question. It comes from what happens after the answer, and that part of the hosted portal hasn't moved.

What actually shipped on August 26

The change arrived quietly, buried in a routine SDK release rather than a headline announcement. Stripe's stripe-node 22.6.0 changelog, pinned to API version 2026-08-26.dahlia, added support for creating, listing, retrieving, updating, and deactivating Billing.FeedbackOption objects, plus a new feedback_options field on BillingPortal.Configuration.features.subscription_cancel.cancellation_reason.

Mechanically, it works the way most Stripe object lifecycles do. You create a feedback option the same way you'd create a coupon or a price — it gets an ID, it stays referenceable in old subscription records even after you stop using it, and you deactivate it rather than delete it, so historical cancel data doesn't silently lose its labels the day you retire a reason. Attach the IDs of the ones you want to feedback_options on your portal configuration, and customers see your wording instead of — or alongside — Stripe's original eight: too expensive, missing features, switched to another tool, not using it enough, customer service, too complicated, low quality, and other.

SetupWho defines the reasonsRetention offerBuild effort
Hosted portal, built-in options onlyStripe (fixed 8-value enum)One static coupon for everyoneNone — dashboard toggle
Hosted portal + feedback_optionsYou, via the APIStill one static coupon for everyoneA few hours — API calls, no UI work
Custom intercept (own code or CancelFlow)You, fully custom copy and logicDifferent offer per reason selectedDays to build from scratch; minutes with a drop-in tool

Read that middle row carefully, because it's where most of the confusion about this release is going to come from. feedback_options upgrades the question. It does nothing to the answer.

Worth flagging for anyone who already pulls cancellation reasons into a warehouse or a Sigma query: switching to custom options doesn't retroactively relabel anything. Subscriptions cancelled before you make the switch keep their original cancellation_details.feedback value from the old enum. Anything cancelled after keeps a reference to the specific feedback option ID that was active at the time, even if you later deactivate it. That's the same pattern Stripe uses for prices and coupons — deactivating doesn't erase the historical reference, it just stops the option from being offered going forward — so a churn report spanning the transition will have a clean split point rather than silently blended categories.

Why the fixed eight were never enough

Stripe's original cancellation-reason enum was written to cover subscription businesses in general, which meant it covered almost none of them precisely. A marketplace, a dev-tools API, a fitness app, and a project-management tool all got the same eight buttons. "Missing features" tells a product team nothing about which feature. "Switched to another tool" tells sales nothing about which competitor. We've made this same point about free-text cancel surveys in our guide to writing a cancel reason survey that actually produces usable data — generic categories are easy to ship and expensive to act on, because someone still has to go read the free-text overflow to find out what actually happened.

Teams that wanted sharper categories had exactly one workaround before August 26: stop using Stripe's hosted reason step entirely and build their own, usually as part of a full cancellation intercept like the one we cover in building a Stripe cancellation flow. That's still the right call if you want reason-based offer routing. But if all you wanted was better labels on the same eight-question dropdown, building an entire custom flow to get there was a lot of engineering for a UX-copy problem. feedback_options closes that specific gap — the one between "the categories are wrong" and "I need to rebuild the whole cancel screen."

The part that doesn't change: one offer, for everyone

Stripe's Billing Portal retention feature has always worked the same way, and this release doesn't touch it. In your portal settings, under Cancellations, you pick one coupon from a dropdown. That's the entire configuration surface. Every customer who reaches the cancel screen and clicks through — whether they picked "too expensive" or a custom reason you wrote yourself — sees that same coupon, or none at all if you haven't set one.

Retention offer deflection rate by targeting
Single generic discount, shown to everyone17%
Offer matched to the stated cancel reason23%

Source: Chargebee Retention, subscription cancellation data (2024–2026)

The mismatch that gap represents is exactly what we've written about in pause vs. discount vs. downgrade: a subscriber who says they're not using the product enough doesn't want 20% off, they want a pause. A subscriber who's hitting a feature ceiling doesn't want a discount either — they want to know if the feature is coming. Feed both of those people the same coupon and the ones who take it are the price-sensitive minority you'd have converted anyway. The rest see an offer that has nothing to do with why they're leaving, which reads less like an attempt to help and more like a coupon someone forgot to personalize — the kind of gap we cover in more detail in why customers actually cancel and what to do about each reason.

None of that is a knock on what Stripe shipped. Better cancel-reason data has real value independent of what you do with it in the moment — it's cleaner input for your churn health score, cleaner input for your product roadmap, cleaner input for whoever reviews cancellation trends monthly. Stripe just hasn't extended the hosted portal to close the loop from "here's why I'm leaving" to "here's the specific thing that might change your mind," and there's no changelog signal suggesting that's coming next.

Deciding whether this release is enough on its own

The honest answer depends on what you were actually missing. If your only complaint about Stripe's hosted portal was that the eight built-in reasons didn't map cleanly to your product, migrating to feedback_options is worth doing this week — it's an API change, not a rebuild, and it makes every future cancel-reason report meaningfully more useful with almost no engineering cost.

If what you actually wanted was for the cancellation screen to behave differently depending on the answer — show a pause instead of a discount, surface a roadmap note instead of a generic "sorry to see you go" — custom reasons alone won't get you there. That still requires intercepting the cancel action before it reaches Stripe, reading the selected reason client-side, and deciding what to show before the subscription update ever fires. That's precisely the layer CancelFlow sits in: it captures the same kind of reason data this new API formalizes, but it also routes a specific save offer to each answer automatically, which is the piece that actually moves the deflection numbers above. If you're trying to estimate what closing that 6-point gap between a generic offer and a matched one is worth on your own subscriber base, our churn calculator will turn it into an MRR number in under a minute.

Frequently asked questions

What is Stripe's Billing.FeedbackOption API?+

It's a new resource Stripe shipped on August 26, 2026 (API version 2026-08-26.dahlia, stripe-node 22.6.0) that lets you create, list, retrieve, update, and deactivate your own custom cancellation-reason options. You attach the IDs of the ones you create to the feedback_options field on a Billing Portal configuration's subscription_cancel.cancellation_reason feature, alongside the fixed built-in options field that's been there for years.

Do the old fixed cancellation reasons in Stripe still work?+

Yes. The options field — the enum with too_expensive, missing_features, switched_service, unused, customer_service, too_complex, low_quality, and other — hasn't been removed or deprecated. feedback_options is additive: you can keep the built-in list, replace it with your own, or run both at once if you want a mix of Stripe's defaults and reasons specific to your product.

Does Stripe route a different retention offer based on which cancellation reason a customer picks?+

No, and that hasn't changed with this release. The Billing Portal's retention feature supports exactly one coupon, configured once in your portal settings, shown to every customer who tries to cancel regardless of which reason — built-in or custom — they select. Reason-based offer routing (a pause for low engagement, a discount for price sensitivity, a feature callout for a missing capability) still requires intercepting the cancellation before Stripe's hosted flow, either with your own code or a tool like CancelFlow.

Should I switch to feedback_options or build a custom cancellation flow?+

If you're using Stripe's hosted Billing Portal purely for reporting — you want cleaner cancel-reason data than the generic eight-option enum gives you — feedback_options is a same-day API change worth making. If your actual goal is showing a different save offer depending on why someone's leaving, feedback_options alone won't get you there; you still need a flow that intercepts the cancel action and reads the reason before Stripe processes it.

Try CancelFlow

Stop losing subscribers today

One script tag. One function call. A live cancellation flow in under 10 minutes.

Start free trial →
← All postsHome