Bookings

Create, manage, and track bookings.

Overview

Bookings represent scheduled appointments. Create bookings, handle cancellations, and manage rescheduling.

Creating Bookings

Basic Booking

TypeScript:

const booking = await client.calendar.bookings.create({
  eventTypeId: 'evt_xxx',
  startTime: '2024-01-15T10:00:00-05:00',
  attendee: {
    name: 'John Doe',
    email: 'john@example.com',
  },
});
 
console.log('Booking UID:', booking.uid);
console.log('Meeting URL:', booking.meetingUrl);

Python:

booking = client.calendar.bookings.create(
    event_type_id="evt_xxx",
    start_time="2024-01-15T10:00:00-05:00",
    attendee={
        "name": "John Doe",
        "email": "john@example.com",
    },
)
 
print(f"Booking UID: {booking.uid}")
print(f"Meeting URL: {booking.meeting_url}")

With All Options

const booking = await client.calendar.bookings.create({
  eventTypeId: 'evt_xxx',
  startTime: '2024-01-15T10:00:00-05:00',
 
  // Attendee details
  attendee: {
    name: 'John Doe',
    email: 'john@example.com',
    phone: '+1234567890',
    timezone: 'America/New_York',
  },
 
  // Additional info
  notes: 'Looking forward to discussing the proposal',
  guests: ['guest1@example.com', 'guest2@example.com'],
 
  // Question responses
  responses: {
    company_name: 'Acme Corp',
    company_size: '50-100',
  },
 
  // Metadata for your system
  metadata: {
    dealId: 'deal_123',
    source: 'website',
  },
 
  // For team events, specify host
  hostId: 'user_xxx',
});

Booking Properties

PropertyTypeDescription
uidstringUnique booking identifier
eventTypeIdstringRelated event type
hostIdstringHost user ID
startTimestringStart time (ISO 8601)
endTimestringEnd time (ISO 8601)
statusstringPENDING, CONFIRMED, CANCELLED
attendeeobjectAttendee details
meetingUrlstringVideo conferencing URL
locationobjectMeeting location

Getting Bookings

Get by UID

const booking = await client.calendar.bookings.get('booking_uid');

List Bookings

// List all bookings
const bookings = await client.calendar.bookings.list({
  count: 50,
  offset: 0,
});
 
// Filter by status
const upcoming = await client.calendar.bookings.list({
  status: 'CONFIRMED',
});
 
// Filter by date range
const thisWeek = await client.calendar.bookings.list({
  startDate: '2024-01-15',
  endDate: '2024-01-22',
});
 
// Filter by event type
const demos = await client.calendar.bookings.list({
  eventTypeId: 'evt_demo',
});
 
// Filter by attendee email
const userBookings = await client.calendar.bookings.list({
  attendeeEmail: 'john@example.com',
});

Booking Status

StatusDescription
PENDINGAwaiting confirmation
CONFIRMEDBooking confirmed
CANCELLEDBooking cancelled
COMPLETEDMeeting completed
NO_SHOWAttendee didn't show

Check Status

const booking = await client.calendar.bookings.get(uid);
 
if (booking.status === 'PENDING') {
  console.log('Awaiting host confirmation');
} else if (booking.status === 'CONFIRMED') {
  console.log('Booking confirmed for', booking.startTime);
}

Confirmation Workflow

For event types requiring confirmation:

Confirm Booking

await client.calendar.bookings.confirm(booking.uid);

Reject Booking

await client.calendar.bookings.reject(booking.uid, {
  reason: 'Schedule conflict, please rebook for next week',
});

Cancellation

Cancel by Attendee

await client.calendar.bookings.cancel(booking.uid, {
  reason: 'Something came up',
  cancelledBy: 'attendee',
});

Cancel by Host

await client.calendar.bookings.cancel(booking.uid, {
  reason: 'Need to reschedule due to emergency',
  cancelledBy: 'host',
  notifyAttendee: true,
});

Cancellation Policies

Respect event type cancellation deadlines:

const eventType = await client.calendar.eventTypes.get(booking.eventTypeId);
 
const bookingStart = new Date(booking.startTime);
const now = new Date();
const hoursUntil = (bookingStart.getTime() - now.getTime()) / (1000 * 60 * 60);
const deadlineHours = eventType.cancellationDeadline / 60;
 
if (hoursUntil < deadlineHours) {
  console.log('Cancellation deadline has passed');
} else {
  await client.calendar.bookings.cancel(booking.uid);
}

