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

# Get calendar dates

> Returns calendar dates with availability and price data. Per-night prices include any active discount promotions.

`selectable` indicates whether the user can continue the booking flow from the date. It follows the visit type's date-range and starting-day rules and requires a price for that date, but it does not require recorded capacity for the complete stay. A selectable date can therefore produce an `ON_DEMAND` booking configuration. Use the booking configuration response to distinguish a stay that can be confirmed from one that can only be requested. `price` is `null` when the date is not available or when the query is not specific enough to calculate a final price.

### Default month when you omit the date range

Omit both `date_from` and `date_to` and the response starts at the first month that contains a stay you can actually book, rather than at the current month. Use this for the initial calendar load, when you do not yet know which month to show.

A month qualifies when it contains a check-in date where all of the following hold for the visit type's minimum stay length:

- every occupied night has remaining capacity,
- every occupied night has a price, and the check-out date is priced as well,
- the date is an allowed starting day for the visit type.

The check-in date counts as an occupied night; the check-out date does not consume capacity.

The response then covers that month and the following one, as it always does. The search looks up to 24 months ahead.

Months that are closer but only bookable on request are skipped, because no stay in them can be confirmed from recorded availability. If no bookable stay is found, the response keeps the normal fallback calendar instead of returning an empty array. Priced dates that satisfy the visit type's starting-day and date-range rules remain `selectable`, including dates whose resulting stay is `ON_DEMAND`.

This applies when `hotel_id` and `visit_type_id` are set and the visit type is not on request. `room_type_id` is optional. Without it, the API searches the hotel's room types that match `guests`; every night of the stay must fit into the same room type, and capacity from different room types is never combined. Send `guests` on the initial request so the API searches the correct room occupancy. If you omit it, all room occupancies are considered.

Pass `date_from` or `date_to` to disable the automatic first-bookable-month search and control the range yourself. A `date_from` in the past is clamped to the current date.




## OpenAPI

````yaml /api/v1/openapi.yaml get /calendar/dates
openapi: 3.0.3
info:
  title: SpaPortal API v1
  version: '1.0'
  description: Public API for booking clients that integrate with SpaPortal.
servers:
  - url: https://spaportal.cz/api/v1
    description: Production
security:
  - bearerAuth: []
  - accessTokenQuery: []
tags:
  - name: System
  - name: Catalog
  - name: Availability
  - name: Pricing
  - name: Booking
paths:
  /calendar/dates:
    get:
      tags:
        - Availability
      summary: Get calendar dates
      description: >
        Returns calendar dates with availability and price data. Per-night
        prices include any active discount promotions.


        `selectable` indicates whether the user can continue the booking flow
        from the date. It follows the visit type's date-range and starting-day
        rules and requires a price for that date, but it does not require
        recorded capacity for the complete stay. A selectable date can therefore
        produce an `ON_DEMAND` booking configuration. Use the booking
        configuration response to distinguish a stay that can be confirmed from
        one that can only be requested. `price` is `null` when the date is not
        available or when the query is not specific enough to calculate a final
        price.


        ### Default month when you omit the date range


        Omit both `date_from` and `date_to` and the response starts at the first
        month that contains a stay you can actually book, rather than at the
        current month. Use this for the initial calendar load, when you do not
        yet know which month to show.


        A month qualifies when it contains a check-in date where all of the
        following hold for the visit type's minimum stay length:


        - every occupied night has remaining capacity,

        - every occupied night has a price, and the check-out date is priced as
        well,

        - the date is an allowed starting day for the visit type.


        The check-in date counts as an occupied night; the check-out date does
        not consume capacity.


        The response then covers that month and the following one, as it always
        does. The search looks up to 24 months ahead.


        Months that are closer but only bookable on request are skipped, because
        no stay in them can be confirmed from recorded availability. If no
        bookable stay is found, the response keeps the normal fallback calendar
        instead of returning an empty array. Priced dates that satisfy the visit
        type's starting-day and date-range rules remain `selectable`, including
        dates whose resulting stay is `ON_DEMAND`.


        This applies when `hotel_id` and `visit_type_id` are set and the visit
        type is not on request. `room_type_id` is optional. Without it, the API
        searches the hotel's room types that match `guests`; every night of the
        stay must fit into the same room type, and capacity from different room
        types is never combined. Send `guests` on the initial request so the API
        searches the correct room occupancy. If you omit it, all room
        occupancies are considered.


        Pass `date_from` or `date_to` to disable the automatic
        first-bookable-month search and control the range yourself. A
        `date_from` in the past is clamped to the current date.
      operationId: getCalendarDates
      parameters:
        - $ref: '#/components/parameters/AcceptLanguage'
        - name: visit_type_id
          in: query
          schema:
            type: integer
          description: Visit type ID.
        - name: hotel_id
          in: query
          schema:
            type: integer
          description: Hotel ID.
        - name: room_type_id
          in: query
          schema:
            type: integer
          description: Room type ID.
        - name: destination_id
          in: query
          schema:
            type: integer
          description: Destination ID.
        - name: guests
          in: query
          schema:
            type: integer
            minimum: 1
            maximum: 2
          description: Number of guests.
        - $ref: '#/components/parameters/DateFrom'
        - $ref: '#/components/parameters/DateTo'
      responses:
        '200':
          description: Calendar dates with availability and optional price data.
          headers:
            Content-Language:
              $ref: '#/components/headers/ContentLanguage'
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/CalendarDate'
              examples:
                default:
                  $ref: '#/components/examples/CalendarDatesResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
