Skip to content

Webhook Events

Receive real-time notifications when events occur in Contio MeetingOS.

Full Reference

For complete event schemas and field documentation, see the Webhook Events Reference.

Webhook Management

To manage webhook delivery status and event filtering, see Webhook Management.

Overview

Webhooks allow your application to receive push notifications for key events:

Event Type Description
workflow.assignment.created Action item assigned to your workflow
action_item.created New action item created
action_item.updated Action item status changed
action_item.completed Action item marked as completed
meeting.created New meeting created
meeting.updated Meeting properties changed
meeting.completed Meeting processing completed, notes available
calendar_event.created Calendar event synced from external calendar
calendar_event.updated Calendar event updated in external calendar
calendar_event.deleted Calendar event deleted from external calendar
agenda_item.created Agenda item created in a meeting
agenda_item.updated Agenda item updated
agenda_item.deleted Agenda item deleted
participant.added Participant(s) added to a meeting
participant.removed Participant removed from a meeting
user.connection.revoked User disconnected from your app

Quick Start

1. Configure Webhook URL

Set your webhook URL when creating a workflow:

const workflow = await admin.createWorkflow({
  name: 'CRM Integration',
  webhook_url: 'https://your-app.com/webhooks/contio',
  matching_rules: { keywords: ['follow-up', 'sales'] },
  is_active: true
});

2. Implement Webhook Handler

import express from 'express';
import { WebhookVerifier } from '@contio/partner-sdk';

const app = express();
const verifier = new WebhookVerifier(process.env.WEBHOOK_SECRET!);

app.post('/webhooks/contio',
  express.raw({ type: 'application/json' }),
  (req, res) => {
    const signature = req.headers['x-contio-signature'] as string;
    const timestamp = req.headers['x-contio-timestamp'] as string;

    if (!verifier.verifySignature(req.body, signature, timestamp).isValid) {
      return res.status(401).json({ error: 'Invalid signature' });
    }

    const event = JSON.parse(req.body.toString());
    processWebhookAsync(event); // Process async, respond fast

    res.status(200).json({ received: true });
});

Event Payload Structure

All events follow a consistent envelope:

{
  "event_type": "workflow.assignment.created",
  "event_id": "evt-uuid",
  "timestamp": "2025-01-15T10:30:00Z",
  "partner_app_id": "app-uuid",
  "data": { /* event-specific payload */ }
}

Minimal Payloads

Webhook payloads are intentionally minimal (IDs + key state). Use the Partner API to fetch full details when needed.

Signature Verification

All webhooks include a signature for security:

Header Description
X-Contio-Signature HMAC-SHA256 signature
X-Contio-Timestamp Unix timestamp of signature

Manual Verification

import crypto from 'crypto';

function verifyWebhook(
  payload: Buffer,
  signature: string,
  timestamp: string,
  secret: string
): boolean {
  const signedPayload = `${timestamp}.${payload.toString()}`;
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(signedPayload)
    .digest('hex');

  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expectedSignature)
  );
}

Delivery & Retries

  • Timeout: 30 seconds
  • Retries: 3 attempts with exponential backoff
  • Retry intervals: 1 min, 5 min, 30 min

Retry Failed Deliveries

// List failed deliveries
const deliveries = await admin.getWebhookDeliveries({
  status: 'failed'
});

// Retry a specific delivery
await admin.retryWebhookDelivery(deliveryId);

Best Practices

  1. Respond quickly - Return 200 within 5 seconds, process async
  2. Verify signatures - Always validate webhook authenticity
  3. Handle duplicates - Use event_id for idempotency
  4. Monitor failures - Check delivery status regularly