# Booking flow

This guide walks through a complete booking, from loading services to a
confirmed booking. It is the same sequence the Cliento booking widget uses.
All example payloads on this page are real responses from a test account.

A booking without online payment takes six steps:

1. `GET /settings/` and `GET /ref-data/` to load services and resources
2. `GET /resources/slots` to find available slots
3. `POST /booking/reserve` to hold the selected slot
4. `POST /booking/customer` to add the customer details
5. `POST /booking/confirmation-options` to find out how to confirm
6. `POST /booking/confirm` to complete the booking

All paths are relative to the [base URL](https://developers.cliento.com/docs/widget-api.md#base-url). The full
reference for each endpoint is in [Creating a booking](https://developers.cliento.com/docs/widget-api/booking.md).

## 1. Load settings and ref-data

Fetch [settings](https://developers.cliento.com/docs/widget-api/reference-data.md#fetch-settings) and
[ref-data](https://developers.cliento.com/docs/widget-api/reference-data.md#fetch-ref-data) once when your booking UI
loads. Ref-data contains the services and resources, and the mappings that tell
you which resource performs which service. Use this to render your service and
resource selection.

## 2. Find available slots

Ask for [available slots](https://developers.cliento.com/docs/widget-api/availability.md) for the selected service and
resources, one date window at a time:

```bash
curl "{baseUrl}/resources/slots?srvIds=68811&resIds=12816&fromDate=2026-10-26&toDate=2026-11-01"
```

Each slot in the response has an opaque `key`. Pass it unchanged to the reserve
call.

## 3. Reserve the slot

```bash
curl -X POST "{baseUrl}/booking/reserve" \
  -H "Content-Type: application/json" \
  -d '{"slotKey": "MzE3MToxMjgxNjo2ODgxMToxNzkz..."}'
```

```json
{
  "cbUuid": "4674c65b-a64f-43a5-94c7-af3b59053cc6",
  "cbRef": "mK0k22O3",
  "reservationExpiry": "2026-10-23T09:46:24Z",
  "services": [
    { "id": 68811, "name": "Women's haircut", "price": 595.0, "priceFrom": false, "duration": 45 }
  ],
  "price": 595.0
}
```

The `cbUuid` in the response is the id of the reservation. It identifies the
booking through the rest of the flow, so pass it in every following call.

The slot is now held for you until `reservationExpiry`, about five minutes.
Complete the booking before then. If someone else holds the slot, the reserve
call returns `410` with an empty body. Fetch slots again and let the customer
pick a new time.

If the customer picks a new time while already holding one, include the current
`cbUuid` in the new reserve call. The old hold is then released automatically.
If the customer abandons the booking, release the hold:

```bash
curl -X POST "{baseUrl}/booking/release" \
  -H "Content-Type: application/json" \
  -d '{"cbUuid": "4674c65b-a64f-43a5-94c7-af3b59053cc6"}'
```

## 4. Add customer details

Check [custom fields](https://developers.cliento.com/docs/widget-api/reference-data.md#fetch-custom-fields) for the
resource to know if the account has extra form fields. Then send the customer
details:

```bash
curl -X POST "{baseUrl}/booking/customer" \
  -H "Content-Type: application/json" \
  -d '{
    "cbUuid": "4674c65b-a64f-43a5-94c7-af3b59053cc6",
    "name": "Test Testsson",
    "phone": "+46701234567",
    "email": "test@example.com",
    "note": "",
    "customFields": [],
    "allowMarketing": false,
    "bookedSpecificResource": false
  }'
```

A `200` response means the details were saved. The response body has no
information. Phone numbers must be in E.164 format, for example `+46701234567`.

## 5. Get confirmation options

Ask how the booking should be confirmed:

```bash
curl -X POST "{baseUrl}/booking/confirmation-options" \
  -H "Content-Type: application/json" \
  -d '{"cbUuid": "4674c65b-a64f-43a5-94c7-af3b59053cc6"}'
```

```json
{
  "cbUuid": "4674c65b-a64f-43a5-94c7-af3b59053cc6",
  "cbRef": "mK0k22O3",
  "reservationExpiry": "2026-10-23T09:46:24Z",
  "confirmationMethod": "NoPin",
  "paymentAmountIncVat": null,
  "paymentProviders": [],
  "allowDiscountVoucher": false,
  "saleItems": [],
  "attributes": { "pbk_allowMarketing": false },
  "prefs": { "...": "same preference object as in settings, shortened here" }
}
```

`confirmationMethod` decides the next step:

| Value | Meaning |
| --- | --- |
| `NoPin` | Confirm directly with `pin` set to `null` |
| `Pin` | An SMS with a PIN code was just sent to the customer's phone. Ask the customer for the code and pass it in the confirm call. A demo account sends no SMS and returns the code as [`demoPin`](https://developers.cliento.com/docs/widget-api/booking.md#get-confirmation-options) |
| `Payment` | The booking requires online payment. Step 6 is then `POST /booking/pay` instead of `/booking/confirm`, see [Payments](https://developers.cliento.com/docs/widget-api/payments.md) |

## 6. Confirm the booking

```bash
curl -X POST "{baseUrl}/booking/confirm" \
  -H "Content-Type: application/json" \
  -d '{"cbUuid": "4674c65b-a64f-43a5-94c7-af3b59053cc6", "pin": null}'
```

```json
{
  "cbUuid": "4674c65b-a64f-43a5-94c7-af3b59053cc6",
  "cbRef": "mK0k22O3",
  "smsReminderEnabled": true,
  "emailConfirmSent": true,
  "smsConfirmSent": true,
  "paymentStatus": "Unpaid",
  "paymentProvider": "None"
}
```

The response status is `201` and the booking now exists in the calendar.
Cliento sends the confirmation email and SMS according to the account settings,
so your client does not need to notify the customer. If the reservation expired
before you confirmed, the call returns `404`. Reserve a new slot and try again.

The booking can later be looked up and cancelled with the `cbUuid`, see
[Retrieving and cancelling a booking](https://developers.cliento.com/docs/widget-api/manage-booking.md).
