Documentation ›CRM: leads, tasks, calendar

Calendar & Booking

What is it?

When enabled, the AI can schedule appointments for customers during a conversation. AI asks "when do you want to come?", checks the practitioner's working hours and busy slots, and writes the booking into the dashboard. Operator sees it on the Calendar page immediately.

Default: OFF.

Booking is OFF by default for every account. The AI never tries to book unless you explicitly turn it on. Setup is two steps:

  1. Go to Settings and turn on Booking (calendar). The Practitioners page and its link then appear in the menu — they are hidden while booking is off, because the page is empty without it.
  2. Open Practitioners and add at least one bookable resource (see below).

After that, AI on every channel (voice, WhatsApp, Telegram, Instagram and the chat on your website) can see who is available and book a visit.

Practitioners = bookable resources (not necessarily people):

"Practitioner" in the system is just a thing with a schedule that holds time slots. Pick whatever naming convention fits your business — examples by industry:

  • Clinic / dental: doctor name + specialty
  • Lab / diagnostics: the service itself (per-room if multiple rooms run in parallel)
  • Beauty / hair salon: master name + their service
  • Auto service: work bay or service type
  • Law firm: lawyer name OR generic "Consultation"

The AI uses whatever you put in the name field verbatim in its confirmation message — so pick something that sounds natural when the AI says it back to the customer.

Working hours format:

JSON keyed by weekday (3-letter lowercase). Each value is a list of ["HH:MM", "HH:MM"] open/close pairs in YOUR timezone. Missing key or empty list = closed that day.

Generic Mon-Fri schedule with a one-hour midday break:

{"mon": [["09:00", "13:00"], ["14:00", "18:00"]],
 "tue": [["09:00", "13:00"], ["14:00", "18:00"]],
 "wed": [["09:00", "13:00"], ["14:00", "18:00"]],
 "thu": [["09:00", "13:00"], ["14:00", "18:00"]],
 "fri": [["09:00", "13:00"], ["14:00", "18:00"]]}

Empty dict {} = treated as "always open" — useful while you're still configuring; the AI won't reject any time. Once you fill in real hours, AI refuses out-of-hours requests with an explanation.

What happens when AI books an appointment:

  1. AI checks the practitioner's working hours — refuses out-of-hours requests, asks the caller for a different time
  2. AI checks for conflicts — refuses double-booking, asks for a different slot
  3. Appointment saved to DB → appears on the Calendar page, on the contact's timeline (calendar card), and on the lead's timeline
  4. If a recent lead exists for this contact at stage new or contacted, it auto-advances to qualified in the kanban
  5. A Task "Confirm appointment at HH:MM" is auto-created for the morning of the appointment — operator gets a Telegram reminder an hour before due
  6. AI confirms verbally with a one-line message in the account's language

Rescheduling and cancelling:

With Booking on, the AI also gets reschedule_appointment and cancel_appointment on every channel. Both find the customer's own upcoming appointment by the phone they are calling or writing from (carrier caller ID on voice, the WhatsApp number in chat) — a customer can never touch someone else's slot by naming an id.

  • One upcoming appointment → it is moved / cancelled directly; the AI confirms the new time (or the cancellation) only after the system returned success.
  • Several upcoming appointments → the AI gets the list back and asks the customer which one (by day and time).
  • None found (booked from another number, or by the front desk without a phone) → the AI asks which phone the booking was made with, or takes name + phone for the front desk. It never claims it moved or cancelled anything.
  • A move keeps the same practitioner and duration and passes the same checks as a new booking: working hours, no double-booking, Google free/busy when the calendar is mirrored. The Google event is recreated on a move and deleted on a cancel.
  • Both actions appear on the contact's timeline ("appointment rescheduled" / "appointment cancelled"); a cancelled slot is immediately bookable again.

How the operator works with the Calendar:

  • Daily view: Calendar shows today by default. Use prev/next buttons or ?date=YYYY-MM-DD for any day.
  • Status changes: Click "Change status" on a scheduled/confirmed appointment. Operator marks confirmed / completed / no-show / cancelled.
  • Contact link: Each appointment card has a link to the customer's contact card — opens their full cross-channel history.
  • Cancelled slots are reusable: the AI can book over a cancelled appointment (the conflict check excludes cancelled).

Common pitfalls:

  • You forgot to flip the toggle. Practitioners exist, but Booking is OFF in Settings → AI still doesn't book, and the Practitioners link leaves the menu. Turn Booking on and both come back.
  • You flipped the toggle without practitioners. Calendar page shows "no practitioners configured" and AI refuses bookings.
  • Wrong working hours format. Use the JSON template above. Empty list [] means closed; missing weekday key also means closed.
  • Customer-side reminders. The Task created on the morning OF the appointment is for the operator. WhatsApp reminders to the customer at T-24h / T-2h are a separate opt-in — see the "Appointment reminders" section below.

Adding a booking by hand:

Not every appointment comes through the AI — a client phones the desk or walks in. Click "+ Add appointment" at the top of the Calendar, pick practitioner / date / time / duration, fill the customer name + phone, and save. Past dates are allowed (handy for back-filling); the booking appears on the day grid like an AI one.