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

# Create booking

> Creates a booking or a non-binding booking request.

When `binding_booking` is `false`, SpaPortal creates a non-binding request and an operator can contact the customer later. When `binding_booking` is `true`, the billed contact must include an address.

The price is always calculated server-side from the current price list; any price sent in the request body is ignored. The stay costs the requested room type's configured price whatever share of its beds is occupied, so `guests` must hold at least one guest and no more than the room type has beds.

The first `Accept-Language` value determines the customer communication language for automated emails.




## OpenAPI

````yaml /api/v1/openapi.yaml post /booking
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:
  /booking:
    post:
      tags:
        - Booking
      summary: Create booking
      description: >
        Creates a booking or a non-binding booking request.


        When `binding_booking` is `false`, SpaPortal creates a non-binding
        request and an operator can contact the customer later. When
        `binding_booking` is `true`, the billed contact must include an address.


        The price is always calculated server-side from the current price list;
        any price sent in the request body is ignored. The stay costs the
        requested room type's configured price whatever share of its beds is
        occupied, so `guests` must hold at least one guest and no more than the
        room type has beds.


        The first `Accept-Language` value determines the customer communication
        language for automated emails.
      operationId: createBooking
      parameters:
        - $ref: '#/components/parameters/AcceptLanguage'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BookingCreateRequest'
            examples:
              default:
                $ref: '#/components/examples/BookingCreateRequest'
      responses:
        '200':
          description: Created booking or booking request.
          headers:
            Content-Language:
              $ref: '#/components/headers/ContentLanguage'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BookingCreateResponse'
              examples:
                default:
                  $ref: '#/components/examples/BookingCreateResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          description: Multiple companies matched the booking payload.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '422':
          description: >
            The request is well formed but the booking cannot be made. The most

            common causes are no price defined for the requested stay, room type
            or

            currency, more guests than the room type has beds, no capacity left
            for

            the requested dates, and dates that do not fit the visit type.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
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.
  schemas:
    BookingCreateRequest:
      type: object
      required:
        - visit_type_id
        - hotel_id
        - room_type_id
        - date_from
        - date_to
        - billed_to
        - guests
      properties:
        binding_booking:
          type: boolean
          default: false
        currency:
          type: string
          enum:
            - CZK
            - EUR
          default: CZK
        visit_type_id:
          type: integer
        hotel_id:
          type: integer
        room_type_id:
          type: integer
        date_from:
          type: string
          format: date
        date_to:
          type: string
          format: date
        customer_note:
          type: string
          nullable: true
        affilUserName:
          type: string
          nullable: true
        billed_to:
          $ref: '#/components/schemas/BilledTo'
        guests:
          type: array
          minItems: 1
          description: >
            The people staying in the room. At least one guest is required, and
            there

            cannot be more guests than the requested room type has beds — a
            request

            that exceeds the room's capacity is rejected with `422`.


            Occupancy does not change the price: the stay always costs the
            room's

            configured price, so one guest in a double pays the double-room
            rate.

            This holds for price lists quoted per person too, because the
            per-person

            rate is multiplied by the room's bed count.
          items:
            $ref: '#/components/schemas/BookingGuest'
    BookingCreateResponse:
      type: object
      additionalProperties: true
      properties:
        _id:
          $ref: '#/components/schemas/ObjectId'
        id:
          oneOf:
            - type: integer
            - type: string
    ErrorResponse:
      type: object
      required:
        - success
        - message
      properties:
        success:
          type: boolean
          example: false
        message:
          type: string
    BilledTo:
      type: object
      required:
        - gender
        - first_name
        - last_name
        - email
        - phone
        - consent_marketing
      properties:
        gender:
          type: string
          enum:
            - male
            - female
        first_name:
          type: string
        last_name:
          type: string
        email:
          type: string
          format: email
        phone:
          type: string
        consent_marketing:
          type: boolean
        address:
          type: object
          nullable: true
          properties:
            street:
              type: string
            house_number:
              type: string
            city:
              type: string
            zip_code:
              type: string
            country:
              type: string
              maxLength: 3
    BookingGuest:
      type: object
      required:
        - gender
        - first_name
        - last_name
        - birth_date
      properties:
        gender:
          type: string
          enum:
            - male
            - female
        first_name:
          type: string
        last_name:
          type: string
        birth_date:
          type: string
          format: date
        loyalty_program_id:
          type: integer
          nullable: true
        loyalty_program_code:
          type: string
          nullable: true
    ObjectId:
      type: string
      pattern: ^[0-9a-fA-F]{24}$
      description: Object id (24-character hex string) for the same entity.
      example: 66f16191f739705faa020001
    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:
    BookingCreateRequest:
      summary: Booking request
      value:
        binding_booking: true
        currency: EUR
        visit_type_id: 1
        hotel_id: 1
        room_type_id: 1
        date_from: '2026-04-01'
        date_to: '2026-04-21'
        customer_note: I prefer the corner room on the third floor.
        affilUserName: e-shop@pawlik-aquaforum.cz
        billed_to:
          gender: male
          first_name: Bohuslav
          last_name: Martinu
          email: bohuslav@example.com
          phone: '+420355455675'
          consent_marketing: true
          address:
            street: Milady Horakove
            house_number: 5A
            city: Praha
            zip_code: '16000'
            country: CZE
        guests:
          - gender: female
            first_name: Charlotte
            last_name: Martinu
            birth_date: '1894-01-01'
            loyalty_program_id: 1
            loyalty_program_code: GOLD000001
    BookingCreateResponse:
      summary: Created booking
      value:
        _id: 66f16191f739705faa020009
        id: 66f16191f739705faa020009
  headers:
    ContentLanguage:
      description: Languages included in the response.
      schema:
        type: string
        example: cs_CZ,de
  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'
  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.

````