POST /v2/integrations/shopify/webhook/{topic} is the public wire-protocol endpoint
Shopify webhooks land on after a merchant connects their store to droplinked. It is the
hot path that keeps droplinked’s InventoryOS catalog mirror in sync with the merchant’s
Shopify store of record.
This page documents the wire protocol for engineers configuring Shopify webhooks
themselves. For the merchant-facing integration walkthrough — how to connect a store,
authorize the droplinked Shopify app, and verify the sync is healthy — see
Connect your Shopify store.
Although this endpoint has no JWT and no IP allowlist, it is not an open ingest: every
request is HMAC-validated against the per-shop webhook secret that droplinked issued at
connection time. Unauthed traffic is rejected with a 401.
Supported topics
The{topic} path segment selects the handler. Currently wired:
Additional topics will be added as the integration matures. Unknown topics return 404 with
message: "shopify_webhook_topic_not_supported".
HMAC validation
Shopify computes an SHA-256 HMAC over the raw request body using the per-shop webhook secret and sends the result in theX-Shopify-Hmac-Sha256 header. Droplinked re-computes
the expected HMAC server-side using the secret it stored at connection time and
constant-time-compares against the header.
On HMAC mismatch the endpoint returns 401 with reason
shopify_webhook_auth_failed.
The body is not parsed when validation fails, so no side effects fire.
If the X-Shopify-Shop-Domain does not resolve to a connected shop, the endpoint returns
404 with a message instructing the operator to call POST /admin/shopify-integration/connect
first.
Configuring the webhook in Shopify Admin
In Shopify Admin → Settings → Notifications → Webhooks, add one webhook per supported topic. For each:
The URL
<topic> segment must match exactly one of the supported topics in the table
above. Example URLs:
Example request
A Shopify-emittedproducts-create webhook lands on droplinked as:
Response — 200 OK
Response — 401 Unauthorized (HMAC mismatch)
Response — 404 Not Found (shop not connected)
Response — 404 Not Found (unsupported topic)
Response — 400 Bad Request (malformed body)
Body forwarding and normalization
After HMAC validation, droplinked normalizes the Shopify product shape into its InventoryOS catalog model. The mapping is:
The Shopify store remains the source of truth — droplinked’s mirror is a
read-projection. Edits made in droplinked’s admin UI for Shopify-sourced products are
rejected; merchants edit in Shopify and the webhook reconciles the mirror.
Operator setup
Before pointing Shopify webhooks at this endpoint, the merchant must be connected via the admin API:1
Operator calls connect (SUPER_ADMIN-gated)
POST /admin/shopify-integration/connect registers the shop’s *.myshopify.com
domain, issues a per-shop webhook signing secret, and links the Shopify store to a
droplinked shop record.2
Operator passes the secret to the merchant
The webhook signing secret is returned in the response body of the connect call. It is
only retrievable once — re-running connect rotates the secret and invalidates the old
one.
3
Merchant configures webhooks in Shopify Admin
Following the table above, the merchant adds one webhook per supported topic using the
issued secret as the signing secret.
4
Verify with a test product
Create a draft product in Shopify. Droplinked should receive the
products-create
webhook within seconds and mirror the product into InventoryOS. The connection-health
surface in admin shows the most recent successful webhook timestamp per topic.Related
- Connect your Shopify store — merchant-facing integration walkthrough.
- InventoryOS — the catalog model the webhook body is normalized into.