# Cliento API reference: Booking

Base URL: `https://api.cliento.com`

The Booking APIs let an integration read a location's bookings. They also list its resources and
its services. Creating and changing bookings through the API is coming soon.

A booking is built from these:

- **Resources.** A resource is what gets booked. It is most often a person, sometimes a room or a
  piece of equipment.
- **Services.** A service is something the location offers, such as a haircut. It has a name and
  a default duration and price.
- **Resource services.** A resource service is a service as one resource offers it. It uses the
  service's duration and price unless the resource has its own.
- **Schedules.** A schedule says when a resource works.
- **Availability.** Availability says when a service can be booked. It is worked out from the
  resource services, the schedules and the bookings already made.
- **Bookings.** A booking is a time on a resource, usually for a customer and one or more
  services.

**Getting started with bookings**

A booking needs other things to exist first. Set them up in this order:

1. **Add a resource.** A booking is always made on a resource, so the location needs at least
   one. Resources are added in Cliento today. List them with
   `GET /v1/locations/{locationId}/resources`.
2. **Add the services the location offers.** Services are added in Cliento today. List them with
   `GET /v1/locations/{locationId}/services`.
3. **Enable each service for the resources that offer it.** That creates a resource service, with
   the duration and price that apply to that resource. It is done in Cliento today. Read a
   resource's resource services with
   `GET /v1/locations/{locationId}/resources/{resourceId}/services`.
4. **Create the customer the booking is for.** Create a person with
   `POST /v1/locations/{locationId}/persons`, a company with
   `POST /v1/locations/{locationId}/companies`, or a vehicle with
   `POST /v1/locations/{locationId}/vehicles`.
5. **Create the booking.** A booking is a time on the resource, for the customer, with one or
   more of the resource's services. Bookings are made in Cliento or by customers online today.
   Read them with `GET /v1/locations/{locationId}/bookings`.

Adding resources and services, enabling a service for a resource and creating a booking through
the API are coming soon.

A reservation skips steps 2 to 4. It only blocks time on a resource, such as a lunch break or a
staff meeting, and needs no service and no customer.

Only the resource is required. Staff can make a booking in Cliento without a customer, without a
service, or with a service the resource is not enabled for. Expect to read bookings like that. A
schedule is not required either: it decides when a service can be booked online, not whether a
booking can exist.

## Resources

The Resources API lists a location's resources and the services each one can be booked for. Use
it to show which resources can be booked. A resource's resource services give the duration and
price of each service.

A resource is what gets booked in the calendar. It is most often a person, sometimes a room or a
piece of equipment. Every booking is made on at least one resource.

A resource belongs to one location and has an id of the form `res_...`.
`GET /v1/locations/{locationId}/resources` lists the resources. Reading resources needs the scope
`resources:read`, and reading a resource's services needs `services:read`.

- **A resource is not a staff member.** A staff member is a person who works at the location. A
  resource is what bookings are made on. A staff member names the resources it is linked to in
  `resourceIds`.
- **Resources are listed in groups.** `groupId` names the group.
  `GET /v1/locations/{locationId}/resource-groups` lists the groups in the order the location
  shows them.
- **The services a resource can be booked for** are its resource services, read with
  `GET /v1/locations/{locationId}/resources/{resourceId}/services`. Each is one service as this
  resource offers it. It has the service's name, description, group, type and VAT. Its duration
  and price are the resource's own where the resource has them, and the service's defaults where
  it does not.
- **The same services with the location's defaults** are read with
  `GET /v1/locations/{locationId}/services?resourceId=...`.
- **`onlineBookingEnabled`** says whether the resource is open for online booking at all. Whether
  a given service can be booked online with it is `onlineBookingAllowed` on the resource service.
- **`status`** is `paused` for a resource that is paused for billing, up to and including
  `pausedUntil`. A paused resource keeps its bookings but takes no new online bookings.
- **A deleted resource** is left out of the list. It still answers by id, with `status`
  `deleted`, because earlier bookings refer to it.
- **`onlineName`** is the name customers see in online booking, when it differs from `name`.

### List resources

`GET /v1/locations/{locationId}/resources`

Scope: `resources:read`

Stability: preview

The location's resources, without those that are deleted.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `locationId` | path | string | Yes |  |
| `limit` | query | integer (int32) | No | Page size, 1 to 200. Default 50. |
| `after` | query | string | No | The `nextCursor` of the previous page. |

**Responses**

| Status | Description | Body |
| --- | --- | --- |
| 200 | OK | ResourceList |
| default | Any failure. See the Errors section. | Error |

### Get a resource

`GET /v1/locations/{locationId}/resources/{resourceId}`

Scope: `resources:read`

Stability: preview

Also answers for a deleted resource, with `status` `deleted`.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `locationId` | path | string | Yes |  |
| `resourceId` | path | string | Yes |  |

