What Is a Stripe Webhook?
A Stripe webhook is an HTTP callback Stripe sends to your server when a payment event occurs — subscription created, invoice paid, payment failed — enabling your app to react to billing events in real time.
Stripe's entire payment lifecycle is event-driven. When a customer pays, cancels, or when a card expires, Stripe sends a POST request to your webhook endpoint with a JSON payload describing the event.
The events you must handle:
checkout.session.completed— new subscription or one-time payment confirmedcustomer.subscription.updated— plan change, trial endedcustomer.subscription.deleted— cancellationinvoice.payment_failed— dunning — notify user, retry logicinvoice.payment_succeeded— renewal confirmed
Never trust the client redirect: After Stripe Checkout, Stripe redirects the user to your success URL. This redirect is unreliable — users close the tab, mobile browsers interrupt it, or the network drops. Your app should never change subscription state based on the success URL alone. Always use the webhook.
Verifying the webhook signature:
const sig = request.headers['stripe-signature'];
const event = stripe.webhooks.constructEvent(
rawBody, // must be raw Buffer, not parsed JSON
sig,
process.env.STRIPE_WEBHOOK_SECRET
);
If signature verification fails, return 400 immediately. Don't process unverified events.
Idempotency is required:
Stripe retries webhooks if your endpoint returns a non-2xx response. Your handler must deduplicate — use the event.id as a unique key and skip events you've already processed.