# API reference: Bookings

> Every bookings endpoint: what it takes, what it answers with, and which key it needs.

## When a service can be booked

`GET /api/v1/availability` · Any key

| Parameter | Type | Required | |
|---|---|---|---|
| `from` | string |  | Local date, YYYY-MM-DD. Defaults to today. |
| `service` | string | yes | Service id. |
| `staff` | string |  | Only this member of staff. |
| `to` | string |  | Local date, YYYY-MM-DD. Defaults to `from`. |

Answers `200` with [Availability](#availability).

## The rules a booking has to satisfy

`GET /api/v1/booking-settings` · Any key

Answers `200` with [BookingSettings](#bookingsettings).

## List dated closures and special hours

`GET /api/v1/booking-setup/closures` · Secret key only

| Parameter | Type | Required | |
|---|---|---|---|
| `from` | string |  | Local date, YYYY-MM-DD. Defaults to today. |
| `page` | integer |  |  |
| `page_size` | integer |  |  |
| `to` | string |  | Local date, YYYY-MM-DD. |

Answers `200` with [PaginatedClosureList](#paginatedclosurelist).

## Set a dated closure or special hours

`POST /api/v1/booking-setup/closures` · Secret key only

| Field | Type | Required | |
|---|---|---|---|
| `date` | date | yes | Local date, YYYY-MM-DD. |
| `staff` | uuid or null |  | One person's. Left out, the whole business's. |
| `closed` | boolean | yes | True closes the date all day; false opens it between `start` and `end` alone. |
| `start` | time or null |  | Local wall clock, HH:MM. |
| `end` | time or null |  | Local wall clock, HH:MM. |
| `reason` | string |  |  |

Answers `200` with [Closure](#closure).

## Remove a dated closure

`POST /api/v1/booking-setup/closures/remove` · Secret key only

| Field | Type | Required | |
|---|---|---|---|
| `date` | date | yes | Local date, YYYY-MM-DD. |
| `staff` | uuid or null |  | One person's. Left out, the whole business's. |

Answers `200` with [ClosureRemoved](#closureremoved).

## Fetch the opening hours

`GET /api/v1/booking-setup/hours` · Secret key only

Answers `200` with [Hours](#hours).

## Set opening hours

`POST /api/v1/booking-setup/hours` · Secret key only

| Field | Type | Required | |
|---|---|---|---|
| `staff` | uuid or null |  | One person's own hours. Left out, the business's. |
| `monday` | list of [WindowRequest](#windowrequest) |  | Replaces every block of that day. An empty list closes it; a day left out keeps its hours. |
| `tuesday` | list of [WindowRequest](#windowrequest) |  | Replaces every block of that day. An empty list closes it; a day left out keeps its hours. |
| `wednesday` | list of [WindowRequest](#windowrequest) |  | Replaces every block of that day. An empty list closes it; a day left out keeps its hours. |
| `thursday` | list of [WindowRequest](#windowrequest) |  | Replaces every block of that day. An empty list closes it; a day left out keeps its hours. |
| `friday` | list of [WindowRequest](#windowrequest) |  | Replaces every block of that day. An empty list closes it; a day left out keeps its hours. |
| `saturday` | list of [WindowRequest](#windowrequest) |  | Replaces every block of that day. An empty list closes it; a day left out keeps its hours. |
| `sunday` | list of [WindowRequest](#windowrequest) |  | Replaces every block of that day. An empty list closes it; a day left out keeps its hours. |

Answers `200` with [Hours](#hours).

## Put somebody on the business's hours

`POST /api/v1/booking-setup/hours/shared` · Secret key only

| Field | Type | Required | |
|---|---|---|---|
| `staff` | uuid | yes | Who goes back to the business's week, their own hours removed. |

Answers `200` with [Hours](#hours).

## Fetch every booking rule

`GET /api/v1/booking-setup/rules` · Secret key only

Answers `200` with [Rules](#rules).

## Change the booking rules

`POST /api/v1/booking-setup/rules` · Secret key only

| Field | Type | Required | |
|---|---|---|---|
| `confirmation_mode` | [ConfirmationModeEnum](#confirmationmodeenum) |  |  |
| `payment_mode` | [PaymentModeEnum](#paymentmodeenum) |  |  |
| `deposit_type` | [DepositTypeEnum](#deposittypeenum) |  | Send `deposit_value` with a new type, since its number reads differently under each. * `percent` - percent * `fixed` - fixed |
| `deposit_value` | integer |  | A percentage up to 100 when `deposit_type` is percent, minor units when it is fixed. |
| `min_lead_minutes` | integer |  | The shortest notice, at most a year. |
| `max_horizon_days` | integer |  | How many days ahead. |
| `slot_granularity_minutes` | [SlotGranularityMinutesEnum](#slotgranularityminutesenum) |  | A divisor of the hour. * `5` - 5 * `10` - 10 * `15` - 15 * `20` - 20 * `30` - 30 * `60` - 60 |
| `cancellation_window_minutes` | integer |  | 0 means customers ring up to cancel. |
| `payment_window_minutes` | integer |  |  |
| `allow_customer_reschedule` | boolean |  |  |
| `max_per_customer_per_day` | integer or null |  | Null means no limit. |
| `require_phone` | boolean |  |  |
| `reminder_hours` | [ReminderHoursEnum](#reminderhoursenum) or NullEnum |  | Hours before the appointment, one of the values listed. Null sends no reminder. * `2` - 2 * `4` - 4 * `12` - 12 * `24` - 24 * `48` - 48 * `72` - 72 |
| `manage_url` | string |  | An https address on the website. It must carry {token}, where the booking's manage token goes, and may carry {id}. Empty links to the page this platform hosts for each booking. |

Answers `200` with [Rules](#rules).

## Make the test rules the live rules

`POST /api/v1/booking-setup/rules/apply` · Secret key only

Answers `200` with [Rules](#rules).

## Drop the test rules

`POST /api/v1/booking-setup/rules/discard` · Secret key only

Answers `200` with [Rules](#rules).

## List every service as it is set up

`GET /api/v1/booking-setup/services` · Secret key only

| Parameter | Type | Required | |
|---|---|---|---|
| `page` | integer |  |  |
| `page_size` | integer |  |  |

Answers `200` with [PaginatedServiceSetupList](#paginatedservicesetuplist).

## Add a service

`POST /api/v1/booking-setup/services` · Secret key only · needs an `Idempotency-Key`

| Field | Type | Required | |
|---|---|---|---|
| `name` | string | yes |  |
| `description` | string |  |  |
| `duration_minutes` | integer | yes | Minutes with the customer. |
| `buffer_before_minutes` | integer |  | Minutes blocked before it, not sold. |
| `buffer_after_minutes` | integer |  | Minutes blocked after it, not sold. |
| `price_amount` | integer |  | Minor units of the website's currency, so 6500 is 65.00. 0 takes no payment for it. |
| `payment_mode` | [ServicePaymentModeEnum](#servicepaymentmodeenum) |  | `inherit`, the default, follows the booking rules. * `inherit` - inherit * `none` - none * `optional` - optional * `required` - required * `deposit` - deposit |
| `is_active` | boolean |  | Offered to customers. True when left out. |

Answers `201` with [ServiceSetup](#servicesetup).

## Change a service

`POST /api/v1/booking-setup/services/{service_id}` · Secret key only

| Parameter | Type | Required | |
|---|---|---|---|
| `service_id` | uuid | yes |  |

| Field | Type | Required | |
|---|---|---|---|
| `name` | string |  |  |
| `description` | string |  |  |
| `duration_minutes` | integer |  | Minutes with the customer. |
| `buffer_before_minutes` | integer |  | Minutes blocked before it, not sold. |
| `buffer_after_minutes` | integer |  | Minutes blocked after it, not sold. |
| `price_amount` | integer |  | Minor units of the website's currency, so 6500 is 65.00. 0 takes no payment for it. |
| `payment_mode` | [ServicePaymentModeEnum](#servicepaymentmodeenum) |  | `inherit`, the default, follows the booking rules. * `inherit` - inherit * `none` - none * `optional` - optional * `required` - required * `deposit` - deposit |
| `is_active` | boolean |  | Offered to customers. True when left out. |

Answers `200` with [ServiceSetup](#servicesetup).

## Remove a service

`POST /api/v1/booking-setup/services/{service_id}/delete` · Secret key only

| Parameter | Type | Required | |
|---|---|---|---|
| `service_id` | uuid | yes |  |

Answers `200` with [Removed](#removed).

## Make a test-only service live

`POST /api/v1/booking-setup/services/{service_id}/make-live` · Secret key only

| Parameter | Type | Required | |
|---|---|---|---|
| `service_id` | uuid | yes |  |

Answers `200` with [ServiceSetup](#servicesetup).

## Move a service up or down the list

`POST /api/v1/booking-setup/services/{service_id}/move` · Secret key only · needs an `Idempotency-Key`

| Parameter | Type | Required | |
|---|---|---|---|
| `service_id` | uuid | yes |  |

| Field | Type | Required | |
|---|---|---|---|
| `direction` | [DirectionEnum](#directionenum) | yes | Swap with the one before, or after. * `up` - up * `down` - down |

Answers `200` with [ServiceSetup](#servicesetup).

## Set who does a service, and on what terms

`POST /api/v1/booking-setup/services/{service_id}/staff` · Secret key only

| Parameter | Type | Required | |
|---|---|---|---|
| `service_id` | uuid | yes |  |

| Field | Type | Required | |
|---|---|---|---|
| `staff` | uuid | yes | Who does it. |
| `price_amount` | integer or null |  | Their own price in minor units. Left out or null charges the service's. |
| `duration_minutes` | integer or null |  | Their own minutes with the customer. Left out or null takes the service's. |

Answers `200` with [ServiceSetup](#servicesetup).

## Take somebody off a service

`POST /api/v1/booking-setup/services/{service_id}/staff/{staff_id}/remove` · Secret key only

| Parameter | Type | Required | |
|---|---|---|---|
| `service_id` | uuid | yes |  |
| `staff_id` | uuid | yes |  |

Answers `200` with [ServiceSetup](#servicesetup).

## List everybody as they are set up

`GET /api/v1/booking-setup/staff` · Secret key only

| Parameter | Type | Required | |
|---|---|---|---|
| `page` | integer |  |  |
| `page_size` | integer |  |  |

Answers `200` with [PaginatedStaffSetupList](#paginatedstaffsetuplist).

## Add somebody who takes bookings

`POST /api/v1/booking-setup/staff` · Secret key only · needs an `Idempotency-Key`

| Field | Type | Required | |
|---|---|---|---|
| `name` | string | yes |  |
| `email` | email or empty |  | For their own notifications. Never shown to customers. |
| `phone` | string |  |  |
| `timezone` | string |  | An IANA zone such as Europe/Zurich, for somebody working on another clock. Empty is the website's. |
| `is_active` | boolean |  | Taking bookings. True when left out. |

Answers `201` with [StaffSetup](#staffsetup).

## Change somebody's details

`POST /api/v1/booking-setup/staff/{staff_id}` · Secret key only

| Parameter | Type | Required | |
|---|---|---|---|
| `staff_id` | uuid | yes |  |

| Field | Type | Required | |
|---|---|---|---|
| `name` | string |  |  |
| `email` | email or empty |  | For their own notifications. Never shown to customers. |
| `phone` | string |  |  |
| `timezone` | string |  | An IANA zone such as Europe/Zurich, for somebody working on another clock. Empty is the website's. |
| `is_active` | boolean |  | Taking bookings. True when left out. |

Answers `200` with [StaffSetup](#staffsetup).

## Remove somebody

`POST /api/v1/booking-setup/staff/{staff_id}/delete` · Secret key only

| Parameter | Type | Required | |
|---|---|---|---|
| `staff_id` | uuid | yes |  |

Answers `200` with [Removed](#removed).

## Make a test-only person live

`POST /api/v1/booking-setup/staff/{staff_id}/make-live` · Secret key only

| Parameter | Type | Required | |
|---|---|---|---|
| `staff_id` | uuid | yes |  |

Answers `200` with [StaffSetup](#staffsetup).

## Move somebody up or down the list

`POST /api/v1/booking-setup/staff/{staff_id}/move` · Secret key only · needs an `Idempotency-Key`

| Parameter | Type | Required | |
|---|---|---|---|
| `staff_id` | uuid | yes |  |

| Field | Type | Required | |
|---|---|---|---|
| `direction` | [DirectionEnum](#directionenum) | yes | Swap with the one before, or after. * `up` - up * `down` - down |

Answers `200` with [StaffSetup](#staffsetup).

## List bookings

`GET /api/v1/bookings` · Secret key only

| Parameter | Type | Required | |
|---|---|---|---|
| `from` | string |  | Local date, YYYY-MM-DD. |
| `page` | integer |  | A page number within the paginated result set. |
| `page_size` | integer |  | Number of results to return per page. |
| `status` | string |  | One of `pending_payment`, `pending_confirmation`, `confirmed`, `cancelled`, `expired`, `completed`, `no_show`. |
| `to` | string |  | Local date, YYYY-MM-DD. |

Answers `200` with [PaginatedBookingList](#paginatedbookinglist).

## Book an appointment

`POST /api/v1/bookings` · Any key · needs an `Idempotency-Key`

| Field | Type | Required | |
|---|---|---|---|
| `service` | uuid | yes |  |
| `starts_at` | date-time | yes |  |
| `staff` | uuid or null |  |  |
| `customer_email` | email | yes |  |
| `customer_name` | string |  |  |
| `customer_phone` | string |  |  |
| `notes` | string |  |  |
| `success_url` | uri or empty |  | With a publishable key, on one of the key's allowed origins, and https for a live key. A secret key may name any URL. {id} in it becomes the booking's id. |
| `cancel_url` | uri or empty |  | With a publishable key, on one of the key's allowed origins, and https for a live key. A secret key may name any URL. {id} in it becomes the booking's id. |

Answers `201` with [Booking](#booking).

## Fetch one booking

`GET /api/v1/bookings/{booking_id}` · Any key

| Parameter | Type | Required | |
|---|---|---|---|
| `booking_id` | uuid | yes |  |
| `token` | string |  | The booking's manage token. |

Answers `200` with [Booking](#booking).

## Cancel a booking

`POST /api/v1/bookings/{booking_id}/cancel` · Any key

| Parameter | Type | Required | |
|---|---|---|---|
| `booking_id` | uuid | yes |  |

| Field | Type | Required | |
|---|---|---|---|
| `token` | string |  | This booking's manage token. Not needed with a secret key. |
| `reason` | string |  |  |

Answers `200` with [Booking](#booking).

## Open a payment page for an existing booking

`POST /api/v1/bookings/{booking_id}/checkout` · Any key

| Parameter | Type | Required | |
|---|---|---|---|
| `booking_id` | uuid | yes |  |

| Field | Type | Required | |
|---|---|---|---|
| `token` | string |  | This booking's manage token. Not needed with a secret key. |
| `success_url` | uri or empty |  | With a publishable key, on one of the key's allowed origins, and https for a live key. A secret key may name any URL. {id} in it becomes the booking's id. |
| `cancel_url` | uri or empty |  | With a publishable key, on one of the key's allowed origins, and https for a live key. A secret key may name any URL. {id} in it becomes the booking's id. |

Answers `200` with [Booking](#booking).

## Move a booking to another time

`POST /api/v1/bookings/{booking_id}/reschedule` · Any key

| Parameter | Type | Required | |
|---|---|---|---|
| `booking_id` | uuid | yes |  |

| Field | Type | Required | |
|---|---|---|---|
| `token` | string |  | This booking's manage token. Not needed with a secret key. |
| `starts_at` | date-time | yes |  |
| `staff` | uuid or null |  |  |

Answers `200` with [Booking](#booking).

## List bookable services

`GET /api/v1/services` · Any key

| Parameter | Type | Required | |
|---|---|---|---|
| `page` | integer |  | A page number within the paginated result set. |
| `page_size` | integer |  | Number of results to return per page. |

Answers `200` with [PaginatedServiceList](#paginatedservicelist).

## Fetch one service

`GET /api/v1/services/{service_id}` · Any key

| Parameter | Type | Required | |
|---|---|---|---|
| `service_id` | uuid | yes |  |

Answers `200` with [Service](#service).

## List staff who take bookings

`GET /api/v1/staff` · Any key

| Parameter | Type | Required | |
|---|---|---|---|
| `page` | integer |  | A page number within the paginated result set. |
| `page_size` | integer |  | Number of results to return per page. |

Answers `200` with [PaginatedStaffList](#paginatedstafflist).

## Fetch one member of staff

`GET /api/v1/staff/{staff_id}` · Any key

| Parameter | Type | Required | |
|---|---|---|---|
| `staff_id` | uuid | yes |  |

Answers `200` with [Staff](#staff).

## Shapes

### Availability

| Field | Type | Always there | |
|---|---|---|---|
| `timezone` | string | yes |  |
| `service` | uuid | yes |  |
| `slots` | list of [Slot](#slot) | yes |  |

### BookingSettings

| Field | Type | Always there | |
|---|---|---|---|
| `timezone` | string | yes |  |
| `currency` | string | yes |  |
| `payment_mode` | string | yes | One of `none`, `optional`, `required`, `deposit`. |
| `confirmation_mode` | string | yes | One of `automatic`, `manual`. |
| `min_lead_minutes` | integer | yes |  |
| `max_horizon_days` | integer | yes |  |
| `slot_granularity_minutes` | integer | yes |  |
| `cancellation_window_minutes` | integer | yes |  |
| `allow_customer_reschedule` | boolean | yes |  |
| `require_phone` | boolean | yes |  |

### PaginatedClosureList

| Field | Type | Always there | |
|---|---|---|---|
| `count` | integer | yes |  |
| `results` | list of [Closure](#closure) | yes |  |

### Closure

| Field | Type | Always there | |
|---|---|---|---|
| `date` | date | yes | Local date, YYYY-MM-DD. |
| `staff` | uuid or null | yes | One person's. Null for the whole business. |
| `closed` | boolean | yes | Closed all day, rather than open between `start` and `end`. |
| `start` | time or null | yes |  |
| `end` | time or null | yes |  |
| `reason` | string | yes |  |

### ClosureRemoved

| Field | Type | Always there | |
|---|---|---|---|
| `date` | date | yes |  |
| `staff` | uuid or null | yes |  |
| `removed` | boolean | yes | False when the date already followed the week. |

### Hours

| Field | Type | Always there | |
|---|---|---|---|
| `timezone` | string | yes | The website's clock, which the business's hours are read on. |
| `business` | [Week](#week) | yes |  |
| `staff` | list of [StaffHours](#staffhours) | yes |  |

### Rules

| Field | Type | Always there | |
|---|---|---|---|
| `test_copy` | boolean | yes | Whether test keys are held to a test copy of the rules. A test key reads that copy here when there is one, and the live rules otherwise. |
| `confirmation_mode` | string | yes | One of `automatic`, `manual`. |
| `payment_mode` | string | yes | One of `none`, `optional`, `required`, `deposit`. |
| `deposit_type` | string | yes | One of `percent`, `fixed`. |
| `deposit_value` | integer | yes | A percentage when `deposit_type` is percent, minor units when it is fixed. |
| `min_lead_minutes` | integer | yes | The shortest notice a booking may be made at. |
| `max_horizon_days` | integer | yes | How many days ahead a booking may be made. |
| `slot_granularity_minutes` | integer | yes | How often a time is offered, on the clock. |
| `cancellation_window_minutes` | integer | yes | Until how long before the appointment a customer may cancel. 0 means they ring up. |
| `payment_window_minutes` | integer | yes | How long an unpaid booking holds its time. |
| `allow_customer_reschedule` | boolean | yes |  |
| `max_per_customer_per_day` | integer or null | yes | Null means no limit. |
| `require_phone` | boolean | yes |  |
| `reminder_hours` | integer or null | yes | How many hours before the appointment a confirmed customer is reminded by email. Null sends no reminder. |
| `manage_url` | string | yes | Where a customer manages their booking on the website, with {id} and {token} filled in. Empty links to the page this platform hosts for each booking. |

### PaginatedServiceSetupList

| Field | Type | Always there | |
|---|---|---|---|
| `count` | integer | yes |  |
| `results` | list of [ServiceSetup](#servicesetup) | yes |  |

### ServiceSetup

| Field | Type | Always there | |
|---|---|---|---|
| `id` | uuid | yes |  |
| `slug` | string | yes |  |
| `name` | string | yes |  |
| `description` | string | yes |  |
| `duration_minutes` | integer | yes | Minutes with the customer. |
| `buffer_before_minutes` | integer | yes | Minutes blocked before it, not sold. |
| `buffer_after_minutes` | integer | yes | Minutes blocked after it, not sold. |
| `price` | [Money](#money) | yes |  |
| `payment_mode` | string | yes | One of `inherit`, `none`, `optional`, `required`, `deposit`. `inherit` follows the booking rules. |
| `is_active` | boolean | yes | Offered to customers. False once retired. |
| `test_only` | boolean | yes | Offered to test keys alone, until made live. |
| `bookable` | boolean | yes | Whether a customer can book it now: active, and somebody taking bookings does it. For a test key, test-only rows count. |
| `sort_order` | integer | yes |  |
| `staff` | list of [SetupLink](#setuplink) | yes | Who does it, and on what terms. |

### Removed

| Field | Type | Always there | |
|---|---|---|---|
| `id` | uuid | yes |  |
| `result` | [ResultEnum](#resultenum) | yes | `retired` when it has appointments on record: it is kept, and offered to nobody. * `deleted` - deleted * `retired` - retired |

### PaginatedStaffSetupList

| Field | Type | Always there | |
|---|---|---|---|
| `count` | integer | yes |  |
| `results` | list of [StaffSetup](#staffsetup) | yes |  |

### StaffSetup

| Field | Type | Always there | |
|---|---|---|---|
| `id` | uuid | yes |  |
| `name` | string | yes |  |
| `email` | string | yes | For their own notifications. Never shown to customers. |
| `phone` | string | yes |  |
| `timezone` | string | yes | Their own clock. Empty means the website's. |
| `is_active` | boolean | yes | Taking bookings. False once retired. |
| `test_only` | boolean | yes | Offered to test keys alone, until made live. |
| `own_hours` | boolean | yes | Whether they keep hours of their own, or work the business's. |
| `sort_order` | integer | yes |  |
| `services` | list of uuid | yes | The services they do. |

### PaginatedBookingList

| Field | Type | Always there | |
|---|---|---|---|
| `count` | integer | yes |  |
| `results` | list of [Booking](#booking) | yes |  |

### Booking

| Field | Type | Always there | |
|---|---|---|---|
| `id` | uuid | yes |  |
| `livemode` | boolean | yes | False for a booking a test key made, which is test data. |
| `status` | string | yes | One of `pending_payment`, `pending_confirmation`, `confirmed`, `cancelled`, `expired`, `completed`, `no_show`. |
| `starts_at` | date-time | yes |  |
| `ends_at` | date-time | yes |  |
| `service` | uuid | yes |  |
| `staff` | uuid | yes |  |
| `price` | [Money](#money) | yes |  |
| `amount_due` | [Money](#money) | yes |  |
| `balance_due` | [Money](#money) | yes |  |
| `payment_mode` | string | yes | One of `none`, `optional`, `required`, `deposit`. |
| `manage_token` | string |  | Only on the answer to the call that made the booking, and never again. Whoever holds it may cancel or reschedule this booking. |
| `customer` | [BookingCustomer](#bookingcustomer) | yes |  |
| `notes` | string | yes |  |
| `created_at` | date-time | yes |  |
| `expires_at` | date-time or null | yes | When an unpaid hold on the slot runs out. Null for anything not waiting on payment. |
| `payment` | [PaymentHandle](#paymenthandle) |  | Absent when nothing is owed and nothing was ever offered. |

### PaginatedServiceList

| Field | Type | Always there | |
|---|---|---|---|
| `count` | integer | yes |  |
| `results` | list of [Service](#service) | yes |  |

### Service

| Field | Type | Always there | |
|---|---|---|---|
| `id` | uuid | yes |  |
| `slug` | string | yes |  |
| `name` | string | yes |  |
| `description` | string | yes |  |
| `duration_minutes` | integer | yes |  |
| `price` | [Money](#money) | yes |  |
| `payment_mode` | string | yes | One of `none`, `optional`, `required`, `deposit`. A service following the business's rule says the rule. |
| `sort_order` | integer | yes |  |
| `staff` | list of uuid |  |  |
| `staff_pricing` | list of [StaffPricing](#staffpricing) |  |  |

### PaginatedStaffList

| Field | Type | Always there | |
|---|---|---|---|
| `count` | integer | yes |  |
| `results` | list of [Staff](#staff) | yes |  |

### Staff

| Field | Type | Always there | |
|---|---|---|---|
| `id` | uuid | yes |  |
| `name` | string | yes |  |
| `services` | list of uuid | yes |  |
| `sort_order` | integer | yes |  |

### WindowRequest

| Field | Type | Always there | |
|---|---|---|---|
| `start` | time | yes | Local wall clock, HH:MM. |
| `end` | time | yes | Local wall clock, HH:MM, after `start`. |

### ConfirmationModeEnum

| Field | Type | Always there | |
|---|---|---|---|

### PaymentModeEnum

| Field | Type | Always there | |
|---|---|---|---|

### DepositTypeEnum

| Field | Type | Always there | |
|---|---|---|---|

### SlotGranularityMinutesEnum

| Field | Type | Always there | |
|---|---|---|---|

### ReminderHoursEnum

| Field | Type | Always there | |
|---|---|---|---|

### ServicePaymentModeEnum

| Field | Type | Always there | |
|---|---|---|---|

### DirectionEnum

| Field | Type | Always there | |
|---|---|---|---|

### Slot

| Field | Type | Always there | |
|---|---|---|---|
| `start` | date-time | yes |  |
| `end` | date-time | yes |  |
| `staff` | list of uuid | yes |  |

### Week

| Field | Type | Always there | |
|---|---|---|---|
| `monday` | list of [Window](#window) | yes | Every block worked that day, in order. Empty when closed. |
| `tuesday` | list of [Window](#window) | yes | Every block worked that day, in order. Empty when closed. |
| `wednesday` | list of [Window](#window) | yes | Every block worked that day, in order. Empty when closed. |
| `thursday` | list of [Window](#window) | yes | Every block worked that day, in order. Empty when closed. |
| `friday` | list of [Window](#window) | yes | Every block worked that day, in order. Empty when closed. |
| `saturday` | list of [Window](#window) | yes | Every block worked that day, in order. Empty when closed. |
| `sunday` | list of [Window](#window) | yes | Every block worked that day, in order. Empty when closed. |

### StaffHours

| Field | Type | Always there | |
|---|---|---|---|
| `staff` | uuid | yes |  |
| `name` | string | yes |  |
| `own_hours` | boolean | yes | False while they work the business's week, which `days` then shows. |
| `timezone` | string | yes | The clock their hours are read on. |
| `days` | [Week](#week) | yes |  |

### Money

| Field | Type | Always there | |
|---|---|---|---|
| `amount` | integer | yes |  |
| `currency` | string | yes |  |

### SetupLink

| Field | Type | Always there | |
|---|---|---|---|
| `staff` | uuid | yes |  |
| `name` | string | yes |  |
| `price_amount` | integer or null | yes | Their own price in minor units. Null charges the service's. |
| `duration_minutes` | integer or null | yes | Their own minutes with the customer. Null takes the service's. |

### ResultEnum

| Field | Type | Always there | |
|---|---|---|---|

### BookingCustomer

| Field | Type | Always there | |
|---|---|---|---|
| `email` | email or empty | yes | Empty for somebody the business booked in without an address, or erased. |
| `name` | string | yes | Empty once the business has erased the customer. |

### PaymentHandle

| Field | Type | Always there | |
|---|---|---|---|
| `required` | boolean | yes |  |
| `amount` | [Money](#money) | yes |  |
| `checkout_url` | string | yes |  |
| `expires_at` | date-time or null | yes |  |
| `status` | string | yes | The payment page's own status while one is open. Otherwise `paid`, `unpaid` (not paid, and the booking no longer holds its time) or `unavailable` (owed, with no page open: offer it again). |

### StaffPricing

| Field | Type | Always there | |
|---|---|---|---|
| `staff` | uuid | yes |  |
| `price` | [Money](#money) | yes |  |
| `duration_minutes` | integer | yes |  |

### Window

| Field | Type | Always there | |
|---|---|---|---|
| `start` | time | yes | Local wall clock, HH:MM. |
| `end` | time | yes | Local wall clock, HH:MM, after `start`. |
