LevelChatDocs
Docs
Webhooks

Webhooks

Reliable, signed event delivery.

LevelChat delivers events as outbound HTTPS POSTs. Receivers must be idempotent — we deliver at-least-once and retry on backoff: 0s, 30s, 1m, 5m, 15m, 1h, 6h, 24h then dead-letter.

Register an endpoint

~
curl -X POST $LC_API_URL/v1/webhooks \
  -H "Authorization: Bearer lc_pk_xxx.yyy" \
  -d '{
    "url": "https://your-app.example/lc-events",
    "events": ["room.ended","recording.ready","qos.alert"]
  }'

The response includes a one-time-readable secret you'll use to verify the HMAC signature.

Verify a delivery

TypeScript
import { createHmac, timingSafeEqual } from 'node:crypto';

export function verify(req: Request, secret: string): boolean {
  const sig = req.headers.get('x-levelchat-signature'); // "sha256=..."
  const ts = req.headers.get('x-levelchat-timestamp');
  if (!sig || !ts) return false;
  const expected = createHmac('sha256', secret).update(`${ts}.${req.body}`).digest('hex');
  const got = sig.replace(/^sha256=/, '');
  return timingSafeEqual(Buffer.from(expected), Buffer.from(got));
}

Reject anything older than 5 minutes — replay protection is your responsibility.

Event catalog

The full list lives in the API reference. The high-traffic ones:

EventWhenUse it for
room.endedLast participant left or host endedBilling rollups, ticket close
recording.readyCompression + HLS doneEmail notification, CDN mirror
participant.leftPer-participant disconnectAttendance, session reconciliation
qos.alertLoss storm / low bitrate / high RTTPager, customer support tooling
license.revokedOn-prem license invalidatedForce-stop on tenants you've offboarded

Headers

text
X-LevelChat-Webhook-Id:   wh_01HF...
X-LevelChat-Event:        room.ended
X-LevelChat-Delivery:     d_01HF...
X-LevelChat-Timestamp:    1735000000000
X-LevelChat-Signature:    sha256=...

Dedupe on X-LevelChat-Webhook-Id. The same event can be delivered more than once if your endpoint fails a previous attempt.