Issue Summary
When a host clicks "Request Reschedule" on a confirmed booking, Cal.com cancels the original booking and fires a BOOKING_CANCELLED webhook. The rescheduledToUid field in that webhook payload is always null — even though the cancellation was clearly triggered by a reschedule request, not a permanent cancellation by choice.
This is directly inconsistent with the attendee-initiated reschedule flow, where rescheduledToUid is correctly populated with the new booking's UID. Because there is no reliable field in the payload to distinguish a "host-requested reschedule" from a true cancellation, webhook consumers — Zapier workflows, Make automations, n8n pipelines, CRM integrations, payment processors — have no way to react correctly. They treat every host reschedule request as a permanent cancellation, causing wrong refunds, wrong CRM status updates, and broken downstream automations.
Steps to Reproduce
- Go to Settings → Webhooks and create a new webhook pointing to a receiver such as [webhook.site](https://webhook.site).
- Set the trigger to
BOOKING_CANCELLED.
- Create a confirmed booking on any event type (book as an attendee, then confirm as host if needed).
- As the host, go to Bookings → find the confirmed booking → click the "Request Reschedule" button.
- Enter a reschedule reason and submit.
- Open your webhook receiver and inspect the payload delivered to it.
Actual Results
- The
BOOKING_CANCELLED webhook fires with rescheduledToUid: null.
- The payload looks identical to a genuine permanent cancellation — there is no field indicating the booking was cancelled as part of a reschedule request:
{
"triggerEvent": "BOOKING_CANCELLED",
"payload": {
"uid": "original-booking-uid-abc123",
"status": "CANCELLED",
"rescheduledToUid": null,
"cancellationReason": "Reschedule requested"
}
}
- Any automation listening on
BOOKING_CANCELLED treats this as a final cancellation — triggering refunds, CRM updates, or notification flows incorrectly.
Expected Results
- The
BOOKING_CANCELLED webhook triggered by "Request Reschedule" should be distinguishable from a genuine cancellation.
- At minimum, a dedicated boolean field like
"rescheduleRequested": true should be included in the payload when the cancellation originates from a host reschedule request:
{
"triggerEvent": "BOOKING_CANCELLED",
"payload": {
"uid": "original-booking-uid-abc123",
"status": "CANCELLED",
"rescheduledToUid": null,
"rescheduleRequested": true,
"cancellationReason": "Reschedule requested by host"
}
}
- Alternatively, a new dedicated trigger
BOOKING_RESCHEDULE_REQUESTED could be introduced to fire specifically in this scenario, keeping BOOKING_CANCELLED reserved for true cancellations.
- This would allow integrations to branch their logic correctly and not misfire on reschedule requests.
Technical Details
- Affected surface: Webhooks —
BOOKING_CANCELLED trigger
- Trigger path: Host clicks "Request Reschedule" → booking is marked
CANCELLED → webhook fires
- Relevant source files to investigate:
packages/features/bookings/lib/handleCancelBooking.ts — handles the cancellation and fires the webhook; does not set any reschedule-request indicator in the payload
packages/features/webhooks/lib/sendPayload.ts — constructs and dispatches the webhook payload
packages/prisma/zod-utils.ts — defines the webhook payload schema
- Why
rescheduledToUid is null by design (but still a bug): The "Request Reschedule" flow is intentionally two-step — step 1 cancels the original booking and emails the attendee, step 2 is when the attendee picks a new time. There is no new booking UID at step 1. However, the absence of any indicator that this is step 1 of a reschedule — rather than a final cancellation — is what makes this a bug. Consumers have no way to know.
- Node.js version: Reproducible on Node.js 18.x and 20.x.
Evidence
Configured a BOOKING_CANCELLED webhook on an event type, created a confirmed booking, then triggered "Request Reschedule" as the host. The received payload showed rescheduledToUid: null with no other distinguishing field.
Then tested the attendee-initiated reschedule flow on the same event type. That webhook payload correctly contained rescheduledToUid populated with the new booking UID, confirming the inconsistency between the two flows.
Issue Summary
When a host clicks "Request Reschedule" on a confirmed booking, Cal.com cancels the original booking and fires a
BOOKING_CANCELLEDwebhook. TherescheduledToUidfield in that webhook payload is alwaysnull— even though the cancellation was clearly triggered by a reschedule request, not a permanent cancellation by choice.This is directly inconsistent with the attendee-initiated reschedule flow, where
rescheduledToUidis correctly populated with the new booking's UID. Because there is no reliable field in the payload to distinguish a "host-requested reschedule" from a true cancellation, webhook consumers — Zapier workflows, Make automations, n8n pipelines, CRM integrations, payment processors — have no way to react correctly. They treat every host reschedule request as a permanent cancellation, causing wrong refunds, wrong CRM status updates, and broken downstream automations.Steps to Reproduce
BOOKING_CANCELLED.Actual Results
BOOKING_CANCELLEDwebhook fires withrescheduledToUid: null.{ "triggerEvent": "BOOKING_CANCELLED", "payload": { "uid": "original-booking-uid-abc123", "status": "CANCELLED", "rescheduledToUid": null, "cancellationReason": "Reschedule requested" } }BOOKING_CANCELLEDtreats this as a final cancellation — triggering refunds, CRM updates, or notification flows incorrectly.Expected Results
BOOKING_CANCELLEDwebhook triggered by "Request Reschedule" should be distinguishable from a genuine cancellation."rescheduleRequested": trueshould be included in the payload when the cancellation originates from a host reschedule request:{ "triggerEvent": "BOOKING_CANCELLED", "payload": { "uid": "original-booking-uid-abc123", "status": "CANCELLED", "rescheduledToUid": null, "rescheduleRequested": true, "cancellationReason": "Reschedule requested by host" } }BOOKING_RESCHEDULE_REQUESTEDcould be introduced to fire specifically in this scenario, keepingBOOKING_CANCELLEDreserved for true cancellations.Technical Details
BOOKING_CANCELLEDtriggerCANCELLED→ webhook firespackages/features/bookings/lib/handleCancelBooking.ts— handles the cancellation and fires the webhook; does not set any reschedule-request indicator in the payloadpackages/features/webhooks/lib/sendPayload.ts— constructs and dispatches the webhook payloadpackages/prisma/zod-utils.ts— defines the webhook payload schemarescheduledToUidis null by design (but still a bug): The "Request Reschedule" flow is intentionally two-step — step 1 cancels the original booking and emails the attendee, step 2 is when the attendee picks a new time. There is no new booking UID at step 1. However, the absence of any indicator that this is step 1 of a reschedule — rather than a final cancellation — is what makes this a bug. Consumers have no way to know.Evidence
Configured a
BOOKING_CANCELLEDwebhook on an event type, created a confirmed booking, then triggered "Request Reschedule" as the host. The received payload showedrescheduledToUid: nullwith no other distinguishing field.Then tested the attendee-initiated reschedule flow on the same event type. That webhook payload correctly contained
rescheduledToUidpopulated with the new booking UID, confirming the inconsistency between the two flows.