Skip to main content
The Calendar battery is OMNI’s shared appointment calendar. Its endpoints, under /v1/calendar/…, let your own systems do what the team does there: read the booking types and the team, ask which times are free, book a contact in, and move, confirm, complete or cancel what was booked. An appointment booked through the API is the same appointment the panel shows. The same rules decide when someone is free, and the contact gets the account’s confirmation and reminders, as when the team books.
  • The endpoints exist when the account’s plan includes Calendar; otherwise they answer 404 module_off.
  • You need a key with calendar:read to read booking types, the team, free times and appointments, and calendar:write to book, move, confirm and cancel appointments and to set up booking types (see Keys and scopes).
  • Teammates are named by their email, everywhere.
  • Times are answered in the account’s timezone, with its offset — 2026-10-08T10:30:00+05:30. A time you send must carry its offset too.

Find a free time, then book it

1

Pick the booking type

GET /v1/calendar/booking-types lists what people can book: how long each lasts, the prep time before it, and who takes it. Note the id of the one you want.
2

Ask for its free times

GET /v1/calendar/free-times with booking_type, and the days to look at:
Each free start comes with the teammate free then:
Without to, a week is answered; ask for at most 31 days at a time. Add staff (an email) for one teammate’s times only.
3

Book it

POST /v1/calendar/appointments with the contact, the booking type, and a starts_at from the free times, unchanged:
The answer is the appointment, confirmed — or requested, if you send that as status. Send an Idempotency-Key header so a retried request books only once.
4

If the time has gone

Someone may book the same time between your two calls. Then booking is refused with 409 slot_taken: ask for the free times again and offer another.

What decides a free time

A time is free for a teammate when the appointment and its prep time both fit in their working hours, clear of time off, busy times on a calendar they connected, and their other upcoming appointments (with those appointments’ prep). A teammate has one appointment at a time. Teammates marked as not taking bookings are left out. The account’s own settings apply too: the minimum notice — how soon from now a booking can start — and how far ahead it can be booked. Days past that are simply not answered. When appointments are switched off in the account’s Calendar settings, free times are refused with 409 calendar_off, and booking with 409 invalid_state.

Endpoints

Booking types and the team

A booking type lasts 5 to 480 minutes (slot_minutes), with 0 to 240 minutes of prep before it (prep_minutes). Its mode is online, physical (in person) or either, chosen when booking.

Appointments

Every appointment says where it was booked in source: panel, inbox, agent, workflow, link (online booking) or api for yours.

Status

An appointment is requested or confirmed while it is upcoming, and ends completed, cancelled or no_show. Asking at the wrong moment — moving a completed appointment, say — is refused with invalid_state (409), and the message says why. Once an appointment is done, canceled or a no-show, reminders not yet sent are dropped. Moving or canceling tells the contact, as when the team does it.

Webhook events

Rather than asking, subscribe a webhook endpoint to: They are sent whoever made the change — the team in the panel, the contact, an AI agent, online booking or the API. Each carries data.appointment, in the shape GET …/appointments/{appointment_id} answers (without its history), and data.change: what happened, as a line of that history.
An appointment’s status is spelled cancelled; its event is appointment.canceled, like OMNI’s other events.