# Booksy API

> Every Booksy endpoint on Cotlet: inputs, JSON Schema, cURL, Python and Node.js examples and an example response for each call.

Source: https://cotlet.dev/docs/api/booksy

Docs sections: [Get started](https://cotlet.dev/docs.md) · [REST API](https://cotlet.dev/docs/api.md) · [MCP](https://cotlet.dev/docs/mcp.md) · [SDKs & CLI](https://cotlet.dev/docs/sdks.md) · [Integrations](https://cotlet.dev/docs/integrations.md)

13 endpoints for Booksy. Each one is a POST with a JSON body, called with your API key.

- Base URL: `https://cotlet.dev/api/v1/booksy`
- Connects with: Your own Booksy Biz account (owner or a staff account that can see the calendar; Pro-only reports need Booksy Biz Pro)
- Integration page: https://cotlet.dev/integrations/booksy-api-mcp-server

## Endpoints

| Endpoint | Access | Description |
|---|---|---|
| `list_appointments` | read | Appointments in a date range with client, service, staff, time and status. |
| `get_appointment` | read | One appointment: services, staff, price, client and notes. |
| `find_open_slots` | read | Free start times for a service on one day, based on working hours, breaks and time off. |
| `list_clients` | read | Clients with contact details and last visit. |
| `get_client` | read | One client card: contact details, notes and appointment history. |
| `list_services` | read | Your service menu with duration, price and the staff who offer each. |
| `list_staff` | read | Staff members with their working hours and the services they offer. |
| `get_report` | read | Numbers from Stats & Reports for a period, as JSON. |
| `create_appointment` | write | Book a client into your calendar. |
| `reschedule_appointment` | write | Move an appointment to a new time or staff member. |
| `add_client` | write | Add a client card to your client list. |
| `add_time_off` | write | Block time in a staff member's calendar so no one can book it. |
| `send_message_blast` | write | Send one message to chosen clients by email, SMS or push notification. |

## List appointments

`POST https://cotlet.dev/api/v1/booksy/list_appointments`

Access: read.

Lists appointments from your Booksy calendar between two days, in start order. Limit it to one staff member to see a single calendar. Each item has the client, service, staff member, start, end and status, and get_appointment returns the rest.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `from` | date | yes | First day, inclusive. |
| `to` | date | yes | Last day, inclusive. |
| `staff_id` | string | no | Only one staff member, from list_staff. |
| `cursor` | string | no | Next page cursor from the previous call. |

### Request

**cURL**

```bash
curl -X POST https://cotlet.dev/api/v1/booksy/list_appointments \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"from":"2026-10-01","to":"2026-10-01"}'
```

**Python**

```python
result = client.call("booksy", "list_appointments", {"from":"2026-10-01","to":"2026-10-01"})
```

**Node.js**

```js
const result = await cotlet.call('booksy', 'list_appointments', {"from":"2026-10-01","to":"2026-10-01"});
```

**CLI**

```bash
cotlet call booksy list_appointments --data '{"from":"2026-10-01","to":"2026-10-01"}'
```

### Example response

```json
{
  "appointments": [
    {
      "appointment_id": "apt_58213904",
      "client": "Anna Novak",
      "service": "Haircut",
      "staff": "Tom",
      "start": "2026-10-12T10:00:00-04:00",
      "end": "2026-10-12T10:45:00-04:00",
      "status": "confirmed"
    },
    {
      "appointment_id": "apt_58213977",
      "client": "Mark Ellis",
      "service": "Beard trim",
      "staff": "Tom",
      "start": "2026-10-12T11:30:00-04:00",
      "end": "2026-10-12T12:00:00-04:00",
      "status": "confirmed"
    }
  ],
  "next_cursor": null
}
```

## Get appointment

`POST https://cotlet.dev/api/v1/booksy/get_appointment`

Access: read.

Returns one appointment with its services, staff member, price, client and internal notes. Use it before changing an appointment.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `appointment_id` | string | yes | Appointment ID from list_appointments. |

### Request

**cURL**

```bash
curl -X POST https://cotlet.dev/api/v1/booksy/get_appointment \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"appointment_id":"appointment_8c41d2"}'
```

**Python**

```python
result = client.call("booksy", "get_appointment", {"appointment_id":"appointment_8c41d2"})
```

**Node.js**

```js
const result = await cotlet.call('booksy', 'get_appointment', {"appointment_id":"appointment_8c41d2"});
```

**CLI**

```bash
cotlet call booksy get_appointment --data '{"appointment_id":"appointment_8c41d2"}'
```

### Example response

```json
{
  "appointment_id": "apt_58213904",
  "client": {
    "client_id": "cl_1042",
    "name": "Anna Novak"
  },
  "services": [
    {
      "name": "Haircut",
      "price": 35
    }
  ],
  "staff": "Tom",
  "start": "2026-10-16T15:00:00-04:00",
  "end": "2026-10-16T15:45:00-04:00",
  "status": "confirmed",
  "note": "Prefers a scissor cut"
}
```

## Find open slots

`POST https://cotlet.dev/api/v1/booksy/find_open_slots`

Access: read.

Returns free start times for one service on one day, in time order. It follows working hours, breaks, time off and the duration and buffer set on the service. Limit it to one staff member or leave it open to anyone who offers the service.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `service_id` | string | yes | Service ID from list_services. |
| `date` | date | yes | Day to check. |
| `staff_id` | string | no | Only this staff member. Default: anyone who offers the service. |

### Request

**cURL**

```bash
curl -X POST https://cotlet.dev/api/v1/booksy/find_open_slots \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"service_id":"service_8c41d2","date":"2026-10-01"}'
```

**Python**

```python
result = client.call("booksy", "find_open_slots", {"service_id":"service_8c41d2","date":"2026-10-01"})
```

**Node.js**

```js
const result = await cotlet.call('booksy', 'find_open_slots', {"service_id":"service_8c41d2","date":"2026-10-01"});
```

**CLI**

```bash
cotlet call booksy find_open_slots --data '{"service_id":"service_8c41d2","date":"2026-10-01"}'
```

### Example response

```json
{
  "date": "2026-10-17",
  "service": "Haircut",
  "slots": [
    {
      "start": "2026-10-17T10:00:00-04:00",
      "staff_id": "stf_2291"
    },
    {
      "start": "2026-10-17T11:30:00-04:00",
      "staff_id": "stf_2291"
    }
  ]
}
```

## List clients

`POST https://cotlet.dev/api/v1/booksy/list_clients`

Access: read.

Lists clients from your client list with contact details and the date of the last visit. Search by name, email or phone, or keep only clients who have not visited for a number of days. Pages are cursor based.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `query` | string | no | Name, email or phone to search for. |
| `not_visited_days` | integer | no | Only clients whose last visit is older than this many days. |
| `limit` | integer | no | Page size. Default: 50. |
| `cursor` | string | no | Next page cursor from the previous call. |

### Request

**cURL**

```bash
curl -X POST https://cotlet.dev/api/v1/booksy/list_clients \
  -H "Authorization: Bearer $COTLET_API_KEY"
```

**Python**

```python
result = client.call("booksy", "list_clients")
```

**Node.js**

```js
const result = await cotlet.call('booksy', 'list_clients');
```

**CLI**

```bash
cotlet call booksy list_clients
```

### Example response

```json
{
  "clients": [
    {
      "client_id": "cl_1042",
      "name": "Anna Novak",
      "email": "anna@example.com",
      "last_visit": "2026-07-28"
    },
    {
      "client_id": "cl_1187",
      "name": "Mark Ellis",
      "email": "mark@example.com",
      "last_visit": "2026-07-30"
    }
  ],
  "next_cursor": null
}
```

## Get client

`POST https://cotlet.dev/api/v1/booksy/get_client`

Access: read.

Returns one client card with contact details, notes and past appointments, newest first. Look the client up by ID or by email.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `client_id` | string | no | Client ID from list_clients. |
| `email` | string | no | Look up by email instead of ID. |

### Request

**cURL**

```bash
curl -X POST https://cotlet.dev/api/v1/booksy/get_client \
  -H "Authorization: Bearer $COTLET_API_KEY"
```

**Python**

```python
result = client.call("booksy", "get_client")
```

**Node.js**

```js
const result = await cotlet.call('booksy', 'get_client');
```

**CLI**

```bash
cotlet call booksy get_client
```

### Example response

```json
{
  "client_id": "cl_1042",
  "name": "Anna Novak",
  "email": "anna@example.com",
  "notes": "Prefers a scissor cut",
  "appointments": [
    {
      "appointment_id": "apt_58213904",
      "service": "Haircut",
      "start": "2026-10-16T15:00:00-04:00"
    }
  ]
}
```

## List services

`POST https://cotlet.dev/api/v1/booksy/list_services`

Access: read.

Returns the services on your Booksy menu with duration, price and the staff members who offer each one. Use the service ID in find_open_slots and create_appointment.

### Parameters

No parameters.

### Request

**cURL**

```bash
curl -X POST https://cotlet.dev/api/v1/booksy/list_services \
  -H "Authorization: Bearer $COTLET_API_KEY"
```

**Python**

```python
result = client.call("booksy", "list_services")
```

**Node.js**

```js
const result = await cotlet.call('booksy', 'list_services');
```

**CLI**

```bash
cotlet call booksy list_services
```

### Example response

```json
{
  "services": [
    {
      "service_id": "svc_301",
      "name": "Haircut",
      "duration_minutes": 45,
      "price": 35,
      "staff_ids": [
        "stf_2291",
        "stf_2305"
      ]
    },
    {
      "service_id": "svc_302",
      "name": "Beard trim",
      "duration_minutes": 30,
      "price": 20,
      "staff_ids": [
        "stf_2291"
      ]
    }
  ]
}
```

## List staff

`POST https://cotlet.dev/api/v1/booksy/list_staff`

Access: read.

Returns your staff members with their weekly working hours and the services each one offers. Use the staff ID in other tools.

### Parameters

No parameters.

### Request

**cURL**

```bash
curl -X POST https://cotlet.dev/api/v1/booksy/list_staff \
  -H "Authorization: Bearer $COTLET_API_KEY"
```

**Python**

```python
result = client.call("booksy", "list_staff")
```

**Node.js**

```js
const result = await cotlet.call('booksy', 'list_staff');
```

**CLI**

```bash
cotlet call booksy list_staff
```

### Example response

```json
{
  "staff": [
    {
      "staff_id": "stf_2291",
      "name": "Tom",
      "services": [
        "Haircut",
        "Beard trim"
      ],
      "hours": {
        "mon": "09:00-18:00",
        "tue": "09:00-18:00"
      }
    },
    {
      "staff_id": "stf_2305",
      "name": "Kate",
      "services": [
        "Haircut"
      ],
      "hours": {
        "mon": "10:00-19:00",
        "tue": "10:00-19:00"
      }
    }
  ]
}
```

## Get report

`POST https://cotlet.dev/api/v1/booksy/get_report`

Access: read.

Returns the numbers of one Stats & Reports category for a date range. Booksy Biz Lite has Dashboard, Revenue, Appointments and Clients; Cash Flow, Inventory, Staff Members and Marketing need Booksy Biz Pro, and the call fails for other plans.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `category` | enum | yes | dashboard, revenue, appointments, clients, cash_flow, inventory, staff_members or marketing. The last four need Booksy Biz Pro. |
| `from` | date | yes | First day, inclusive. |
| `to` | date | yes | Last day, inclusive. |

### Request

**cURL**

```bash
curl -X POST https://cotlet.dev/api/v1/booksy/get_report \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"category":"staff_members","from":"2026-10-06","to":"2026-10-12"}'
```

**Python**

```python
result = client.call("booksy", "get_report", {"category":"staff_members","from":"2026-10-06","to":"2026-10-12"})
```

**Node.js**

```js
const result = await cotlet.call('booksy', 'get_report', {"category":"staff_members","from":"2026-10-06","to":"2026-10-12"});
```

**CLI**

```bash
cotlet call booksy get_report --data '{"category":"staff_members","from":"2026-10-06","to":"2026-10-12"}'
```

### Example response

```json
{
  "category": "staff_members",
  "from": "2026-10-05",
  "to": "2026-10-11",
  "total": {
    "revenue": 4820,
    "appointments": 96
  },
  "staff": [
    {
      "name": "Tom",
      "revenue": 2310,
      "appointments": 41
    },
    {
      "name": "Kate",
      "revenue": 1640,
      "appointments": 33
    },
    {
      "name": "Sam",
      "revenue": 870,
      "appointments": 22
    }
  ]
}
```

## Create appointment

`POST https://cotlet.dev/api/v1/booksy/create_appointment`

Access: write. Confirm: waits for the user's OK before it runs.

Books one client for one service at a start time. Pick a start from find_open_slots. Booksy applies its automatic confirmation and the client is part of the booking. By default you confirm each call; you can switch that off for this tool.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `client_id` | string | yes | Client ID from list_clients or add_client. |
| `service_id` | string | yes | Service ID from list_services. |
| `start` | datetime | yes | ISO 8601 with time zone. |
| `staff_id` | string | no | Staff member. Default: first one free. |
| `note` | string | no | Internal note on the appointment. |

### Request

**cURL**

```bash
curl -X POST https://cotlet.dev/api/v1/booksy/create_appointment \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"client_id":"client_8c41d2","service_id":"service_8c41d2","start":"2026-10-01T09:00:00Z"}'
```

**Python**

```python
result = client.call("booksy", "create_appointment", {"client_id":"client_8c41d2","service_id":"service_8c41d2","start":"2026-10-01T09:00:00Z"})
```

**Node.js**

```js
const result = await cotlet.call('booksy', 'create_appointment', {"client_id":"client_8c41d2","service_id":"service_8c41d2","start":"2026-10-01T09:00:00Z"});
```

**CLI**

```bash
cotlet call booksy create_appointment --data '{"client_id":"client_8c41d2","service_id":"service_8c41d2","start":"2026-10-01T09:00:00Z"}'
```

### Example response

```json
{
  "appointment_id": "apt_58214120",
  "status": "confirmed",
  "client": "Mark Ellis",
  "service": "Beard trim",
  "staff": "Tom",
  "start": "2026-10-20T10:00:00-04:00",
  "end": "2026-10-20T10:30:00-04:00"
}
```

## Reschedule appointment

`POST https://cotlet.dev/api/v1/booksy/reschedule_appointment`

Access: write. Confirm: waits for the user's OK before it runs.

Moves one appointment to a new start time and optionally to another staff member. Booksy booking rules that limit rescheduling still apply, so the call can be refused. By default you confirm each call; you can switch that off for this tool.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `appointment_id` | string | yes | Appointment ID from list_appointments. |
| `start` | datetime | yes | New start, ISO 8601 with time zone. |
| `staff_id` | string | no | New staff member. Default: unchanged. |

### Request

**cURL**

```bash
curl -X POST https://cotlet.dev/api/v1/booksy/reschedule_appointment \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"appointment_id":"apt_58213904","start":"2026-10-17T11:30:00-04:00","staff_id":"stf_2291"}'
```

**Python**

```python
result = client.call("booksy", "reschedule_appointment", {"appointment_id":"apt_58213904","start":"2026-10-17T11:30:00-04:00","staff_id":"stf_2291"})
```

**Node.js**

```js
const result = await cotlet.call('booksy', 'reschedule_appointment', {"appointment_id":"apt_58213904","start":"2026-10-17T11:30:00-04:00","staff_id":"stf_2291"});
```

**CLI**

```bash
cotlet call booksy reschedule_appointment --data '{"appointment_id":"apt_58213904","start":"2026-10-17T11:30:00-04:00","staff_id":"stf_2291"}'
```

### Example response

```json
{
  "appointment_id": "apt_58213904",
  "status": "confirmed",
  "service": "Haircut",
  "staff": "Tom",
  "start": "2026-10-17T11:30:00-04:00",
  "end": "2026-10-17T12:15:00-04:00"
}
```

## Add client

`POST https://cotlet.dev/api/v1/booksy/add_client`

Access: write.

Adds one client card with a name and optional phone, email and note. It reaches no one and you can edit the card in Booksy, so add_client runs without asking first.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `name` | string | yes | Full name. |
| `phone` | string | no | Phone in international format. |
| `email` | string | no | Email address. |
| `note` | string | no | Internal note. |

### Request

**cURL**

```bash
curl -X POST https://cotlet.dev/api/v1/booksy/add_client \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"Jane Doe"}'
```

**Python**

```python
result = client.call("booksy", "add_client", {"name":"Jane Doe"})
```

**Node.js**

```js
const result = await cotlet.call('booksy', 'add_client', {"name":"Jane Doe"});
```

**CLI**

```bash
cotlet call booksy add_client --data '{"name":"Jane Doe"}'
```

### Example response

```json
{
  "client_id": "cl_1310",
  "name": "Lena Fox",
  "email": "lena@example.com"
}
```

## Add time off

`POST https://cotlet.dev/api/v1/booksy/add_time_off`

Access: write.

Blocks a period in one staff member's calendar, like time off set in the app, so no one can book during it. It reaches no client and you can remove the block in Booksy, so add_time_off runs without asking first.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `staff_id` | string | yes | Staff ID from list_staff. |
| `start` | datetime | yes | ISO 8601 with time zone. |
| `end` | datetime | yes | ISO 8601 with time zone. |
| `reason` | string | no | Internal label, e.g. vacation. |

### Request

**cURL**

```bash
curl -X POST https://cotlet.dev/api/v1/booksy/add_time_off \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"staff_id":"staff_8c41d2","start":"2026-10-01T09:00:00Z","end":"2026-10-01T09:00:00Z"}'
```

**Python**

```python
result = client.call("booksy", "add_time_off", {"staff_id":"staff_8c41d2","start":"2026-10-01T09:00:00Z","end":"2026-10-01T09:00:00Z"})
```

**Node.js**

```js
const result = await cotlet.call('booksy', 'add_time_off', {"staff_id":"staff_8c41d2","start":"2026-10-01T09:00:00Z","end":"2026-10-01T09:00:00Z"});
```

**CLI**

```bash
cotlet call booksy add_time_off --data '{"staff_id":"staff_8c41d2","start":"2026-10-01T09:00:00Z","end":"2026-10-01T09:00:00Z"}'
```

### Example response

```json
{
  "time_off_id": "to_7714",
  "staff_id": "stf_2291",
  "start": "2026-10-19T09:00:00-04:00",
  "end": "2026-10-19T18:00:00-04:00",
  "reason": "vacation"
}
```

## Send Message Blast

`POST https://cotlet.dev/api/v1/booksy/send_message_blast`

Access: write. Confirm: waits for the user's OK before it runs.

Sends one Message Blast to the clients you list, by email, SMS or a push notification to the Booksy Client App. SMS comes from an automated number, so clients cannot reply, and Booksy adds a link to your profile at the bottom. By default you confirm each call; you can switch that off for this tool.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `channel` | enum | yes | email, sms or push. |
| `message` | string | yes | Message text. |
| `client_ids` | string[] | yes | Recipients from list_clients. |

### Request

**cURL**

```bash
curl -X POST https://cotlet.dev/api/v1/booksy/send_message_blast \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"channel":"email","message":"Thursday Happy Hour: 20% off any cut, 4 to 6 pm. Book in the app.","client_ids":["cl_1042","cl_1187","cl_1203"]}'
```

**Python**

```python
result = client.call("booksy", "send_message_blast", {"channel":"email","message":"Thursday Happy Hour: 20% off any cut, 4 to 6 pm. Book in the app.","client_ids":["cl_1042","cl_1187","cl_1203"]})
```

**Node.js**

```js
const result = await cotlet.call('booksy', 'send_message_blast', {"channel":"email","message":"Thursday Happy Hour: 20% off any cut, 4 to 6 pm. Book in the app.","client_ids":["cl_1042","cl_1187","cl_1203"]});
```

**CLI**

```bash
cotlet call booksy send_message_blast --data '{"channel":"email","message":"Thursday Happy Hour: 20% off any cut, 4 to 6 pm. Book in the app.","client_ids":["cl_1042","cl_1187","cl_1203"]}'
```

### Example response

```json
{
  "blast_id": "mb_2208",
  "channel": "email",
  "recipients": 3,
  "status": "sent"
}
```
