Volley / Templates / Shopify orders/create webhook

Webhooks template

Shopify orders/create webhook, as a sequence diagram

What Shopify sends when an order is placed, how your app should answer, and the background job that follows, with the headers, order JSON and Admin API call on their arrows.

Sequence diagram of a Shopify orders/create webhook across Shopify, App, Queue, Worker and Shopify Admin API: the delivery, HMAC check, enqueue and 200 OK or 401, then a worker tags the order through GraphQL.

Click any arrow in the editor to see its request and response as a table or the raw body. Change the hosts, ids and fields to match your integration, then share a link or embed it in your README.

Step by step

  1. Shopify posts the order with X-Shopify-Topic: orders/create, the shop domain, the API version, a webhook id and an HMAC signature.
  2. Your app checks the HMAC: an HMAC-SHA256 of the raw body with the app's client secret, base64 encoded.
  3. Your app queues the work and answers 200 right away, or 401 if the signature is wrong.
  4. A worker does the slow part, here tagging the order through the GraphQL Admin API with X-Shopify-Access-Token.

Easy to get wrong

  • Shopify waits only a few seconds and retries failures, so slow handlers cause duplicate deliveries. Answer first.
  • Use X-Shopify-Webhook-Id to drop duplicates.
  • Compute the HMAC over the raw bytes. A re-serialized body will not match.

The source

The whole diagram is this plain text. Copy it into your repo, or open it in the editor.

shopify-order-webhook.volley
title: Shopify orders/create webhook
order: Shopify, App, Queue, Worker, Shopify Admin API

Shopify -> App: POST /webhooks/shopify (orders/create)
in: Delivery
```http
POST /webhooks/shopify HTTP/1.1
Content-Type: application/json
X-Shopify-Topic: orders/create
X-Shopify-Shop-Domain: example-store.myshopify.com
X-Shopify-API-Version: 2025-07
X-Shopify-Webhook-Id: b54557e4-bdd9-4b37-8a5f-bf7d70bcd043
X-Shopify-Hmac-Sha256: <redacted>

{
  "id": 820982911946154508,
  "name": "#1001",
  "email": "jon@example.com",
  "financial_status": "paid",
  "total_price": "49.00",
  "currency": "USD",
  "line_items": [{ "sku": "TEE-BLK-M", "quantity": 1, "price": "49.00" }]
}
```

App -> App: Verify the HMAC over the raw body
note: Compute an HMAC-SHA256 of the raw request body with the app's client secret, base64 encode it and compare it with `X-Shopify-Hmac-Sha256`.

if: Signature is valid
  App ->> Queue: Enqueue order 820982911946154508
  App --> Shopify: 200 OK
else: Signature is invalid
  App --> Shopify: 401 Unauthorized
end
note: Shopify waits only a few seconds for a response and retries failed deliveries, so answer first and do the work in the background. Use `X-Shopify-Webhook-Id` to skip duplicates.

...: {fas-clock} Moments later

Queue ->> Worker: Order job

Worker -> Shopify Admin API: POST /admin/api/2025-07/graphql.json
in: Tag the order
```http
POST /admin/api/2025-07/graphql.json HTTP/1.1
Content-Type: application/json
X-Shopify-Access-Token: <redacted>

{ "query": "mutation { tagsAdd(id: \"gid://shopify/Order/820982911946154508\", tags: [\"synced\"]) { userErrors { field message } } }" }
```

Shopify Admin API --> Worker: 200 OK
out: Result
```json
{ "data": { "tagsAdd": { "userErrors": [] } } }
```

Related

Make this Shopify orders/create webhook diagram yours.

Open it in the editor, change it to match your integration and share the link. Free, with no account.