Stripe webhook event
customer.subscription.deleted
What the cancellation event means, when it fires, what to email after, how to capture the reason, and how to queue win-back.
What this event means
A subscription ended. The customer no longer has an active recurring charge. Whether they cancelled directly, ran out of trial, or were churned out by failed payments, the event is your single signal that the relationship is over for now.
When it fires
- Customer cancelled immediately.
- Customer cancelled at period end, and the period has now expired.
- Stripe ended the subscription after all failed-payment retries.
- You ended the subscription manually via the API.
Cancel now vs cancel at period end
cancel_at_period_end = false ends access right away and fires the event immediately. cancel_at_period_end = true keeps the subscription active until the current billing period ends; the event fires only at that point. Most SaaS uses period-end cancellation so customers get what they paid for.
Watch for the cancellation_details.reason field. The common values are cancellation_requested (voluntary), payment_disputed, and payment_failed (involuntary). Treat involuntary cancellations as failed-payment recovery, not lost causes.
Example event payload
{
"id": "evt_1Q...",
"type": "customer.subscription.deleted",
"data": {
"object": {
"id": "sub_PaA...",
"customer": "cus_PaA...",
"status": "canceled",
"canceled_at": 1758500000,
"cancel_at_period_end": false,
"cancellation_details": {
"reason": "cancellation_requested",
"feedback": "too_expensive",
"comment": null
},
"items": { "data": [ { "price": { "id": "price_..." } } ] }
}
}
}What email to send
Subject: What could we have done?
Hi {{first_name}},
You just cancelled {{product}}. No pressure — but if you have 30 seconds, I'd love to know what we got wrong or what was missing.
Anything you share goes straight to me. No surveys, no sales follow-up.
Thanks for trying it,
{{founder}}Send this within an hour of the event. Plain text. From a real person. Not from a marketing address.
How to capture the reason
- Listen for the customer's reply on an inbound email webhook.
- Classify the reason. Pricing, missing feature, too complex, switched tool, not using it, business changed.
- Store the reason against the customer record for later win-back.
- When you ship something that addresses the reason, email the matching cohort.
How to queue win-back
Win-backs only convert when something has genuinely changed. Tie captured reasons to product changes:
- Missing feature → email when the feature ships.
- Pricing → email when you launch a smaller plan.
- Too complex → email when you simplify onboarding.
- Switched tool → email when you close the specific gap.
- Failed payment → email the moment the card update path opens.
When to use this page
Use this as the reference for wiring your cancellation workflow, or when debugging why a subscription appears canceled in Stripe without anyone on your team having seen it. For the wider event map, see the Stripe Webhook Event Decoder.
What to do next
Building this whole pipeline — cancellation webhook, founder email, inbound reply capture, reason classification, win-back queue — is a real engineering project. ChurnNote already does it for you.
Frequently Asked Questions
What does customer.subscription.deleted mean?
It is the Stripe webhook event that fires when a subscription ends. The subscription object's status becomes canceled. The event is your last chance to email the customer and learn why they left.
When does it fire?
Three main scenarios. (1) The customer cancelled immediately. (2) The customer cancelled at period end and the period has now ended. (3) All payment retries failed and Stripe ended the subscription on its own. The cancellation_details.reason field tells you which.
How is cancel-now different from cancel-at-period-end?
Cancel-now ends access immediately and fires the event right away. Cancel-at-period-end leaves the subscription active until the end of the current billing period; the event fires only when that period ends. Most SaaS uses cancel-at-period-end so customers get what they paid for.
What should I send after this event?
A plain-text email from a real person, asking the customer what could have been done differently. Not a survey link. Not a discount. Just a one-question email. Typical reply rates are 25-40%.
How does this connect to win-back?
Capture the reason in the reply. Tag the customer with that reason. When you ship something that addresses it — a new plan, a missing feature, a simpler workflow — email the matching cohort with a reason-specific win-back.
How ChurnNote helps
ChurnNote turns cancellation events into founder-style emails, churn reasons, and win-back opportunities.
ChurnNote connects to Stripe or Lemon Squeezy and automatically captures cancellation reasons, recovers failed payments, and queues win-back emails. So you stop losing revenue silently.
Start recovering churnNext step
Already have a stack of cancellation replies?
The Cancellation Reply Analyzer groups them by reason and flags win-back candidates.
Related tools