Skip to main content
External booking is a two-step conversation with the diary: ask what is free, then book one of the answers. Both steps run on the same engine as the PracticeHub calendar and online booking, so a slot the API offers is a slot the practice would book.
1

Find free slots

Slots are in the clinic timezone, earliest first, at most 50 per day. unavailable_dates lists days in the range with nothing free — handy for greying out a calendar without a request per day.
2

Book one of them

Copy starts_at, ends_at, practitioner_id, location_id and appointment_type_id straight from the slot — and resource_id too when the slot carries one (resource-view locations, calendar_view = 1 on GET /locations, need it; practitioner-view locations return null and need none). For a group slot send its group_master_id instead of starts_at/ends_at — you are taking a place in an existing session.
3

Know what booking does — and doesn't — check

POST /appointments does not look at the practitioner’s diary. Like a staff member clicking a time in the PracticeHub calendar, it books what you send: the patient, location, practitioner, type and resource are validated, but a time that is already taken is written alongside the existing appointment, not refused. Someone may book the same time between your two calls; if that matters to you, re-check availability just before you post (or reconcile afterwards). The one capacity rule that is enforced is a group session’s size — 409 group_full when it is full. The Idempotency-Key makes a retry of the same booking safe, but a new time is a new request.

Parameters

Two views of the diary

visibility=online (default)

What a patient sees when booking online. The location, appointment type and (if given) practitioner must be enabled for online booking — otherwise 422 not_online_bookable — and every online-booking rule applies: minimum advance notice, how far ahead, daily caps, online-only availability guides, slot clustering. Use this for websites, apps and marketplaces.

visibility=all

What the front desk could book: every open slot for practitioners who provide the type, subject only to physical capacity (columns / resources). No online-booking rules. Use this for staff-facing tools and internal automations.

Booking is what the calendar allows staff

GET /availability is how you look before you leap; POST /appointments books what you send, exactly as a staff member clicking the calendar would — it does not check whether the practitioner is free at that time, and there is no locking between two callers. That is deliberate: a data migration or a practice that double-books on purpose needs to be able to write wherever it says. For a public flow, always book a slot /availability returned, and re-query if any time has passed since you fetched it.

Not the same as practitioner_availabilities

practitioner_availabilities is a resource: the raw working-hours records (who is in, where, when). GET /availability is a computation over those records, existing appointments, closures, resources and the appointment type — the free time that is left. Read the first to know when someone works; call the second to know when they can be booked.
Rate limits are per account (120 requests a minute across all of its API keys). A booking widget serving many visitors should fetch a week at a time and re-check only when the visitor picks a day, rather than polling per day.