> ## Documentation Index
> Fetch the complete documentation index at: https://docs.keebai.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Scheduling overview

> Branches, services, professionals, availability, and appointments — the booking model and the two-step confirmation flow.

The scheduling surface backs booking flows on your own site or app: read the catalog, ask what is available, and create appointments — without sending anyone to the Keebai portal.

## What you can do

<CardGroup cols={2}>
  <Card title="Read the catalog" icon="store" href="/dev/endpoints/scheduling-branches-list">
    Branches, services, and professionals, with the rules that tie them together.
  </Card>

  <Card title="Query availability" icon="calendar-days" href="/dev/endpoints/scheduling-availability">
    Open slots for a given date, a range of dates, or simply the next ones available.
  </Card>

  <Card title="Book" icon="calendar-plus" href="/dev/endpoints/scheduling-appointment-create">
    Create an appointment with the customer's data embedded — no prior customer record needed.
  </Card>

  <Card title="Confirm or cancel" icon="calendar-check" href="/dev/endpoints/scheduling-appointment-confirm">
    Move an appointment out of `pending`, or release the slot.
  </Card>
</CardGroup>

## Scopes

| Scope                             | Grants                                                                                                                                                                                        |
| --------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `scheduling:branches:read`        | [List](/dev/endpoints/scheduling-branches-list) and [read](/dev/endpoints/scheduling-branch-get) branches.                                                                                    |
| `scheduling:services:read`        | [List](/dev/endpoints/scheduling-services-list) and [read](/dev/endpoints/scheduling-service-get) services.                                                                                   |
| `scheduling:professionals:read`   | [List](/dev/endpoints/scheduling-professionals-list) and [read](/dev/endpoints/scheduling-professional-get) professionals.                                                                    |
| `scheduling:availability:read`    | Query availability [by date](/dev/endpoints/scheduling-availability), [by range](/dev/endpoints/scheduling-availability-range), or [next slots](/dev/endpoints/scheduling-availability-next). |
| `scheduling:appointments:read`    | [Read an appointment](/dev/endpoints/scheduling-appointment-get) by id.                                                                                                                       |
| `scheduling:appointments:create`  | [Create appointments](/dev/endpoints/scheduling-appointment-create).                                                                                                                          |
| `scheduling:appointments:confirm` | [Confirm](/dev/endpoints/scheduling-appointment-confirm) a pending appointment.                                                                                                               |
| `scheduling:appointments:cancel`  | [Cancel](/dev/endpoints/scheduling-appointment-cancel) an appointment.                                                                                                                        |

A public site that only displays branches, services and open times needs the four `:read` scopes and nothing more. Add the appointment scopes only to the token that actually books.

## The booking model

A **branch** is a location. It offers **services**, each with a duration and its own rules about which **professionals** can deliver it. Availability is computed from that combination, so a slot is always specific to a service — asking "what is free on Tuesday" without naming a service has no answer.

The customer is **embedded in the appointment**, not referenced. You do not create a customer record first; you pass name, and optionally phone and email, inside the booking. That also means scheduling customers are separate from [CRM customers](/dev/crm/overview) — the two are not linked automatically.

## Appointments land in `pending`

Creating an appointment does **not** confirm it. It lands in `pending` and stays there until you call [confirm](/dev/endpoints/scheduling-appointment-confirm) explicitly.

That extra step exists so you can build flows where something has to happen in between — a payment clears, a human validates, or the customer confirms from a link. If your flow has none of that, chain create and confirm in the same request handler.

Confirm only accepts an appointment that is currently `pending`; anything else returns `409`.

## Ids and time

The appointment `_id` is a **UUID v4** generated by Keebai, not a Mongo `ObjectId` like the rest of the platform. Branch, service, and professional ids *are* ObjectIds.

Dates are `YYYY-MM-DD` and times are `HH:mm` in the **branch's** timezone, not UTC and not the caller's. If the service defines a duration you can omit `end_time` and Keebai computes it.

## Errors

```json theme={null}
{
  "error": {
    "code": "SLOT_NOT_AVAILABLE",
    "message": "El profesional no tiene disponibilidad para el horario solicitado."
  }
}
```

| Status | When                                                                                |
| ------ | ----------------------------------------------------------------------------------- |
| `400`  | Bad date or time format, missing fields, malformed email.                           |
| `401`  | Missing, invalid, revoked, or expired token.                                        |
| `403`  | The token lacks the scope the endpoint requires.                                    |
| `409`  | The slot is taken, or the appointment is not in a state that allows the transition. |
| `429`  | You hit a [rate limit](/dev/rate-limits).                                           |

Branch on `error.code`, not on the message text — a `409` on create means the slot is gone, a `409` on confirm means someone already confirmed or cancelled it.

## Next steps

<CardGroup cols={2}>
  <Card title="List branches" icon="store" href="/dev/endpoints/scheduling-branches-list">
    Start from the locations available to your tenant.
  </Card>

  <Card title="Create an appointment" icon="calendar-plus" href="/dev/endpoints/scheduling-appointment-create">
    Book a slot with the customer embedded.
  </Card>
</CardGroup>
