> ## 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.

# Availability & Booking Search

Find available time slots for services and resources. This guide covers the typical search flow and advanced scenarios like recurring bookings, series, and waitlists.

For general request conventions, see [JSON-API Conventions](/developers/guides/json-api-conventions). For authentication, see [Authentication](/developers/guides/authentication).

***

## Prerequisites

* An organization with at least one **resource** and one **service** configured
* Public API endpoints — no authentication required (availability is public by default)
* Organization context is derived from the resource/service being queried

***

## Domain Model

```text theme={null}
Organization
  ├── Resources (rooms, desks, people, etc.)
  │     └── Schedule Groups → Schedules (weekly recurring) + Timeslots (fixed date-time blocks)
  └── Services (what can be booked — duration, pricing, capacity)
        └── Optional: own Schedules/Timeslots to constrain time further
```

Resources and Services exist at the same level under an Organization with a **many-to-many** relationship. A service can be offered on multiple resources, and a resource can have multiple services.

* A **resource** is the bookable entity (e.g. a meeting room, a therapist). It has **schedule groups** containing **schedules** (weekly recurring availability) and/or **timeslots** (fixed date-time blocks).
* A **service** defines booking rules: duration constraints, pricing, capacity. Services may optionally have their own schedules/timeslots — when present, a slot is bookable only when the resource's and service's availability periods overlap.
* A **booking** always belongs to both a resource and a service.
* A **blocker** is a booking without a service, with `is_blocker` flag set to `true`. It blocks availability on a resource without representing a real booking.

### How Availability is Calculated

The availability engine merges a resource's schedules and timeslots into **availability periods** (= opening hours). These are then combined with the service's duration settings to generate **bookable intervals**. Existing bookings and blockers reduce the remaining capacity.

***

## Typical Search Flow

Request path documentation:

* `paths/public/availability.yaml` for all `/api/v1/availability/*` endpoints in this guide
* `paths/public/availability.yaml` for `GET /api/v1/service-configuration`
* `paths/public/availability.yaml` for `GET /api/v1/intervals/waitlist-start` and `GET /api/v1/intervals/waitlist-end`

The standard booking search follows these steps:

<Steps>
  <Step title="Get Service Configuration">
    Retrieve booking rules and the next available date for a service:

    ```http theme={null}
    GET /api/v1/service-configuration?service_id={service_uuid}&resource_id={resource_uuid}
    ```

    **Response** includes:

    | Field                         | Description                          |
    | ----------------------------- | ------------------------------------ |
    | `mainService`                 | Service identity and pricing         |
    | `unit`                        | Duration unit (minutes, hours, days) |
    | `minDuration` / `maxDuration` | Allowed booking duration range       |
    | `price`                       | Pricing rules and modifiers          |
    | `meta.next_available_date`    | First date with availability         |

    Use `next_available_date` to initialize the calendar view.
  </Step>

  <Step title="Find Available Dates">
    Get a list of dates with available slots within a range:

    ```http theme={null}
    GET /api/v1/availability/start-dates?service_id={service_uuid}&start_date=2026-04-01&end_date=2026-04-30
    ```

    Optional parameters:

    | Parameter             | Description                                        |
    | --------------------- | -------------------------------------------------- |
    | `resource_id`         | Limit to a specific resource                       |
    | `original_booking_id` | Exclude an existing booking's time (for rebooking) |

    **Response:** An array of date strings that have at least one available slot.
  </Step>

  <Step title="Get Start Time Intervals">
    Once the user selects a date, fetch available start times:

    ```http theme={null}
    GET /api/v1/availability/start?service_id={service_uuid}&date=2026-04-15
    ```

    Optional parameters:

    | Parameter     | Type    | Description                                   |
    | ------------- | ------- | --------------------------------------------- |
    | `resource_id` | string  | Limit to a specific resource                  |
    | `duration`    | integer | Desired duration in minutes (narrows results) |

    **Response:** An array of interval objects:

    ```json theme={null}
    [
      {
        "start_date": "2026-04-15T09:00:00+02:00",
        "available": true,
        "number_available": 3,
        "remaining_number_available": 2,
        "resource_ids": ["r1", "r2", "r3"]
      },
      {
        "start_date": "2026-04-15T10:00:00+02:00",
        "available": false,
        "unavailability_type": "booked_out"
      }
    ]
    ```

    #### Unavailability Types

    | Type                 | Meaning                                |
    | -------------------- | -------------------------------------- |
    | `none`               | Available                              |
    | `booked_out`         | All capacity taken                     |
    | `lead_time_conflict` | Too close to current time              |
    | `under_min_duration` | Remaining time is below minimum        |
    | `staggered_conflict` | Conflicts with staggered booking rules |
  </Step>

  <Step title="Get End Time Intervals (Flexible Duration Only)">
    If the service allows flexible (variable) duration, fetch valid end times after the user picks a start. This lets the user request multiple possible end intervals for the chosen start interval.

    ```http theme={null}
    GET /api/v1/availability/end?service_id={service_uuid}&date_time=2026-04-15T09:00:00%2B02:00
    ```

    Optional parameters:

    | Parameter     | Type    | Description                       |
    | ------------- | ------- | --------------------------------- |
    | `resource_id` | string  | Limit to a specific resource      |
    | `adhoc`       | boolean | Whether this is an ad-hoc booking |

    **Response:** Array of end intervals with availability status.

    <Note>
      Skip this step for services with fixed or auto duration — the end time is calculated automatically from `start_date + duration`.
    </Note>
  </Step>
