> ## Documentation Index
> Fetch the complete documentation index at: https://docs.anny.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Booking Calendars

Retrieve booking-focused calendar data and occupancy counts for display in calendar UIs. This endpoint belongs to the Bookings surface, even though the aggregate route itself lives in the misc path file.

For general conventions, see [JSON-API Conventions](/developers/guides/json-api-conventions). For availability search, see [Availability & Booking Search](/developers/guides/availability).

***

## Prerequisites

* At least one resource with a configured schedule
* Public endpoint — no authentication required for basic usage

***

## Unified Calendar View

Request path documentation:

* `paths/public/misc.yaml` for `GET /api/v1/calendar-events`

The main endpoint aggregates multiple data sources into a single response:

```http theme={null}
GET /api/v1/calendar-events?resource_id={resource_uuid}&start_date=2026-04-01T00:00:00Z&end_date=2026-04-30T23:59:59Z
```

### Parameters

| Parameter | Type | Required | Description |
| - | - | - | - |
| `resource_id` | string/array | Yes | Single UUID or array of resource UUIDs |
| `start_date` | string | No | Range start (ISO 8601). If omitted, uses the start of `end_date`'s day, or the start of today in the request timezone. |
| `end_date` | string | No | Range end (ISO 8601). If omitted, uses the end of the start day's day. |
| `timezone` | string | No | Timezone for local date calculations (e.g. `Europe/Berlin`) |
| `filter[exclude_child_resources]` | boolean | No | Only show parent resource data |
| `filter[with_empty_booking_counts]` | boolean | No | Include `booking_count` periods whose count is `0`. Off by default. |

### Multiple Resources

Query multiple resources in a single request:

```http theme={null}
GET /api/v1/calendar-events?resource_id[]={uuid_1}&resource_id[]={uuid_2}&start_date=2026-04-01T00:00:00Z
```

***

## Event Types

The response contains events of different types, combined from booking and availability data sources:

| Type | Description |
| - | - |
| `period` | A raw availability slot from the resource's schedule |
| `period_fragment` | Remaining availability after bookings are subtracted |
| `booking` | An accepted booking (includes customer data for small-capacity resources) |
| `reserved_booking` | A temporary hold — no customer details exposed |
| `blocker` | A manually blocked time slot included in the aggregated calendar response |
| `booking_count` | Aggregated booking count for high-capacity resources (>25 slots) |

### Response Structure

```json theme={null}
{
  "data": {
    "events": [
      {
        "id": "event-uuid",
        "type": "booking",
        "timeslot_id": "9a93435a-86b2-449f-85ef-d47d477b9abe",
        "title": "Session 1",
        "start_date": "2026-04-15T10:00:00Z",
        "end_date": "2026-04-15T11:00:00Z",
        "resource_id": "res-uuid",
        "resource_name": "Meeting Room A",
        "resource_info": [
          {
            "id": 15,
            "name": "Projector",
            "slug": "projector",
            "category_name": "Equipment"
          }
        ],
        "quota": 1,
        "occupancy": 1.0,
        "is_available": false,
        "is_blocker": false,
        "display_label": "Jane Doe - Workshop",
        "customers": [
          { "id": "cust-1", "first_name": "Jane", "last_name": "Doe" }
        ],
        "bookings": [
          { "id": "book-uuid", "status": "accepted" }
        ],
        "color_map": { "bg": "#3b82f6", "text": "#ffffff" }
      },
      {
        "id": "period-uuid",
        "type": "period_fragment",
        "start_date": "2026-04-15T11:00:00Z",
        "end_date": "2026-04-15T18:00:00Z",
        "resource_id": "res-uuid",
        "is_available": true,
        "quota": 1,
        "occupancy": 0.0
      }
    ],
    "resources_with_schedule": ["res-uuid"]
  }
}
```

Timeslot-backed events can include `timeslot_id`. Use it to fetch the canonical timeslot resource through the admin timeslot endpoints, open the matching editor, or reconcile calendar cards with `resource_info` and allocation state.

### Admin context (`display_lines`)

When the request runs with an organization context, the admin calendar renders backend-composed `display_lines` below `display_label`. Each line is `{ key, icon, label, image, object }`; order is significant. `key` identifies the line kind so clients can find or override a specific line without parsing `label` (`time` for the formatted clock range, `timeslot` for the timeslot title, `customer`, `service`, `resource`, `admin_note`, `customer_note`, `order_item`).

For `timeslot` events the lines are: `time`, then `timeslot` when the title is non-empty, then `resource`. Untitled timeslots omit the title line; the time range is the information.

For a single confirmed booking in admin context the lines are: `customer` (only when the headline is a custom description) → `time` → `timeslot` (when the timeslot has a specific title) → `service` → `resource` → `admin_note` → `customer_note`.

Non-admin responses do not receive this enrichment: `display_lines` stay the public composition, and `is_paid` stays `null`.

For a single confirmed booking in admin context, the event also includes `add_on_count`: the sum of add-on quantities on that booking. Aggregated events leave the field `null` at the event level and put the count on each nested `bookings[]` entry. Sequence wrappers report only their own add-ons, not those of child bookings. Non-admin responses always get `null`.

### Capacity-Based Rendering

The API adapts its response based on resource capacity:

* **Small resources** (capacity ≤ 25): Returns individual `booking` events with customer details. Use these to render detailed calendar entries.
* **Large resources** (capacity > 25): Returns `booking_count` events with aggregated occupancy numbers. Use these for heatmap or occupancy bar display. Periods with count `0` are omitted unless you send `filter[with_empty_booking_counts]=true`.

***

## Booking Detail Preview

For calendar detail views, use the booking preview endpoint to get a summary of a specific booking without fetching the full resource:

```http theme={null}
GET /api/v1/customer-accounts/{account_id}/booking-preview/{booking_id}
```

***

## Common Patterns

### Daily Calendar View

```http theme={null}
GET /api/v1/calendar-events?resource_id={uuid}&start_date=2026-04-15T00:00:00Z&end_date=2026-04-15T23:59:59Z&timezone=Europe/Berlin
```

### Weekly Multi-Resource View

```http theme={null}
GET /api/v1/calendar-events?resource_id[]={uuid_1}&resource_id[]={uuid_2}&start_date=2026-04-14T00:00:00Z&end_date=2026-04-20T23:59:59Z
```

### Correlate a Calendar Event to Timeslot CRUD

When an event includes `timeslot_id`, you can jump from the aggregate calendar response to the admin timeslot resource:

```http theme={null}
GET /api/v1/timeslots/{timeslot_id}?include=resource,series,resource_allocations.resource
```

For the full admin workflow, see [Admin Timeslot Management](/developers/guides/admin/timeslot-management).

## Common Errors

| Error | Cause | Solution |
| - | - | - |
| Empty `events` array | Resource has no schedule configured | Verify the resource has an active schedule |
| Missing customer data | High-capacity resource | Use `booking_count` events instead of individual bookings |
| `422` — resource\_id required | Missing parameter | Always include at least one `resource_id` |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.