Stayput / Guides

Guide · facts checked 5 Nov 2026

Cancel a Stripe subscription now or at period end: what changes

For a cancel flow, set cancel_at_period_end to true: the customer keeps the access they paid for and you can undo the cancellation, with one update, until the period ends. Cancelling immediately (DELETE) is final: Stripe says a canceled subscription cannot be reactivated, so a customer who changes their mind needs a new subscription.

The three ways to cancel, side by side

CallWhen it takes effectProration and refundCan you undo it?
DELETE /v1/subscriptions/{id}Immediately. Status becomes canceled.prorate and invoice_now both default to false: no credit for unused time and no final invoice unless you ask.No. A new subscription is needed.
cancel_at_period_end=trueAt the end of the current billing period.Nothing to refund: the customer finishes the period they paid for. Pending prorations stay and are collected at period end.Yes, set it back to false any time before the period ends.
cancel_at=<timestamp>At the date you set.A date inside the current period creates prorations unless you disable them. A date more than one period away always prorates. A custom cancel date cannot come with a refund.Moving the date is documented. Stripe’s guide describes stopping a pending cancel with cancel_at_period_end=false; test clearing a cancel_at in test mode before you rely on it.

Every cell comes from Stripe’s cancel guide and its cancel and update API references, read on the date at the top of this page. Stripe also lets you end a subscription after a set number of billing periods by creating a subscription schedule with end_behavior set to cancel.

Why a cancel flow should schedule the cancel, not delete

Stripe’s wording is plain: “You can’t reactivate a canceled subscription.” A subscription scheduled to cancel is different: “You can reactivate subscriptions scheduled for cancellation by updating cancel_at_period_end to false. You can reactivate the subscription at any time up to the end of the period.”

That is the whole case for scheduling. A customer who clicks cancel, sees an offer later, gets a win-back email or simply changes their mind still has a live subscription to keep. After a DELETE the only route back is a new subscription with a new ID. It is also fairer to the customer: they leave when they paid up to, not when they clicked.

Treat the scheduled state as the moment the customer has decided, not the moment they have gone. The offer step belongs before it. If they decline every offer, or never see one, the cancel still goes through with one click; a flow that hides that path loses the customer’s trust. The full flow, with the webhook that sees the scheduled cancel, is in how to build a cancel flow with Stripe.

Immediate cancel: proration, invoices and refunds

If you do need to end a subscription now (a fraud case, a request to delete an account, a refund policy you have promised), these are the switches:

  • prorate=true creates a proration invoice item that credits the remaining unused time until the period end. Default: false.
  • invoice_now=true creates a final invoice for any un-invoiced metered usage and any new or pending proration items. Default: false.
  • With both left at false on an immediate cancel, Stripe removes pending prorations, and per its guide, metered usage is discarded and the customer gets no credit.
  • The credit is not a refund. Stripe’s guide says that if you owe the customer a credit you can add it to their credit balance for future invoices, and that to refund them you issue the refund and then adjust the account balance back to zero.

In the Dashboard the same choice appears as a refund option: a prorated amount, the last payment in full, or no refund. Decide the policy first and then pick the call; the API will not choose one for you.

Scheduling a date with cancel_at

cancel_at is useful when the customer asks to leave on a specific day, for example the end of a quarter. Two things surprise people:

  • A date before the current period ends changes the period: the subscription items’ current_period_end moves to the cancel_at date and Stripe creates prorations for the change, unless you set proration_behavior to none. Passing always_invoice invoices those prorated items immediately.
  • A date more than one period away leaves the cycle alone until the subscription renews into the period that holds the date, and you cannot disable prorations for it.

Stripe also notes that adding a cancel date, or moving one earlier, sets the billing cycle anchor to the new date. If your reporting reads the anchor, check it after you schedule one.

The webhooks that tell you which one happened

EventWhat Stripe says it means
customer.subscription.updatedSent for any subscription update, including when cancel_at_period_end is set to true.
customer.subscription.deletedSent when a subscription is canceled: a direct call to delete it, or a subscription with cancel_at_period_end: true reaching the end of its period.

So a scheduled cancel produces two events weeks apart: an updated when the customer decides and a deleted when access ends. Count the first as the decision and the second as the outcome. If a customer is later won back, the updated event that sets cancel_at_period_end back to false is the candidate save. Whether it counts as one is a measurement question, answered in what counts as a save.

Record the reason on the subscription, even after it is canceled

Stripe says that once a subscription is canceled you can no longer update it, except for its metadata and cancellation_details. So a reason captured after the cancel, from a survey email for example, can still be attached to the subscription. The fields are comment, feedback (eight fixed values) and feedback_option for your own labels. The values and how to read them back are in the cancellation reason API guide.

Before you ship

  • Default to cancel_at_period_end=true for a customer-initiated cancel, and reserve DELETE for cases you can name.
  • If you use DELETE, set prorate and invoice_now on purpose, and write down the refund policy they implement.
  • Handle both events: the updated that schedules the cancel and the deleted that ends it.
  • Try each call in Stripe test mode, with a sk_test_ key, before it touches a live subscription. Test mode is also where you confirm how clearing a cancel_at behaves on your account.

See the scheduled cancel in a sample session

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