How to Handle Stripe Webhooks in a Bolt App
Set up a webhook endpoint in your Bolt-generated app to handle Stripe payment events like successful checkouts and subscription changes.
Before you start
- ✓A Bolt account with an existing app
- ✓A Stripe account with a product created
- ✓A deployment URL (Vercel, Railway, etc.)
Step by step
Create the webhook endpoint
Ask Bolt to generate a server-side API route that receives Stripe webhook events.
Paste this into Bolt:
Create an API route at /api/webhooks/stripe that: 1. Reads the raw request body 2. Verifies the Stripe webhook signature using STRIPE_WEBHOOK_SECRET 3. Handles these events: checkout.session.completed, customer.subscription.updated, customer.subscription.deleted 4. Returns 200 to acknowledge receipt 5. Logs the event type for debugging
Add Stripe to your dependencies
Install the Stripe Node.js SDK in your Bolt project.
Paste this into Bolt:
Install the stripe npm package and add it to the project dependencies.
Handle the checkout.session.completed event
When a checkout succeeds, update the user's status in your database.
Paste this into Bolt:
In the Stripe webhook handler, when checkout.session.completed fires: 1. Get the customer email from the session 2. Find the user in the database by email 3. Set their subscription_status to 'active' 4. Set subscription_id to the Stripe subscription ID 5. Log the successful activation
Set up the webhook in Stripe Dashboard
Go to Stripe → Developers → Webhooks → Add endpoint. Enter your deployed URL + /api/webhooks/stripe.
# Endpoint URL: https://your-app.vercel.app/api/webhooks/stripe # Events to listen for: - checkout.session.completed - customer.subscription.updated - customer.subscription.deleted
Test with Stripe CLI
Use the Stripe CLI to test webhooks locally before deploying.
# Install Stripe CLI, then: stripe listen --forward-to localhost:3000/api/webhooks/stripe # In another terminal, trigger a test event: stripe trigger checkout.session.completed
Common errors
Webhook signature verification failed
The webhook secret doesn't match what Stripe sent.
Fix: Use the webhook signing secret from the Stripe Dashboard (starts with whsec_), not your API key.
Request body already parsed
Your framework parsed the JSON body before Stripe could verify the raw signature.
Fix: Disable body parsing for the webhook route. In Next.js: export const config = { api: { bodyParser: false } }
Webhook times out
Your handler takes too long and Stripe retries the event.
Fix: Move heavy processing to a background job. Return 200 immediately and process async.
Related guides
Weekly Newsletter
Get next week's fix before you need it.
Join developers getting weekly vibe coding tips, error fixes, and tool updates.
Subscribe on Substack →