How to Handle Stripe Webhooks in Development and Production
Learn how to configure Stripe webhooks in local development using the Stripe CLI and transition seamlessly to a production environment. Secure your webhook endpoints and manage environment-specific settings the right way.
How to Properly Handle Stripe Webhooks in Development and Production
Setting up Stripe webhooks correctly is essential to ensure your application reacts to events like successful payments. Here’s a complete guide to setting it up locally for development using Stripe CLI, and how to transition smoothly to a production environment.
Here is some code to get started:
Log into Stripe CLI
./stripe login
Listen for events and forward to your dev server
./stripe listen --forward-to localhost:5000/request/webhook
This command sets up a Stripe CLI listener that captures webhook events from Stripe and forwards them to your local backend server. This is vital because, in test mode, Stripe can’t reach localhost directly.
But in production, this setup changes:
To make webhooks work in production, follow these steps:
✅ Step 1: Deploy your backend publicly
Your Flask/FastAPI backend must be accessible via a public URL, for example:
https://yourdomain.com/request/webhook
✅ Step 2: Set webhook in Stripe Dashboard
Go to <a href="https://dashboard.stripe.com/webhooks" target="_blank">Stripe Dashboard > Developers > Webhooks</a>
Click “**+ Add endpoint**”
Enter your production URL:
https://yourdomain.com/request/webhook
Select the relevant event types like:
checkout.session.completed
payment_intent.succeeded
✅ Step 3: Use correct API keys
In development, use sk_test_...
In production, switch to sk_live_... via environment variables
✅ Step 4: Secure your webhook endpoint (recommended)
Use signature verification to ensure the webhook request is from Stripe.
import stripe
import os
from flask import request
endpoint_secret = os.environ["STRIPE_SIGNING_SECRET"]
payload = request.data
sig_header = request.headers.get("Stripe-Signature")
try:
event = stripe.Webhook.construct_event(
payload, sig_header, endpoint_secret
)
except stripe.error.SignatureVerificationError:
return "Invalid signature", 400
✅ Summary Table
| Environment | Webhook Endpoint | Secret Key Type | Webhook Setup |
|---|---|---|---|
| Development | http://localhost:5000/request/webhook | sk_test_... | Stripe CLI (forward-to) |
| Production | https://yourdomain.com/request/webhook | sk_live_... | Stripe Dashboard > Webhooks |