Skip to main content
Every webhook route authenticates the delivery with the Shopify app library, which verifies the X-Shopify-Hmac-Sha256 header (base64 HMAC over the raw body) before the payload is read. Handlers always respond with a success response and log their own failures internally, so Shopify is never prompted into retry storms; the background order sync (see Background jobs) acts as the safety net for missed deliveries.

Handled topics

Subscriptions are declared in the app configuration with per-topic callback URIs. Order and refund webhooks require the read_orders scope, and their payloads follow the API version declared in the app configuration.

Ordering and delivery guarantees

Webhook delivery order is not guaranteed. An orders/updated can arrive before orders/create, and a refund can precede its order. The handlers are written for this: order upserts are idempotent, refunds that arrive early are skipped and re-applied when the order catches up, and the background order sync reconciles anything the webhook stream missed.

Attribution coupling

orders/create and orders/updated are the only paths that can produce attributed metrics. Attribution works exclusively from the order’s cart token:
  1. The token is matched against the cart-token-to-session map the storefront tracker built during add-to-cart events.
  2. Products the same session added to its cart inside the attribution window (default 7 days, configurable 1–30) are marked as attributed on the order’s line items.
Orders ingested by the Admin API catch-up sync carry no cart token, so they count as orders but remain not attributable. The admin UI labels this honestly — see Measurement for the full attribution contract.

Data minimization in practice

Order rows store what the metrics need — line items, prices, discounts, refunds, test and cancellation flags, attribution state — and no customer names, emails, or addresses. That is why customers/data_request can be answered with a confirmation that there is nothing personal to export, and customers/redact only needs to remove the listed order rows. See Privacy for the merchant-facing summary.