Stripe webhook · Cancellation feedback
The Stripe webhook tool for cancellation feedback.
Stripe sends a webhook when a subscription is cancelled. ChurnNote listens for that event, sends an exit email from your domain, captures the reply, and groups the reason into a churn taxonomy — all without writing or maintaining a webhook handler yourself.
Quick answer
Subscribe to customer.subscription.deleted in Stripe, verify the webhook signature, look up the customer email, send a plain-text exit email from your domain, capture the reply, and group the reason into a churn taxonomy. ChurnNote does this whole pipeline natively for $12/mo — no webhook handler code to write or maintain.
What the webhook handler looks like (build-it-yourself)
If you'd rather build the pipeline yourself, here's the shape of it. ChurnNote does this for you, but the code is helpful for understanding what's happening under the hood.
// /api/webhooks/stripe
import Stripe from 'stripe'
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!)
export async function POST(req: Request) {
const body = await req.text()
const sig = req.headers.get('stripe-signature')!
// 1. Verify the webhook
const event = stripe.webhooks.constructEvent(
body, sig, process.env.STRIPE_WEBHOOK_SECRET!,
)
if (event.type === 'customer.subscription.deleted') {
const sub = event.data.object as Stripe.Subscription
// 2. Look up the customer
const customer = await stripe.customers.retrieve(sub.customer as string)
// 3. Send the exit email (Resend / SES / Postmark)
await sendExitEmail({
to: (customer as Stripe.Customer).email!,
from: 'you@yourdomain.com',
subject: 'quick question',
body: writePersonalEmailBody(customer, sub),
})
// 4. Set up inbound parser to capture the reply
// (out of scope for this snippet — see Resend Inbound)
// 5. When reply lands, group the reason
// (this is the part most teams skip and regret)
}
return new Response('ok', { status: 200 })
}What this snippet doesn't show: signature rotation, retry handling, inbound email parsing, threading replies to the original email, an AI step to group the reason, deliverability tuning, suppression handling. Those are the parts that make this a multi-week project rather than an afternoon.
What ChurnNote handles for you
- 1
Subscribe to customer.subscription.deleted
In your Stripe dashboard, register a webhook endpoint and select the customer.subscription.deleted event. Stripe will POST to your endpoint every time a subscription is cancelled.
- 2
Verify the webhook signature
Stripe signs every webhook with your webhook secret. Use stripe.webhooks.constructEvent(body, sig, secret) to verify the payload before processing — never trust unsigned requests.
- 3
Look up the customer email
The webhook gives you a subscription object with a customer ID. Call stripe.customers.retrieve(id) to get the email and any metadata you stored on the customer.
- 4
Send the cancellation email
Use a transactional sender (Resend, SES, Postmark, SendGrid) to send a plain-text email from your domain. Keep it under five lines, ask one open question, and use your real reply-to address.
- 5
Capture the reply
Set up an inbound email parser (Resend Inbound, SendGrid Inbound Parse, or a forwarding rule into a webhook) so replies get ingested back into your system, not just sitting in your inbox.
- 6
Group the reason and store it
Tag each reply by reason — pricing, missing feature, too complex, switched tool, bad experience, no longer needed — and store it on the customer record alongside their LTV and tenure. The tag drives win-back targeting later.
Steps 1–6 are what ChurnNote does the moment you connect Stripe. You don't write any handler code; you just paste an API key.
FAQ
Which Stripe webhook fires when a customer cancels?▼
What's the difference between customer.subscription.deleted and customer.subscription.updated?▼
Do I need to write a webhook handler myself to collect cancellation feedback?▼
Can I use Zapier or Make instead of code?▼
How fast does the email get sent after cancellation?▼
What about customer.subscription.deleted from failed payments?▼
What other Stripe webhooks does ChurnNote subscribe to?▼
Skip the webhook handler. Get the feedback.
ChurnNote subscribes to the Stripe webhook on your account, runs the whole pipeline, and gives you a clean dashboard. $12/mo flat.
Get started