A webhook is an HTTP request that one system sends to a URL you choose as soon as an event happens, such as a new order or a refund. Your app gets the event data straight away, instead of asking an API again and again whether anything has changed.
A webhook is an HTTP request that one system sends to a URL you choose as soon as an event happens, such as a new order or a refund. Your app gets the event data straight away, instead of asking an API again and again whether anything has changed.
What is the difference between a webhook and an API?
Direction. With an API, your app asks for data when it wants it. With a webhook, the other system sends the data to your URL the moment an event happens, so nobody has to keep asking.

The arithmetic is simple. A store that polls for new orders every 60 seconds makes 1,440 calls a day, and on a quiet day nearly all of them find nothing. A subscription makes one delivery per order and none in between.
GitHub’s webhook docs put the trade-off plainly: “Webhooks require less effort and less resources than polling an API.” Shopify’s version works by subscription. An app picks a topic, such as orders/create, and a destination: an HTTPS URL, a Google Pub/Sub topic or an Amazon EventBridge source. Shopify’s webhook overview lists the headers each delivery carries, including X-Shopify-Topic, X-Shopify-Webhook-Id and X-Shopify-Hmac-Sha256, and warns that deliveries can arrive out of order: an update can land before the create.
How does HMAC verification prove a delivery came from Shopify?
Compute an HMAC-SHA256 of the raw request body with your app’s private client key, base64-encode it, and compare it in constant time with the X-Shopify-Hmac-SHA256 header. Reject anything that doesn’t match.
The HTTPS delivery page stresses the raw body, because body-parsing middleware changes it first. After that key is rotated, it can take up to an hour before deliveries are signed with the new one, so accept both during the switch.
On 18 October 2026 we built a receiver and checked one signed delivery 6 ways. Only the raw body, base64 and the current key passed. Re-serialising the parsed JSON failed even in compact form, because a weight written 1.50 came back as 1.5.

What happens when a delivery fails?
Shopify needs a 200 response within a one-second connection timeout and five seconds overall. Anything else counts as a failure, and Shopify retries 8 times over the next 4 hours.
After 8 consecutive failures, a subscription created through the Admin API is deleted. In our test, a handler that did 6 seconds of work before answering was cut off at 5.012 seconds, while one that queued the work answered in 0.010 seconds. Sending the same delivery twice showed why ids matter, since Shopify says repeats happen after timeouts and retries: only a receiver that stores X-Shopify-Webhook-Id values knew the second was a repeat.

Example (a hypothetical bakery taking 600 orders a week): its accounting sync answers each orders/create webhook at once, queues the order, skips ids it has seen, and runs a nightly API check for anything missed. A Shopify custom app or a Shopify Flow workflow can sit on either end. Our business automation team builds webhook receivers like this and monitors them.