Shopify Webhooks

Shopify Webhooks with HMAC, Made Safe.

Shopify retries 8 times over 4 hours and may remove subscriptions after repeated failures. EventDock verifies HMAC, adds DLQ/replay, and alerts you before incidents bite revenue.

Works with webhooks from

Stripe Shopify GitHub Twilio SendGrid

What Shopify actually does

Shopify retries webhooks 8 times over approximately 4 hours using exponential backoff.

After multiple failures in a 24-hour period, webhook subscriptions created via the Admin API can be automatically removed—meaning no more deliveries until you recreate the subscription.

Protect revenue with reliable webhooks

EventDock adds the safety net your Shopify app needs to avoid lost orders and deleted subscriptions.

HMAC-SHA256 Verification

Validate X-Shopify-Hmac-Sha256 signatures automatically with visual mismatch debugging.

  • Automatic HMAC validation
  • Base64 encoding handled
  • Constant-time comparison

DLQ & Safe Replay

Failed events stored with full audit trail. Replay to staging before production safely.

  • Never drop order events
  • Test with staging replays
  • Full event history

Smart Alerts

Get notified on failure spikes and signature mismatches before Shopify may auto-remove your Admin API subscription.

  • Email + Slack alerts
  • Failure rate monitoring
  • Alert before potential subscription removal

Shopify Quick-Start

Add EventDock to your Shopify app in under 5 minutes

1

Create EventDock endpoint

Choose Shopify as the provider and paste your upstream URL where orders/events should be delivered.

2

Paste app shared secret

Copy your Shopify app's shared secret (Client secret) from the App setup page into EventDock so we can verify HMAC signatures.

3

Register webhook with EventDock URL

Use the EventDock ingest URL when creating your Shopify webhook subscription (via Admin API or app dashboard).

4

Test & enable alerts

Send a test order event, verify it appears in EventDock, and turn on alerts for DLQ events.

Test your Shopify HMAC with curl
curl -s https://api.eventdock.app/in/<endpoint-id> \
  -H "X-Shopify-Hmac-Sha256: <base64-hmac>" \
  -H "Content-Type: application/json" \
  --data '{"id":123456789,"total_price":"99.00"}'

In EventDock, open Stream → verify HMAC verdict and replay to staging.

HMAC verification example

Validate Shopify webhook signatures correctly

Node.js verification

Shopify signs payloads with HMAC-SHA256 and encodes as base64 in X-Shopify-Hmac-Sha256. CRITICAL: Decode both values to bytes before timing-safe comparison.

const crypto = require('crypto');

function verifyShopifyHMAC(payload /* raw string */, hmacHeader /* base64 */, secret) {
  // Compute HMAC-SHA256 (bytes), then compare against header (bytes)
  const digestB64 = crypto.createHmac('sha256', secret)
    .update(payload, 'utf8')
    .digest('base64');

  // CRITICAL: Decode both base64 strings to bytes for timing-safe comparison
  const a = Buffer.from(digestB64, 'base64');
  const b = Buffer.from(hmacHeader, 'base64');
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}

// Express: raw body required to avoid mutation
app.post('/shopify-webhook',
  express.raw({ type: 'application/json' }),
  (req, res) => {
    const ok = verifyShopifyHMAC(
      req.body.toString('utf8'),
      req.header('X-Shopify-Hmac-Sha256'),
      process.env.SHOPIFY_SHARED_SECRET
    );
    res.sendStatus(ok ? 200 : 401);
  });

Python verification

import hmac
import hashlib
import base64

def verify_shopify_hmac(payload: bytes, hmac_header: str, secret: str) -> bool:
    """Verify Shopify HMAC-SHA256 signature."""
    # Compute expected HMAC
    expected = base64.b64encode(
        hmac.new(
            secret.encode('utf-8'),
            payload,
            hashlib.sha256
        ).digest()
    ).decode('utf-8')

    # Constant-time comparison
    return hmac.compare_digest(expected, hmac_header)

# Usage in Flask
@app.route('/shopify-webhook', methods=['POST'])
def shopify_webhook():
    hmac_header = request.headers.get('X-Shopify-Hmac-Sha256')
    secret = os.environ['SHOPIFY_SECRET']

    if not verify_shopify_hmac(request.data, hmac_header, secret):
        return 'Unauthorized', 401

    # Process webhook...
    return 'OK', 200

Frequently Asked Questions

How many times does Shopify retry webhooks?

Shopify retries webhooks 8 times over approximately 4 hours using exponential backoff. The retry schedule starts with short intervals and gradually increases between attempts.

Can Shopify delete my webhook subscription?

Yes. After multiple failures in a 24-hour period, Shopify can automatically remove a webhook subscription created via the Admin API. EventDock monitors failure rates and alerts you well before this happens.

Does EventDock change Shopify webhook payloads?

No. EventDock preserves the original webhook body exactly as sent by Shopify and stores it encrypted. We forward the original headers and payload to your upstream endpoint unchanged.

How do I verify Shopify HMAC signatures?

Shopify signs webhook payloads with HMAC-SHA256 in the X-Shopify-Hmac-Sha256 header. Compute the HMAC of the raw request body using your app's shared secret, encode it as base64, and perform a constant-time comparison with the header value.

What happens if my endpoint is slow or down?

EventDock buffers incoming webhooks and handles retries with exponential backoff. Even if your upstream is temporarily unavailable or slow, we ensure events are queued and delivered when your service recovers.

Can I replay Shopify webhooks to a staging environment?

Yes. EventDock allows one-click replay of any webhook to production or staging endpoints with full audit trail, making it easy to test webhook handling logic without affecting production data.

Start free — never miss a Shopify order

5,000 events/month free. No credit card required. 5-minute setup.

Start Free Trial

Other providers: Stripe · GitHub