# Widget API overview

With the Widget API you build your own booking experience: a fully custom booking flow on your
site, or a native app. It is for when the [booking widget](https://developers.cliento.com/docs/widget.md) cannot be shaped
into what you need. It is the API that Cliento's own widget runs on.

It is a JSON API called straight from the customer's browser. It needs no API key, and one
account id is all you need to start.

| To | Read |
| --- | --- |
| See a whole booking from start to finish | [Booking flow](https://developers.cliento.com/docs/widget-api/booking-flow.md) |
| Load the account's services, resources and settings | [Settings and ref-data](https://developers.cliento.com/docs/widget-api/reference-data.md) |
| Find free times | [Availability](https://developers.cliento.com/docs/widget-api/availability.md) |
| Reserve a time, add the customer and confirm | [Creating a booking](https://developers.cliento.com/docs/widget-api/booking.md) |
| Look up or cancel a booking afterwards | [Retrieving and cancelling a booking](https://developers.cliento.com/docs/widget-api/manage-booking.md) |
| Take payment when the account requires it | [Payments](https://developers.cliento.com/docs/widget-api/payments.md) and [Payment endpoints](https://developers.cliento.com/docs/widget-api/payment-endpoints.md) |
| Show the account's reviews | [Reviews](https://developers.cliento.com/docs/widget-api/reviews.md) |

If you are new to the API, start with the [Booking flow](https://developers.cliento.com/docs/widget-api/booking-flow.md) guide.

## Base URL

All endpoints in this documentation are relative to the following base URL:

```
https://apibk.cliento.com/api/v2/partner/cliento/{id}
```

The `id` identifies your Cliento account, which is one location of a business. It is
the same id the booking widget uses. You will find it in Cliento (go to **Admin > Onlinebokning > Bokningssida / Widget**).

For example, to fetch the services and resources of the account `1uAKYvE7mWcnxxdMuixis`:

```bash
curl https://apibk.cliento.com/api/v2/partner/cliento/1uAKYvE7mWcnxxdMuixis/ref-data/
```

## Authentication

The API does not use API keys. Requests are unauthenticated, and the account is
identified by the `id` in the URL. Calls are made directly from the customer's
browser and CORS is open for any origin, so you need no server of your own.

Send these headers on every request:

| Header | Value |
| --- | --- |
| `Accept` | `application/json` |
| `Content-Type` | `application/json` (for POST requests) |

## API stability

The API is not versioned. It is the API behind Cliento's own widget and it
changes when the widget does. Changes are made with care, but expect to
update a custom client when the API changes. Accept responses with fields you
do not know, and ignore them.

> **A versioned API is planned**
>
> We are planning a versioned Widget API, so that a custom client can rely on one version while
> the widget moves on. Until it is released, the API changes when the widget does.

## Rate limits

The API is rate limited. Normal customer behaviour stays well within the
limits. A limited request returns
`429` with a `Retry-After` header and a body like
`{"key": "retry", "retryAfterSeconds": 30}`. Wait that long and repeat the
same call. Do not poll the [status endpoint](https://developers.cliento.com/docs/widget-api/payment-endpoints.md#booking-status)
more often than every few seconds.

## Captcha

Some accounts require a Google reCAPTCHA v3 token on the booking requests. They
have `web_requiresCaptcha` set to `true` in their
[settings](https://developers.cliento.com/docs/widget-api/reference-data.md#fetch-settings). The token goes in the `captchaResponse` field
of `/booking/reserve`, `/booking/customer`, `/booking/confirm` and
`/booking/pay`. For an account without the setting, send `null`.

The captcha uses Cliento's reCAPTCHA site key, and reCAPTCHA only issues
tokens on domains registered for that key. Before your client goes live on an
account with captcha, tell us in the chat at the bottom of the page which
domains your booking UI runs on. Cliento registers them and gives you the site key. Then:

```javascript
// Load https://www.google.com/recaptcha/api.js?render={siteKey}
const token = await grecaptcha.execute(siteKey, { action: 'confirm' });
// send as captchaResponse
```

Fetch a fresh token for every request: tokens are single use and short lived.
The widget uses the action `reserve` for `/booking/reserve`, `customer` for
`/booking/customer` and `confirm` for `/booking/confirm` and `/booking/pay`. A rejected token returns `400` with
code `0` and the message `Captcha failed`.

## Errors

Successful responses use `200`, `201` or `204`. Error responses use standard
HTTP status codes. `400` responses have a JSON body with a numeric `code`, a
`message` and `details`, for example
`{"code": 3, "message": "Reservation not found for uuid: …", "details": ""}`.
Other error responses have a short plain text body or no body at all.

| Status | Meaning |
| --- | --- |
| 400 | The request body or parameters are invalid, or the request was rejected by the captcha. The body is JSON with `code`, `message` and `details` |
| 402 | Payment required or a payment result, see [Payments](https://developers.cliento.com/docs/widget-api/payments.md) |
| 403 | Not allowed: a wrong PIN, an unknown reservation on `/booking/pay`, or a [cancellation](https://developers.cliento.com/docs/widget-api/manage-booking.md#cancel-a-booking) past the deadline. Usually an empty body |
| 404 | Unknown account id or entity. Also a reservation that was released, or has expired and been removed |
| 409 | Conflict, the operation is not possible in the current state |
| 410 | From `/booking/reserve`, the slot is no longer available. From `/booking/{cbUuid}/status`, the reservation is gone: released, or expired and removed. For a reservation that is gone, `/booking/pay` answers `403` and the other calls answer `404` |
| 418 | The request was refused. From `/booking/confirm` and `/booking/pay` the reservation is gone as well: reserve a new slot |
| 429 | Rate limited, see [Rate limits](#rate-limits) |

## Endpoints

| Method | Path | Description |
| --- | --- | --- |
| GET | `/settings/` | [Booking settings for the account](https://developers.cliento.com/docs/widget-api/reference-data.md#fetch-settings) |
| GET | `/ref-data/` | [Services, resources and mappings](https://developers.cliento.com/docs/widget-api/reference-data.md#fetch-ref-data) |
| GET | `/custom-fields/resource/{resourceHashId}` | [Custom form fields](https://developers.cliento.com/docs/widget-api/reference-data.md#fetch-custom-fields) |
| GET | `/resources/slots` | [Available slots](https://developers.cliento.com/docs/widget-api/availability.md) |
| POST | `/booking/reserve` | [Reserve a slot](https://developers.cliento.com/docs/widget-api/booking.md#reserve-a-slot) |
| POST | `/booking/release` | [Release a reservation](https://developers.cliento.com/docs/widget-api/booking.md#release-a-reservation) |
| POST | `/booking/customer` | [Add customer details](https://developers.cliento.com/docs/widget-api/booking.md#add-customer-details) |
| POST | `/booking/confirmation-options` | [Get confirmation options](https://developers.cliento.com/docs/widget-api/booking.md#get-confirmation-options) |
| POST | `/booking/confirm` | [Confirm the booking](https://developers.cliento.com/docs/widget-api/booking.md#confirm-the-booking) |
| POST | `/booking/payment-provider` | [Choose payment provider](https://developers.cliento.com/docs/widget-api/payment-endpoints.md#choose-payment-provider) |
| POST | `/booking/pay` | [Pay and confirm](https://developers.cliento.com/docs/widget-api/payment-endpoints.md#pay-and-confirm) |
| POST | `/booking/{cbUuid}/status` | [Booking status](https://developers.cliento.com/docs/widget-api/payment-endpoints.md#booking-status) |
| POST | `/klarna/session` | [Create a Klarna session](https://developers.cliento.com/docs/widget-api/payment-endpoints.md#create-a-klarna-session) |
| POST | `/booking/validate-voucher` | [Validate a voucher](https://developers.cliento.com/docs/widget-api/payment-endpoints.md#validate-a-voucher) |
| POST | `/booking/voucher` | [Apply or remove a voucher](https://developers.cliento.com/docs/widget-api/payment-endpoints.md#apply-or-remove-a-voucher) |
| GET | `/reviews/` | [Reviews](https://developers.cliento.com/docs/widget-api/reviews.md) |

The payment endpoints are only used when the account requires online payment,
see [Payments](https://developers.cliento.com/docs/widget-api/payments.md).

Two more endpoints retrieve and cancel an existing booking. They are not under
the account base URL: the `{ref}` in the path identifies the booking by itself. See
[Retrieving and cancelling a booking](https://developers.cliento.com/docs/widget-api/manage-booking.md).

| Method | Path | Description |
| --- | --- | --- |
| GET | `https://apibk.cliento.com/api/v2/booking/{ref}` | [Retrieve a booking](https://developers.cliento.com/docs/widget-api/manage-booking.md#retrieve-a-booking) |
| DELETE | `https://apibk.cliento.com/api/v2/booking/{ref}` | [Cancel a booking](https://developers.cliento.com/docs/widget-api/manage-booking.md#cancel-a-booking) |
