8 min read
Jan 03, 2026

Webhooks

Receive real-time notifications when events occur in Pivot using webhooks.

Webhooks allow you to receive real-time notifications when events occur in Pivot. When an event happens, Pivot sends an HTTP POST request to your configured endpoint with details about the event.

Creating a Webhook

To create a webhook, send a POST request to the webhooks endpoint:

Terminal window
POST /v1/organizations/{organization_id}/webhooks
Authorization: Bearer your_api_key
Content-Type: application/json
{
"content": {
"name": "My Webhook",
"description": "Notifications for room messages",
"endpoint_url": "https://your-server.com/webhook",
"subscriptions": [
{
"subject_type": "WEBHOOK_SUBJECT_TYPE_ROOM",
"subject_id": "<room_uuid>",
"subscription_type": "WEBHOOK_SUBSCRIPTION_TYPE_MESSAGE_SENT",
"filter": {
"room_type": "chat"
}
}
]
}
}

The response includes the webhook details and a secret for signature verification:

{
"webhook": {
"id": "webhook-uuid",
"organization_id": "org-uuid",
"name": "My Webhook",
"endpoint_url": "https://your-server.com/webhook",
"status": "WEBHOOK_STATUS_ACTIVE",
"subscriptions": [...]
},
"secret": "your-webhook-secret"
}

Important: Store the secret securely. It cannot be retrieved again and is required to verify webhook signatures.

Event Types

MESSAGE_SENT

Triggered when a message is sent in a subscribed room.

Payload example:

{
"event_type": "message_sent",
"subject": {
"type": "room",
"id": "room-uuid"
},
"timestamp": "2026-01-01T12:00:00Z",
"data": {
"message_id": "msg-uuid",
"room_id": "room-uuid",
"user_id": "user-uuid",
"status": "SENT",
"created_at": "2026-01-01T12:00:00Z"
}
}

ROOM_RECORDING_TRANSCRIPT_PUBLISHED

Triggered when a room recording transcript is ready.

Payload example:

{
"event_type": "room_recording_transcript_published",
"subject": {
"type": "room",
"id": "room-uuid"
},
"timestamp": "2026-01-01T12:00:00Z",
"data": {
"recording_id": "recording-uuid",
"room_id": "room-uuid",
"created_at": "2026-01-01T12:00:00Z"
}
}

Subscription Subjects

Subscriptions define what entities trigger webhook notifications:

Subject TypeDescription
WEBHOOK_SUBJECT_TYPE_ROOMEvents for a specific room
WEBHOOK_SUBJECT_TYPE_SPACEEvents for all rooms in a space

Filters

Optionally filter events using the filter object:

{
"subject_type": "WEBHOOK_SUBJECT_TYPE_ROOM",
"subject_id": "room-uuid",
"subscription_type": "WEBHOOK_SUBSCRIPTION_TYPE_MESSAGE_SENT",
"filter": {
"room_type": "chat"
}
}

Available filter options:

  • room_type: Filter by room type (e.g., “chat”, “post”, “video”)

Verifying Webhook Signatures

All webhook payloads include security headers:

HeaderDescription
X-Pivot-SignatureHMAC-SHA256 signature of the payload
X-Pivot-EventThe event type (e.g., “message_sent”)
X-Pivot-DeliveryUnique delivery identifier

Verification Example (Node.js)

const crypto = require('crypto');
function verifySignature(payload, signature, secret) {
const expectedSignature =
'sha256=' +
crypto.createHmac('sha256', secret).update(payload).digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expectedSignature)
);
}
// Usage
app.post('/webhook', (req, res) => {
const signature = req.headers['x-pivot-signature'];
const isValid = verifySignature(
JSON.stringify(req.body),
signature,
process.env.WEBHOOK_SECRET
);
if (!isValid) {
return res.status(401).send('Invalid signature');
}
// Process the webhook
res.status(200).send('OK');
});

Managing Webhooks

List Webhooks

Terminal window
GET /v1/organizations/{organization_id}/webhooks

Update Webhook

Terminal window
PATCH /v1/organizations/{organization_id}/webhooks/{webhook_id}
{
"content": {
"name": "Updated Name",
"status": "WEBHOOK_STATUS_INACTIVE"
}
}

Delete Webhook

Terminal window
DELETE /v1/organizations/{organization_id}/webhooks/{webhook_id}

View Webhook Logs

Terminal window
GET /v1/organizations/{organization_id}/webhooks/{webhook_id}/logs

Logs are retained for 30 days and include delivery status, response codes, and retry counts.

Best Practices

  1. Respond quickly - Return a 2xx status code within 15 seconds
  2. Verify signatures - Always validate the webhook signature before processing
  3. Use HTTPS - Only use HTTPS endpoints for security
  4. Handle idempotency - Use the X-Pivot-Delivery header to detect duplicate deliveries
  5. Monitor logs - Check webhook logs regularly to debug issues

Retry Policy

Failed webhook deliveries are retried up to 5 times with exponential backoff:

RetryDelay
11 minute
25 minutes
330 minutes
42 hours
524 hours

After all retries are exhausted, organization admins receive an email notification about the failed webhook.

Automatic Pausing

To protect your system and ours, webhooks are automatically paused if they experience sustained failures:

  • Threshold: 10 consecutive event failures (across different events, not retries of the same event)
  • Time window: Failures must occur within a 3-day period
  • Status change: Webhook status changes from WEBHOOK_STATUS_ACTIVE to WEBHOOK_STATUS_PAUSED

When a webhook is paused:

  1. Organization admins receive an email notification explaining why the webhook was paused
  2. No further delivery attempts are made until the webhook is reactivated
  3. The failure counter has a 3-day expiration (TTL). After 3 days, the counter is automatically cleared, but the webhook remains paused — reactivation requires manual action by an organization admin (see below)

Reactivating a Paused Webhook

To reactivate a paused webhook, update its status to active:

Terminal window
PATCH /v1/organizations/{organization_id}/webhooks/{webhook_id}
{
"content": {
"status": "WEBHOOK_STATUS_ACTIVE"
}
}

Before reactivating, ensure your endpoint is functioning correctly to avoid the webhook being paused again.

Authorization

ActionRequired Role
List webhooksOrganization reader role
Create/Update/Delete webhooksOrganization admin or super_admin

When creating subscriptions, you must have admin access to the room’s space or the space itself.

Was this guide helpful?