You copied the code and the database to a new host, switched DNS, and everything looks fine until someone pays and nothing unlocks. Stripe doesn't know you moved. It keeps sending events to the URL you registered, and the new server may not have the secret that matches.
whsec_ value in your env vars, every event fails signature verification.This is the simplest cutover. Stripe's update call lets you edit "the url, the list of enabled_events, and the status of your endpoint" (Stripe API: Update a webhook endpoint). The endpoint, and the secret Stripe generated for it, stay the same, so the new host needs the same whsec_ value the old host used. You can also change the URL on the endpoint's page in the Workbench Webhooks tab.
curl https://api.stripe.com/v1/webhook_endpoints/we_123 \
-u "sk_live_...:" \
--data-urlencode "url=https://www.newdomain.com/api/webhooks/stripe"
secret when the endpoint is created (Stripe API: The Webhook Endpoint object); otherwise reveal it on the endpoint's page in Workbench (source).www), and the same trailing-slash form your app serves. A curl -i -X POST to it should return 400 for an unsigned request, not a 3xx.A new endpoint gets its own new secret (source), so set the new whsec_ on the new host. While both endpoints are enabled, Stripe sends each event to both. If both hosts write to the same database, make the handler skip event IDs it has already processed (see duplicate Stripe webhook events). When the new endpoint shows 2xx deliveries, disable or delete the old one.
If you'd rather keep a single endpoint but change its secret (for example, because the old one was pasted into a repo you're abandoning), roll it: in the endpoint's overflow menu, Roll secret lets you expire the old secret immediately or keep it valid for up to 24 hours while you update your server (Stripe docs: Roll endpoint signing secrets).
Events that failed during the cutover aren't lost straight away. In live mode Stripe retries "for up to three days with an exponential back off", but "If your destination has been disabled or deleted when we attempt a retry, we prevent future retries of that event" (Stripe docs: Automatic retries). So fix the URL rather than deleting a failing endpoint. To push events yourself, click Resend on an event in the Dashboard (up to 15 days after it was created) or run stripe events resend <event_id> --webhook-endpoint=<endpoint_id> (up to 30 days) (Stripe CLI: events resend, source). Older than that, or a lot of them? Follow finding Stripe webhooks that failed silently to list failed deliveries and sync from the Checkout Sessions themselves.
STRIPE_WEBHOOK_SECRET for the right endpoint and the right mode (live secret for the live endpoint).Paste your webhook URL. WebhookProof sends 3 harmless test requests and tells you whether Stripe can reach it and whether it rejects unsigned events. If it finds a problem, the $9 fix pack gives you the exact copy-paste fix for your stack (refundable for 14 days).
Run the free checkYes. Stripe sends events to the URL registered on the endpoint, and it treats redirects as failed deliveries, so set the endpoint to the exact final https URL on the new domain.
Updating an existing endpoint edits its URL, enabled events or status; the endpoint keeps its secret. Creating a new endpoint gives you a new secret, and test and live endpoints always have different secrets.
Stripe retries live events for up to three days unless the endpoint was disabled or deleted. You can also resend an event from the Dashboard for up to 15 days, or with the Stripe CLI for up to 30 days.
Yes. Stripe sends each event to every enabled endpoint, so make the handler skip event IDs it has already processed, then disable the old endpoint once the new one returns 2xx.
Stripe webhook not working? Check these 7 things in order · A customer paid but didn't get access. What went wrong? · No signatures found matching the expected signature for payload · Stripe webhook failing with a 307 or 308 redirect
Last reviewed 2026-10-25. WebhookProof is an independent tool, not affiliated with Stripe, Inc.. Quotes are from the linked documentation.