Skip to main content

Webhook Overview

Webhooks let your app passively receive store events — when an order is created, a product is updated, or an app is uninstalled, Shoplazza actively POSTs the event payload to the URL you registered in advance.

tip

Want the event list directly? Go to Webhook Events.

Prerequisites

Before your endpoint can receive a webhook:

  • The merchant has installed your app on their store.
  • Your app has subscribed to the event (topic) at a specific API version.

Register a subscription

Send an authenticated POST to the webhooks endpoint — every request carries an Access-Token: <access_token> header.

POST https://<shop>/openapi/2022-01/webhooks

Request body:

{
"topic": "products/create", // event to subscribe to; see Webhook Events for the full list
"address": "https://your-app.example.com/webhook/products-create" // your HTTPS endpoint
}

Response — the created subscription object:

{
"id": "1234",
"topic": "products/create",
"address": "https://your-app.example.com/webhook/products-create",
"format": "json",
"created_at": "2024-01-15T08:30:00Z",
"updated_at": "2024-01-15T08:30:00Z"
}
note

The request body differs by API version. The example above is for 2022-01, which takes a flat body. From 2025-06 onward, the body must wrap the subscription in a webhook object:

{ "webhook": { "topic": "products/create", "address": "https://your-app.example.com/webhook/products-create" } }

Create, query, update, and delete subscriptions with the full Webhook API. Each subscription object (id, topic, address, format, created_at, updated_at) is documented there.

How it works

Delivery format

When an event fires, Shoplazza sends an HTTP POST with a JSON body and a set of headers.

Request headers

HeaderDescriptionExample
X-Shoplazza-TopicThe event that triggered this delivery.orders/create
X-Shoplazza-Hmac-Sha256Base64-encoded HMAC-SHA256 signature of the request body, keyed by your app's Client Secret.
X-Shoplazza-Shop-DomainDomain of the store that generated the event.example.myshoplaza.com
X-Shoplazza-Api-VersionAPI version used to serialize the payload.2025-06
X-Shoplazza-Deduplication-IDDeduplication ID for this delivery; unchanged across retries of the same event.

Request body

The body is the resource payload for the topic. For example, products/update:

{
"product": {
"id": "325431fd-102b-4374-9769-2b3c171f28e8",
"title": "ICOICE Ocean Green | 1 Year",
"vendor": "ICOICE",
"published": true,
"inventory_quantity": 78386,
"created_at": "2023-08-10T06:58:08Z",
"updated_at": "2026-06-22T10:54:12Z"
// ...more fields: handle, tags, image, images, options, variants
}
}

See the products/update event page for the full payload structure.

Delivery rules

  • Timeout: Your endpoint must return a 2xx status within 5 seconds.
  • Success: Any 2xx status is treated as success.
  • Retry: Only a 5xx response triggers a retry. In production, a failed delivery is retried up to ~11 times over ~24 hours with growing intervals: 1m, 1m, 5m, 10m, 30m, 1h, 2h, then every 4h.
  • Exhausted: After retries are exhausted, the delivery is dropped. The subscription is not removed.
  • Duplicates: The same event may arrive more than once. Make your handler idempotent — for example, skip an event whose X-Shoplazza-Deduplication-ID you have already processed.
warning

Timeouts and connection failures are not retried — only an explicit 5xx response is. Return 2xx quickly and process the event asynchronously, so a slow handler doesn't cause you to miss events.

Verify the signature

After receiving a POST request delivered by Shoplazza, your app must verify the signature before trusting the payload.

Every webhook request carries a base64-encoded X-Shoplazza-Hmac-Sha256 header, generated by running HMAC-SHA256 over the raw request body with your app's Client Secret and base64-encoding the result. To verify, compute the same value and compare it against the header using a time-safe comparison; a match means the payload is trustworthy. Verify before your app responds to the webhook.

note

The difference from the OAuth callback (Scenario 1): Webhook signs the raw body and outputs base64; OAuth signs the sorted query string and outputs hex.

For algorithm steps and multi-language code (Ruby, Node.js), see HMAC Signature Verification · Scenario 2.