Skip to main content

Booking Intents

A BookingIntent tracks the lifecycle of a multi-step booking attempt, enabling slot holding and progressive data collection before creating an appointment.

Booking intents are useful when your booking flow spans multiple steps or screens. Rather than collecting all information upfront and creating an appointment in a single call, you can create a booking intent early in the flow, hold the selected time slot so it isn't taken by someone else, and gradually attach data as the user progresses. When the user confirms, you complete the intent and an Appointment is created.

Lifecycle

A booking intent moves through these statuses:

pending ──▶ slot_selected ──▶ completed

└──▶ abandoned
StatusDescription
pendingThe initial status. No time slot has been selected yet.
slot_selectedA time slot has been selected (start_at and end_at are set). The slot may be held depending on the hold policy.
completedThe booking intent has been completed and an Appointment has been created.
abandonedThe booking intent has been explicitly abandoned. Any active slot hold is released.

Status transitions happen automatically. When you update a booking intent to include start_at and end_at, the status transitions from pending to slot_selected. You don't set the status directly — it is derived from the state of the intent.

Slot holding

Slot holding prevents double-booking by temporarily blocking a time slot while the user completes the booking flow. When enabled, the selected slot is blocked from availability for other callers until the hold expires or the intent is completed or abandoned.

Configure slot holding with these fields:

FieldTypeDescription
hold_enabledbooleanWhether slot holding is enabled. When omitted at creation, falls back to the service's hold policy.
hold_durationstringThe hold duration as an ISO 8601 duration string (e.g., PT10M for 10 minutes). Falls back to the service's hold policy.
hold_untilstringRead-only. The UTC datetime when the current hold expires. Set automatically when a slot is selected with holding enabled.

When a service is set on the booking intent, the service's default hold policy (the "Hold selected slots" setting under Booking Policy) is automatically applied unless hold_enabled or hold_duration is explicitly provided when creating or updating the booking intent.

When a hold expires, the slot becomes available to other callers again. The booking intent itself remains in slot_selected status — an expired hold does not abandon the intent.

Progressive client data

The client_data field lets you collect client information incrementally across multiple updates. Each update merges the provided fields with existing values rather than replacing them entirely.

For example, you might collect the client's name on one screen and their email on the next:

# Step 1: Collect name
curl -X PATCH /v1/booking_intents/:id \
-d '{"client_data": {"first_name": "Jane", "last_name": "Doe"}}'

# Step 2: Collect email
curl -X PATCH /v1/booking_intents/:id \
-d '{"client_data": {"email": "jane@example.com"}}'

After both updates, client_data contains all three fields. When the booking intent is completed, this data is used to create or match a Client and populate the resulting appointment.

The available client_data fields are: first_name, last_name, email, phone, locale, time_zone, and reference_id.

Completing a booking intent

To complete a booking intent, call the Complete booking intent endpoint. Completion requires:

  • The status must be slot_selected (a time slot must be set).
  • A service must be assigned.

The complete endpoint accepts the same update fields as the update endpoint (service_id, provider_id, start_at, end_at, client_data, etc.). These fields are applied atomically before the intent is completed, so you can finalize data and complete in a single request.

On success, the booking intent transitions to completed status and the resulting Appointment is available in the appointment field of the response.

Abandoning a booking intent

Call the Abandon booking intent endpoint to explicitly abandon a booking intent. This releases any active slot hold and transitions the status to abandoned.

Abandon a booking intent when the user exits the booking flow without completing it, so the held slot is freed up for other callers.

Authenticated vs. public API

Booking intents are available through two API surfaces:

  • Authenticated API — Uses your API key. Full control over all fields. Returns the complete BookingIntent object.
  • Public API — No API key required. Intended for client-side use. Restricted capabilities and returns a simplified PublicBookingIntent object that omits sensitive and admin-only fields.

A common pattern is to use the authenticated API on your server to create a booking intent with pre-configured settings and locked fields, then hand the intent ID to the client to complete the flow via the public API.

CapabilityAuthenticated APIPublic API
Create / update / completeYesYes
AbandonYesYes
List / getYesGet only
Set hold_enabled / hold_durationYesNo
Set locked_fieldsYesNo
Set metadataYesNo
Set slot_prevalidatedYesNo
Link client_idYesNo
Returns full objectYesNo

Locked fields

The authenticated API can lock specific fields so that the public API cannot modify them. This is useful when your server pre-selects values (like a service or provider) that the end user should not be able to change.

Set locked_fields when creating or updating a booking intent via the authenticated API:

curl -X POST /v1/booking_intents \
-d '{
"service_id": "srv_1234567890",
"locked_fields": ["service_id", "provider_id"]
}'

The lockable fields are: service_id, provider_id, start_at, end_at, time_zone, and client_data.

When updating via the authenticated API, locked_fields replaces the existing set entirely.

Auto-assigning a provider

Set auto_assign_provider to true when you want the system to automatically select an available provider for the chosen time slot. This is useful when your flow lets the user pick a time without choosing a specific provider.

Auto-assignment is evaluated when a time slot is selected, so the held slot is reserved for a specific provider's schedule and remains bookable at completion. If a provider_id is also specified, the explicit provider takes precedence.

Webhook events

Four webhook events are emitted during the booking intent lifecycle:

EventDescription
booking_intent.createdA new booking intent was created.
booking_intent.updatedA booking intent was updated.
booking_intent.completedA booking intent was completed.
booking_intent.abandonedA booking intent was abandoned.

See the Webhooks guide for details on registering webhooks and handling events.

Key properties

PropertyTypeDescription
idstringThe unique identifier (e.g., bi_d025a96ac0c6).
statusenumThe current status: pending, slot_selected, completed, or abandoned.
start_atZonedDateTimeThe start time of the selected slot.
end_atZonedDateTimeThe end time of the selected slot.
hold_untilstringWhen the current slot hold expires (UTC).
client_dataobjectProgressive client data collected during the booking flow.
locked_fieldsarrayFields locked from update via the public API.
appointmentAppointmentThe resulting appointment (set when completed).

See the BookingIntent schema for complete details.