Shopify Webhook Example

Inspect a Shopify webhook request as it arrives at your endpoint. See the resource JSON and the headers Shopify sends with it. Find out how a delivery is signed and how long you have to answer one. Catch a real Shopify webhook on a URL of your own with the ReqBin Webhook Tester. No sign-up, nothing to install.

What is a Shopify webhook?

A Shopify webhook is an HTTP POST request that Shopify sends to a URL you registered, telling your server that something changed in a store: an order was paid, a product was updated, a customer was created, a fulfilment shipped. These changes happen inside Shopify, so the only way it can tell your server is to send it a request carrying the resource. Deliveries are grouped by topic — orders/paid, products/update.

How do I receive Shopify webhooks while developing on localhost?

Shopify can deliver requests only to public URLs. A dev server on localhost is not reachable by Shopify, so nothing it sends arrives there. To make your localhost URL public, you need to install a tunnel, which is not a trivial task.

A simpler option is to use a ReqBin webhook URL. It is public, it takes whatever Shopify posts to it, and it shows you each request, as soon as it lands.

How do I connect a ReqBin webhook URL to Shopify?

  1. Create a webhook URL with the ReqBin Webhook Tester and copy it.
  2. In the Shopify admin, create the subscription:
    1. Open Settings, then Notifications, then Webhooks, and click Create webhook.
    2. Pick the Event you want and JSON as the Format.
    3. Paste the ReqBin URL into URL, choose the Webhook API version, and click Save.
  3. Place your test order and read the Shopify webhook details on your inbox page.

Can I edit a caught request and send it to my own server?

Yes. On the inbox page, select any of the requests you received from Shopify and press Open in API Tester. The request opens in the ReqBin API tester with everything that arrived. Enter your URL, change what you need, and send the request to your server. To send requests to localhost or to another server on your local network, you need to add the ReqBin Google Chrome Extension to your browser using this link.

What does a Shopify webhook payload look like?

Shopify sends the object that changed in the request's body: an order, a product or a customer, with all its details.

Shopify Webhook Example
{
  "id": 820982911946154508,
  "order_number": 1234,
  "financial_status": "paid",
  "currency": "USD",
  "total_price": "49.00",
  "created_at": "2026-09-11T09:14:05-04:00",
  "customer": {
    "id": 115310627314723954,
    "email": "[email protected]"
  },
  "line_items": [
    {
      "id": 866550311766439020,
      "title": "Annual plan",
      "quantity": 1,
      "price": "49.00"
    }
  ]
}

The X-Shopify-Topic header says whether the order is paid, updated or cancelled. The body is the same for all three. The full list of topics is in the Shopify webhook reference.

What headers does Shopify add to the request?

Seven, on top of the ones any POST carries:

HeaderValue
X-Shopify-Topicorders/paid
X-Shopify-Hmac-Sha256XWmrwMey6OsLMeiZKwP4FppHH3cmAiiJJAweH5Jp3F8=
X-Shopify-Shop-Domainocto-store.myshopify.com
X-Shopify-API-Version2026-07
X-Shopify-Webhook-Idb54557e4-bdd9-4b37-9fb3-20c8bb5e2d1f
X-Shopify-Triggered-At2026-09-11T09:14:07.123Z
X-Shopify-Event-Id2f1c1cf8-6e2b-4c66-9a6b-9d2bb2e1f0a3

X-Shopify-Webhook-Id is unique per delivery and is what you deduplicate on. X-Shopify-Event-Id is shared by every delivery that one merchant action produced.

How does Shopify sign a webhook?

Your production endpoint URL is public, so anyone who knows or guesses it can post to it. Shopify signs every delivery, and you need to verify the signature before trusting the request. The signature arrives in X-Shopify-Hmac-Sha256: an HMAC-SHA256 of the raw request body, keyed with your app's client secret and base64-encoded.

Does Shopify retry a failed webhook?

Yes, eight times over four hours. You have little time to answer: one second to connect, five seconds for the whole request, and a 200 OK. After eight consecutive failures a subscription created through the Admin API is deleted, and warning emails go to the app's emergency developer address.

Updated: