01Subscribe
In Supplier Admin or Retailer Admin, open Developers and add the HTTPS endpoint and events. Save the whsec_ signing secret when it appears; it is shown once. The same page lists deliveries and sends a test.
02Events
| Event | For | When |
|---|---|---|
stock.updated | Retailers | A stock row changed; stockId and updatedAt. |
stock.updated.v2 | Retailers | The same change, with tier, provenance and observation time. |
stock.confirmed | Retailers | A person confirmed stock without changing it. |
lead.created | Brands | A shopper reserved a product. |
import.completed | Brands | An import reached a terminal outcome. |
Payloads carry identifiers and times, not personal data. Read details through the API. Stock updates deliver the latest state; confirmations are not collapsed.
03Check the signature
Read X-Stockisto-Event, X-Stockisto-Delivery-Id and X-Stockisto-Signature. The signature header is t=<unixSeconds>,v1=<hexHmac>. Verify HMAC-SHA256 over the timestamp, a full stop and the raw request body. Never reserialize parsed JSON.
Accept any matching v1 during rotation, ignore unknown tags, and reject timestamps more than 5 minutes away. Pass the unmodified body as a Buffer or UTF-8 string to this Node.js function. Return 2xx only after accepting the event; deduplicate by delivery id.
X-Stockisto-Event: lead.created
X-Stockisto-Delivery-Id: DELIVERY_ID
X-Stockisto-Signature: t=1791374400,v1=SIGNATURE
const crypto = require("node:crypto");
function verify(header, rawBody, secret) {
const pairs = String(header)
.split(",")
.map((p) => p.trim().split("="));
const timestamps = pairs.filter(([k]) => k === "t");
if (timestamps.length !== 1) return false;
const t = timestamps[0][1];
if (!/^\d+$/.test(t) || Math.abs(Date.now() / 1000 - Number(t)) > 300)
return false;
const want = crypto
.createHmac("sha256", secret)
.update(t + ".")
.update(rawBody)
.digest();
return pairs.some(
([k, v]) =>
k === "v1" &&
/^[0-9a-f]{64}$/.test(v) &&
crypto.timingSafeEqual(Buffer.from(v, "hex"), want),
);
}
04Retries
A delivery gets up to 5 attempts, with retries after 1, 5, 30 and 120 minutes. Inspect the delivery log in Developers. A blocked endpoint can fail without further attempts.
05Rotate the secret
- Choose Rotate and save the new secret and the old secret’s retirement time.
- Both secrets sign each delivery for 7 days. Deploy the new secret during that overlap.
- After 7 days, only the new secret signs. A new signature scheme adds a tag such as
v2; the old scheme stays for at least 90 days.