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
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.
EventDock adds the safety net your Shopify app needs to avoid lost orders and deleted subscriptions.
Validate X-Shopify-Hmac-Sha256 signatures automatically with visual mismatch debugging.
Failed events stored with full audit trail. Replay to staging before production safely.
Get notified on failure spikes and signature mismatches before Shopify may auto-remove your Admin API subscription.
Add EventDock to your Shopify app in under 5 minutes
Choose Shopify as the provider and paste your upstream URL where orders/events should be delivered.
Copy your Shopify app's shared secret (Client secret) from the App setup page into EventDock so we can verify HMAC signatures.
Use the EventDock ingest URL when creating your Shopify webhook subscription (via Admin API or app dashboard).
Send a test order event, verify it appears in EventDock, and turn on alerts for DLQ events.
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.
Validate Shopify webhook signatures correctly
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);
});
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
Shopify retries webhooks 8 times over approximately 4 hours using exponential backoff. The retry schedule starts with short intervals and gradually increases between attempts.
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.
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.
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.
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.
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.
5,000 events/month free. No credit card required. 5-minute setup.
Start Free Trial