{
  "openapi": "3.0.3",
  "info": {
    "title": "BookingClub Inner API",
    "version": "1.0.1",
    "description": "BookingClub Inner API v1 for reference data, properties, availability, bookings, cancellation and booking modification. Price-changing modification is supported for direct internal pending hotel items and direct TL2 API bookings when provider penalty is zero and only date/occupancy changes are requested; WTX-backed, room/rate/property/nationality, paid or commission-paid items require manual review."
  },
  "servers": [
    {
      "url": "https://api.bookingclub.net/v1"
    },
    {
      "url": "https://bookingclub.net/api/v1"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "paths": {
    "/": {
      "get": {
        "summary": "API metadata",
        "operationId": "getApiMetadata",
        "responses": {
          "200": {
            "$ref": "#/components/responses/JsonResponse"
          }
        }
      }
    },
    "/reference/{resource}": {
      "get": {
        "summary": "List reference data",
        "operationId": "listReferenceData",
        "parameters": [
          {
            "name": "resource",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "countries",
                "regions",
                "cities",
                "airports",
                "currencies",
                "currency-rates",
                "nationalities",
                "languages",
                "meal-plans"
              ]
            }
          },
          {
            "name": "q",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "countryId",
            "in": "query",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "regionId",
            "in": "query",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "cityId",
            "in": "query",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 1000
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500
            }
          },
          {
            "name": "language",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Optional language code for localized names; defaults to the main language."
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/JsonResponse"
          }
        }
      }
    },
    "/properties": {
      "get": {
        "summary": "List visible properties",
        "operationId": "listProperties",
        "parameters": [
          {
            "name": "name",
            "in": "query",
            "schema": {
              "type": "string",
              "description": "Property name search term."
            }
          },
          {
            "name": "propertyId",
            "in": "query",
            "schema": {
              "type": "string",
              "description": "Exact property identifier returned by the API."
            }
          },
          {
            "name": "countryId",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "regionId",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "cityId",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "source",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "all",
                "internal",
                "api",
                "wtx",
                "wtx_internal",
                "wtx_api",
                "tlapi",
                "tlapi2"
              ]
            },
            "description": "Filter by inventory source; default is all."
          },
          {
            "name": "updatedSince",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time",
              "description": "Return properties updated at or after this date/time where supported by the source."
            }
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "description": "1-based page number."
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "description": "Page size. Runtime maximum is 200."
            }
          },
          {
            "name": "language",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Optional language code for localized names; defaults to the main language."
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/JsonResponse"
          }
        }
      }
    },
    "/properties/{propertyId}": {
      "get": {
        "summary": "Get property details",
        "operationId": "getProperty",
        "parameters": [
          {
            "name": "propertyId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "language",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Optional language code for localized names; defaults to the main language."
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/JsonResponse"
          }
        }
      }
    },
    "/hotels/availability": {
      "post": {
        "summary": "Search hotel availability",
        "operationId": "searchHotelAvailability",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/HotelAvailabilityRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/JsonResponse"
          }
        }
      }
    },
    "/tours": {
      "get": {
        "summary": "List tours",
        "operationId": "listTours",
        "responses": {
          "200": {
            "$ref": "#/components/responses/JsonResponse"
          }
        },
        "parameters": [
          {
            "name": "name",
            "in": "query",
            "schema": {
              "type": "string",
              "description": "Tour name search term."
            }
          },
          {
            "name": "countryId",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "cityId",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 1000,
              "description": "1-based page number."
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "description": "Page size. Runtime maximum is 200."
            }
          },
          {
            "name": "language",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Optional language code for localized names; defaults to the main language."
          }
        ]
      }
    },
    "/tours/{tourId}": {
      "get": {
        "summary": "Get tour details",
        "operationId": "getTour",
        "parameters": [
          {
            "name": "tourId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "language",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Optional language code for localized names; defaults to the main language."
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/JsonResponse"
          }
        }
      }
    },
    "/tours/availability": {
      "post": {
        "summary": "Search tour availability",
        "operationId": "searchTourAvailability",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TourAvailabilityRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/JsonResponse"
          }
        }
      }
    },
    "/transfers": {
      "get": {
        "summary": "List transfers",
        "operationId": "listTransfers",
        "responses": {
          "200": {
            "$ref": "#/components/responses/JsonResponse"
          }
        },
        "parameters": [
          {
            "name": "name",
            "in": "query",
            "schema": {
              "type": "string",
              "description": "Transfer name search term."
            }
          },
          {
            "name": "countryId",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "cityId",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 1000,
              "description": "1-based page number."
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "description": "Page size. Runtime maximum is 200."
            }
          },
          {
            "name": "language",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Optional language code for localized names; defaults to the main language."
          }
        ]
      }
    },
    "/transfers/{transferId}": {
      "get": {
        "summary": "Get transfer details",
        "operationId": "getTransfer",
        "parameters": [
          {
            "name": "transferId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "language",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Optional language code for localized names; defaults to the main language."
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/JsonResponse"
          }
        }
      }
    },
    "/transfers/availability": {
      "post": {
        "summary": "Search transfer availability",
        "operationId": "searchTransferAvailability",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TransferAvailabilityRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/JsonResponse"
          }
        }
      }
    },
    "/bookings": {
      "get": {
        "summary": "List bookings",
        "operationId": "listBookings",
        "responses": {
          "200": {
            "$ref": "#/components/responses/JsonResponse"
          }
        },
        "parameters": [
          {
            "name": "bookingNumber",
            "in": "query",
            "schema": {
              "type": "string",
              "description": "Exact BookingClub booking number."
            }
          },
          {
            "name": "clientReference",
            "in": "query",
            "schema": {
              "type": "string",
              "description": "Client-supplied reference substring."
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 9,
              "enum": [
                0,
                1,
                2,
                3,
                4,
                5,
                6,
                7,
                8,
                9
              ]
            },
            "description": "Booking status code as an integer. Text values such as pending are rejected by runtime validation."
          },
          {
            "name": "bookingDateFrom",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time",
              "description": "Filter bookings created at or after this date/time."
            }
          },
          {
            "name": "bookingDateTo",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time",
              "description": "Filter bookings created at or before this date/time."
            }
          },
          {
            "name": "firstCheckInFrom",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time",
              "description": "Filter by first item check-in date/time from this value."
            }
          },
          {
            "name": "firstCheckInTo",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time",
              "description": "Filter by first item check-in date/time through this value."
            }
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 1000,
              "description": "1-based page number."
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "description": "Page size. Runtime maximum is 200."
            }
          }
        ]
      },
      "post": {
        "summary": "Create booking",
        "operationId": "createBooking",
        "description": "Creates a booking. Requires Idempotency-Key. Retrying the same request with the same key returns the stored response; sending the same booking payload again too quickly with a different key returns DUPLICATE_BOOKING_REQUEST.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateBookingRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/JsonResponse"
          },
          "409": {
            "$ref": "#/components/responses/JsonResponse"
          }
        }
      }
    },
    "/bookings/{bookingNumber}": {
      "get": {
        "summary": "Get booking",
        "operationId": "getBooking",
        "parameters": [
          {
            "$ref": "#/components/parameters/BookingNumber"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/JsonResponse"
          }
        }
      },
      "patch": {
        "summary": "Compatibility alias for modify",
        "operationId": "modifyBookingCompatibility",
        "parameters": [
          {
            "$ref": "#/components/parameters/BookingNumber"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ModifyBookingRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/JsonResponse"
          }
        },
        "description": "Compatibility alias for POST /bookings/{bookingNumber}/modify. Requires Idempotency-Key and the same ModifyBookingRequest body."
      }
    },
    "/bookings/{bookingNumber}/cancel-quote": {
      "post": {
        "summary": "Get cancellation quote",
        "operationId": "getCancellationQuote",
        "parameters": [
          {
            "$ref": "#/components/parameters/BookingNumber"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/JsonResponse"
          },
          "409": {
            "$ref": "#/components/responses/JsonResponse"
          }
        },
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CancelQuoteRequest"
              }
            }
          }
        },
        "description": "Calculates cancellation penalties. Body may include itemIds to quote selected future-service items only. The response includes a top-level cancelToken (opaque signed string, prefix rt_, ~15 min TTL) bound to the booking, exact item set, item state and penalties; send it back to POST /cancel. Multiple confirmed provider items must be quoted/cancelled individually. Same-day, past-service, completed, cancelled, or rejected items are not cancellable through this API."
      }
    },
    "/bookings/{bookingNumber}/cancel": {
      "post": {
        "summary": "Cancel booking or selected items",
        "operationId": "cancelBooking",
        "parameters": [
          {
            "$ref": "#/components/parameters/BookingNumber"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/JsonResponse"
          },
          "409": {
            "$ref": "#/components/responses/JsonResponse"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CancelBookingRequest"
              }
            }
          }
        },
        "description": "Applies cancellation after cancel-quote. Requires Idempotency-Key, confirm=true, the same itemIds selection and the cancelToken returned by cancel-quote. Provider penalty/cancellation failures never become a local zero-penalty cancellation. Multiple confirmed provider items must be processed one at a time. Same-day, past-service, completed, cancelled, rejected or changed items are rejected and require a fresh quote or manual review."
      }
    },
    "/bookings/{bookingNumber}/modify-quote": {
      "post": {
        "summary": "Get modify quote",
        "operationId": "getModifyQuote",
        "parameters": [
          {
            "$ref": "#/components/parameters/BookingNumber"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ModifyBookingRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/JsonResponse"
          },
          "409": {
            "$ref": "#/components/responses/JsonResponse"
          }
        },
        "description": "Validates proposed changes and returns old/new price and penalty. When the change is price-affecting, the response item object includes a modifyToken (opaque signed string, prefix rt_, ~15 min TTL) that binds the quoted price; send it back on POST /modify. modifyToken is only present for price-affecting quotes."
      }
    },
    "/bookings/{bookingNumber}/modify": {
      "post": {
        "summary": "Apply modify",
        "operationId": "modifyBooking",
        "parameters": [
          {
            "$ref": "#/components/parameters/BookingNumber"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ModifyBookingRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/JsonResponse"
          },
          "400": {
            "$ref": "#/components/responses/JsonResponse"
          },
          "409": {
            "$ref": "#/components/responses/JsonResponse"
          }
        },
        "description": "Applies a modification after modify-quote. Requires Idempotency-Key and confirm=true. A price-affecting modify (date, room, rate, occupancy, nationality or currency change) also requires the modifyToken returned by modify-quote; guest/comment-only changes do not. Missing modifyToken on a price-affecting modify returns 400 VALIDATION_ERROR (field modifyToken). A price drift since the quote returns 409 PRICE_CHANGED (field modifyToken, with details.quotedPrice and details.currentPrice). A price-affecting modify to a stay whose check-in is today or in the past returns 409 NOT_MODIFIABLE."
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer"
      }
    },
    "parameters": {
      "BookingNumber": {
        "name": "bookingNumber",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        }
      },
      "IdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": true,
        "schema": {
          "type": "string",
          "minLength": 1,
          "maxLength": 128
        }
      }
    },
    "responses": {
      "JsonResponse": {
        "description": "BookingClub JSON envelope",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/JsonEnvelope"
            }
          }
        }
      }
    },
    "schemas": {
      "JsonEnvelope": {
        "type": "object",
        "required": [
          "success",
          "requestId",
          "data",
          "errors"
        ],
        "properties": {
          "success": {
            "type": "boolean"
          },
          "requestId": {
            "type": "string"
          },
          "data": {
            "type": "object",
            "nullable": true
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "object"
            }
          }
        }
      },
      "HotelAvailabilityRequest": {
        "type": "object",
        "required": [
          "propertyId",
          "checkIn",
          "checkOut",
          "currency",
          "rooms"
        ],
        "properties": {
          "propertyId": {
            "type": "string"
          },
          "checkIn": {
            "type": "string",
            "format": "date"
          },
          "checkOut": {
            "type": "string",
            "format": "date"
          },
          "currency": {
            "type": "string"
          },
          "nationalityId": {
            "type": "integer"
          },
          "rooms": {
            "type": "array",
            "minItems": 1,
            "maxItems": 10,
            "items": {
              "$ref": "#/components/schemas/RoomRequest"
            }
          }
        }
      },
      "RoomRequest": {
        "type": "object",
        "required": [
          "adults"
        ],
        "properties": {
          "adults": {
            "type": "integer",
            "minimum": 1
          },
          "childrenAges": {
            "type": "array",
            "maxItems": 10,
            "items": {
              "type": "integer",
              "minimum": 0,
              "maximum": 17
            }
          }
        }
      },
      "TourAvailabilityRequest": {
        "type": "object",
        "required": [
          "tourId",
          "checkIn",
          "checkOut",
          "currency",
          "adults"
        ],
        "properties": {
          "tourId": {
            "type": "integer"
          },
          "checkIn": {
            "type": "string",
            "format": "date"
          },
          "checkOut": {
            "type": "string",
            "format": "date"
          },
          "currency": {
            "type": "string"
          },
          "adults": {
            "type": "integer",
            "minimum": 1
          },
          "childrenAges": {
            "type": "array",
            "maxItems": 10,
            "items": {
              "type": "integer",
              "minimum": 0,
              "maximum": 17
            }
          },
          "vehicleId": {
            "type": "integer"
          },
          "languageId": {
            "type": "integer"
          },
          "nationalityId": {
            "type": "integer"
          }
        }
      },
      "TransferAvailabilityRequest": {
        "type": "object",
        "required": [
          "transferKind",
          "checkIn",
          "currency",
          "adults"
        ],
        "properties": {
          "transferKind": {
            "type": "integer",
            "enum": [
              1,
              2,
              3
            ]
          },
          "checkIn": {
            "type": "string",
            "format": "date"
          },
          "currency": {
            "type": "string"
          },
          "adults": {
            "type": "integer",
            "minimum": 1
          },
          "pickupAirportId": {
            "type": "integer"
          },
          "dropOffAirportId": {
            "type": "integer"
          },
          "pickupCityId": {
            "type": "integer"
          },
          "dropOffCityId": {
            "type": "integer"
          },
          "pickupHotelId": {
            "type": "integer",
            "description": "Internal accommodation ID returned as a numeric propertyId by GET /properties."
          },
          "dropOffHotelId": {
            "type": "integer",
            "description": "Internal accommodation ID returned as a numeric propertyId by GET /properties."
          },
          "transferId": {
            "type": "integer"
          },
          "vehicleId": {
            "type": "integer"
          },
          "childrenAges": {
            "type": "array",
            "maxItems": 10,
            "items": {
              "type": "integer",
              "minimum": 0,
              "maximum": 17
            }
          },
          "nationalityId": {
            "type": "integer"
          },
          "flightNumber": {
            "type": "string"
          },
          "time": {
            "type": "string"
          }
        }
      },
      "CreateBookingRequest": {
        "type": "object",
        "required": [
          "holder",
          "items"
        ],
        "properties": {
          "clientReference": {
            "type": "string"
          },
          "holder": {
            "$ref": "#/components/schemas/Holder"
          },
          "items": {
            "type": "array",
            "minItems": 1,
            "maxItems": 20,
            "items": {
              "$ref": "#/components/schemas/BookingItemRequest"
            }
          },
          "note": {
            "type": "string"
          }
        }
      },
      "Holder": {
        "type": "object",
        "required": [
          "firstName",
          "lastName"
        ],
        "properties": {
          "firstName": {
            "type": "string"
          },
          "lastName": {
            "type": "string"
          },
          "email": {
            "type": "string",
            "format": "email",
            "maxLength": 120
          },
          "phone": {
            "type": "string"
          }
        }
      },
      "BookingItemRequest": {
        "type": "object",
        "required": [
          "type",
          "rateToken",
          "guests"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "hotel",
              "tour",
              "transfer"
            ]
          },
          "rateToken": {
            "type": "string",
            "maxLength": 12000
          },
          "guests": {
            "type": "array",
            "maxItems": 40,
            "items": {
              "$ref": "#/components/schemas/Guest"
            }
          },
          "specialRequests": {
            "type": "string",
            "maxLength": 500
          }
        }
      },
      "Guest": {
        "type": "object",
        "required": [
          "firstName",
          "lastName"
        ],
        "properties": {
          "firstName": {
            "type": "string"
          },
          "lastName": {
            "type": "string"
          },
          "gender": {
            "type": "integer"
          },
          "type": {
            "type": "string",
            "enum": [
              "adult",
              "child"
            ]
          },
          "age": {
            "type": "integer",
            "minimum": 0,
            "maximum": 17
          }
        }
      },
      "ModifyBookingRequest": {
        "type": "object",
        "required": [
          "itemId"
        ],
        "properties": {
          "itemId": {
            "type": "integer"
          },
          "confirm": {
            "type": "boolean"
          },
          "changes": {
            "$ref": "#/components/schemas/ModifyBookingChanges"
          },
          "guests": {
            "type": "array",
            "maxItems": 40,
            "items": {
              "$ref": "#/components/schemas/Guest"
            }
          },
          "specialRequests": {
            "type": "string",
            "maxLength": 500
          },
          "bookingComment": {
            "type": "string"
          },
          "customerComment": {
            "type": "string"
          },
          "checkIn": {
            "type": "string",
            "format": "date"
          },
          "checkOut": {
            "type": "string",
            "format": "date"
          },
          "roomId": {
            "type": "string"
          },
          "contractId": {
            "type": "integer"
          },
          "rateId": {
            "type": "string"
          },
          "adults": {
            "type": "integer"
          },
          "childrenAges": {
            "type": "array",
            "maxItems": 10,
            "items": {
              "type": "integer",
              "minimum": 0,
              "maximum": 17
            }
          },
          "nationalityId": {
            "type": "integer"
          },
          "currency": {
            "type": "string",
            "description": "Required when date, room, rate, occupancy, nationality or currency is changed."
          },
          "modifyToken": {
            "type": "string",
            "description": "Opaque signed token (prefix rt_, ~15 min TTL) returned by modify-quote as item.modifyToken. Required for a price-affecting modify and bound to the exact requested changes, item state and quoted price; not needed for guest/comment-only changes. If any bound value changed, request a fresh modify quote."
          }
        }
      },
      "ModifyBookingChanges": {
        "type": "object",
        "description": "Same fields as top-level modify body except itemId and confirm. Use this object for clearer request bodies.",
        "properties": {
          "guests": {
            "type": "array",
            "maxItems": 40,
            "items": {
              "$ref": "#/components/schemas/Guest"
            }
          },
          "specialRequests": {
            "type": "string",
            "maxLength": 500
          },
          "bookingComment": {
            "type": "string"
          },
          "customerComment": {
            "type": "string"
          },
          "checkIn": {
            "type": "string",
            "format": "date"
          },
          "checkOut": {
            "type": "string",
            "format": "date"
          },
          "roomId": {
            "type": "string"
          },
          "contractId": {
            "type": "integer"
          },
          "rateId": {
            "type": "string"
          },
          "adults": {
            "type": "integer"
          },
          "childrenAges": {
            "type": "array",
            "maxItems": 10,
            "items": {
              "type": "integer",
              "minimum": 0,
              "maximum": 17
            }
          },
          "nationalityId": {
            "type": "integer"
          },
          "currency": {
            "type": "string"
          }
        }
      },
      "CancelQuoteRequest": {
        "type": "object",
        "properties": {
          "itemIds": {
            "type": "array",
            "maxItems": 20,
            "description": "Optional positive booking item IDs to quote; omit or send an empty array to quote all cancellable items.",
            "items": {
              "type": "integer",
              "minimum": 1
            }
          }
        },
        "additionalProperties": false
      },
      "CancelBookingRequest": {
        "type": "object",
        "required": [
          "confirm",
          "cancelToken"
        ],
        "properties": {
          "confirm": {
            "type": "boolean",
            "enum": [
              true
            ],
            "description": "Must be true. Runtime returns VALIDATION_ERROR when confirm is omitted or not true."
          },
          "cancelToken": {
            "type": "string",
            "description": "Opaque signed token (prefix rt_, ~15 min TTL) returned by cancel-quote as the top-level cancelToken. Required and bound to the booking, selected items, item state and quoted penalties. If any bound value changed, request a fresh cancellation quote."
          },
          "itemIds": {
            "type": "array",
            "maxItems": 20,
            "description": "Optional positive booking item IDs to cancel; omit or send an empty array to cancel all cancellable items.",
            "items": {
              "type": "integer",
              "minimum": 1
            }
          }
        },
        "additionalProperties": false
      }
    }
  }
}
