Gareth Wilson Gareth Wilson

Guide to SHOPLINE Webhooks: Features and Best Practices

Published


SHOPLINE webhooks notify your app about store activity: an order is created, a product updates, a collection changes. If you're building on the SHOPLINE Open Platform, webhooks are how you react to store events without polling. If you've integrated Shopify, this will feel familiar, SHOPLINE's webhook model is a close clone.

This guide covers how SHOPLINE webhooks work, the topics you'll subscribe to, how to verify the X-Shopline-Hmac-Sha256 header, the retry behavior, and the best practices for production.

What are SHOPLINE webhooks?

SHOPLINE Open Platform (developer.shopline.com) webhooks are HTTP POSTs delivered to a URL you subscribe per topic. They're signed with an HMAC-SHA256 of the raw body, keyed with your app secret, in the X-Shopline-Hmac-Sha256 header, Shopify-style. Companion headers identify the topic and shop.

SHOPLINE webhook features

FeatureDetails
ConfigurationAdmin REST API: POST https://{handle}.myshopline.com/admin/openapi/{version}/webhooks.json (body must include api_version)
Signature headerX-Shopline-Hmac-Sha256
Signature schemeHMAC-SHA256 of the raw body, keyed with the app secret
Encodinglowercase hex (verified against real deliveries)
Other headersX-Shopline-Topic, X-Shopline-Shop-Domain, X-Shopline-Shop-Id, X-Shopline-Webhook-Id (stable across resends)
TopicsShopify-style slash format (orders/create)
Acknowledgement5-second timeout
RetriesUp to 19 over 48h, then the subscription is auto-removed
SDKNone published

Common topics

SHOPLINE topics use the Shopify-style slash format:

TopicFires when
orders/createAn order is created
orders/updatedAn order updates
products/createA product is created
products/updateA product updates
collect/deleteA collect is deleted

Subscribe to the topics you process, and consult SHOPLINE's webhook reference for the full list.

Setting up SHOPLINE webhooks

Subscribe via the Admin REST API: POST https://{handle}.myshopline.com/admin/openapi/{version}/webhooks.json with { topic, address, api_version }. Your app secret (Developer Center > App credentials) is the HMAC key.

api_version is required in the body. Omit it and the request fails with a 400, even though the URL already contains a version segment. Include api_version explicitly in the JSON payload.

Securing SHOPLINE webhooks

Each delivery carries an X-Shopline-Hmac-Sha256 header: a lowercase-hex HMAC-SHA256 of the raw request body, keyed with your app secret. Verify against the raw, un-parsed body and compare in constant time. (Despite the Shopify-style header name, SHOPLINE uses hex, not base64, confirmed against real deliveries.)

const crypto = require("crypto");

const APP_SECRET = process.env.SHOPLINE_APP_SECRET;

function verify(rawBody, signature) {
  const expected = crypto.createHmac("sha256", APP_SECRET).update(rawBody).digest("hex");
  const a = Buffer.from(expected);
  const b = Buffer.from(signature || "");
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}

app.post("/webhook", express.raw({ type: "application/json" }), (req, res) => {
  if (!verify(req.body, req.headers["x-shopline-hmac-sha256"])) {
    return res.sendStatus(401);
  }

  res.sendStatus(200); // acknowledge within 5s
  processQueue.add({
    topic: req.headers["x-shopline-topic"],
    body: JSON.parse(req.body),
  });
});

The same check in Python:

import hashlib
import hmac
import os

APP_SECRET = os.environ["SHOPLINE_APP_SECRET"].encode()


def verify(raw_body: bytes, signature: str) -> bool:
    expected = hmac.new(APP_SECRET, raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, signature or "")

SHOPLINE webhook limitations and pain points

api_version is required on creation

The Problem: POST /webhooks.json returns a 400 if the request body doesn't include api_version, even though the URL path already carries a version segment. The failure isn't obviously about the missing field, so it's easy to lose time on it.

Why It Happens: SHOPLINE validates api_version from the body, not the URL, on webhook creation.

Workarounds:

  • Always include api_version in the JSON body (alongside topic and address).

How Hookdeck Can Help: Once created, point the webhook address at Hookdeck for verification, queuing, and retries, so the one-time creation quirk is behind you and delivery is reliable from then on.

Two developer platforms

The Problem: SHOPLINE has a newer Open Platform (developer.shopline.com) and an older one (open-api.docs.shoplineapp.com). Following the wrong docs leads to wrong headers or endpoints.

Why It Happens: SHOPLINE runs two developer platforms.

Workarounds:

  • Use the newer Open Platform (the one this guide and the source align with).

How Hookdeck Can Help: Hookdeck's filters and normalization insulate your app from platform differences.

The 5-second timeout and auto-removal

The Problem: You must respond within 5 seconds, and after up to 19 retries over 48 hours the subscription is auto-removed, so a sustained outage loses the subscription entirely.

Why It Happens: SHOPLINE caps the ack time and prunes failing subscriptions.

Workarounds:

  • Acknowledge fast, process off a queue, and monitor/recreate a removed subscription; dedupe on X-Shopline-Webhook-Id (stable across resends).

How Hookdeck Can Help: Hookdeck acknowledges within the window, deduplicates on the webhook id, and retries to your downstream on its own schedule, so the subscription stays alive. See our guide to webhook idempotency.

Raw-body handling

The Problem: The signature is over the raw body, so a JSON parser upstream breaks verification.

Why It Happens: The signed content is the exact bytes.

Workarounds:

  • Capture the raw body before parsing.

How Hookdeck Can Help: Hookdeck verifies against the bytes as received.

Best practices

Include api_version when creating webhooks

Put api_version in the POST /webhooks.json body, or creation fails with a 400.

Verify the lowercase-hex signature over the raw body

Compute a lowercase-hex HMAC-SHA256 over the raw body with the app secret and compare in constant time.

Acknowledge within 5 seconds, process asynchronously

Return 200 quickly and defer work to a queue. See why to process webhooks asynchronously.

Dedupe on the webhook id

Use X-Shopline-Webhook-Id (stable across resends) as an idempotency key.

Use the newer Open Platform

Follow developer.shopline.com for headers, topics, and the subscribe endpoint.

Make SHOPLINE webhooks production-ready

Hookdeck verifies X-Shopline-Hmac-Sha256, deduplicates, and durably queues every store event

Conclusion

SHOPLINE webhooks are a Shopify-style clone, with two things the docs get wrong or gloss over: the X-Shopline-Hmac-Sha256 signature is lowercase hex (not base64), and webhook creation requires api_version in the body or it 400s. Verify the hex HMAC over the raw body, use the slash-format topics, acknowledge within 5 seconds, and dedupe on the webhook id to survive the 48-hour retry window and auto-removal.

Hookdeck verifies the signature, deduplicates, and durably queues every event at the edge, so your app only ever processes verified, unique store events.

Get started with Hookdeck for free and handle SHOPLINE webhooks reliably in minutes.


Gareth Wilson

Gareth Wilson

Product Marketing

Multi-time founding marketer, Gareth is PMM at Hookdeck and author of the newsletter, Community Inc.