Skip to content

Shopify webhooks

Shopify’s signature scheme differs from Stripe’s and GitHub’s in one way that trips almost everyone up: the digest is base64-encoded, not hex. Most other failures are the wrong secret or a mutated body.

Create a catchbin endpoint with the Shopify provider and copy its URL. Add that URL as a webhook subscription in Shopify — from the admin, from your app (webhookSubscriptionCreate), or with shopify app generate webhook — choosing the topics you care about (for example orders/create, products/update). Then paste the webhook’s shared secret into the catchbin endpoint. The event label shows the Shopify topic, read from the X-Shopify-Topic header.

HMAC-SHA256 over the raw request body, with the result base64-encoded. There is no timestamp and no prefix — the header value is just the base64 digest:

X-Shopify-Hmac-SHA256: XWmrwMey6OsLMeiZKwP4FppHH3cmAiiJJAweH5Jo4bM=

catchbin compares against the base64 form natively.

Symptom Cause Fix
Digest looks like base64, your code expects hex Base64 vs hex Compare the base64 digest
Fails on every event; you pasted the Admin API key Wrong secret Use the webhook shared secret
Byte length differs from what Shopify sent Body mutated Verify the raw bytes
No X-Shopify-Hmac-SHA256 on the request Missing header Confirm the caller is Shopify

Symptom. A hand-rolled verifier that works for Stripe or GitHub fails for Shopify.

Why. Stripe and GitHub send hex digests; Shopify sends base64. A verifier that hex-decodes the header, or hex-encodes its own HMAC before comparing, will never match Shopify’s base64 value.

Fix. Compute the HMAC-SHA256 of the raw body and compare it as base64. catchbin does this for you, so a catchbin “mismatch” on a Shopify endpoint usually means the secret or the body differs — not the encoding.

Wrong secret: Admin API key vs webhook secret

Section titled “Wrong secret: Admin API key vs webhook secret”

Symptom. Total failure from the first event.

Why. The value used to sign is the webhook’s shared secret, not your Admin API access token or API key. Pasting the API key is the second-most-common Shopify failure.

Fix. Use the right shared secret for how the webhook was created:

  • App webhooks (most common): the app’s client secret (API secret key) from the app settings.
  • Admin-created (store) webhooks: the per-store webhook signing secret shown in the admin notifications/webhooks settings.
  • CLI/API-created subscriptions: the same app client secret applies.

Paste that value into catchbin once; it is stored encrypted and never displayed again.

Symptom. Nothing verified on a new endpoint, secret confirmed.

Why. A proxy or middleware re-serialized the JSON before it reached the verifier, so the bytes Shopify signed differ from the bytes received.

Fix. Hash the raw request body. catchbin’s diagnostic includes the received body byte count to help you spot this.

Symptom. Recorded as a missing-header failure.

Why. The delivery carried no X-Shopify-Hmac-SHA256 — for example a manual curl, or a non-Shopify caller hitting the URL.

Fix. Confirm the request actually came from Shopify. Genuine Shopify deliveries always include the header.

Replay a captured Shopify event to any target. Strip mode drops the signature header; --resign computes a fresh X-Shopify-Hmac-SHA256 over the replayed body using the target’s secret so a verifying target accepts it.