Skip to main content

Verify Events deliveries

Developer preview

Events is in developer preview on the unstable API version, available today for a subset of topics. Use it for early testing ahead of a stable release and broader topic coverage. For topics not yet supported, use webhooks alongside Events in the same shopify.app.toml. As Events expands topic coverage, it will become the primary subscription mechanism.

Each delivery includes an HMAC signature to confirm it came from Shopify, and a delivery ID you can use to detect duplicates. Verify both before processing.


Every delivery includes a base64-encoded HMAC signature in the Shopify-Hmac-Sha256 header, generated using your app's client secret and the raw request body. Verify this signature before processing the payload to confirm the delivery came from Shopify. HMAC verification applies to HTTPS deliveries only, as Google Cloud Pub/Sub and Amazon EventBridge deliveries don't require it.

If you're using the React Router template, verification is handled automatically before your handler runs:

app/routes/events.jsx

import { authenticate } from "../shopify.server";

export const action = async ({ request }) => {
const { shop, session, topic } = await authenticate.webhook(request);

console.log(`Received ${topic} webhook for ${shop}`);

return new Response();
};

Always verify HMAC before trusting payload contents. Skip verification only in development with mock tools. If you rotate your app's client secret, it can take up to an hour for the HMAC digest to be generated using the new secret.

To validate manually, compute HMAC-SHA256 of the raw request body using your app's client secret as the key, then compare it to the decoded header value. Reject any delivery where the signatures don't match. For code examples and common pitfalls, see Manual verification for webhooks.


Shopify minimizes duplicate deliveries, but your app might receive the same delivery more than once, for example, after a network timeout or a retry.

Process deliveries using idempotent operations so that receiving the same delivery twice doesn't produce a different outcome. If your processing isn't idempotent, use Shopify-Webhook-Id to detect and skip duplicates:

  1. Extract Shopify-Webhook-Id from the request headers.
  2. Check your persistent store for that ID.
  3. If it exists, skip processing and return a success response.
  4. If it's new, process the delivery and save the ID.
Note

If you have more than one subscription matching the same change, you'll receive a separate delivery per subscription. Each has a different Shopify-Webhook-Id but shares the same Shopify-Event-Id. Use Shopify-Webhook-Id to deduplicate individual deliveries. Use Shopify-Event-Id to correlate deliveries that originated from the same merchant action.



Was this page helpful?