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.

Banner

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

EnvironmentWebhook EndpointSecret Key TypeWebhook Setup
Developmenthttp://localhost:5000/request/webhooksk_test_...Stripe CLI (forward-to)
Productionhttps://yourdomain.com/request/webhooksk_live_...Stripe Dashboard > Webhooks
How to Handle Stripe Webhooks in Development and Production | Software Engineer Blog