**Responses**

| Status | Description | Body |
| --- | --- | --- |
| 200 | OK | Resource |
| default | Any failure. See the Errors section. | Error |

### Get a resource by id

`GET /v1/resources/{resourceId}`

Scope: `resources:read`

Stability: preview

The same resource as under its location, found from its id. For a caller that holds an id and not the location it belongs to. The answer carries `locationId`.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `resourceId` | path | string | Yes |  |

**Responses**

| Status | Description | Body |
| --- | --- | --- |
| 200 | OK | Resource |
| default | Any failure. See the Errors section. | Error |

### List a resource's resource services

`GET /v1/locations/{locationId}/resources/{resourceId}/services`

Scope: `services:read`

Stability: preview

Lists the services the resource can be booked for, in the order the location lists its services. Each is a resource service. It has the duration, price and online booking setting that apply for this resource. `ownValues` says whether they are the resource's own or the service's defaults.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `locationId` | path | string | Yes |  |
| `resourceId` | path | string | Yes |  |
| `limit` | query | integer (int32) | No | Page size, 1 to 200. Default 50. |
| `after` | query | string | No | The `nextCursor` of the previous page: a service id. |

**Responses**

| Status | Description | Body |
| --- | --- | --- |
| 200 | OK | ResourceServiceList |
| default | Any failure. See the Errors section. | Error |

### Get a resource service

`GET /v1/locations/{locationId}/resources/{resourceId}/services/{serviceId}`

Scope: `services:read`

Stability: preview

One service as this resource offers it.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `locationId` | path | string | Yes |  |
| `resourceId` | path | string | Yes |  |
| `serviceId` | path | string | Yes |  |

**Responses**

| Status | Description | Body |
| --- | --- | --- |
| 200 | OK | ResourceService |
| default | Any failure. See the Errors section. | Error |

### List resource groups

`GET /v1/locations/{locationId}/resource-groups`

Scope: `resources:read`

Stability: preview

The groups the location's resources are listed under, in display order.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `locationId` | path | string | Yes |  |
| `limit` | query | integer (int32) | No | Page size, 1 to 200. Default 50. |
| `after` | query | string | No | The `nextCursor` of the previous page. |

**Responses**

| Status | Description | Body |
| --- | --- | --- |
| 200 | OK | ResourceGroupList |
| default | Any failure. See the Errors section. | Error |

## Services

The Services API lists the services a location offers, with their names, durations and prices.
Use it to show what can be booked at a location.

A service is something a location offers, such as a haircut, a massage or a class. The location
gives it a name and a default duration and price.

A resource service is a service as one resource offers it. It uses the service's defaults unless
the resource has its own duration or price. To read what one resource offers, read that
resource's resource services.

A service belongs to one location and has an id of the form `svc_...`.
`GET /v1/locations/{locationId}/services` lists the services in the order the location shows
them. Reading needs the scope `services:read`.

- **Services are listed in groups.** `groupId` names the group.
  `GET /v1/locations/{locationId}/service-groups` lists the groups in display order.
- **A resource service** says that a resource can be booked for a service. It has the service's
  name, description, group, type and VAT. Its duration, price and online booking setting are the
  ones that apply to that resource. Use them when you know which resource a booking is for.
- **`ownValues`** says where a resource service's values come from. When it is false, the
  resource service follows the service's defaults and changes when they do. When it is true, it
  has its own values, which stay when the service changes.
- **Resource services are read in two places**: in `resourceServices` on the service, one for each
  resource it can be booked for, and per resource under
  `/v1/locations/{locationId}/resources/{resourceId}/services`.
- **A service can be booked online with a resource when three things hold**: the service is shown
  online (`shownOnline`), the resource service allows online booking (`onlineBookingAllowed`), and
  the resource is open for online booking (`onlineBookingEnabled` on the resource). A resource
  that is paused takes no online bookings whatever the three say.
- **`onlineBookingAllowed` on the service is the default.** The resource service follows it
  unless the resource has its own setting. A service can be shown without being bookable, so
  that customers see it and call.
- **`afterTimeMinutes`** is time kept free after the booking. It is not part of what the customer
  is told the service takes.
- **`priceFrom`** marks a starting price: the final price is set at the visit.
- **An add-on** (`addOn`) is booked together with another service, never on its own.
- **A service can have parts with different VAT rates**, listed in `vatParts`. A vaccination is
  an example: the vaccine is a medical part with no VAT, and the certificate issued with it is a
  part at 25 % VAT. The service's `price` is then the sum of the parts' prices. When the service
  is paid for at the point of sale or online, each part is sold at its own rate. The service's
  `vatPercent` is the single rate used where the service is not split into its parts.
- **A deleted service** is left out of the list. It still answers by id, with `status` `deleted`,
  because earlier bookings refer to it.
- A location can charge more in the evening or on holidays. Those prices are not returned yet;
  `price` is the ordinary one.
- Prices follow "Amounts" in the introduction.

### List services

`GET /v1/locations/{locationId}/services`

Scope: `services:read`

Stability: preview

The location's services in the order the location lists them, without those that are deleted.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `locationId` | path | string | Yes |  |
| `resourceId` | query | string | No | Only the services that have a resource service for this resource. |
| `limit` | query | integer (int32) | No | Page size, 1 to 200. Default 50. |
| `after` | query | string | No | The `nextCursor` of the previous page. |

**Responses**

| Status | Description | Body |
| --- | --- | --- |
| 200 | OK | ServiceList |
| default | Any failure. See the Errors section. | Error |

### Get a service

`GET /v1/locations/{locationId}/services/{serviceId}`

Scope: `services:read`

Stability: preview

Also answers for a deleted service, with `status` `deleted`.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `locationId` | path | string | Yes |  |
| `serviceId` | path | string | Yes |  |

**Responses**

| Status | Description | Body |
| --- | --- | --- |
| 200 | OK | Service |
| default | Any failure. See the Errors section. | Error |

### Get a service by id

`GET /v1/services/{serviceId}`

Scope: `services:read`

Stability: preview

The same service as under its location, found from its id. For a caller that holds an id and not the location it belongs to. The answer carries `locationId`.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `serviceId` | path | string | Yes |  |

**Responses**

| Status | Description | Body |
| --- | --- | --- |
| 200 | OK | Service |
| default | Any failure. See the Errors section. | Error |

### List service groups

`GET /v1/locations/{locationId}/service-groups`

Scope: `services:read`

Stability: preview

The groups the location's services are listed under, in display order.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `locationId` | path | string | Yes |  |
| `limit` | query | integer (int32) | No | Page size, 1 to 200. Default 50. |
| `after` | query | string | No | The `nextCursor` of the previous page. |

**Responses**

| Status | Description | Body |
| --- | --- | --- |
| 200 | OK | ServiceGroupList |
| default | Any failure. See the Errors section. | Error |

## Schedules

**Coming soon.** Read and change when a location is open and when each resource works.

## Availability

**Coming soon.** Ask when a service can be booked, across the resources that offer it.

## Bookings

The Bookings API lets an integration read a location's bookings: the ones that start in a period,
or one by id. Use it when another system needs to show or count what is booked, such as a
customer portal, a reporting tool or a screen in the salon. Creating, moving and cancelling
bookings through the API is coming soon.

A booking is a time on one or more resources. Its `type` says what kind it is:

- An `appointment` has the services that were booked and the customers it is for.
- A `class` has services and customers too. It has a number of places, and each customer books
  one.
- A `reservation` only blocks the time, such as a lunch break or a staff meeting. It has no
  service and no customer.

A booking belongs to one location and has an id of the form `bkg_...`. Reading needs the scope
`bookings:read`.

- **The list takes a period**: `from` and `to`, at most 62 days apart, matched against
  `startsAt`. Add `resourceId` for one resource's bookings, or `customerId` for one person's,
  company's or vehicle's.
- **`resources`** names the resources the booking is on. Exactly one is the primary resource, the
  one the booking was made with.
- **`customers`** names the persons, companies and vehicles the booking is for. The id's prefix
  says which type, and that type's API has the full record.
- **A customer on a booking has its `name`**, when the customer has one. A key that also has the scope
  `customers:read` gets the contact details too: the phone numbers, the email address, the
  number that identifies the customer and what the customer wrote when booking
  (`customerNote`). That number is `identityNumber` for a person, `organisationNumber` for a
  company and `registrationNumber` for a vehicle.
- **A customer registered at a location your key cannot use** is returned with its `name` only.
- **The customer's values are the current ones**, read with the booking. Read and change the
  customer itself through its own API.
- **The services are kept as they were when the booking was made**: `name`, `durationMinutes` and
  `price`. A later change to the service, or to the resource service, does not change a booking
  already made. `serviceId` still refers to the service.
- **`startsAt` and `endsAt` are in UTC.** They are the start and end of the time taken on the
  resource. The last `afterTimeMinutes` of that time are kept free after the services, so the
  services end that many minutes before `endsAt`.
- **`status`** is `booked` until staff set `show`, `no_show` or `done`, or the booking is
  `cancelled`. A cancelled booking stays readable and stays in the list.
- **Each customer has a status of their own.** On an appointment it is the booking's. On a class,
  one customer can cancel while the others stay booked. `places` and `placesBooked` say how many
  places the class has and how many are taken.
- **A `nextCursor` here marks a start time, not a booking.** It stays good when the last booking
  of a page is moved or removed before you ask for the next page.
- **A booking that is moved while you page** can show up twice if it moves to a later time, and
  can be missed if it moves to an earlier one. Read the period again when that matters.
- **A booking also has** its `payments`, the `sales` it was sold in, its SMS `reminders`, the
  location's own `customFields`, and the `series` it recurs in.
- **A sale** is identified by `saleId`. It is read in full from the Sales API, which is coming
  soon. Reviews are read from the Reviews API, which is coming soon too.
- **A reservation says what the time is blocked for** in `reservationType`, such as `lunch` or
  `vacation`, when staff gave a reason.
- **Nothing from a patient's medical record is returned.** A location that keeps medical records
  has its health declarations and warnings in the record, not in the booking.
- **A booking that a customer has started online and not yet completed is not returned**, in the
  list or by id.
- Prices follow "Amounts" in the introduction.

### List bookings

`GET /v1/locations/{locationId}/bookings`

Scope: `bookings:read`

Stability: preview

The location's bookings that start in a period, in order of start time, one page at a time. The period is at most 62 days; read a longer one in several calls. Cancelled bookings are included, with `status` `cancelled`. A booking a customer has started online and not yet completed is not.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `locationId` | path | string | Yes |  |
| `from` | query | string | Yes | Only bookings that start at or after this time, in UTC. Example: `2026-10-20T00:00:00Z`. |
| `to` | query | string | Yes | Only bookings that start before this time, in UTC. Example: `2026-10-27T00:00:00Z`. |
| `resourceId` | query | string | No | Only bookings on this resource. |
| `customerId` | query | string | No | Only bookings for this person, company or vehicle. |
| `limit` | query | integer (int32) | No | Page size, 1 to 200. Default 50. |
| `after` | query | string | No | The `nextCursor` of the previous page. |

**Responses**

| Status | Description | Body |
| --- | --- | --- |
| 200 | OK | BookingList |
| default | Any failure. See the Errors section. | Error |

### Get a booking

`GET /v1/locations/{locationId}/bookings/{bookingId}`

Scope: `bookings:read`

Stability: preview

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `locationId` | path | string | Yes |  |
| `bookingId` | path | string | Yes |  |

**Responses**

| Status | Description | Body |
| --- | --- | --- |
| 200 | OK | Booking |
| default | Any failure. See the Errors section. | Error |

### Get a booking by id

`GET /v1/bookings/{bookingId}`

Scope: `bookings:read`

Stability: preview

The same booking as under its location, found from its id. For a caller that holds an id and not the location it belongs to. The answer carries `locationId`.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `bookingId` | path | string | Yes |  |

**Responses**

| Status | Description | Body |
| --- | --- | --- |
| 200 | OK | Booking |
| default | Any failure. See the Errors section. | Error |

## Schemas

### Booking

A time on one or more resources, at one location. An appointment or a class has the services that were booked and the customers it is for. A reservation only blocks the time. The services' names, durations and prices are kept as they were when the booking was made, so a later change to a service does not change the booking.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `afterTimeMinutes` | integer (int32) | Yes | Time kept free on the resource after the services, for cleaning up or resting. It is part of the time between `startsAt` and `endsAt`. Example: `15`. |
| `createdAt` | string (date-time) | Yes |  |
| `customFields` | array of CustomField | Yes | The location's own fields on the booking, with their values. |
| `customers` | array of BookingCustomer | Yes | The customers the booking is for: persons, companies and vehicles. Empty for a reservation, and for a class nobody has booked yet. |
| `description` | string | No | A text of its own for the booking: what a reservation is for, or what staff wrote in place of a service. Example: `Staff meeting`. |
| `doneAt` | string (date-time) | No | When staff set the booking as done. Left out until then. |
| `endsAt` | string (date-time) | Yes | When the time held on the resource ends, in UTC. The last `afterTimeMinutes` of it are the time kept free after the services. Example: `2026-10-20T08:45:00Z`. |
| `id` | string | Yes | Example: `bkg_5Rt8mKq2Wn7Xb4Vd9HyLcA`. |
| `locationId` | string | Yes | Example: `loc_4fK9xQ2mLr8TzB1vNc7HdW`. |
| `minPlaces` | integer (int32) | No | For a class: the fewest customers it runs with. Left out for other bookings. Example: `3`. |
| `note` | string | No | Staff's note on the booking. Not shown to the customer. |
| `payments` | array of BookingPayment | Yes | The payments made for the booking. |
| `places` | integer (int32) | No | For a class: how many places it has. Left out for other bookings. Example: `12`. |
| `placesBooked` | integer (int32) | No | For a class: how many places are booked. Left out for other bookings. Example: `7`. |
| `price` | string | No | The price of the booking as a whole, when it has one. Follows "Amounts" in the introduction. Example: `595.00`. |
| `priceFrom` | boolean | Yes | True when the price is a starting price. Example: `false`. |
| `reminders` | array of BookingReminder | Yes | The SMS reminders for the booking. |
| `reservationType` | string | No | For a reservation: what the time is blocked for, in lower case, such as `lunch` or `vacation`. Left out when staff gave none. The list is open. Example: `lunch`. |
| `resources` | array of BookingResource | Yes | The resources the booking is on. One of them is the primary resource. |
| `sales` | array of BookingSale | Yes | The sales the booking was sold in. |
| `series` | BookingSeries | No | For a booking that recurs: the series it belongs to. |
| `services` | array of BookingService | Yes | The services booked, as they were when booked. Empty for a reservation. |
| `startsAt` | string (date-time) | Yes | When the booking starts, in UTC. Example: `2026-10-20T08:00:00Z`. |
| `status` | string | Yes | `booked`; `show` and `no_show`, which staff set when the customer came or did not; `done`, which staff set when the work is finished; or `cancelled`. For a class, each customer has a status of their own. More values may be added. Example: `booked`. |
| `type` | string | Yes | `appointment`: a time for one customer, or for the customers that come together, such as a person and their vehicle. `class`: a time several customers book a place at. `reservation`: time blocked on the resource, with no customer. The list is open, so accept a value you do not know. Example: `appointment`. |
| `updatedAt` | string (date-time) | Yes |  |

### BookingCustomer

A customer on a booking: a person, a company or a vehicle, with that customer's own status on the booking. It has the customer's name, when there is one. An API key that also has the scope `customers:read` gets the contact details and the number that identifies the customer too, so a booking can be shown without reading each customer. These are the customer's current values. The customer is changed through its own API.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `bookedAs` | string | No | The name the customer was booked under, when it differs from the customer's own. |
| `bookedAt` | string (date-time) | Yes |  |
| `cancelledAt` | string (date-time) | No |  |
| `cancelledChannel` | string | No | Where the customer was cancelled from, with the same values as `channel`. Left out for a customer who is not cancelled. Example: `web`. |
| `channel` | string | Yes | Where the customer was booked from: `web` for online booking, `calendar` for staff in Cliento, `api` for this API. More values may be added. Example: `web`. |
| `customFields` | array of CustomField | Yes | The location's own fields for this customer on the booking. |
| `customerId` | string | Yes | The person, company or vehicle. The id's prefix says which, and that type's API has the rest. Example: `per_2QCtWVSaVO7yCRYBj1zsbA`. |
| `customerNote` | string | No | What the customer wrote when booking online. Only with the scope `customers:read`. |
| `email` | string | No | Only with the scope `customers:read`. Example: `anna.lindqvist@example.com`. |
| `identityNumber` | IdentityNumber | No | For a person: the identity number, such as a personnummer. Only with the scope `customers:read`. |
| `name` | string | No | The customer's name; for a vehicle, what it is called in Cliento. Example: `Anna Lindqvist`. |
| `organisationNumber` | string | No | For a company: the organisation number. Only with the scope `customers:read`. Example: `5560360793`. |
| `otherPhoneNumber` | string | No | Another phone number. Only with the scope `customers:read`. Example: `+4686543210`. |
| `phoneNumber` | string | No | Mobile number. Only with the scope `customers:read`. Example: `+46701234567`. |
| `price` | string | No | This customer's price, where each customer has one, as on a class. Example: `195.00`. |
| `priceFrom` | boolean | Yes | True when the price is a starting price. Example: `false`. |
| `registrationNumber` | string | No | For a vehicle: the registration number. Only with the scope `customers:read`. Example: `ABC123`. |
| `status` | string | Yes | This customer's status on the booking, with the same values as the booking's `status`. It differs from the booking's on a class, where one customer can cancel and the others stay booked. Example: `booked`. |
| `type` | string | Yes | `person`, `company` or `vehicle`. More values may be added. Example: `person`. |

### BookingList

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `data` | array of Booking | Yes |  |
| `nextCursor` | string | No | Pass as `after` to fetch the next page. Absent on the last page. Example: `1792483200000.bkg_5Rt8mKq2Wn7Xb4Vd9HyLcA`. |

### BookingPayment

A payment for a booking: made online when booking, in advance, or at the point of sale. Belongs to the booking, and to one of its customers when it was made for one.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `amount` | string | Yes | Example: `595.00`. |
| `customerId` | string | No | The customer the payment was made for, when it was made for one. Example: `per_2QCtWVSaVO7yCRYBj1zsbA`. |
| `paidOn` | string (date) | No | The day of the payment, in the location's time zone. Example: `2026-10-18`. |
| `provider` | string | Yes | Who handled the payment, in lower case, such as `stripe` or `klarna`. The list is open, so accept a value you do not know. Example: `stripe`. |
| `reference` | string | No | The payment's reference, as shown to the customer. |
| `refundedAmount` | string | Yes | Example: `0.00`. |
| `refundedOn` | string (date) | No | The day of the refund, when there is one. |
| `status` | string | Yes | `paid`, `unpaid`, or a refund state such as `refunded` or `refunded_partially`. More values may be added. Example: `paid`. |
| `type` | string | Yes | `online` for a payment made when booking online, `pre_paid` for one made in advance, `pos` for one made at the point of sale. More values may be added. Example: `online`. |

### BookingReminder

An SMS reminder sent, or to be sent, to a customer about a booking.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `customerId` | string | Yes | Example: `per_2QCtWVSaVO7yCRYBj1zsbA`. |
| `status` | string | Yes | How far the message has come, in lower case, such as `pending`, `sent` or `delivered`. The list is open, so accept a value you do not know. Example: `delivered`. |
| `statusAt` | string (date-time) | Yes | When it got that status. |
| `type` | string | Yes | `pre_reminder` for one sent before the booking; `post_reminder1` and `post_reminder2` for those sent after it. More values may be added. Example: `pre_reminder`. |

### BookingResource

A resource a booking is on.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `primary` | boolean | Yes | True for the booking's primary resource: the one it was booked with. A booking has exactly one. The others are held for the same time, such as a room. Example: `true`. |
| `resourceId` | string | Yes | Example: `res_4Hn7pQw2Zt9Lk3Vd6XyRbA`. |

### BookingSale

A sale that a booking was sold in: a sale at the point of sale, an order or an invoice. The sale belongs to a merchant and is read in full from the Sales API, which is coming soon; this is the part a booking refers to.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `createdAt` | string (date-time) | No | When the sale was created. |
| `customerId` | string | No | The customer the sale was made to, when it names one. Example: `per_2QCtWVSaVO7yCRYBj1zsbA`. |
| `invoiceStatus` | string | No | For a sale with an invoice: whether the invoice is paid, such as `unpaid` or `paid`. The list is open. Example: `unpaid`. |
| `paidAmount` | string | Yes | What has been paid in the sale as a whole. A sale can cover more than this booking. Example: `595.00`. |
| `saleId` | string | Yes | Example: `sal_8Hd3kWq5Zn2Tb7Xc4LmPyR`. |
| `status` | string | Yes | The sale's state, in lower case, such as `open`, `paid` or `void`. The list is open, so accept a value you do not know. Example: `paid`. |
| `type` | string | Yes | `pos_sale`, `order` or `invoice`. More values may be added. Example: `pos_sale`. |

### BookingSeries

A series of bookings that recur. Each booking in it is a booking of its own and has the series' id. The series has the rule the bookings were made from.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | string | Yes | Example: `bks_6Wq2nYd8Rk4Tc9Xb3HmLzP`. |
| `recurrenceRule` | string | Yes | The recurrence rule, as an iCalendar RRULE. Example: `FREQ=WEEKLY;COUNT=10`. |

### BookingService

A service on a booking, with its name, duration and price as they were when it was booked.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `durationMinutes` | integer (int32) | Yes | Example: `45`. |
| `name` | string | Yes | Example: `Haircut`. |
| `price` | string | No | Example: `595.00`. |
| `priceFrom` | boolean | Yes | True when the price is a starting price. Example: `false`. |
| `serviceId` | string | Yes | Example: `svc_3Gk8rTn5Ym1Wc7Zp2LdQxB`. |

### CustomField

A field a location has added of its own, with the value given for one booking or one customer on it.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `key` | string | Yes | Example: `allergies`. |
| `label` | string | No | Example: `Allergies`. |
| `type` | string | No | The kind of field, in lower case, such as `text` or `checkbox`. The list is open. Example: `text`. |
| `value` | any value | No | The value, of the JSON type the field holds. Left out when not given. Example: `None`. |

### Error

The body of every non-2xx response.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `code` | string | Yes | Stable, machine-readable error code. Values today: `invalid_request`, `validation_failed`, `entity_not_found`, `duplicate`, `merchant_required`, `code_already_used`, `gift_card_already_used`, `pin_not_recognised`, `insufficient_stock`, `not_allowed`, `request_in_progress`, `idempotency_key_reused`, `unauthenticated`, `forbidden`, `account_blocked`, `rate_limited`, `route_not_found`, `method_not_allowed`, `internal_error`. |
| `details` | object of any value | No | Extra detail. For `validation_failed`, `fieldErrors` maps each rejected field to the reason. |
| `message` | string | Yes | Human-readable explanation. Not stable; do not parse it. |

### IdentityNumber

A number issued by an authority that identifies a person, such as a personnummer. The accepted format of each type is listed under Persons.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `number` | string | Yes | In the format of its type: twelve digits for a Swedish personnummer. Example: `198604122385`. |
| `type` | string | Yes | The kind of number, in lower case, such as `se_personnummer` or `foreign`. More values may be added. Example: `se_personnummer`. |

### Resource

What gets booked: most often a person, sometimes a room or a piece of equipment. A resource belongs to one location.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `createdAt` | string (date-time) | No | When it was created, in UTC. Left out when that is not known. Example: `2026-03-02T08:15:00Z`. |
| `groupId` | string | No | The group the resource is listed under. Left out for a deleted resource. Example: `rgr_5Jk9wQe2Ty6Nb3Vx8MzLcA`. |
| `id` | string | Yes | Example: `res_4Hn7pQw2Zt9Lk3Vd6XyRbA`. |
| `locationId` | string | Yes | Example: `loc_4fK9xQ2mLr8TzB1vNc7HdW`. |
| `name` | string | Yes | The name staff see in the calendar. Example: `Anna`. |
| `onlineBookingEnabled` | boolean | Yes | Whether the resource is open for online booking at all. Which services customers may book with it is on the resource service. Example: `true`. |
| `onlineName` | string | No | The name customers see in online booking, when it differs. Example: `Anna L.`. |
| `pausedUntil` | string | No | For a paused resource: the last day of the pause. Example: `2026-12-31`. |
| `status` | string | Yes | `active`, `paused` or `deleted`. A paused resource is paused for billing: it keeps its bookings but takes no new online bookings. A deleted resource is left out of the list but still answers by id, since earlier bookings refer to it. The status is not changed through the API. More values may be added. Example: `active`. |
| `type` | string | Yes | What kind of thing it is, as one lower-case word such as `person` or `room`. Set when the resource is created. The list is open, so accept a value you do not know. Example: `person`. |
| `updatedAt` | string (date-time) | Yes | When it last changed, in UTC. Example: `2026-10-12T09:24:31.512Z`. |

### ResourceGroup

A group of resources: a heading the location lists them under, such as "Stylists" or "Rooms".

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | string | Yes | Example: `rgr_5Jk9wQe2Ty6Nb3Vx8MzLcA`. |
| `locationId` | string | Yes | Example: `loc_4fK9xQ2mLr8TzB1vNc7HdW`. |
| `name` | string | Yes | Example: `Stylists`. |

### ResourceGroupList

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `data` | array of ResourceGroup | Yes |  |
| `nextCursor` | string | No | Pass as `after` to fetch the next page. Absent on the last page. Example: `rgr_5Jk9wQe2Ty6Nb3Vx8MzLcA`. |

### ResourceList

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `data` | array of Resource | Yes |  |
| `nextCursor` | string | No | Pass as `after` to fetch the next page. Absent on the last page. Example: `res_4Hn7pQw2Zt9Lk3Vd6XyRbA`. |

### ResourceService

A service as one resource offers it: what is booked. It is identified by its resource and its service. The name, description, group, type and VAT are the service's, and are changed on the service. The duration, after-time, price and online booking setting are the service's defaults, unless the resource overrides them with its own, as `ownValues` says.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `addOn` | boolean | Yes | An add-on is booked together with another service, never on its own. Example: `false`. |
| `afterTimeMinutes` | integer (int32) | Yes | Time kept free after the booking, for cleaning up or resting. Example: `15`. |
| `description` | string | No | The service's description. Example: `Wash, cut and styling.`. |
| `durationMinutes` | integer (int32) | Yes | Example: `45`. |
| `groupId` | string | No | The group the service is listed under. Example: `sgr_8Vc2nXd5Rt1Kq7Lm4HwYpZ`. |
| `locationId` | string | Yes | Example: `loc_4fK9xQ2mLr8TzB1vNc7HdW`. |
| `name` | string | Yes | The service's name. Example: `Haircut`. |
| `onlineBookingAllowed` | boolean | Yes | Whether customers may book the service with this resource in online booking. Online booking also requires that the service is shown online (`shownOnline`) and that the resource is open for online booking (`onlineBookingEnabled`). Example: `true`. |
| `ownValues` | boolean | Yes | False: the resource service follows the service, and its duration, after-time, price and online booking setting are the service's defaults and change with them. True: it overrides them with its own, which stay when the service changes. Example: `false`. |
| `price` | string | Yes | Example: `650.00`. |
| `priceFrom` | boolean | Yes | True when the price is a starting price, shown to customers as "from". Example: `false`. |
| `resourceId` | string | Yes | Example: `res_4Hn7pQw2Zt9Lk3Vd6XyRbA`. |
| `serviceId` | string | Yes | Example: `svc_3Gk8rTn5Ym1Wc7Zp2LdQxB`. |
| `shownOnline` | boolean | Yes | Whether the service is shown to customers in online booking. Example: `true`. |
| `type` | string | Yes | How the service is booked, such as `appointment` or `class`. The same value as the service's `type`. The list is open, so accept a value you do not know. Example: `appointment`. |
| `updatedAt` | string (date-time) | Yes | When it last changed, in UTC. Example: `2026-10-12T09:24:31.512Z`. |
| `vatParts` | array of ServiceVatPart | No | For a service that consists of parts accounted for at different VAT rates, such as a vaccine with no VAT and a certificate at 25 %: the service's parts, at the service's default prices. Left out for every other service. |
| `vatPercent` | string | Yes | The service's VAT rate, included in the price. A service with `vatParts` is sold with each part at its own rate when it is paid for at the point of sale or online. This is then the single rate used where the service is not split into its parts. Example: `25`. |

### ResourceServiceList

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `data` | array of ResourceService | Yes |  |
| `nextCursor` | string | No | Pass as `after` to fetch the next page. Absent on the last page. Example: `svc_3Gk8rTn5Ym1Wc7Zp2LdQxB`. |

### Service

A service as the location defines it: something the location offers, with its name and the default duration, price and settings. Belongs to a location. What is booked is a resource service, which follows these defaults unless the resource overrides them.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `addOn` | boolean | Yes | An add-on is booked together with another service, never on its own. Example: `false`. |
| `afterTimeMinutes` | integer (int32) | Yes | Time kept free after the booking, for cleaning up or resting. Example: `15`. |
| `createdAt` | string (date-time) | No | When it was created, in UTC. Left out when that is not known. Example: `2026-03-02T08:15:00Z`. |
| `description` | string | No | Example: `Wash, cut and styling.`. |
| `durationMinutes` | integer (int32) | Yes | Example: `45`. |
| `groupId` | string | No | The group the service is listed under. Left out for a deleted service. Example: `sgr_8Vc2nXd5Rt1Kq7Lm4HwYpZ`. |
| `id` | string | Yes | Example: `svc_3Gk8rTn5Ym1Wc7Zp2LdQxB`. |
| `locationId` | string | Yes | Example: `loc_4fK9xQ2mLr8TzB1vNc7HdW`. |
| `name` | string | Yes | Example: `Haircut`. |
| `onlineBookingAllowed` | boolean | Yes | The default for the service's resource services: whether customers may book the service themselves in online booking. A resource can override it. A service can be shown without being bookable, so that customers see it and call. Example: `true`. |
| `price` | string | Yes | Example: `595.00`. |
| `priceFrom` | boolean | Yes | True when the price is a starting price, shown to customers as "from". Example: `false`. |
| `resourceServices` | array of ResourceService | Yes | The service's resource services: one for each resource the service can be booked for. The same resource services are read per resource under `/resources/{resourceId}/services`. |
| `shownOnline` | boolean | Yes | Whether the service is shown to customers in online booking. Example: `true`. |
| `status` | string | Yes | `active`, or `deleted` for a service that has been removed: it is left out of the list but still answers by id, since earlier bookings refer to it. More values may be added. Example: `active`. |
| `type` | string | Yes | How it is booked, as one lower-case word such as `appointment` or `class`. Set when the service is created. The list is open, so accept a value you do not know. Example: `appointment`. |
| `updatedAt` | string (date-time) | Yes | When it last changed, in UTC. Example: `2026-10-12T09:24:31.512Z`. |
| `vatParts` | array of ServiceVatPart | No | For a service that consists of parts accounted for at different VAT rates, such as a vaccine with no VAT and a certificate at 25 %: the parts. Left out for every other service. |
| `vatPercent` | string | Yes | The VAT rate included in the price. A service with `vatParts` is sold with each part at its own rate when it is paid for at the point of sale or online. This is then the single rate used where the service is not split into its parts. Example: `25`. |

### ServiceGroup

A group of services: a heading the location lists them under, such as "Hair" or "Colour".

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `addOns` | boolean | Yes | True for the group that holds the location's add-ons. Example: `false`. |
| `id` | string | Yes | Example: `sgr_8Vc2nXd5Rt1Kq7Lm4HwYpZ`. |
| `locationId` | string | Yes | Example: `loc_4fK9xQ2mLr8TzB1vNc7HdW`. |
| `name` | string | Yes | Example: `Hair`. |

### ServiceGroupList

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `data` | array of ServiceGroup | Yes |  |
| `nextCursor` | string | No | Pass as `after` to fetch the next page. Absent on the last page. Example: `sgr_8Vc2nXd5Rt1Kq7Lm4HwYpZ`. |

### ServiceList

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `data` | array of Service | Yes |  |
| `nextCursor` | string | No | Pass as `after` to fetch the next page. Absent on the last page. Example: `svc_3Gk8rTn5Ym1Wc7Zp2LdQxB`. |

### ServiceVatPart

One part of a service that consists of several, with its share of the price and the VAT rate that part is booked at.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `description` | string | Yes | Example: `Treatment`. |
| `price` | string | Yes | Example: `600.00`. |
| `vatPercent` | string | Yes | Example: `25`. |
