Shopify with Hookwatch Webhook Tester
This inbox is set up for Shopify: create a webhook in the store admin or subscribe your app to a topic with this URL, and each delivery appears here with its X-Shopify-Topic, shop domain and raw body. The Signature tab computes the base64 HMAC-SHA256 of the body with your secret, so you can see whether the key or your body handling is wrong.
- Copy the inbox URL at the top of the tool. It ends in /shopify so store deliveries stand out in the list.
- In the Shopify admin open Settings → Notifications → Webhooks, create a webhook for the event you handle (for example Order creation), choose JSON and paste the URL. For an app, register the URL as the topic's endpoint instead.
- Press Send test on the webhook, place a test order, or press Send a signed test Shopify event here for a known-good delivery.
- Select the request. The Signature tab reads X-Shopify-Hmac-Sha256 and the Headers tab shows the topic, shop domain, API version and webhook id.
- Paste the signing key: the one on the Notifications page for admin webhooks, or the app's client secret for app webhooks. Invalid shows the base64 digest computed from the raw body next to the one Shopify sent.
What to know
Shopify computes HMAC-SHA256 over the raw request body and sends the digest base64-encoded in X-Shopify-Hmac-Sha256. Two details trip people up. The digest is base64, not hex, so comparing it with a hex string from a default hash helper never matches. And the key depends on who created the webhook: subscriptions made by an app are signed with that app's client secret (the API secret key), while webhooks created by hand in the admin are signed with the key shown under Settings → Notifications → Webhooks. An Admin API access token is not a signing key and will never match.
As with every body-signed webhook, the bytes matter. Frameworks that parse the JSON before your handler sees it, for example a global express.json(), hand you a re-serialised body with different whitespace. Read the raw body on the webhook route (express.raw({ type: 'application/json' }), await request.text() in a Remix or Next.js handler), verify, then parse. Compare with a constant-time function on the decoded bytes or on the two base64 strings.
Each delivery carries X-Shopify-Topic (orders/create, products/update, app/uninstalled…), X-Shopify-Shop-Domain, X-Shopify-API-Version, X-Shopify-Webhook-Id, X-Shopify-Event-Id and X-Shopify-Triggered-At. Shopify expects your endpoint to answer with a 200-series status within five seconds and retries failed deliveries up to eight times over the following four hours, so the same event can arrive more than once. Use X-Shopify-Event-Id to recognise a repeat of an event you have already handled.
Public and custom apps must also handle the mandatory compliance topics customers/data_request, customers/redact and shop/redact, which are signed the same way. A fast way to check them is to point the compliance webhook URLs in your app configuration at this inbox, trigger them from a development store, and verify the HMAC here before writing the handler. On Pro, the Compare view shows two deliveries field by field, which helps when an orders/updated payload differs from the orders/create one you coded against.
Updated · Cosmovex
Questions
Which secret signs Shopify webhooks?
For webhooks your app subscribes to, the app's client secret (API secret key) from the Partner Dashboard or the app settings. For webhooks created in the store admin under Settings → Notifications, the key Shopify shows in that Webhooks section. Access tokens are never used for signing.
Why is my Shopify HMAC always different?
Usually because the digest is compared as hex instead of base64, the wrong key is used, or the body was parsed and re-serialised before hashing. If this page shows Valid with your key, the key is right and your server needs to hash the raw request body.
How do I send a test Shopify webhook?
In the admin open Settings → Notifications → Webhooks and press Send test next to the webhook. The test delivery is signed like a real one. You can also press Send a signed test Shopify event here to see a known-good request signed with the demo secret.
How long does Shopify wait for a response?
Shopify expects a 200-series response within five seconds. Slower or failed responses count as failures and the delivery is retried up to eight times over four hours, so make the handler acknowledge quickly and do the work in a background job.
Is my Shopify secret sent to your server?
No. The HMAC is computed in your browser with WebCrypto. The delivery itself is stored on our server so it can show in your inbox; the key you paste stays in this browser's storage.
The free plan covers everything on this page. Hookwatch Webhook Tester Pro ($5/mo, billed monthly) is described on the Hookwatch Webhook Tester page.