Using webhooks

Upcoming Change - HTTPS required.

After July 1st 2018, apps will be required to use HTTPS webhook addresses. This doesn't include the notifications in the admin.

Learn More.

What is a webhook?

Webhooks are a useful tool for apps that want to execute code after a specific event happens on a shop, for example, after a customer creates a cart on the storefront, or a merchant creates a new product in their admin.

Instead of telling your app to make an API call every X number of minutes to check if a specific event has occured on a shop, you can register webhooks, which send an HTTP POST request from the shop telling your app that the event has occurred. This uses many less API requests overall, allowing you to build more robust apps, and update your app instantly after a webhook is received.

Webhook event data can be stored as JSON or XML, and is commonly used when:

  • Placing an order
  • Changing a product's price
  • Notifying your IM client or your pager when you are offline
  • Collecting data for data-warehousing
  • Integrating your accounting software
  • Filtering the order items and informing various shippers about the order
  • Removing customer data from your database when they uninstall your app

Webhook events

Webhooks can be registered for many events. Please check the api reference for a full list.

Configure a webhook

You can configure your webhooks, one of two ways: through the API or through your store admin.

Configure a webhook through the API

The trouble with testing your webhooks through the API is that you need a publicly visible URL to handle them. Unlike client-side redirects, webhooks originate directly from the server. This means that you cannot use the following as an endpoint in your testing environment:

  • Localhost
  • Any URL ending in the word "internal" (i.e.
  • "Fake" domains like
  • Shopify domains (i.e. and

There are a couple of tools that make working with webhooks during development much easier:

  • Pagekite makes local websites or SSH servers publicly accessible in mere seconds and works over any internet connection.
  • ngrok creates a tunnel from the public internet ( to a port on your local machine. You can give this URL to anyone to allow them to try out a web site you're developing without doing any deployment.

View our Webhook API Reference guide.

Configure a webhook through your store admin

If you are developing an app for a particular shop, you can configure your webhooks through your shop admin:

  1. In the Webhooks section, click Create a webhook:

  2. Select the event type you want to listen for from the drop-down box and enter the URL (http:// or https://) where you want to receive notifications.

After you have created at least one webhook, you will be presented with a secret that you can use to validate the integrity of these webhooks:

List of webhooks

Shopify lets you test your webhooks to verify that the endpoint is receiving notifications. In the list of order notifications you will see your webhook. You will also see a "send test notification" link. This "send test notification" link allows you to send an example order to the URL you provided.

If you want to capture the contents of a webhook to examine them, the easiest way is to set up a new subscription with a service like LocalTunnel, RequestBin or PostCatcher (described above) which will capture the result and let you view it in a browser.

Receive a webhook

Once you register a webhook URL with Shopify, we will issue a HTTP POST request to the URL specified every time that event occurs. The request's POST parameters will contain XML/JSON data relevant to the event that triggered the request.

Shopify verifies SSL certificates when delivering payloads to HTTPS webhook addresses. Please ensure your server is correctly configured to support HTTPS with a valid SSL certificate.

Respond to a webhook

Your webhook acknowledges that it received data by sending a 200 OK response. Any response outside of the 200 range will let Shopify know that you did not receive your webhook, including 301 Redirect. Shopify does not follow redirects for webhook notifications and will consider a redirection as an error response.

Shopify has implemented a 5-second timeout period and a retry period for subscriptions. We wait 5 seconds for a response to each request, and if there isn't one or we get an error, we retry the connection to a total of 19 times over the next 48 hours. A webhook will be deleted if there are 19 consecutive failures for the exact same webhook. You should monitor the admin of your webhook tool for failing webhooks.

If you're receiving a Shopify webhook, the most important thing to do is respond quickly. There have been several historical occurrences of apps that do some lengthy processing when they receive a webhook that triggers the timeout. This has led to situations where webhooks were removed from functioning apps.

To make sure that apps don't accidentally run over the timeout limit, we now recommend that apps defer processing until after the response has been sent.

Verify a webhook created through the API

Webhooks created through the API by a Shopify App can be verified by calculating a digital signature.

Each webhook request includes a base64-encoded X-Shopify-Hmac-SHA256 header, which is generated using the app's shared secret along with the data sent in the request.

Webhooks created manually through the Shopify admin will need to be verified with the secret found within the webhooks section of the notifications area.

To verify that the request came from Shopify, compute the HMAC digest according to the following algorithm and compare it to the value in the X-Shopify-Hmac-SHA256 header. If they match, you can be sure that the Webhook was sent from Shopify and the data has not been compromised.

Note that if you are using a Rack based framework such as Ruby on Rails or Sinatra the header you are looking for is HTTP_X_SHOPIFY_HMAC_SHA256

Below is a simple example in Ruby using the Sinatra web framework of how one might verify a webhook request.

require 'rubygems'
require 'base64'
require 'openssl'
require 'sinatra'

# The Shopify app's shared secret, viewable from the Partner dashboard
SHARED_SECRET = 'my_shared_secret'

helpers do
  # Compare the computed HMAC digest based on the shared secret and the request contents
  # to the reported HMAC in the headers
  def verify_webhook(data, hmac_header)
    calculated_hmac = Base64.strict_encode64(OpenSSL::HMAC.digest('sha256', SHARED_SECRET, data))
    ActiveSupport::SecurityUtils.secure_compare(calculated_hmac, hmac_header)

# Respond to HTTP POST requests sent to this web service
post '/' do
  data =
  verified = verify_webhook(data, env["HTTP_X_SHOPIFY_HMAC_SHA256"])

  # Output 'true' or 'false'
  puts "Webhook verified: #{verified}"

And here's a PHP version:


define('SHOPIFY_APP_SECRET', 'my_shared_secret');

function verify_webhook($data, $hmac_header)
  $calculated_hmac = base64_encode(hash_hmac('sha256', $data, SHOPIFY_APP_SECRET, true));
  return hash_equals($hmac_header, $calculated_hmac);

$hmac_header = $_SERVER['HTTP_X_SHOPIFY_HMAC_SHA256'];
$data = file_get_contents('php://input');
$verified = verify_webhook($data, $hmac_header);
error_log('Webhook verified: '.var_export($verified, true)); //check error.log to see the result


What do I do if everything blows up?

Your hosting center exploded and your app has been offline for more than 48 hours. It's back on its feet now, but you've missed a pile of data that was sent to you in the meantime. Not only that, but Shopify has cancelled your webhooks because you weren't responding for an extended period of time. How do you catch up? Let's tackle the problems in order of importance.

Getting your webhook subscriptions back should be straightforward as your app already has the code that registered them in the first place.One thing you should do is add a quick check that fetches all the existing webhooks and only registers the ones that you need. If you know for sure that they're gone you can just re-run that and you'll be good to go.

Importing the missing data is trickier. The best way to get it back is to build a harness that fetches data from the time period you were down for that feeds it into the webhook processing code one object at a time. The only caveat is that you'll need the processing code to be sufficiently decoupled from the request handlers that you can call it separately.

Sign up for a Partner account to get started.

Sign up