APPSOCOMDocs

Webhooks

Appsocom Live can tell your backend when rooms start and end, and when people join and leave. Set your webhook URL on the project page in the console, or with the API.

Events

Event When
room_started the first person joined
room_finished the room ended: reason is empty (2 minutes after the last person left) or closed (DELETE /rooms/:roomId)
participant_joined someone joined
participant_left someone left: reason is left, kicked or token-expired
track_published someone turned on their mic, camera or screen share
track_unpublished they turned it off
webhook_test you pressed "Send test event"

Each delivery is a POST with a JSON body:

json
{
  "id": "6f1c…",
  "event": "participant_joined",
  "tenant": "pch8a9p0z11a",
  "roomId": "class-1",
  "createdAt": 1763000000000,
  "seq": 2,
  "participant": { "id": "…", "userId": "u_7", "name": "Ada", "role": "student", "metadata": { "team": "blue" } }
}

track_* events add "track": { "kind": "video", "trackName": "…" }. tenant is your project ID.

Verify the signature

Every delivery is signed with your project's webhook secret (whsec_…, shown in the console). The X-SfuKit-Signature header is t=<unix time>,v1=<hex>, where v1 is HMAC-SHA256 of "<t>.<raw body>". Check it before trusting the body:

ts
import { verifyWebhook } from "@appsocom/node";

app.post("/appsocom-webhook", express.raw({ type: "application/json" }), (req, res) => {
  const event = verifyWebhook(process.env.APPSOCOM_WEBHOOK_SECRET!, req.body, req.get("x-sfukit-signature"));
  if (!event) return res.status(401).end();
  // handle event.event …
  res.status(204).end();
});

The Python, PHP, Dart and Go SDKs have the same check (verify_webhook, Webhooks::verify, verifyWebhook, sfukit.VerifyWebhook). Use the raw body, before any JSON parsing.

Retries and order

  • Answer with any 2xx within 10 seconds. Anything else is retried with backoff (10 s, 20 s, 40 s… up to an hour, 10 attempts).
  • A retry repeats the same id, so ignore ids you've already handled.
  • Deliveries can arrive out of order. seq counts up within each room session.

Manage it with the API

bash
curl -X PUT https://api.appsocom.dev/webhook -H "Authorization: Bearer $APPSOCOM_API_KEY" \
  -H "Content-Type: application/json" -d '{"url":"https://your-app.example/appsocom-webhook"}'
# → {"url":"https://your-app.example/appsocom-webhook","secret":"whsec_…"}   ({"url":null} turns it off)

curl https://api.appsocom.dev/webhook -H "Authorization: Bearer $APPSOCOM_API_KEY"                         # URL and secret
curl -X POST https://api.appsocom.dev/webhook/rotate-secret -H "Authorization: Bearer $APPSOCOM_API_KEY"   # new secret, used at once
curl -X POST https://api.appsocom.dev/webhook/test -H "Authorization: Bearer $APPSOCOM_API_KEY"            # → {"delivered":true,"status":200}

The URL must use https://.