# Calendar booking endpoints

> Booking settings, booking types, open times, offers and booking a picked time through the workspace's Cal.com or Calendly.

Source: https://docs.ayinbox.com/api/reference/booking/

These endpoints run [calendar booking](/guides/booking/). Every route answers `503 booking_disabled` while the instance has it off. Gates and scopes are in the [scope map](/api/endpoints/#calendar-booking); error codes are under [calendar booking refusals](/api/error-codes/#calendar-booking-refusals).

Settings [#settings]

`GET /booking/settings` returns `{settings}`: `mode` (`off`, `draft`), `chase_max_touches`, `chase_window_days`, `usable_types`, and `missing`, which lists for each mode what it still needs.

`PUT /booking/settings` takes any of `{mode, chase_max_touches, chase_window_days}`. `mode` is `off` or `draft`; `auto` answers `403 booking_auto_send_required`. Leaving `off` checks every booking type with its provider.

`POST /booking/auto` takes no body. It answers `409 booking_auto_unavailable` with `details.reasons` while automatic booking cannot run.

`GET /booking/summary` returns `{summary: {open, needs_you, booked_30d, median_first_response_seconds}}`.

Booking types [#booking-types]

`GET /booking/profiles` returns `data` plus `pagination`. Each type has `id`, `name`, `connection_id`, `provider`, `event_type_ref`, `event_type_name`, `duration_minutes`, `scheduling_url`, `is_default`, `campaign_id`, `locale`, `slots_per_offer`, `min_notice_minutes`, `horizon_days`, `prospect_hours_start`, `prospect_hours_end`, `status` (`unchecked`, `ok`, `plan_required`, `reauth_required`, `event_type_missing`), `status_detail` and `can_lookup`.

`POST /booking/profiles` takes `{connection_id, event_type_ref}` and any of the offer rules. The event type is read from the provider; one with `blockers` answers `400 booking_event_type_unsupported`. Send an `Idempotency-Key`.

`PATCH /booking/profiles/:id` changes the offer rules. A `campaign_id` on either write must belong to the workspace, or the call answers `404`. `DELETE /booking/profiles/:id` answers `409 booking_attempt_in_flight` while a booking on the type is being confirmed.

`GET /booking/connections/:id/event-types` returns `data`: `ref`, `name`, `duration_minutes`, `scheduling_url`, `video_location`, `blockers` and `can_lookup`.

Open times [#open-times]

`GET /booking/availability?thread_id=&contact_id=&profile_id=&timezone=&limit=` returns `{profile_id, timezone, timezone_source, slots: [{start_at, end_at, label}]}`, read live from the provider with the booking type's minimum notice applied.

Offers [#offers]

`GET /booking/offers?status=&thread_id=&contact_id=&campaign_id=&limit=&cursor=` returns `data` plus `pagination`. `GET /booking/offers/:id` returns `{offer, slots, events}`; each event carries `kind`, `decided_by`, `confidence` and `evidence`, the words a decision rests on.

`POST /booking/offers` with `{thread_id, profile_id?, timezone?, slot_starts?}` returns `{offer, block, slots}`. It sends nothing. Put the block in a reply; the offer becomes `offered` when that reply is sent with every time in it.

`POST /booking/offers/:id/book` with `{slot_id}` or `{start_at}` and `send_confirmation` books on the provider for the contact's stored address:

```json
{
  "meeting": { "id": "...", "scheduled_for": "2026-11-10T14:30:00Z", "join_url": "https://..." },
  "offer": { "id": "...", "status": "booked" },
  "confirmation": { "id": "...", "status": "pending" }
}
```

A `202` with `outcome: "unknown"` means the provider's answer is being confirmed by lookup; nothing is posted again. `409 booking_slot_taken` carries `alternatives`, already written into a draft. One booking runs per offer at a time: another while it is being confirmed answers `409 booking_attempt_in_flight`.

`POST /booking/offers/:id/stop`, `/resume` and `/pick/reject` move the offer and return `{offer}`.

Booking access [#booking-access]

`PUT /integrations/connections/:id/booking-credential` with `{api_key, base_url}` checks the key with the provider and stores it sealed. The response is `{connection, booking_access, account}`, where `account` is `{name, email, can_book, can_lookup, admin}`. The key is never returned.
