Skip to main content

Webhooks

The app receives six Shopify webhook topics, all mounted at /webhooks/* and verified with HMAC-SHA256 before processing.

Registered topics

The three GDPR topics are declared as compliance-topic subscriptions in shopify.app.toml; the legacy privacy-compliance table is not used.

Processing pipeline

  • Every route verifies the HMAC signature over the unparsed body before JSON parsing. The signature header must be the canonical base64 form of the SHA-256 digest, and the JSON root must be an object.
  • Each delivery requires X-Shopify-Webhook-Id and a route-matching X-Shopify-Topic. The delivery ID is claimed atomically in D1; completed duplicates return 200 with duplicate: true, a concurrent live delivery returns retryable 503, and an ID reused for a different topic or payload returns 409.
  • Customer compliance deliveries require a valid positive customer ID before their receipt is claimed; subscription updates require an object envelope with a recognized status before the claim.
  • Handlers return 200 only after required verification and D1/KV work completes. A verified shop/redact whose work is queued may return 202. Handler failures mark the claim failed and return 500 so Shopify can retry.

Signature verification

Shopify sends X-Shopify-Hmac-Sha256 (a base64 HMAC-SHA256 digest), X-Shopify-Topic, X-Shopify-Shop-Domain, X-Shopify-Api-Version, and X-Shopify-Webhook-Id. The Worker computes HMAC-SHA256 of the raw body with the app secret and compares it in constant time; a mismatch returns 401 before any receipt is claimed.

Handling summary

  • app/uninstalled verifies the signed domain and/or stored Shop GID, then probes currentAppInstallation with any current session. A still-installed result preserves all data; a revoked offline session triggers cleanup, while a revoked online (staff) session deletes only that session row.
  • shop/update normalizes the payload domain and updates sessions.primary_domain monotonically for the matching offline session.
  • customers/data_request returns matching audit events, customer-linked retail workflow records with internal fields removed, and an ID-only customer object.
  • customers/redact deletes audit rows matching the validated customer ID.
  • shop/redact persists durable signed redaction work, guards against a live reinstall, and purges shop-scoped D1 and KV data.
Shopify retries failed deliveries up to eight times over a four-hour window. The receipt lease is five minutes so a terminated Worker does not suppress later retries. Pcnaid Documentation › Shopify Ecosystem › POS True Retail Operations Suite › Developer