# List booking links

List your booking links and upcoming confirmed bookings. Each link includes its public URL and availability settings.

POST https://api.brigg.app/v1/operations/meetings.ListBookingLinks

## Access & visibility

Allow `meetings.ListBookingLinks` on your API key.

**Acting member required.** Send `Brigg-Act-As` with an [approved member account ID](https://developer.brigg.app/authentication#member-delegation). The key supplies permissions; the member selects whose data is used.

The selected member must be active and approved by the credential. This selects whose private data is used; the credential supplies permissions. Private ownership and project boundaries still apply.

[Set up authentication](https://developer.brigg.app/authentication) · [Choose permissions](https://developer.brigg.app/permissions)

## Request

No parameters. Send an empty JSON object (`{}`).

## Booking links and individual bookings

A booking link belongs to the acting member and advertises availability in its IANA `timezone`. Availability times are local wall-clock times in that zone; confirmed bookings use numeric timestamps. Use [List booking links](https://developer.brigg.app/reference/meetings/ListBookingLinks) to read both links (`items`) and their confirmed bookings starting in the next 366 days (`upcoming_bookings`).

The link ID changes or deactivates the booking page. An individual booking ID cancels one confirmed appointment. Deactivating a link stops new bookings without cancelling appointments already made. A link with future bookings cannot be deleted; deactivate it or cancel those bookings first. Active links require a connected writable calendar.

## Response

Returns **200 OK** with a JSON body.

This operation has no continuation cursor. An empty `items` array means no matching visible results were returned.
| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `upcoming_bookings` | array of [object](#response-upcoming-bookings) | Yes | Confirmed bookings starting in the next 366 days across these links, separate from the link definitions. An empty array means no upcoming bookings were returned; inactive links can still have appointments. |
| `items` | array of [Booking link](#booking-link-response-items) | Yes | Booking links owned by the acting member; upcoming bookings are returned separately. This operation has no cursor pagination. |

### response.upcoming_bookings[]

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | string | Yes | Individual booking ID. Pass this to CancelBooking to cancel this appointment, not the link_id. |
| `link_id` | string | Yes | Booking-link ID matching items[].id. Use it for link updates or deactivation, not to cancel one appointment. |
| `start_at` | number | Yes | Booking start time in Unix milliseconds. |
| `end_at` | number | Yes | Booking end time in Unix milliseconds. |
| `timezone` | string | No | Invitee's IANA timezone, when recorded. start_at and end_at are absolute Unix millisecond timestamps; format them in the desired display zone. |
| `invitee_name` | string | Yes | Name supplied by the person who booked the meeting. |
| `invitee_email` | string | Yes | Email address of the person who booked the meeting. |
| `note` | string or null | No | Optional note supplied by the invitee when booking. Null means no note was supplied. |

### Booking link · response.items[]

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | string | Yes | Booking link ID. Use it to update or delete this link. |
| `org_id` | string | Yes | Workspace that owns the link. |
| `owner_account_id` | string | Yes | Member whose calendar supplies the available time slots. |
| `slug` | string | Yes | Unique URL segment for this link within the workspace. |
| `name` | string | Yes | Meeting name displayed to invitees. |
| `description` | string or null | Yes | Introduction displayed on the booking page. |
| `duration_minutes` | integer | Yes | Default meeting length in minutes; the shortest length when several are offered. |
| `duration_options` | array of integer or null | Yes | Offered meeting lengths in minutes. Null means a fixed duration_minutes. |
| `location_kind` | string | Yes | video creates a conference link; phone, in_person and custom use location_detail for instructions or an address. Allowed: `"video"`, `"phone"`, `"in_person"`, `"custom"`. |
| `location_detail` | string or null | Yes | Address, phone instructions or other location details. |
| `timezone` | string | Yes | IANA time zone used to interpret the weekly availability, for example Europe/Oslo. |
| `availability` | [WeeklyAvailability](#weeklyavailability-response-items-availability) | Yes | Bookable local-time intervals by weekday. Missing or empty days are unavailable. |
| `window_days` | integer | Yes | How many days into the future invitees can book. |
| `min_notice_minutes` | integer | Yes | Minimum time before a meeting can start, in minutes. |
| `buffer_before_minutes` | integer | Yes | Minutes reserved before each meeting. |
| `buffer_after_minutes` | integer | Yes | Minutes reserved after each meeting. |
| `max_per_day` | integer | Yes | Maximum bookings per day. Zero means no daily limit. |
| `questions` | array of [object](#response-items-questions) or null | Yes | Additional questions shown to invitees. Null means no questions. |
| `reminder_hours` | integer | Yes | Hours before the meeting to send a reminder. Zero disables reminders. |
| `collect_phone` | boolean | Yes | Whether invitees are asked for a phone number. |
| `active` | boolean | Yes | Whether invitees can make new bookings through this link. |
| `created_at` | integer | Yes | Creation time in Unix milliseconds. |
| `updated_at` | integer | Yes | Last change in Unix milliseconds. |
| `url` | string | Yes | Public booking URL to share with invitees. Format: uri. |

### WeeklyAvailability · response.items[].availability

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `mon` | array of [object](#response-items-availability-mon) | No | Monday availability intervals in the booking link's timezone. At most 6 items. |
| `tue` | array of [object](#response-items-availability-tue) | No | Tuesday availability intervals in the booking link's timezone. At most 6 items. |
| `wed` | array of [object](#response-items-availability-wed) | No | Wednesday availability intervals in the booking link's timezone. At most 6 items. |
| `thu` | array of [object](#response-items-availability-thu) | No | Thursday availability intervals in the booking link's timezone. At most 6 items. |
| `fri` | array of [object](#response-items-availability-fri) | No | Friday availability intervals in the booking link's timezone. At most 6 items. |
| `sat` | array of [object](#response-items-availability-sat) | No | Saturday availability intervals in the booking link's timezone. At most 6 items. |
| `sun` | array of [object](#response-items-availability-sun) | No | Sunday availability intervals in the booking link's timezone. At most 6 items. |

### response.items[].availability.mon[]

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `start` | string | Yes | Start of the interval. Pattern: `^([01]\d\|2[0-3]):[0-5]\d$`. |
| `end` | string | Yes | End of the interval; must be later than its start. Pattern: `^([01]\d\|2[0-3]):[0-5]\d$`. |

### response.items[].availability.tue[]

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `start` | string | Yes | Start of the interval. Pattern: `^([01]\d\|2[0-3]):[0-5]\d$`. |
| `end` | string | Yes | End of the interval; must be later than its start. Pattern: `^([01]\d\|2[0-3]):[0-5]\d$`. |

### response.items[].availability.wed[]

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `start` | string | Yes | Start of the interval. Pattern: `^([01]\d\|2[0-3]):[0-5]\d$`. |
| `end` | string | Yes | End of the interval; must be later than its start. Pattern: `^([01]\d\|2[0-3]):[0-5]\d$`. |

### response.items[].availability.thu[]

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `start` | string | Yes | Start of the interval. Pattern: `^([01]\d\|2[0-3]):[0-5]\d$`. |
| `end` | string | Yes | End of the interval; must be later than its start. Pattern: `^([01]\d\|2[0-3]):[0-5]\d$`. |

### response.items[].availability.fri[]

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `start` | string | Yes | Start of the interval. Pattern: `^([01]\d\|2[0-3]):[0-5]\d$`. |
| `end` | string | Yes | End of the interval; must be later than its start. Pattern: `^([01]\d\|2[0-3]):[0-5]\d$`. |

### response.items[].availability.sat[]

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `start` | string | Yes | Start of the interval. Pattern: `^([01]\d\|2[0-3]):[0-5]\d$`. |
| `end` | string | Yes | End of the interval; must be later than its start. Pattern: `^([01]\d\|2[0-3]):[0-5]\d$`. |

### response.items[].availability.sun[]

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `start` | string | Yes | Start of the interval. Pattern: `^([01]\d\|2[0-3]):[0-5]\d$`. |
| `end` | string | Yes | End of the interval; must be later than its start. Pattern: `^([01]\d\|2[0-3]):[0-5]\d$`. |

### response.items[].questions[]

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | string | Yes | Stable question key you choose, unique within this link, such as project_goal. Reuse it when editing that question; no create-record call is needed. At least 1 character. At most 40 characters. |
| `label` | string | Yes | Text shown for this booking question or choice. At least 1 character. At most 200 characters. |
| `kind` | string | Yes | Question control: text is a short answer, textarea a longer answer, select a choice from options, and checkbox a yes/no response. Allowed: `"text"`, `"textarea"`, `"select"`, `"checkbox"`. |
| `required` | boolean | No | Whether the invitee must answer this booking question. |
| `options` | array of string | No | Choices for a select question; at least one is required when kind=select. Omit for other controls. At least 1 item. At most 12 items. |

## Errors & retries

This operation reads data. It needs no idempotency key and can be retried after a transient failure.

For rate limits, follow the server’s retry guidance and back off. See [HTTP errors](https://developer.brigg.app/http#errors) and [safe retries and limits](https://developer.brigg.app/reliability).

| HTTP status | Code | What to do |
| --- | --- | --- |
| 400 | `invalid_json` | Send a JSON object with Content-Type: application/json. |
| 400 | `invalid_input` | Check the request fields and types. |
| 401 | `invalid_key` | The workspace API key is missing, invalid or revoked. |
| 403 | `forbidden` | Check the key’s operation and resource grants. Supply Brigg-Act-As with a member authorized by the key’s delegation grant. The selected member must be active and approved by the credential. This selects whose private data is used; the credential supplies permissions. Private ownership and project boundaries still apply. |
| 404 | `not_found` | The requested operation or resource is not available to this credential. |
| 429 | `rate_limited` | Wait for Retry-After before retrying. |

## Next steps

- [List calendar connections](https://developer.brigg.app/reference/meetings/ListCalendarConnections)
- [Update booking link](https://developer.brigg.app/reference/meetings/UpdateBookingLink)
- [Cancel booking](https://developer.brigg.app/reference/meetings/CancelBooking)

[Download OpenAPI](https://developer.brigg.app/openapi.json) · [Versioning & retirement](https://developer.brigg.app/versioning)

## Examples

### Links and their upcoming appointments

Match upcoming_bookings[].link_id to items[].id; use the appointment's own id when cancelling one booking.
#### cURL


```sh
curl 'https://api.brigg.app/v1/operations/meetings.ListBookingLinks' \
  -H "Authorization: Bearer $BRIGG_API_KEY" \
  -H 'Content-Type: application/json' \
  -H "Brigg-Act-As: $BRIGG_ACT_AS" \
  --data-raw '{}'
```

#### TypeScript


```typescript
const actAs = process.env.BRIGG_ACT_AS;
if (!actAs) throw new Error("Set BRIGG_ACT_AS to an approved member account ID.");

const response = await fetch("https://api.brigg.app/v1/operations/meetings.ListBookingLinks", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.BRIGG_API_KEY}`,
    "Content-Type": "application/json",
    "Brigg-Act-As": actAs,
  },
  body: JSON.stringify({}),
});
const result = await response.json();
if (!response.ok) throw new Error(`${response.status}: ${result.error} — ${result.message}`);
console.log(result);
```

#### Python


```python
import json
import os
from urllib.request import Request, urlopen
from urllib.error import HTTPError

payload = {}
request = Request(
    "https://api.brigg.app/v1/operations/meetings.ListBookingLinks",
    data=json.dumps(payload).encode("utf-8"),
    headers={
        "Authorization": f"Bearer {os.environ['BRIGG_API_KEY']}",
        "Content-Type": "application/json",
        "Brigg-Act-As": os.environ["BRIGG_ACT_AS"],
    },
    method="POST",
)
try:
    with urlopen(request) as response:
        print(json.load(response))
except HTTPError as error:
    print(error.code, json.load(error))
    raise
```

#### Response example


```json
{
  "items": [
    {
      "id": "bkl_example",
      "org_id": "o_example",
      "owner_account_id": "a_example",
      "slug": "project-introduction",
      "name": "Project introduction",
      "description": null,
      "duration_minutes": 30,
      "duration_options": null,
      "location_kind": "video",
      "location_detail": null,
      "timezone": "Europe/Oslo",
      "availability": {
        "mon": [
          {
            "start": "09:00",
            "end": "17:00"
          }
        ]
      },
      "window_days": 30,
      "min_notice_minutes": 240,
      "buffer_before_minutes": 0,
      "buffer_after_minutes": 0,
      "max_per_day": 0,
      "questions": null,
      "reminder_hours": 24,
      "collect_phone": false,
      "active": true,
      "created_at": 1794301200000,
      "updated_at": 1794301200000,
      "url": "https://example.com/book/project-introduction"
    }
  ],
  "upcoming_bookings": [
    {
      "id": "bk_project_intro",
      "link_id": "bkl_example",
      "start_at": 1794823200000,
      "end_at": 1794825000000,
      "timezone": "Europe/Oslo",
      "invitee_name": "Alex Morgan",
      "invitee_email": "alex@example.com",
      "note": "Please bring the onboarding checklist."
    }
  ]
}
```

### This member has no booking links

This is an authorized empty result for the acting member, not the workspace's complete link catalogue.
#### cURL


```sh
curl 'https://api.brigg.app/v1/operations/meetings.ListBookingLinks' \
  -H "Authorization: Bearer $BRIGG_API_KEY" \
  -H 'Content-Type: application/json' \
  -H "Brigg-Act-As: $BRIGG_ACT_AS" \
  --data-raw '{}'
```

#### TypeScript


```typescript
const actAs = process.env.BRIGG_ACT_AS;
if (!actAs) throw new Error("Set BRIGG_ACT_AS to an approved member account ID.");

const response = await fetch("https://api.brigg.app/v1/operations/meetings.ListBookingLinks", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.BRIGG_API_KEY}`,
    "Content-Type": "application/json",
    "Brigg-Act-As": actAs,
  },
  body: JSON.stringify({}),
});
const result = await response.json();
if (!response.ok) throw new Error(`${response.status}: ${result.error} — ${result.message}`);
console.log(result);
```

#### Python


```python
import json
import os
from urllib.request import Request, urlopen
from urllib.error import HTTPError

payload = {}
request = Request(
    "https://api.brigg.app/v1/operations/meetings.ListBookingLinks",
    data=json.dumps(payload).encode("utf-8"),
    headers={
        "Authorization": f"Bearer {os.environ['BRIGG_API_KEY']}",
        "Content-Type": "application/json",
        "Brigg-Act-As": os.environ["BRIGG_ACT_AS"],
    },
    method="POST",
)
try:
    with urlopen(request) as response:
        print(json.load(response))
except HTTPError as error:
    print(error.code, json.load(error))
    raise
```

#### Response example


```json
{
  "items": [],
  "upcoming_bookings": []
}
```

## JSON schemas


```json-schema-request
{
  "type": "object",
  "properties": {},
  "additionalProperties": false,
  "examples": [
    {}
  ]
}
```


```json-schema-response
{
  "type": "object",
  "properties": {
    "upcoming_bookings": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Individual booking ID. Pass this to CancelBooking to cancel this appointment, not the link_id."
          },
          "link_id": {
            "type": "string",
            "description": "Booking-link ID matching items[].id. Use it for link updates or deactivation, not to cancel one appointment."
          },
          "start_at": {
            "type": "number",
            "description": "Booking start time in Unix milliseconds."
          },
          "end_at": {
            "type": "number",
            "description": "Booking end time in Unix milliseconds."
          },
          "timezone": {
            "type": "string",
            "description": "Invitee's IANA timezone, when recorded. start_at and end_at are absolute Unix millisecond timestamps; format them in the desired display zone."
          },
          "invitee_name": {
            "type": "string",
            "description": "Name supplied by the person who booked the meeting."
          },
          "invitee_email": {
            "type": "string",
            "description": "Email address of the person who booked the meeting."
          },
          "note": {
            "type": [
              "string",
              "null"
            ],
            "description": "Optional note supplied by the invitee when booking. Null means no note was supplied."
          }
        },
        "required": [
          "id",
          "link_id",
          "start_at",
          "end_at",
          "invitee_name",
          "invitee_email"
        ],
        "additionalProperties": false
      },
      "description": "Confirmed bookings starting in the next 366 days across these links, separate from the link definitions. An empty array means no upcoming bookings were returned; inactive links can still have appointments."
    },
    "items": {
      "type": "array",
      "items": {
        "title": "Booking link",
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Booking link ID. Use it to update or delete this link."
          },
          "org_id": {
            "type": "string",
            "description": "Workspace that owns the link."
          },
          "owner_account_id": {
            "type": "string",
            "description": "Member whose calendar supplies the available time slots."
          },
          "slug": {
            "type": "string",
            "description": "Unique URL segment for this link within the workspace."
          },
          "name": {
            "type": "string",
            "description": "Meeting name displayed to invitees."
          },
          "description": {
            "description": "Introduction displayed on the booking page.",
            "anyOf": [
              {
                "type": "string",
                "description": "Introduction displayed on the booking page."
              },
              {
                "type": "null"
              }
            ]
          },
          "duration_minutes": {
            "type": "integer",
            "description": "Default meeting length in minutes; the shortest length when several are offered."
          },
          "duration_options": {
            "description": "Offered meeting lengths in minutes. Null means a fixed duration_minutes.",
            "anyOf": [
              {
                "type": "array",
                "items": {
                  "type": "integer"
                },
                "description": "Offered meeting lengths in minutes. Null means a fixed duration_minutes."
              },
              {
                "type": "null"
              }
            ]
          },
          "location_kind": {
            "type": "string",
            "enum": [
              "video",
              "phone",
              "in_person",
              "custom"
            ],
            "description": "video creates a conference link; phone, in_person and custom use location_detail for instructions or an address."
          },
          "location_detail": {
            "description": "Address, phone instructions or other location details.",
            "anyOf": [
              {
                "type": "string",
                "description": "Address, phone instructions or other location details."
              },
              {
                "type": "null"
              }
            ]
          },
          "timezone": {
            "type": "string",
            "description": "IANA time zone used to interpret the weekly availability, for example Europe/Oslo."
          },
          "availability": {
            "type": "object",
            "properties": {
              "mon": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "start": {
                      "type": "string",
                      "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$",
                      "description": "Start of the interval."
                    },
                    "end": {
                      "type": "string",
                      "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$",
                      "description": "End of the interval; must be later than its start."
                    }
                  },
                  "required": [
                    "start",
                    "end"
                  ],
                  "additionalProperties": false
                },
                "maxItems": 6,
                "description": "Monday availability intervals in the booking link's timezone."
              },
              "tue": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "start": {
                      "type": "string",
                      "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$",
                      "description": "Start of the interval."
                    },
                    "end": {
                      "type": "string",
                      "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$",
                      "description": "End of the interval; must be later than its start."
                    }
                  },
                  "required": [
                    "start",
                    "end"
                  ],
                  "additionalProperties": false
                },
                "maxItems": 6,
                "description": "Tuesday availability intervals in the booking link's timezone."
              },
              "wed": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "start": {
                      "type": "string",
                      "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$",
                      "description": "Start of the interval."
                    },
                    "end": {
                      "type": "string",
                      "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$",
                      "description": "End of the interval; must be later than its start."
                    }
                  },
                  "required": [
                    "start",
                    "end"
                  ],
                  "additionalProperties": false
                },
                "maxItems": 6,
                "description": "Wednesday availability intervals in the booking link's timezone."
              },
              "thu": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "start": {
                      "type": "string",
                      "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$",
                      "description": "Start of the interval."
                    },
                    "end": {
                      "type": "string",
                      "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$",
                      "description": "End of the interval; must be later than its start."
                    }
                  },
                  "required": [
                    "start",
                    "end"
                  ],
                  "additionalProperties": false
                },
                "maxItems": 6,
                "description": "Thursday availability intervals in the booking link's timezone."
              },
              "fri": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "start": {
                      "type": "string",
                      "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$",
                      "description": "Start of the interval."
                    },
                    "end": {
                      "type": "string",
                      "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$",
                      "description": "End of the interval; must be later than its start."
                    }
                  },
                  "required": [
                    "start",
                    "end"
                  ],
                  "additionalProperties": false
                },
                "maxItems": 6,
                "description": "Friday availability intervals in the booking link's timezone."
              },
              "sat": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "start": {
                      "type": "string",
                      "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$",
                      "description": "Start of the interval."
                    },
                    "end": {
                      "type": "string",
                      "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$",
                      "description": "End of the interval; must be later than its start."
                    }
                  },
                  "required": [
                    "start",
                    "end"
                  ],
                  "additionalProperties": false
                },
                "maxItems": 6,
                "description": "Saturday availability intervals in the booking link's timezone."
              },
              "sun": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "start": {
                      "type": "string",
                      "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$",
                      "description": "Start of the interval."
                    },
                    "end": {
                      "type": "string",
                      "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$",
                      "description": "End of the interval; must be later than its start."
                    }
                  },
                  "required": [
                    "start",
                    "end"
                  ],
                  "additionalProperties": false
                },
                "maxItems": 6,
                "description": "Sunday availability intervals in the booking link's timezone."
              }
            },
            "additionalProperties": false,
            "$schema": "http://json-schema.org/draft-07/schema#",
            "title": "WeeklyAvailability",
            "description": "Bookable local-time intervals by weekday. Missing or empty days are unavailable."
          },
          "window_days": {
            "type": "integer",
            "description": "How many days into the future invitees can book."
          },
          "min_notice_minutes": {
            "type": "integer",
            "description": "Minimum time before a meeting can start, in minutes."
          },
          "buffer_before_minutes": {
            "type": "integer",
            "description": "Minutes reserved before each meeting."
          },
          "buffer_after_minutes": {
            "type": "integer",
            "description": "Minutes reserved after each meeting."
          },
          "max_per_day": {
            "type": "integer",
            "description": "Maximum bookings per day. Zero means no daily limit."
          },
          "questions": {
            "description": "Additional questions shown to invitees. Null means no questions.",
            "anyOf": [
              {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 40,
                      "description": "Stable question key you choose, unique within this link, such as project_goal. Reuse it when editing that question; no create-record call is needed."
                    },
                    "label": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 200,
                      "description": "Text shown for this booking question or choice."
                    },
                    "kind": {
                      "type": "string",
                      "enum": [
                        "text",
                        "textarea",
                        "select",
                        "checkbox"
                      ],
                      "description": "Question control: text is a short answer, textarea a longer answer, select a choice from options, and checkbox a yes/no response."
                    },
                    "required": {
                      "type": "boolean",
                      "description": "Whether the invitee must answer this booking question."
                    },
                    "options": {
                      "type": "array",
                      "items": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 120
                      },
                      "minItems": 1,
                      "maxItems": 12,
                      "description": "Choices for a select question; at least one is required when kind=select. Omit for other controls."
                    }
                  },
                  "required": [
                    "id",
                    "label",
                    "kind"
                  ],
                  "additionalProperties": false
                },
                "maxItems": 5,
                "$schema": "http://json-schema.org/draft-07/schema#",
                "description": "Additional questions shown to invitees. Null means no questions."
              },
              {
                "type": "null"
              }
            ]
          },
          "reminder_hours": {
            "type": "integer",
            "description": "Hours before the meeting to send a reminder. Zero disables reminders."
          },
          "collect_phone": {
            "type": "boolean",
            "description": "Whether invitees are asked for a phone number."
          },
          "active": {
            "type": "boolean",
            "description": "Whether invitees can make new bookings through this link."
          },
          "created_at": {
            "type": "integer",
            "description": "Creation time in Unix milliseconds."
          },
          "updated_at": {
            "type": "integer",
            "description": "Last change in Unix milliseconds."
          },
          "url": {
            "type": "string",
            "description": "Public booking URL to share with invitees.",
            "format": "uri"
          }
        },
        "required": [
          "id",
          "org_id",
          "owner_account_id",
          "slug",
          "name",
          "description",
          "duration_minutes",
          "duration_options",
          "location_kind",
          "location_detail",
          "timezone",
          "availability",
          "window_days",
          "min_notice_minutes",
          "buffer_before_minutes",
          "buffer_after_minutes",
          "max_per_day",
          "questions",
          "reminder_hours",
          "collect_phone",
          "active",
          "created_at",
          "updated_at",
          "url"
        ],
        "additionalProperties": false
      },
      "description": "Booking links owned by the acting member; upcoming bookings are returned separately. This operation has no cursor pagination."
    }
  },
  "required": [
    "items",
    "upcoming_bookings"
  ],
  "additionalProperties": false,
  "examples": [
    {
      "items": [
        {
          "id": "bkl_example",
          "org_id": "o_example",
          "owner_account_id": "a_example",
          "slug": "project-introduction",
          "name": "Project introduction",
          "description": null,
          "duration_minutes": 30,
          "duration_options": null,
          "location_kind": "video",
          "location_detail": null,
          "timezone": "Europe/Oslo",
          "availability": {
            "mon": [
              {
                "start": "09:00",
                "end": "17:00"
              }
            ]
          },
          "window_days": 30,
          "min_notice_minutes": 240,
          "buffer_before_minutes": 0,
          "buffer_after_minutes": 0,
          "max_per_day": 0,
          "questions": null,
          "reminder_hours": 24,
          "collect_phone": false,
          "active": true,
          "created_at": 1794301200000,
          "updated_at": 1794301200000,
          "url": "https://example.com/book/project-introduction"
        }
      ],
      "upcoming_bookings": [
        {
          "id": "bk_project_intro",
          "link_id": "bkl_example",
          "start_at": 1794823200000,
          "end_at": 1794825000000,
          "timezone": "Europe/Oslo",
          "invitee_name": "Alex Morgan",
          "invitee_email": "alex@example.com",
          "note": "Please bring the onboarding checklist."
        }
      ]
    }
  ]
}
```