Rescheduling

Get Available Reschedule Slots

const availability = await client.calendar.availability.get({
  eventTypeId: booking.eventTypeId,
  startDate: '2024-01-20',
  endDate: '2024-01-27',
  excludeBookingUid: booking.uid, // Exclude current booking's slot
});

Reschedule Booking

const rescheduled = await client.calendar.bookings.reschedule(booking.uid, {
  startTime: '2024-01-20T14:00:00-05:00',
  reason: 'Need to move to next week',
  notifyAttendee: true,
});
 
console.log('Rescheduled to:', rescheduled.startTime);

Group Bookings

For event types that allow multiple attendees:

Add Attendee

await client.calendar.bookings.addAttendee(booking.uid, {
  name: 'Jane Smith',
  email: 'jane@example.com',
});

Remove Attendee

await client.calendar.bookings.removeAttendee(booking.uid, {
  email: 'jane@example.com',
});

List Attendees

const booking = await client.calendar.bookings.get(uid);
 
console.log('Primary attendee:', booking.attendee);
console.log('Guests:', booking.guests);
console.log('Total attendees:', 1 + booking.guests.length);

Recurring Bookings

Create Recurring

const booking = await client.calendar.bookings.create({
  eventTypeId: 'evt_weekly_coaching',
  startTime: '2024-01-15T10:00:00-05:00',
  attendee: {
    name: 'John Doe',
    email: 'john@example.com',
  },
  recurring: {
    frequency: 'WEEKLY',
    count: 12, // 12 occurrences
  },
});
 
console.log('Recurring booking created');
console.log('Occurrences:', booking.occurrences.length);

Get Occurrences

const occurrences = await client.calendar.bookings.getOccurrences(booking.uid);
 
for (const occurrence of occurrences) {
  console.log(`${occurrence.date}: ${occurrence.status}`);
}

Cancel Single Occurrence

await client.calendar.bookings.cancelOccurrence(booking.uid, {
  date: '2024-02-05',
  reason: 'Holiday',
});

Cancel All Future

await client.calendar.bookings.cancelAllFuture(booking.uid, {
  fromDate: '2024-03-01',
  reason: 'Project completed',
});

Booking Notes

Add Note

await client.calendar.bookings.addNote(booking.uid, {
  content: 'Discussed Q1 goals, follow up on pricing',
  isPrivate: true, // Only visible to hosts
});

Get Notes

const notes = await client.calendar.bookings.getNotes(booking.uid);
 
for (const note of notes) {
  console.log(`[${note.createdAt}] ${note.content}`);
}

Booking Metadata

Store custom data with bookings:

// Set metadata on creation
const booking = await client.calendar.bookings.create({
  eventTypeId: 'evt_xxx',
  startTime: '...',
  attendee: { ... },
  metadata: {
    salesforceLeadId: 'lead_123',
    campaignId: 'camp_456',
  },
});
 
// Update metadata later
await client.calendar.bookings.update(booking.uid, {
  metadata: {
    ...booking.metadata,
    meetingOutcome: 'interested',
  },
});

Check-in / No-show

Track attendance:

// Mark as attended
await client.calendar.bookings.markAttended(booking.uid);
 
// Mark as no-show
await client.calendar.bookings.markNoShow(booking.uid);

ICS Calendar Invites

Get ICS File

const ics = await client.calendar.bookings.getIcs(booking.uid);
 
// Send as email attachment or download
res.setHeader('Content-Type', 'text/calendar');
res.setHeader('Content-Disposition', 'attachment; filename="booking.ics"');
res.send(ics);

Webhooks for Bookings

Handle booking events:

app.post('/webhooks/calendar', (req, res) => {
  const event = req.body;
 
  switch (event.type) {
    case 'booking.created':
      // New booking
      syncToCRM(event.data.booking);
      break;
 
    case 'booking.confirmed':
      // Host confirmed
      sendConfirmation(event.data.booking);
      break;
 
    case 'booking.cancelled':
      // Booking cancelled
      updateCRM(event.data.booking, 'cancelled');
      break;
 
    case 'booking.rescheduled':
      // Time changed
      updateCalendar(event.data.booking);
      break;
 
    case 'booking.completed':
      // Meeting ended
      requestFeedback(event.data.booking);
      break;
  }
 
  res.status(200).send('OK');
});

Next Steps