Cal.com Sandbox

Concepts

Custom room assignments

Architecture pattern for assigning physical rooms to bookings — a webhook-driven service that runs your own room-scheduling logic and patches the booking location via the Cal.com API.

Cal.com
Patient books a slotCal.com booker — drop-in or custom UI.
triggerEvent: BOOKING_CREATED
Yours
Your webhook handlerPOST /api/webhooks/cal — receives booking payload.
Look up the right room
Yours
Internal room schedulerPicks a room from doctor, equipment, time, and current occupancy.
PATCH /v2/bookings/:uid/location
Cal.com
Cal.com booking updatedlocation: "Room 3B — Floor 2, North wing"
Confirmation email + calendar invite refreshed
Cal.com
Patient & doctor notifiedCal.com sends the room as part of its normal workflow.
Internal room boardyour scheduler — not Cal.com
Room 1AIn use
Floor 1 · until 10:30
Room 1BFree
Floor 1 · ready
Room 2ABlocked
Floor 2 · cleaning
Room 3BAssigned
Floor 2 · → booking #abc123
Room 3CFree
Floor 2 · ready
Room 4AIn use
Floor 3 · until 11:15
Room assignment webhookPOST /api/webhooks/cal
// Triggered by Cal.com whenever a patient confirms a slot
app.post("/api/webhooks/cal", async (req, res) => {
  const { triggerEvent, payload } = req.body;
  if (triggerEvent !== "BOOKING_CREATED") return res.json({ ok: true });

  // 1. Run your room scheduling logic
  const room = await pickRoom({
    doctorId: payload.organizer.id,
    startTime: payload.startTime,
    duration: payload.length,
    equipment: payload.metadata?.equipment,
  });
  // → { name: "3B", floor: 2, building: "North wing" }

  // 2. Push the assignment back to Cal.com
  await fetch(`https://api.cal.com/v2/bookings/${payload.uid}/location`, {
    method: "PATCH",
    headers: {
      "Authorization": `Bearer ${CAL_API_KEY}`,
      "cal-api-version": "2024-08-13",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      location: {
        type: "address",
        address: `Room ${room.name} — Floor ${room.floor}, ${room.building}`,
      },
    }),
  });

  res.json({ ok: true });
});

The same flow works for last-minute swaps — re-run the assigner on a cron or on a room-board change and PATCH again. Cal.com refreshes the calendar invite and notifies both attendees.