Creating a webhook subscription
To create a new webhook subscription, visit/settings/developer/webhooks and proceed to enter the following details:
Subscriber URL
- Cal.com SaaS: Only HTTPS URLs are accepted. HTTP, private/internal IP addresses (e.g.,
10.x.x.x,192.168.x.x,127.0.0.1), andlocalhostare blocked. - Self-hosted: Both HTTP and HTTPS URLs are accepted, and private IP addresses are allowed for internal webhooks.
- All environments: Cloud metadata endpoints (e.g.,
169.254.169.254) and non-HTTP protocols (e.g.,ftp://,file://) are always blocked.
Event triggers
Booking CancelledBooking CreatedBooking RescheduledBooking RejectedBooking RequestedBooking Payment InitiatedBooking PaidMeeting StartedRecording ReadyForm SubmittedMeeting EndedInstant Meeting CreatedInstant Meeting AcceptedBooking No-show UpdatedBooking Location UpdatedAfter Hosts Didn't Join Cal VideoAfter Guests Didn't Join Cal VideoWrong Assignment ReportDelegation Credential ErrorDelegation Credential Secret RotatedDelegation Credential Secret Rotation FailedDelegation Credential Rotation Required
Secret
Custom Payload
Webhook payload reference
Most webhook payloads are wrapped in the following structure:MEETING_STARTED and MEETING_ENDED are exceptions — they use a flat payload where booking fields are at the top level alongside triggerEvent, with no payload wrapper. See meeting started and meeting ended webhooks for details.attendees array in webhook payloads contains only the attendee associated with the specific seat that triggered the webhook. For example, when a new seat is booked, the webhook includes only that seat’s attendee — not all attendees across the entire booking. This applies to all booking-related triggers (BOOKING_CREATED, BOOKING_CANCELLED, BOOKING_RESCHEDULED, etc.).- 2021-10-20
BOOKING_CREATED
BOOKING_CREATED
BOOKING_CANCELLED
BOOKING_CANCELLED
BOOKING_RESCHEDULED
BOOKING_RESCHEDULED
BOOKING_REQUESTED
BOOKING_REQUESTED
BOOKING_REJECTED
BOOKING_REJECTED
BOOKING_PAID
BOOKING_PAID
BOOKING_PAYMENT_INITIATED
BOOKING_PAYMENT_INITIATED
BOOKING_NO_SHOW_UPDATED
BOOKING_NO_SHOW_UPDATED
BOOKING_LOCATION_UPDATED
BOOKING_LOCATION_UPDATED
previousLocation holds the location before the change and existing location holds the new location.MEETING_STARTED
MEETING_STARTED
MEETING_STARTED uses a flat payload structure — booking fields are at the top level, not nested inside a payload object. This webhook fires automatically at the booking’s scheduled start time. See meeting started and meeting ended webhooks for details.MEETING_ENDED
MEETING_ENDED
MEETING_ENDED uses a flat payload structure — booking fields are at the top level, not nested inside a payload object. This webhook fires automatically at the booking’s scheduled end time. See meeting started and meeting ended webhooks for details.RECORDING_READY
RECORDING_READY
RECORDING_TRANSCRIPTION_GENERATED
RECORDING_TRANSCRIPTION_GENERATED
INSTANT_MEETING
INSTANT_MEETING
INSTANT_MEETING_ACCEPTED
INSTANT_MEETING_ACCEPTED
OOO_CREATED
OOO_CREATED
toUser is the redirect/forwarding user and can be null if no redirect is set.FORM_SUBMITTED
FORM_SUBMITTED
name, email, department) are duplicated for backward compatibility. The value field in responses is deprecated; use response instead. For select/multiselect fields, response includes both the label and ID.FORM_SUBMITTED_NO_EVENT
FORM_SUBMITTED_NO_EVENT
FORM_SUBMITTED. Triggered 15 minutes after form submission if no booking was made from the routing form.AFTER_HOSTS_CAL_VIDEO_NO_SHOW
AFTER_HOSTS_CAL_VIDEO_NO_SHOW
AFTER_GUESTS_CAL_VIDEO_NO_SHOW
AFTER_GUESTS_CAL_VIDEO_NO_SHOW
DELEGATION_CREDENTIAL_ERROR
DELEGATION_CREDENTIAL_ERROR
DELEGATION_CREDENTIAL_SECRET_ROTATED
DELEGATION_CREDENTIAL_SECRET_ROTATED
DELEGATION_CREDENTIAL_SECRET_ROTATION_FAILED
DELEGATION_CREDENTIAL_SECRET_ROTATION_FAILED
secretRotationBlocked=true). Transient failures before that 48-hour terminal window are retried automatically and do not fire a webhook. error.code is SECRET_MINT_FAILED when minting the replacement secret failed, or SECRET_PROMOTION_FAILED when a minted pending secret could not be verified with the workspace platform.DELEGATION_CREDENTIAL_ROTATION_REQUIRED
DELEGATION_CREDENTIAL_ROTATION_REQUIRED
optOutAutoSecretRotation=true) whose active secret is approaching expiry — it is a manual-rotation reminder, not a signal that automatic rotation failed or was blocked. Terminal automatic-rotation failures (including an abandoned pending secret) fire DELEGATION_CREDENTIAL_SECRET_ROTATION_FAILED instead. Rotate the secret manually from the delegation credential settings when you receive this event.WRONG_ASSIGNMENT_REPORT
WRONG_ASSIGNMENT_REPORT
Booking No-show Updated webhook payload
This webhook is triggered when an attendee is manually marked or unmarked as no-show on the/bookings/past page.
Example payload when marking an attendee as no-show:
Cal Video No-Show Detection webhooks
These webhooks are triggered automatically when hosts or guests don’t join a Cal Video meeting within the configured time after the booking starts. UnlikeBOOKING_NO_SHOW_UPDATED which requires manual action, these are detected automatically by checking Cal Video participant data.
Example payload when host didn't join (AFTER_HOSTS_CAL_VIDEO_NO_SHOW):
Example payload when guest didn't join (AFTER_GUESTS_CAL_VIDEO_NO_SHOW):
Meeting started and meeting ended webhooks
TheMEETING_STARTED and MEETING_ENDED webhooks are time-delayed — they fire automatically at the booking’s scheduled start time and end time, respectively. You do not need to take any action to trigger them beyond subscribing to these events.
Key behaviors:
- Automatic scheduling: When a booking is confirmed, Cal.com schedules the
MEETING_STARTEDwebhook to fire at the booking’sstartTimeand theMEETING_ENDEDwebhook to fire at the booking’sendTime. - Cancellation handling: If a booking is cancelled or rescheduled, any pending
MEETING_STARTEDandMEETING_ENDEDwebhooks for that booking are automatically cancelled. When a booking is rescheduled, new webhooks are scheduled for the updated times. - Flat payload format: Unlike other webhook events, these two events use a flat payload structure. The booking data is spread at the top level alongside
triggerEvent, rather than nested inside apayloadobject. See the example payloads for the exact structure. - No custom payload template support: Custom payload templates are not applied to
MEETING_STARTEDandMEETING_ENDEDwebhooks. The payload is always sent as raw JSON.
MEETING_STARTED and MEETING_ENDED differs from events like BOOKING_CREATED. Ensure your webhook handler accounts for the flat structure.Delegation credential secret rotation webhooks
Delegation credentials let an organization act on behalf of its members with a workspace platform. Microsoft 365 (Azure Entra ID) delegation credentials authenticate with a client secret that expires, so Cal.com periodically rotates it and emits webhooks so administrators can track rotation health. Google delegation credentials don’t have an expiring secret and are not part of this rotation lifecycle. Subscribe to these events on an organization-scoped webhook to be notified about the delegation credential rotation lifecycle:DELEGATION_CREDENTIAL_SECRET_ROTATED— a pending secret was verified and promoted, and is now active.DELEGATION_CREDENTIAL_SECRET_ROTATION_FAILED— an automatic mint or promotion attempt has kept failing for 48+ hours and rotation is now blocked for that credential (error.codeisSECRET_MINT_FAILEDorSECRET_PROMOTION_FAILED). Transient failures before that terminal window are retried automatically and do not fire a webhook.DELEGATION_CREDENTIAL_ROTATION_REQUIRED— a reminder for credentials that opted out of automatic rotation (optOutAutoSecretRotation=true) whose active secret is nearing expiry. This event does not indicate that automatic rotation failed or was blocked — seeDELEGATION_CREDENTIAL_SECRET_ROTATION_FAILEDfor that. In both cases, an administrator must rotate the secret manually from the delegation credential settings.
DELEGATION_CREDENTIAL_SECRET_ROTATED and DELEGATION_CREDENTIAL_SECRET_ROTATION_FAILED fire only for delegation credentials with automatic secret rotation enabled. DELEGATION_CREDENTIAL_ROTATION_REQUIRED fires only for delegation credentials that have opted out of automatic secret rotation. They are delivered asynchronously with retries on transient network errors and HTTP 408, 429, and 5xx responses.Verifying the authenticity of the received payload
Add a new secret key to your webhook
Wait for the webhook to be triggered
Create an HMAC using the secret key
Verify the payload authenticity
(x-cal-signature-256) with the one you created using the secret key and the body of the payload. If they don’t match, the received payload has been adulterated and cannot be trusted.Adding a custom payload template
Customizable webhooks are a great way reduce the development effort and in many cases remove the need for a developer to build an additional integration service. An example of a custom payload template is provided here:{{type}} represents the event type slug and {{title}} represents the title of the event type. Note that the variables should be added with a double parenthesis as shown above. Here’s a breakdown of the payload that you would receive via an incoming webhook, with an exhaustive list of all the supported variables provided below: