48-hour launch: 40% off with code LAUNCH40, Guide $5.40 / Kit $11.40

Shopify webhook not firing or failing (401, timeouts, removed subscriptions): checklist

Shopify counts a delivery as successful only when your endpoint answers with a 2xx within 5 seconds (with a 1-second connection timeout). Every other outcome is a failure, including 3xx redirects. Shopify then retries 8 times over 4 hours. Work through these in order.

1. Your endpoint is answering 401 (or another 4xx)

A 401 almost always comes from your own code. Your HMAC check rejected the request, or auth middleware blocked it before your handler ran. Common reasons:

2. Your endpoint is too slow

If you do the real work (database writes, API calls, emails) before you respond, you'll hit the 5-second limit under load. Return 200 right away and process in a queue or background job.

3. The subscription was deleted

If 8 retries in a row fail, Shopify automatically deletes subscriptions created through the Admin API and emails warnings to the app's emergency developer address. Webhooks then stop with no error at all. Fix the endpoint, then create the subscription again. Subscriptions declared in shopify.app.toml are managed by Shopify and aren't removed this way.

4. Redirects and URL mismatches

http to https, apex to www, or trailing-slash redirects all count as failures. Register the exact final https URL. Retries go to the address that was configured when the event fired, so keep the old endpoint running for a while after you migrate.

5. Wrong topic, store or API version

Check that the subscription exists on the store you're testing (or in the app config) and uses the topic you expect. Use the delivery metrics in the Partner or Dev Dashboard to see response codes and timings for each attempt.

The guide is Stripe-only. The kit is a self-hosted Cloudflare Worker relay that adds retries, replay and a dead-letter list in front of your endpoint. Answering fast and retrying later helps you avoid removed subscriptions. It verifies Shopify's X-Shopify-Hmac-Sha256 out of the box. Set SCHEME_<ID>=shopify. It works the same way for Stripe, Lemon Squeezy, Paddle Billing, Square, Twilio (status callbacks) and GitHub.

Fix Your Stripe Webhooks guide · Self-Hosted Webhook Relay Kit. Code LAUNCH40 = 40% off until Sun Oct 11, 6:40 AM MT.

Quick test

curl -i -X POST https://your-app.com/webhooks/shopify \
  -H 'Content-Type: application/json' -H 'X-Shopify-Topic: orders/create' -d '{}'
# 3xx  = a redirect in front of your app
# 401  = your HMAC or auth layer (expected here, since this request isn't signed)
# slow = move the work after the 200

Retried deliveries carry the original payload. Use the X-Shopify-Triggered-At header to spot stale ones, and de-duplicate on the webhook ID.

Free download: Webhook debugging cheat sheet.

Fighting webhooks on more than one platform? The Fix Your Stripe Webhooks guide ($9) covers raw-body and signature problems in depth, and the Self-Hosted Webhook Relay Kit ($19) adds retries, replay and a dead-letter list in front of any endpoint.