Skip to content

Bug: rescheduledToUid Is null in BOOKING_CANCELLED Webhook When Triggered via "Request Reschedule" #28543

@Amitverma0509

Description

@Amitverma0509

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

  1. Go to Settings → Webhooks and create a new webhook pointing to a receiver such as [webhook.site](https://webhook.site).
  2. Set the trigger to BOOKING_CANCELLED.
  3. Create a confirmed booking on any event type (book as an attendee, then confirm as host if needed).
  4. As the host, go to Bookings → find the confirmed booking → click the "Request Reschedule" button.
  5. Enter a reschedule reason and submit.
  6. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    🐛 bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions