Webhooks

By setting up webhooks, you can receive automated notifications when events are scheduled, canceled, or modified, allowing you to build powerful integrations with your existing tools and workflows.

Webhooks can be configured for both an individual user as well as each team:

  • User: Receives events from all invite links for the individual user.

  • Team: Receives events only from that team's invite links (collective and round robin invites)

Setting up Webhooks

To set up webhooks for either an individual user or a team:

  1. Navigate to the integrations for your accout or for the team.

  2. Click "Connect" next to the webhooks integration.

  3. Configure the following:

    • Subscriber URL: The endpoint where webhook payloads will be sent

    • Secret Key (Optional): A key that allows you to verify incoming webhooks are genuinely from zcal. If provided, we'll attach an x-zcal-webhook-signature header to all webhook events containing a SHA256 hash of the payload signed with your secret key

  4. Click "Test Endpoint" to verify your configuration.

  5. Save your webhook settings

Webhook Payload

When an event occurs in the system (like a booking being created), we'll send a webhook notification to your endpoint. Each notification has a consistent structure that helps you process the data reliably.

Event Types

The webhook can be triggered by the following events:

Event Type
Description

event.created

Sent when a new booking is created

event.rescheduled

Sent when a booking is rescheduled

event.cancelled

Sent when a booking is cancelled

For detailed documentation about the webhook payload schema see this document:

Webhook Signatures (Optional)

Webhook signatures are optional but recommended for security. When enabled, each webhook request includes a signature in the x-zcal-webhook-signature header. The signature is generated using HMAC SHA-256.

Example Signature Verification (Node.js)

const crypto = require('crypto');

function verifyWebhookSignature(payload, signature, secret) {
    const expectedSignature = crypto
        .createHmac("sha256", secret)
        .update(JSON.stringify(payload))
        .digest("hex");
    
    return signature === expectedSignature;
}

Last updated