Skip to main content
Booking is the one thing a voice agent does that needs somewhere to put the appointment. A sub-account with GoHighLevel books into a GHL calendar. A sub-account without one books into a Team Follow Up calendar, described here. The two are the same shape. Availability comes back as days of start times either way, and a booking answers with the time it actually took, so an integration written against one reads the other unchanged.

What a calendar is

A calendar is a bookable resource with hours and rules. A sub-account can have several, and a campaign names the one its agent books into. The defaults match what a GoHighLevel calendar does, so an agent moved between the two behaves the same.
Hours are validated as a whole. A window that ends at or before it starts is refused rather than wrapped past midnight, because a slot that crossed midnight would land under a different date than anyone expects. On an update the merged calendar is checked, not your patch, so dropping every window, or making the appointment longer than the shortest window it must fit in, is refused with the reason.

Creating one

Try a definition before you save it with Preview slots: it validates the definition and returns the slots it would offer. Pass an existing calendarId as well and what is already booked is counted, so the preview shows what would really be left.

Slots and seats

Free slots answers day by day:
It is computed per request against live bookings and is never cached, because a cached slot is one somebody else may already have taken. A slot holds as many seats as appointmentsPerSlot. confirmed and showed occupy a seat; cancelled and noshow free it. A past appointment that happened keeps its seat, so a second booking can never land on a slot that was genuinely used.

Booking

Three things are worth knowing before you write the call:
  • startTime without an offset is read in the calendar’s zone. Epoch milliseconds and a full ISO instant are both accepted and are unambiguous. A bare 2026-09-24T15:00:00 is read as 15:00 where the calendar lives, which is usually what you meant.
  • The seat is claimed as the booking is written, not checked beforehand, so two callers racing for the last seat cannot both win. The loser gets 409 with errorType: "slot_unavailable". A time outside the hours, inside the notice window or past the lookahead comes back as invalid_time.
  • Read bookedStartTime from the response rather than assuming the time you asked for is the time it took.
Booking ends any chase that contact was in, exactly as when an agent books them on a call, and starts the confirmation campaign on that calendar. Rescheduling claims the new time the same way and only gives up the old seat once the new one is held. The reminders that belonged to the old time are re-anchored to the new one rather than left pointing at a time that has passed.

Time that is not a booking

An event is an entry with no contact: a meeting, a reminder, an hour held back. It carries no lead, starts no campaign and tells nobody. What it does do is occupy the seats it covers, so the agent stops offering that time.

Retiring a calendar

A delete refuses while people still have appointments on it, answering 409 with upcomingCount, so a calendar cannot quietly strand everyone who booked. force=true goes ahead and cancels them, and cancelling a booking tells the attendee.

Calendars that live somewhere else

A sub-account can connect a calendar product it already uses, such as Cal.com. List connections says which calendar systems can be connected, how each one is connected, and whether this sub-account has done it.
1

Paste the credential

Connect a calendar system stores the key. It is not checked against that product at the moment you save it: a key that is right today and revoked tomorrow reads the same, so a connection is proven where it is used.
2

Cancellations are registered at connect time

A cancellation made in that product reaches us only because the connection registered for it. The connection row says whether yours is registered. Reconnect the system if it is not.
3

Read, never write

Their calendars and bookings are read through their own API and shown beside yours. Nothing here writes into that product, because the calendar is managed there.
A reconnect replaces the whole connection and removes what was registered under the old credential first, while that credential can still authenticate the removal. Otherwise it stays live in the customer’s account and every cancellation arrives twice.

Where to go next

Why the agent found nothing

The two settings behind almost every empty diary.

Native Calendar API

Every operation, with schemas and examples.