Webhooks (outbound)
Get a signed HTTPS POST when a board publishes or a screen goes offline/online — the payload shape and how to verify signatures.
Settings → Developer → Webhooks adds an endpoint: a public https URL plus the events you want. Each endpoint gets a signing secret (whsec_…) shown once at creation — store it; we can't show it again. Webhooks are a Pro feature, alongside API access.
Events
- board.published — a publish (or rollback) cut a new live release. Data: boardId, releaseId, version, feedVersion.
- device.offline — a paired screen missed heartbeats for 5+ minutes. Data: deviceId, deviceName, boardName, lastSeenAt.
- device.online — a screen recovered. Data: deviceId, deviceName, boardName.
- ping — the test event from the dashboard's ping button.
Payload & signature
Every delivery POSTs JSON shaped {id, event, createdAt, data} with headers X-CanvasRelay-Event and X-CanvasRelay-Signature: sha256=<hex>. Verify by computing HMAC-SHA256 of the exact raw request body with your endpoint secret and comparing (timing-safe) to the signature.
import crypto from "node:crypto";
function verify(rawBody: string, signature: string, secret: string): boolean {
const expected = "sha256=" + crypto.createHmac("sha256", secret).update(rawBody).digest("hex");
const a = Buffer.from(expected);
const b = Buffer.from(signature);
return a.length === b.length && crypto.timingSafeEqual(a, b);
}Retries & limits
Your endpoint should answer any 2xx within 10 seconds. Failures retry on a backoff — about 1 minute, 5 minutes, 30 minutes, then 2 hours — and stop after 5 attempts. The dashboard shows each endpoint's last delivery status. Endpoints must be public https URLs; private hosts (localhost, .local, private IP ranges) are rejected.
Read next
