Understanding Stripe Webhooks for SaaS Billing
Understanding Stripe Webhooks for SaaS Billing
Stripe webhooks are the backbone of any SaaS billing system. Here's how to handle them correctly.
Essential Webhooks
These are the events you must handle:
customer.subscription.createdcustomer.subscription.updatedcustomer.subscription.deletedinvoice.payment_succeededinvoice.payment_failed
Implementation Pattern
class Payment::WebhooksController < ApplicationController
skip_before_action :verify_authenticity_token
def create
event = Stripe::Webhook.construct_event(
request.body.read,
request.env["HTTP_STRIPE_SIGNATURE"],
Rails.application.credentials.dig(:stripe, :webhook_secret)
)
handle_event(event)
head :ok
end
end
Common Pitfalls
- Not verifying signatures — always verify webhook authenticity
- Not handling idempotency — Stripe may send the same event multiple times
- Ignoring failed payments — set up dunning emails
Testing Locally
Use the Stripe CLI to forward events to your local server:
stripe listen --forward-to localhost:3000/payment/webhooks