Webhooks
Layout POSTs a signed event when an order you initiated changes state. Delivery is fire-and-forget with retry, and never delays or alters an order.
Subscribe
Add a subscription in the console with a notification URL and the events you care about. HTTPS only, and never a private or internal host. Your signing secret is on the Webhooks page.
Verify the signature
Every payload is signed HMAC-SHA256 over the timestamp and the raw body, in an X-Layout-Signature header. Verify it, and check the timestamp to bound replay, before trusting a payload.
import crypto from "node:crypto";
function verify(req, secret) {
const [t, sig] = req.headers["x-layout-signature"].split(",");
const ts = t.slice(2), signature = sig.slice(2);
const expected = crypto
.createHmac("sha256", secret)
.update(ts + "." + req.rawBody)
.digest("hex");
const fresh = Math.abs(Date.now() / 1000 - Number(ts)) < 300;
return fresh && crypto.timingSafeEqual(
Buffer.from(signature), Buffer.from(expected)
);
}
Delivery and retries
- Return
2xxquickly. Anything else is retried with exponential backoff, up to 5 attempts. - After the last attempt a delivery is dead-lettered; replay it from the delivery log.
- Deliveries can arrive out of order or more than once — key on the order id and the event, and make handlers idempotent.
Payload minimalism
Default payloads carry ids, state, and totals only. Card data never appears in a webhook. Richer cart detail is available behind an explicit data agreement.