components:
  parameters:
    AcceptLanguage:
      name: Accept-Language
      in: header
      schema:
        type: string
        example: cs_CZ,de
      description: >-
        Comma-separated list of languages to include. See
        [Localization](/api/v1/localization) for details.
    DateFrom:
      name: date_from
      in: query
      schema:
        type: string
        format: date
      description: Start date in `YYYY-MM-DD` format.
    DateTo:
      name: date_to
      in: query
      schema:
        type: string
        format: date
      description: End date in `YYYY-MM-DD` format.
  headers:
    ContentLanguage:
      description: Languages included in the response.
      schema:
        type: string
        example: cs_CZ,de
  schemas:
    CalendarDate:
      type: object
      properties:
        date:
          type: string
          format: date
        selectable:
          type: boolean
          nullable: true
          description: >-
            Whether the booking flow can start on this date. This follows price,
            date-range, and starting-day rules; it does not guarantee capacity
            for the complete stay. A selectable date may result in an ON_DEMAND
            booking configuration.
        availability:
          type: string
          enum:
            - NOT_AVAILABLE
            - AVAILABLE
            - ON_DEMAND
        price:
          type: object
          nullable: true
          additionalProperties: true
    ErrorResponse:
      type: object
      required:
        - success
        - message
      properties:
        success:
          type: boolean
          example: false
        message:
          type: string
    ValidationErrorResponse:
      type: object
      required:
        - success
        - message
        - errors
      properties:
        success:
          type: boolean
          example: false
        message:
          type: string
        errors:
          type: array
          items:
            type: object
            additionalProperties: true
  examples:
    CalendarDatesResponse:
      summary: Calendar dates
      value:
        - date: '2026-12-01'
          selectable: false
          availability: NOT_AVAILABLE
          price: null
        - date: '2026-12-02'
          selectable: true
          availability: ON_DEMAND
          price:
            is_final: true
            cs_CZ:
              amount: 1590
              currency: CZK
            de:
              amount: 61.2857
              currency: EUR
  responses:
    BadRequest:
      description: Invalid request.
      content:
        application/json:
          schema:
            oneOf:
              - $ref: '#/components/schemas/ErrorResponse'
              - $ref: '#/components/schemas/ValidationErrorResponse'
    Unauthorized:
      description: Invalid API key.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    NotFound:
      description: Resource not found.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    UnprocessableEntity:
      description: Resource exists but cannot be used for this request.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: >-
        See [Authentication](/api/v1/authentication) for how to obtain and send
        your API key.
    accessTokenQuery:
      type: apiKey
      in: query
      name: access_token
      description: >-
        See [Authentication](/api/v1/authentication) for how to obtain and send
        your API key.

````