Help

Webhooks

Event types, the signed payload, and the retry behavior — including the fact that a 4xx is retried exactly like a 5xx.

Register an endpoint in Settings → Webhooks and pick the events you want. The URL must be https:// and must not resolve to a private or loopback address. The signing secret is shown once, at creation.

Events are grouped as device.* (online, offline, paired, unpaired), content.* (created, updated, deleted), schedule.* (activated, deactivated), billing.*, and webhook.dlq. Note that schedule.activated fires when a schedule is created and schedule.deactivated when one is deleted — toggling a schedule off sends nothing.

Every delivery carries this body, plus X-Webhook-Signature, X-Webhook-Event, X-Webhook-Timestamp and X-Webhook-Delivery-Id:

{"event":"content.updated","org_id":"…","emitted_at":"…","data":{…}}

The signature is HMAC-SHA-256, base64, over {X-Webhook-Timestamp}.{raw body}, keyed with your whsec_… secret. Verify it against the raw bytes — the body is re-serialized before sending, so a re-stringified parse will not match. Sheencast does not enforce a freshness window; reject old timestamps yourself.

Any 2xx means delivered and the body is ignored. Everything else is retried — and a 4xx is retried exactly like a 5xx, 12 times over roughly six hours (~1m, 2m, 4m, 8m, 16m, 32m, then hourly). There is no response code that means “stop sending this”; to stop, pause or delete the webhook. After the last attempt the payload moves to the dead-letter queue and a webhook.dlq event fires.

Delivery is at-least-once and unordered — several are in flight at once and retries jitter, so sequence by emitted_at and deduplicate on X-Webhook-Delivery-Id (not Idempotency-Key, which changes on every attempt).

Payload fields per event, and a verification snippet →

← Team & Roles  ·  API Keys →