Stayput / Guides

Guide · facts checked 5 Nov 2026

Win back a canceled Stripe subscriber without making them start over

Stripe says you can't reactivate a canceled subscription, so a win-back is a new subscription on the same customer. Create it with the customer ID and a price, and Stripe will charge the customer's default payment method. If the first charge fails, the subscription is created as incomplete and the customer has to act.

Two cases, two different fixes

Where the subscription isWhat brings the customer back
Scheduled to cancel (cancel_at_period_end is true, period not over)Update the same subscription and set cancel_at_period_end to false. Nothing is created, nothing is re-billed. Stripe: “You can reactivate the subscription at any time up to the end of the period.”
Canceled (status canceled)Create a new subscription for the same customer. Stripe: “You can’t reactivate a canceled subscription.”

The first case is the cheaper win-back, which is the reason a cancel flow should schedule the cancel rather than delete: see cancel now or at period end. The rest of this page is the second case.

Create the new subscription on the existing customer

The customer object survives the cancellation, so you do not collect their details again. The create call needs a customer and at least one item with a price:

curl https://api.stripe.com/v1/subscriptions \
  -u "sk_test_...:" \
  -d customer=cus_XXXX \
  -d "items[0][price]=price_XXXX"

That is Stripe’s own example shape from the Create a subscription reference. Which card gets charged is decided in this order, per the reference: the subscription’s default_payment_method if you pass one (it must belong to the customer, and it takes precedence over default_source); otherwise the customer’s invoice_settings.default_payment_method or default_source. So a returning customer with a default payment method on file can be resubscribed with no card form at all.

Run it in test mode first: create a test customer with a card on file and watch the resubscribe go through before it touches a real one.

What happens if the first charge fails

A card that worked a year ago may have expired. Stripe documents what you get back, controlled by payment_behavior:

  • allow_incomplete (the default since API version 2019-03-14): if payment fails, the subscription is created with status incomplete; otherwise active. Stripe notes this also covers cases where the customer must act, for example 3D Secure authentication.
  • default_incomplete: when the first invoice needs payment, the subscription is created as incomplete without attempting payment, and you confirm the invoice’s PaymentIntent explicitly. Use it when the customer is present and you want to collect or confirm the card in your own screen.
  • error_if_incomplete: a failed payment returns HTTP 402 and no subscription is created. Stripe says it cannot handle payments that need customer action such as 3DS, and recommends the two options above for those.

For a win-back page the customer is looking at, default_incomplete followed by confirming the PaymentIntent in the browser keeps one screen in charge of the whole outcome. For a win-back you trigger without the customer present, expect some to land as incomplete and give them a way to fix the card.

Sweeteners the create call supports

The create reference lists trial_period_days, trial_end and discounts among its parameters, so you can make the return easier with a free stretch or a reduced price. How a coupon is built and applied, and the trap of overwriting an existing discount, is covered in offering a retention discount through the Stripe API. Pick the sweetener from the reason the customer gave when they left, not from habit: reading cancel reasons maps reasons to offers.

One thing to decide before you automate it: a returning customer who is offered a discount every time has a reason to cancel every time. Keep a record of what each win-back cost, as a field you write yourself, so you can see it.

Tell the old and new subscription apart in your numbers

The new subscription has a new ID, so a resubscribe appears in your data as a fresh subscription on an old customer. If you count churn per subscription it will look like one cancellation and one new sign-up, not a save. Store the customer ID against your own win-back record when you create it, so you can say which new subscriptions are returns. How to count a save honestly is on what counts as a save.

Before you ship

  • Resubscribe only customers who left, not customers whose cancel is still scheduled: for those, update cancel_at_period_end to false.
  • Decide how you handle incomplete: a visible way for the customer to update their card.
  • Make the offer match the cancel reason you recorded.
  • Test all three outcomes in test mode: success, a declined card, an authentication-required card.

See a cancel offer before the customer is gone

Run a sample cancel session: play a subscriber, give a reason, and see the offer chosen and the Stripe change behind it.

90 seconds, no sign-up. You play the subscriber; the AI answers, and “Cancel anyway” is always one click away.

Related

Sources, read 5 Nov 2026