Webhooks Guide
Set up event-driven integrations that react to Synento session events.
Set up event-driven integrations that react to Synento session events.
Overview
Synento automatically emits webhook events for key lifecycle moments:
session.created— a new session is created via APIsession.started— the first participant joins a sessionsession.ended— all participants leave (last one departs)recording.ready— stream recording is fully persisted and replayableexport.completed— MP4 export finishes successfully
Setting Up a Webhook Receiver
1. Create the webhook endpoint on your server
// Example: Express.js handler
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
const signature = req.headers['x-synento-signature'] ?? '';
// Verify HMAC-SHA256 over the raw body, exactly as received
const crypto = require('crypto');
const expected = crypto.createHmac('sha256', YOUR_WEBHOOK_SECRET)
.update(req.body)
.digest('hex');
if (signature.length !== expected.length ||
!crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected))) {
return res.status(401).send('Invalid signature');
}
const payload = JSON.parse(req.body.toString());
// Dispatch based on event type
switch (payload.type) {
case 'session.created':
console.log('New session:', payload.session_id);
break;
case 'session.started':
console.log('Session started:', payload.session_id);
break;
case 'session.ended':
console.log('Session ended:', payload.session_id);
break;
case 'recording.ready':
console.log('Recording ready:', payload.session_id);
break;
case 'export.completed':
console.log('Export completed:', payload.session_id);
break;
}
res.status(200).send('OK');
});2. Register the webhook with Synento
curl -X POST https://api.synento.com/v1/webhooks \
-H "Authorization: Bearer sk_live_xxxxx" \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-server.com/webhook",
"events": ["session.created", "session.started", "session.ended"]
}'3. List your webhooks to verify
curl https://api.synento.com/v1/webhooks \
-H "Authorization: Bearer sk_live_xxxxx"Webhook Payload Structure
Each webhook event has the following structure:
{
"id": "<event-uuid>",
"type": "session.started",
"timestamp": "2025-01-01T12:00:00.000Z",
"project_id": "<project-uuid>",
"session_id": "<session-uuid>"
}Signature Verification
Every webhook includes an X-Synento-Signature header containing an HMAC-SHA256 digest of the raw request body, signed with your webhook's secret key.
Always verify this signature before processing — never trust the payload without verification.
The digest is lowercase hex. Compute it over the raw body bytes exactly as they arrived — not over JSON you have parsed and re-serialised, which will not match — and compare in constant time, as the receiver example above does.
Event Delivery & Retry
Synento delivers each webhook with the following reliability guarantees:
| Aspect | Detail |
|---|---|
| Delivery model | Best-effort POST to your endpoint |
| Timeout | 5 seconds per attempt (AbortController) |
| Retry | A failed delivery (network error, timeout or non-2xx) is retried by a background job with exponential backoff, about 2 then 4 minutes apart. Pending retries are stored durably and survive a server restart. |
| Delivery log | Every attempt is recorded; see the Webhooks page in the dashboard |
| Ordering | Events for the same session are generally ordered but not guaranteed |
Monitoring & Debugging
When testing locally:
- Use ngrok or similar to expose your localhost endpoint
- Register the public URL as the webhook target
- Create a session and check your local logs for incoming webhooks
Once verified, switch to a stable production URL.
Best Practices
- Always verify signatures — unverified webhooks could be spoofed
- Respond quickly (200 OK) — process the payload asynchronously; don't block on long operations
- Log all incoming events — use logs to audit and debug event flows
- Handle idempotency — if an event is delivered twice, your handler should handle it gracefully
- Use
session.started+session.ended— together they give you accurate session duration