</Steps>

***

## Additional Endpoints

### Next Available Date

Get the absolute next available date without scanning a range:

```http theme={null}
GET /api/v1/availability/next-date?service_id={service_uuid}
```

Useful for "book next available" shortcuts.

### Availability Periods (Opening Hours)

Get raw availability blocks (opening hours) for a resource:

```http theme={null}
GET /api/v1/availability/periods?service_id={service_uuid}&resource_id={resource_uuid}
```

These represent the merged schedule/timeslot periods — the times when the resource is generally open. Useful for calendar heatmaps or dense schedule displays.

### Upcoming Intervals

Get the next N available intervals from now. This endpoint allows a list-based selection flow without requiring the user to pick a day in a calendar first:

```http theme={null}
GET /api/v1/availability/upcoming-intervals?service_id={service_uuid}
```

| Parameter             | Type    | Description                          |
| --------------------- | ------- | ------------------------------------ |
| `start_date`          | string  | Start scanning from this date        |
| `duration`            | integer | Desired duration in minutes          |
| `include_unavailable` | boolean | Include unavailable slots in results |

***

## Advanced Scenarios

<AccordionGroup>
  <Accordion title="Recurring Bookings">
    For bookings that repeat on a schedule:

    ```http theme={null}
    GET /api/v1/availability/recurring?service_id={service_uuid}&resource_id={resource_uuid}
    ```

    Returns availability data structured for recurring selection (e.g. "every Monday 10:00–11:00").
  </Accordion>

  <Accordion title="Series / Timeslot-Based Bookings">
    Some services use predefined **timeslot series** (e.g. a course with 10 sessions):

    ```http theme={null}
    GET /api/v1/availability/series?timeslot_series_id={series_uuid}&service_id={service_uuid}
    ```

    Get individual intervals within a series:

    ```http theme={null}
    GET /api/v1/availability/series-intervals?timeslot_series_id={series_uuid}
    ```
  </Accordion>

  <Accordion title="Waitlist">
    When a slot is fully booked, the waitlist endpoints provide intervals where customers can register interest:

    ```http theme={null}
    GET /api/v1/intervals/waitlist-start?service_id={service_uuid}&date=2026-04-15
    GET /api/v1/intervals/waitlist-end?service_id={service_uuid}&date_time=2026-04-15T09:00:00%2B02:00
    ```

    These follow the same pattern as start/end intervals but return waitlist-eligible slots.

    For the concrete UI rule set, auth requirements, and the `POST /api/v1/waitlist-spots` payload, see [Waitlist](/developers/guides/customer/waitlist).
  </Accordion>
</AccordionGroup>

***

## Timezone Handling

All dates in requests should include timezone offsets (ISO 8601 / Atom format):

```text theme={null}
2026-04-15T09:00:00+02:00
```

Pass the `timezone` parameter when the user's timezone differs from the resource's configured timezone:

```http theme={null}
GET /api/v1/availability/start?service_id={id}&date=2026-04-15&timezone=America/New_York
```

The API returns dates in the resource's timezone by default. Interval objects include both UTC (`start_date`) and local (`local_date_time`) representations when timezone conversion applies.

***

## Common Errors

| Error                        | Cause                                           | Solution                                                                |
| ---------------------------- | ----------------------------------------------- | ----------------------------------------------------------------------- |
| `422` — service\_id required | Missing `service_id` parameter                  | Always include `service_id` in availability requests                    |
| `422` — invalid date format  | Date not in `Y-m-d` or Atom format              | Use `YYYY-MM-DD` for date-only params, Atom for datetime                |
| Empty results                | Resource has no schedule or service is inactive | Verify the resource has an active schedule and the service is published |
