HookDeploy
Shopify Intermediate

Testing Shopify Webhooks with HookDeploy

Shopify Admin API webhooks, HMAC verification, mandatory webhooks, rate limits, and GDPR compliance webhooks.

HookDeploy Team · May 22, 2026

Shopify webhooks notify your app about store events — orders, products, customers, inventory, and compliance requests. This guide covers setup, verification, and the Shopify-specific quirks that catch developers off guard.

Admin API webhooks vs Partner webhooks

TypeConfigured inScope
Admin API (custom app)Shopify Admin → Settings → NotificationsSingle store
App webhooks (Partner Dashboard)partners.shopify.com → App setupAll stores that install your app
GraphQL webhookSubscriptionCreateAPI callProgrammatic, per shop

For development, configure webhooks in the Shopify Admin of a development store. For production apps, register webhooks via the Partner Dashboard or GraphQL API.

Set up HookDeploy with a development store

  1. Create a Shopify development store
  2. Create a HookDeploy endpoint
  3. In Shopify Admin: Settings → Notifications → Webhooks → Create webhook
  4. Event: start with Order creation or Product creation
  5. Format: JSON
  6. URL: https://hookdeploy.dev/h/{slug}
  7. Webhook API version: latest stable
  8. Save

Shopify sends a test delivery immediately. Verify it appears in HookDeploy.

HMAC verification

Shopify signs every webhook with HMAC-SHA256. The signature is in X-Shopify-Hmac-Sha256, base64-encoded:

const crypto = require('crypto');

function verifyShopifyWebhook(rawBody, hmacHeader, secret) {
  const hash = crypto
    .createHmac('sha256', secret)
    .update(rawBody, 'utf8')
    .digest('base64');

  return crypto.timingSafeEqual(
    Buffer.from(hash),
    Buffer.from(hmacHeader)
  );
}

// Express handler:
const hmac = request.headers['x-shopify-hmac-sha256'];
if (!verifyShopifyWebhook(request.rawBody, hmac, process.env.SHOPIFY_WEBHOOK_SECRET)) {
  return response.status(401).send('Invalid HMAC');
}

The secret is your app’s API secret key (Partner Dashboard → App setup → Client credentials), not the API access token.

Mandatory webhooks for public apps

Public Shopify apps must handle these compliance webhooks:

TopicPurpose
customers/data_requestCustomer requests their data (GDPR)
customers/redactCustomer requests data deletion
shop/redactStore uninstalled your app — delete shop data

Shopify reviews your app for compliance webhook handling before approval. Register these in the Partner Dashboard under App setup → Compliance webhooks.

Test with HookDeploy first — capture the payload structure, then implement handlers.

Common Shopify webhook topics

TopicFires when
orders/createNew order placed
orders/paidOrder payment confirmed
orders/fulfilledOrder fully fulfilled
products/createNew product added
products/updateProduct modified
inventory_levels/updateInventory quantity changes
app/uninstalledMerchant uninstalls your app

Rate limits

Shopify limits webhook delivery rate per shop. Excessive failures can cause Shopify to remove your webhook subscription after 19 failed attempts over 48 hours.

Shopify expects a response within 5 seconds — shorter than Stripe or GitHub. Return 200 immediately:

app.post('/webhooks/shopify', (req, res) => {
  if (!verifyShopifyWebhook(req.rawBody, req.headers['x-shopify-hmac-sha256'], secret)) {
    return res.status(401).send('Unauthorized');
  }
  res.status(200).send('OK');
  processShopifyWebhook(req.body).catch(console.error);
});

GDPR webhooks in detail

customers/data_request — respond within 30 days with customer data you store. Payload includes customer ID and email.

customers/redact — delete customer data within 30 days. Payload includes customer ID.

shop/redact — sent 48 hours after app uninstall. Delete all data for that shop.

These are legal requirements for EU customers. Implement handlers even if you store no customer data (respond with 200 and log the request).

Test with curl

# Compute HMAC for testing (Node.js one-liner):
# node -e "const c=require('crypto');const b='{\"test\":true}';console.log(c.createHmac('sha256','YOUR_SECRET').update(b).digest('base64'))"

curl -X POST "https://hookdeploy.dev/h/YOUR_SLUG" \
  -H "Content-Type: application/json" \
  -H "X-Shopify-Topic: orders/create" \
  -H "X-Shopify-Shop-Domain: your-store.myshopify.com" \
  -H "X-Shopify-Hmac-Sha256: COMPUTED_HMAC" \
  -d '{"id": 12345, "total_price": "29.99", "currency": "USD"}'

Debug delivery failures

In Shopify Admin → Settings → Notifications → Webhooks, each webhook shows recent delivery status.

Common issues:

  • 401 from your handler — HMAC verification failing (wrong secret or parsed body)
  • 404 — HookDeploy slug wrong or endpoint deleted
  • Timeout — handler took > 5 seconds before returning 200
  • Removed webhook — 19 consecutive failures — re-create the webhook subscription

Use HookDeploy to capture the exact payload Shopify sends before building your handler.

Related guides

  • Webhook security best practices

    Signature verification for Stripe, GitHub, and Shopify. HMAC-SHA256, replay attacks, IP allowlisting, HTTPS, and secret rotation.

  • Webhook debugging guide

    Systematic approach to debugging webhook issues — delivery logs, signatures, payloads, curl testing, and common HTTP error codes.

  • Testing Stripe webhooks with HookDeploy

    Complete guide to capturing, inspecting, and debugging Stripe webhook events using HookDeploy, the Stripe CLI, and signature verification.