Skip to contentSellstamp

Developers

Webhooks

Signed HTTP callbacks to your own server for order, payment, fulfilment, product, licensing, support and billing events.

Adding an endpoint

  1. Go to Settings → Webhooks and add an endpoint: a label, an HTTPS URL on a public address, the events you want, and either one store or the whole workspace.
  2. Copy the signing secret it shows you.
  3. Send yourself a test event from the same page to check your endpoint and your verification.

Verifying a request

x-sellstamp-signature is a hex HMAC-SHA256 of the raw request body, keyed with your secret. Hash the bytes you received, before any JSON parsing. A body that is parsed and re-serialised no longer matches, and this is the most common way webhook integrations fail.

import { createHmac, timingSafeEqual } from "node:crypto";

// rawBody: the exact bytes received, e.g. express.raw({ type: "*/*" })
export function verified(rawBody: Buffer, header: string, secret: string) {
  const expected = createHmac("sha256", secret).update(rawBody).digest();
  // One digest normally; "v1=<hex>,v1=<hex>" while a secret roll is in progress.
  return header.split(",").some((part) => {
    const got = Buffer.from(part.replace(/^v1=/, "").trim(), "hex");
    return got.length === expected.length && timingSafeEqual(got, expected);
  });
}

Headers and payload

x-sellstamp-signature
The HMAC above. There is no timestamp in it. The event's createdAt is in the signed body.
x-sellstamp-event
The event type, e.g. order.paid.
x-sellstamp-delivery
A stable delivery ID, equal to id in the body. Use it to ignore a retry of something you already processed.
Body
JSON: id, event, createdAt, and data with the object's type, id and shopId.

Rolling the secret

Roll it from the endpoint’s page. The old secret keeps working for 24 hours, and during that time the signature header carries both digests, newest first. You can end the overlap early.

Retries and failures

  • A failed delivery is retried, up to six attempts in total.
  • After an hour of failures, you get an email.
  • After a day of failures, the endpoint is switched off, and the dashboard says when and why. Events are kept, not replayed.
  • Any delivery in the history can be retried by hand.

Limits

Webhooks are on Growth and above. Only HTTPS to public addresses is accepted, with no custom headers and no mutual TLS: the signature is the authentication. For the full event list, see the webhooks page.