{
  "components": {
    "schemas": {
      "Application": {
        "enum": [
          "auto",
          "manual"
        ],
        "title": "Application",
        "type": "string"
      },
      "AppliedDiscount": {
        "description": "Сработавшая скидка каталога (§19.10): на строку — её доля, в итогах — всего.",
        "properties": {
          "amount": {
            "description": "На сколько уменьшила сумму (с TVA, как `gross`)",
            "title": "Amount",
            "type": "string"
          },
          "application": {
            "$ref": "#/components/schemas/Application"
          },
          "discount_id": {
            "format": "uuid",
            "title": "Discount Id",
            "type": "string"
          },
          "kind": {
            "$ref": "#/components/schemas/DiscountKind"
          },
          "name": {
            "title": "Name",
            "type": "string"
          }
        },
        "required": [
          "discount_id",
          "name",
          "kind",
          "application",
          "amount"
        ],
        "title": "AppliedDiscount",
        "type": "object"
      },
      "DiscountKind": {
        "enum": [
          "line",
          "deal"
        ],
        "title": "DiscountKind",
        "type": "string"
      },
      "HTTPValidationError": {
        "properties": {
          "detail": {
            "items": {
              "$ref": "#/components/schemas/ValidationError"
            },
            "title": "Detail",
            "type": "array"
          }
        },
        "title": "HTTPValidationError",
        "type": "object"
      },
      "I18n3": {
        "additionalProperties": false,
        "description": "Тексты на языках сайта: ro (основной), en, ru.",
        "properties": {
          "en": {
            "default": "",
            "title": "En",
            "type": "string"
          },
          "ro": {
            "default": "",
            "title": "Ro",
            "type": "string"
          },
          "ru": {
            "default": "",
            "title": "Ru",
            "type": "string"
          }
        },
        "title": "I18n3",
        "type": "object"
      },
      "Night": {
        "properties": {
          "base": {
            "title": "Base",
            "type": "string"
          },
          "date": {
            "format": "date",
            "title": "Date",
            "type": "string"
          },
          "price": {
            "title": "Price",
            "type": "string"
          },
          "special_date_id": {
            "anyOf": [
              {
                "format": "uuid",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Special Date Id"
          },
          "special_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Special Name"
          }
        },
        "required": [
          "date",
          "price",
          "base"
        ],
        "title": "Night",
        "type": "object"
      },
      "SiteBookingRequestIn": {
        "additionalProperties": false,
        "description": "Заявка с формы сайта → сделка-бронь на этапе «Заявка» с расчётом цены. Клиент — по телефону\nили e-mail (найден — привязывается, нет — создаётся контакт). Нужен телефон или e-mail.\n\nАнтиспам: `hp` (скрытое поле-ловушка) непустое или `elapsed_ms` < 3000 — ответ как при успехе,\nно сделка не создаётся. Повтор с тем же `request_id` (досылка из очереди плагина) не создаёт\nвторую сделку и возвращает тот же ответ.",
        "properties": {
          "check_in": {
            "format": "date",
            "title": "Check In",
            "type": "string"
          },
          "check_out": {
            "format": "date",
            "title": "Check Out",
            "type": "string"
          },
          "consent": {
            "const": true,
            "description": "Согласие на обработку персональных данных",
            "title": "Consent",
            "type": "boolean"
          },
          "elapsed_ms": {
            "description": "Сколько форма была открыта до отправки, мс",
            "minimum": 0.0,
            "title": "Elapsed Ms",
            "type": "integer"
          },
          "email": {
            "anyOf": [
              {
                "format": "email",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Email"
          },
          "guests": {
            "default": 1,
            "maximum": 100.0,
            "minimum": 1.0,
            "title": "Guests",
            "type": "integer"
          },
          "hp": {
            "default": "",
            "description": "Поле-ловушка: скрыто от людей, должно быть пустым",
            "maxLength": 200,
            "title": "Hp",
            "type": "string"
          },
          "lang": {
            "default": "ro",
            "enum": [
              "ro",
              "en",
              "ru"
            ],
            "title": "Lang",
            "type": "string"
          },
          "message": {
            "anyOf": [
              {
                "maxLength": 2000,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Message"
          },
          "name": {
            "maxLength": 200,
            "minLength": 1,
            "title": "Name",
            "type": "string"
          },
          "page_url": {
            "anyOf": [
              {
                "maxLength": 500,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Page Url"
          },
          "phone": {
            "anyOf": [
              {
                "maxLength": 40,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Phone"
          },
          "request_id": {
            "description": "UUID заявки, создаёт плагин — идемпотентность",
            "format": "uuid",
            "title": "Request Id",
            "type": "string"
          },
          "unit_id": {
            "format": "uuid",
            "title": "Unit Id",
            "type": "string"
          },
          "utm": {
            "anyOf": [
              {
                "additionalProperties": {
                  "maxLength": 200,
                  "type": "string"
                },
                "maxProperties": 10,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Utm"
          }
        },
        "required": [
          "request_id",
          "unit_id",
          "check_in",
          "check_out",
          "name",
          "consent",
          "elapsed_ms"
        ],
        "title": "SiteBookingRequestIn",
        "type": "object"
      },
      "SiteBookingRequestOut": {
        "properties": {
          "currency": {
            "title": "Currency",
            "type": "string"
          },
          "nights": {
            "title": "Nights",
            "type": "integer"
          },
          "request_id": {
            "format": "uuid",
            "title": "Request Id",
            "type": "string"
          },
          "status": {
            "const": "received",
            "title": "Status",
            "type": "string"
          },
          "total": {
            "title": "Total",
            "type": "string"
          }
        },
        "required": [
          "request_id",
          "status",
          "nights",
          "total",
          "currency"
        ],
        "title": "SiteBookingRequestOut",
        "type": "object"
      },
      "SiteDiscount": {
        "properties": {
          "ends_on": {
            "anyOf": [
              {
                "format": "date",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Последний день действия; `null` — бессрочно",
            "title": "Ends On"
          },
          "name": {
            "title": "Name",
            "type": "string"
          },
          "value": {
            "examples": [
              "20.00"
            ],
            "title": "Value",
            "type": "string"
          },
          "value_type": {
            "description": "`fixed` — сумма за ночь",
            "enum": [
              "percent",
              "fixed"
            ],
            "title": "Value Type",
            "type": "string"
          }
        },
        "required": [
          "name",
          "value_type",
          "value",
          "ends_on"
        ],
        "title": "SiteDiscount",
        "type": "object"
      },
      "SiteGroup": {
        "properties": {
          "id": {
            "format": "uuid",
            "title": "Id",
            "type": "string"
          },
          "name": {
            "title": "Name",
            "type": "string"
          },
          "units_count": {
            "title": "Units Count",
            "type": "integer"
          }
        },
        "required": [
          "id",
          "name",
          "units_count"
        ],
        "title": "SiteGroup",
        "type": "object"
      },
      "SiteInfo": {
        "properties": {
          "account_name": {
            "title": "Account Name",
            "type": "string"
          },
          "check_in_time": {
            "title": "Check In Time",
            "type": "string"
          },
          "check_out_time": {
            "title": "Check Out Time",
            "type": "string"
          },
          "currency": {
            "title": "Currency",
            "type": "string"
          },
          "key_name": {
            "title": "Key Name",
            "type": "string"
          },
          "languages": {
            "description": "Языки, на которых есть тексты объектов",
            "items": {
              "enum": [
                "ro",
                "en",
                "ru"
              ],
              "type": "string"
            },
            "title": "Languages",
            "type": "array"
          },
          "timezone": {
            "title": "Timezone",
            "type": "string"
          }
        },
        "required": [
          "account_name",
          "currency",
          "languages",
          "timezone",
          "check_in_time",
          "check_out_time",
          "key_name"
        ],
        "title": "SiteInfo",
        "type": "object"
      },
      "SiteLegacyUrl": {
        "properties": {
          "gone": {
            "description": "Объект удалён — ответить 410 Gone",
            "title": "Gone",
            "type": "boolean"
          },
          "lang": {
            "title": "Lang",
            "type": "string"
          },
          "path": {
            "description": "Путь старого адреса (`/ro/product/<slug>/`): товар WooCommerce или прежний слаг объекта — ключ для 301",
            "title": "Path",
            "type": "string"
          },
          "slug": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "ЧПУ объекта на языке старого адреса; `null` — объект удалён",
            "title": "Slug"
          },
          "unit_id": {
            "format": "uuid",
            "title": "Unit Id",
            "type": "string"
          },
          "url": {
            "description": "Старый адрес: товар WooCommerce или путь прежнего слага",
            "title": "Url",
            "type": "string"
          }
        },
        "required": [
          "url",
          "path",
          "lang",
          "unit_id",
          "slug",
          "gone"
        ],
        "title": "SiteLegacyUrl",
        "type": "object"
      },
      "SiteOccupancyOut": {
        "properties": {
          "date_from": {
            "format": "date",
            "title": "Date From",
            "type": "string"
          },
          "date_to": {
            "format": "date",
            "title": "Date To",
            "type": "string"
          },
          "special_dates": {
            "items": {
              "$ref": "#/components/schemas/SiteSpecialDay"
            },
            "title": "Special Dates",
            "type": "array"
          },
          "units": {
            "items": {
              "$ref": "#/components/schemas/SiteUnitBusy"
            },
            "title": "Units",
            "type": "array"
          }
        },
        "required": [
          "date_from",
          "date_to",
          "units",
          "special_dates"
        ],
        "title": "SiteOccupancyOut",
        "type": "object"
      },
      "SitePhoto": {
        "properties": {
          "position": {
            "title": "Position",
            "type": "integer"
          },
          "url": {
            "description": "Постоянная публичная ссылка `/api/modules/rental/site/photos/{account_id}/{product_id}/{file}` (без ключа)",
            "title": "Url",
            "type": "string"
          }
        },
        "required": [
          "url",
          "position"
        ],
        "title": "SitePhoto",
        "type": "object"
      },
      "SitePrice": {
        "properties": {
          "available": {
            "title": "Available",
            "type": "boolean"
          },
          "per_night": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Средняя цена ночи с учётом скидок",
            "title": "Per Night"
          },
          "per_night_before": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Средняя цена ночи до скидок",
            "title": "Per Night Before"
          },
          "subtotal": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Итог до скидок; `null` — даты недоступны",
            "title": "Subtotal"
          },
          "total": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Итог после скидок; `null` — даты недоступны",
            "title": "Total"
          },
          "unit_id": {
            "format": "uuid",
            "title": "Unit Id",
            "type": "string"
          },
          "violations": {
            "items": {
              "$ref": "#/components/schemas/SiteViolation"
            },
            "title": "Violations",
            "type": "array"
          }
        },
        "required": [
          "unit_id",
          "available",
          "subtotal",
          "total",
          "per_night_before",
          "per_night",
          "violations"
        ],
        "title": "SitePrice",
        "type": "object"
      },
      "SitePricesOut": {
        "properties": {
          "check_in": {
            "format": "date",
            "title": "Check In",
            "type": "string"
          },
          "check_out": {
            "format": "date",
            "title": "Check Out",
            "type": "string"
          },
          "currency": {
            "title": "Currency",
            "type": "string"
          },
          "guests": {
            "title": "Guests",
            "type": "integer"
          },
          "nights": {
            "title": "Nights",
            "type": "integer"
          },
          "units": {
            "items": {
              "$ref": "#/components/schemas/SitePrice"
            },
            "title": "Units",
            "type": "array"
          }
        },
        "required": [
          "check_in",
          "check_out",
          "nights",
          "guests",
          "currency",
          "units"
        ],
        "title": "SitePricesOut",
        "type": "object"
      },
      "SiteQuoteOut": {
        "properties": {
          "available": {
            "description": "Нет блокирующих нарушений — можно отправить заявку",
            "title": "Available",
            "type": "boolean"
          },
          "check_in": {
            "format": "date",
            "title": "Check In",
            "type": "string"
          },
          "check_out": {
            "format": "date",
            "title": "Check Out",
            "type": "string"
          },
          "currency": {
            "title": "Currency",
            "type": "string"
          },
          "discounts": {
            "items": {
              "$ref": "#/components/schemas/AppliedDiscount"
            },
            "title": "Discounts",
            "type": "array"
          },
          "guests": {
            "title": "Guests",
            "type": "integer"
          },
          "nights": {
            "title": "Nights",
            "type": "integer"
          },
          "per_night": {
            "items": {
              "$ref": "#/components/schemas/Night"
            },
            "title": "Per Night",
            "type": "array"
          },
          "subtotal": {
            "title": "Subtotal",
            "type": "string"
          },
          "total": {
            "title": "Total",
            "type": "string"
          },
          "unit_id": {
            "format": "uuid",
            "title": "Unit Id",
            "type": "string"
          },
          "violations": {
            "items": {
              "$ref": "#/components/schemas/SiteViolation"
            },
            "title": "Violations",
            "type": "array"
          }
        },
        "required": [
          "unit_id",
          "check_in",
          "check_out",
          "nights",
          "guests",
          "per_night",
          "subtotal",
          "discounts",
          "total",
          "currency",
          "available",
          "violations"
        ],
        "title": "SiteQuoteOut",
        "type": "object"
      },
      "SiteRange": {
        "properties": {
          "end": {
            "description": "Не включительно: день выезда свободен для заезда",
            "format": "date",
            "title": "End",
            "type": "string"
          },
          "start": {
            "format": "date",
            "title": "Start",
            "type": "string"
          }
        },
        "required": [
          "start",
          "end"
        ],
        "title": "SiteRange",
        "type": "object"
      },
      "SiteSpecialDay": {
        "properties": {
          "end": {
            "description": "Включительно",
            "format": "date",
            "title": "End",
            "type": "string"
          },
          "min_nights": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Min Nights"
          },
          "name": {
            "title": "Name",
            "type": "string"
          },
          "start": {
            "format": "date",
            "title": "Start",
            "type": "string"
          },
          "unit_ids": {
            "anyOf": [
              {
                "items": {
                  "format": "uuid",
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "`null` — все объекты",
            "title": "Unit Ids"
          }
        },
        "required": [
          "start",
          "end",
          "name",
          "unit_ids",
          "min_nights"
        ],
        "title": "SiteSpecialDay",
        "type": "object"
      },
      "SiteUnit": {
        "properties": {
          "address": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Address"
          },
          "amenities": {
            "description": "Удобства на языке `lang` (нет перевода — румынский), по порядку справочника",
            "items": {
              "type": "string"
            },
            "title": "Amenities",
            "type": "array"
          },
          "area_m2": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Площадь, м²",
            "examples": [
              "54.5"
            ],
            "title": "Area M2"
          },
          "base_price": {
            "description": "Цена ночи без скидок — «старая» при `discount`",
            "title": "Base Price",
            "type": "string"
          },
          "bathrooms": {
            "title": "Bathrooms",
            "type": "integer"
          },
          "beds": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Beds"
          },
          "check_in_time": {
            "title": "Check In Time",
            "type": "string"
          },
          "check_out_time": {
            "title": "Check Out Time",
            "type": "string"
          },
          "currency": {
            "title": "Currency",
            "type": "string"
          },
          "description": {
            "title": "Description",
            "type": "string"
          },
          "discount": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SiteDiscount"
              },
              {
                "type": "null"
              }
            ],
            "description": "Скидка в `price`; `null` — без скидки"
          },
          "district": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "District"
          },
          "floor": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "Этаж",
            "title": "Floor"
          },
          "group_id": {
            "anyOf": [
              {
                "format": "uuid",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Group Id"
          },
          "group_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Group Name"
          },
          "has_balcony": {
            "title": "Has Balcony",
            "type": "boolean"
          },
          "has_living": {
            "title": "Has Living",
            "type": "boolean"
          },
          "has_terrace": {
            "title": "Has Terrace",
            "type": "boolean"
          },
          "id": {
            "format": "uuid",
            "title": "Id",
            "type": "string"
          },
          "lang": {
            "description": "Язык текстов; нет текста на языке — румынский",
            "enum": [
              "ro",
              "en",
              "ru"
            ],
            "title": "Lang",
            "type": "string"
          },
          "lat": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Lat"
          },
          "lng": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Lng"
          },
          "max_guests": {
            "title": "Max Guests",
            "type": "integer"
          },
          "name": {
            "title": "Name",
            "type": "string"
          },
          "names": {
            "$ref": "#/components/schemas/I18n3"
          },
          "photos": {
            "items": {
              "$ref": "#/components/schemas/SitePhoto"
            },
            "title": "Photos",
            "type": "array"
          },
          "position": {
            "title": "Position",
            "type": "integer"
          },
          "price": {
            "description": "Цена ночи («от») с безусловной скидкой на объект, действующей сегодня; особые даты не входят. Нет скидки — равна `base_price`",
            "title": "Price",
            "type": "string"
          },
          "rooms": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Rooms"
          },
          "rooms_count": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "Комнат; 0 — студия",
            "title": "Rooms Count"
          },
          "slug": {
            "description": "ЧПУ на языке `lang` (нет — румынский); хранится, уникален среди объектов, при переименовании не меняется",
            "title": "Slug",
            "type": "string"
          },
          "slugs": {
            "additionalProperties": {
              "type": "string"
            },
            "description": "ЧПУ на всех языках — для hreflang",
            "title": "Slugs",
            "type": "object"
          },
          "updated_at": {
            "format": "date-time",
            "title": "Updated At",
            "type": "string"
          }
        },
        "required": [
          "id",
          "lang",
          "slug",
          "slugs",
          "name",
          "description",
          "names",
          "group_id",
          "group_name",
          "address",
          "district",
          "lat",
          "lng",
          "rooms",
          "beds",
          "rooms_count",
          "has_living",
          "has_balcony",
          "has_terrace",
          "bathrooms",
          "floor",
          "area_m2",
          "max_guests",
          "amenities",
          "photos",
          "base_price",
          "price",
          "discount",
          "currency",
          "check_in_time",
          "check_out_time",
          "position",
          "updated_at"
        ],
        "title": "SiteUnit",
        "type": "object"
      },
      "SiteUnitBusy": {
        "properties": {
          "busy": {
            "description": "Подтверждённые брони и блокировки, слитые в интервалы; без гостей и сумм. Заявки дат не занимают и не показываются",
            "items": {
              "$ref": "#/components/schemas/SiteRange"
            },
            "title": "Busy",
            "type": "array"
          },
          "unit_id": {
            "format": "uuid",
            "title": "Unit Id",
            "type": "string"
          }
        },
        "required": [
          "unit_id",
          "busy"
        ],
        "title": "SiteUnitBusy",
        "type": "object"
      },
      "SiteUnitsOut": {
        "properties": {
          "lang": {
            "enum": [
              "ro",
              "en",
              "ru"
            ],
            "title": "Lang",
            "type": "string"
          },
          "units": {
            "description": "Объекты без архивных, по порядку",
            "items": {
              "$ref": "#/components/schemas/SiteUnit"
            },
            "title": "Units",
            "type": "array"
          },
          "updated_at": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Последнее изменение — версия кэша",
            "title": "Updated At"
          }
        },
        "required": [
          "lang",
          "units",
          "updated_at"
        ],
        "title": "SiteUnitsOut",
        "type": "object"
      },
      "SiteViolation": {
        "description": "Нарушения расчёта для сайта: без `tentative_overlap` (заявки других гостей не видны).",
        "properties": {
          "blocking": {
            "description": "Бронь не сохранится (иначе — предупреждение)",
            "title": "Blocking",
            "type": "boolean"
          },
          "code": {
            "enum": [
              "dates_invalid",
              "min_nights",
              "max_guests",
              "occupied",
              "tentative_overlap",
              "blocked",
              "unit_archived"
            ],
            "title": "Code",
            "type": "string"
          },
          "params": {
            "additionalProperties": true,
            "title": "Params",
            "type": "object"
          }
        },
        "required": [
          "code",
          "blocking"
        ],
        "title": "SiteViolation",
        "type": "object"
      },
      "ValidationError": {
        "properties": {
          "ctx": {
            "title": "Context",
            "type": "object"
          },
          "input": {
            "title": "Input"
          },
          "loc": {
            "items": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "integer"
                }
              ]
            },
            "title": "Location",
            "type": "array"
          },
          "msg": {
            "title": "Message",
            "type": "string"
          },
          "type": {
            "title": "Error Type",
            "type": "string"
          }
        },
        "required": [
          "loc",
          "msg",
          "type"
        ],
        "title": "ValidationError",
        "type": "object"
      }
    },
    "securitySchemes": {
      "HTTPBearer": {
        "description": "`tk_<key_id>_<secret>` — только с сервера",
        "scheme": "bearer",
        "type": "http"
      }
    }
  },
  "info": {
    "title": "Type — API сайта аренды",
    "version": "0.1.0"
  },
  "openapi": "3.1.0",
  "paths": {
    "/api/modules/rental/site/booking-requests": {
      "post": {
        "description": "Заявка с формы сайта (ключ проверяется раньше полей: без ключа — 401, а не 422) →\nсделка-бронь на этапе «Заявка», источник `site`, с расчётом цены. Повтор `request_id` — тот же\nответ. Занятые даты, блокировка, мин. срок или гостей больше максимума — 422\n`rental_unavailable`.",
        "operationId": "booking_request_api_modules_rental_site_booking_requests_post",
        "parameters": [
          {
            "description": "IP посетителя сайта",
            "in": "header",
            "name": "x-type-visitor-ip",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "IP посетителя сайта",
              "title": "X-Type-Visitor-Ip"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SiteBookingRequestIn"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SiteBookingRequestOut"
                }
              }
            },
            "description": "Successful Response"
          },
          "400": {
            "description": "`api_key_misplaced` — ключ в query, cookie или теле"
          },
          "401": {
            "description": "`api_key_invalid` — ключ не принят (причина — в журнале сервера)"
          },
          "403": {
            "description": "`scope_missing` — нет права `rental:site`; `scope_unavailable` — модуль выключен"
          },
          "422": {
            "description": "`rental_unavailable` (`violations`) или ошибка полей"
          },
          "429": {
            "description": "`too_many_attempts`, `Retry-After`"
          }
        },
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "summary": "Booking Request",
        "tags": [
          "module:rental"
        ]
      }
    },
    "/api/modules/rental/site/groups": {
      "get": {
        "description": "Группы (районы) с числом неархивных объектов — фильтр каталога.",
        "operationId": "groups_api_modules_rental_site_groups_get",
        "parameters": [
          {
            "description": "IP посетителя сайта",
            "in": "header",
            "name": "x-type-visitor-ip",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "IP посетителя сайта",
              "title": "X-Type-Visitor-Ip"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "items": {
                    "$ref": "#/components/schemas/SiteGroup"
                  },
                  "title": "Response Groups Api Modules Rental Site Groups Get",
                  "type": "array"
                }
              }
            },
            "description": "Successful Response"
          },
          "400": {
            "description": "`api_key_misplaced` — ключ в query, cookie или теле"
          },
          "401": {
            "description": "`api_key_invalid` — ключ не принят (причина — в журнале сервера)"
          },
          "403": {
            "description": "`scope_missing` — нет права `rental:site`; `scope_unavailable` — модуль выключен"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          },
          "429": {
            "description": "`too_many_attempts`, `Retry-After`"
          }
        },
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "summary": "Groups",
        "tags": [
          "module:rental"
        ]
      }
    },
    "/api/modules/rental/site/legacy-urls": {
      "get": {
        "description": "Старые адреса товаров WooCommerce → объект и его ЧПУ: таблица 301 в плагине.",
        "operationId": "legacy_urls_api_modules_rental_site_legacy_urls_get",
        "parameters": [
          {
            "description": "IP посетителя сайта",
            "in": "header",
            "name": "x-type-visitor-ip",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "IP посетителя сайта",
              "title": "X-Type-Visitor-Ip"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "items": {
                    "$ref": "#/components/schemas/SiteLegacyUrl"
                  },
                  "title": "Response Legacy Urls Api Modules Rental Site Legacy Urls Get",
                  "type": "array"
                }
              }
            },
            "description": "Successful Response"
          },
          "400": {
            "description": "`api_key_misplaced` — ключ в query, cookie или теле"
          },
          "401": {
            "description": "`api_key_invalid` — ключ не принят (причина — в журнале сервера)"
          },
          "403": {
            "description": "`scope_missing` — нет права `rental:site`; `scope_unavailable` — модуль выключен"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          },
          "429": {
            "description": "`too_many_attempts`, `Retry-After`"
          }
        },
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "summary": "Legacy Urls",
        "tags": [
          "module:rental"
        ]
      }
    },
    "/api/modules/rental/site/occupancy": {
      "get": {
        "description": "Занятые интервалы по объектам (подтверждённые брони и блокировки), без гостей и сумм;\nособые даты периода — для подсветки в календаре.",
        "operationId": "occupancy_api_modules_rental_site_occupancy_get",
        "parameters": [
          {
            "in": "query",
            "name": "date_from",
            "required": true,
            "schema": {
              "format": "date",
              "title": "Date From",
              "type": "string"
            }
          },
          {
            "description": "Не включительно; не больше 400 дней",
            "in": "query",
            "name": "date_to",
            "required": true,
            "schema": {
              "description": "Не включительно; не больше 400 дней",
              "format": "date",
              "title": "Date To",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "unit_ids",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "items": {
                    "format": "uuid",
                    "type": "string"
                  },
                  "type": "array"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Unit Ids"
            }
          },
          {
            "description": "IP посетителя сайта",
            "in": "header",
            "name": "x-type-visitor-ip",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "IP посетителя сайта",
              "title": "X-Type-Visitor-Ip"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SiteOccupancyOut"
                }
              }
            },
            "description": "Successful Response"
          },
          "400": {
            "description": "`api_key_misplaced` — ключ в query, cookie или теле"
          },
          "401": {
            "description": "`api_key_invalid` — ключ не принят (причина — в журнале сервера)"
          },
          "403": {
            "description": "`scope_missing` — нет права `rental:site`; `scope_unavailable` — модуль выключен"
          },
          "422": {
            "description": "`invalid_period` — больше 400 дней"
          },
          "429": {
            "description": "`too_many_attempts`, `Retry-After`"
          }
        },
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "summary": "Occupancy",
        "tags": [
          "module:rental"
        ]
      }
    },
    "/api/modules/rental/site/photos/{account_id}/{product_id}/{file}": {
      "get": {
        "description": "Постоянная публичная ссылка на фото объекта (без ключа, для `<img>` на сайте): 302 на\nвременную ссылку превью WebP 1920 (без EXIF), `Cache-Control: public, max-age=3000`. Оригинал\nнаружу не отдаётся: перенесённое фото, у которого превью ещё строится, — 503 с\n`Retry-After: 60`. Только фото неархивных объектов аккаунта с включённым модулем; иначе 404.",
        "operationId": "photo_api_modules_rental_site_photos__account_id___product_id___file__get",
        "parameters": [
          {
            "in": "path",
            "name": "account_id",
            "required": true,
            "schema": {
              "format": "uuid",
              "title": "Account Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "product_id",
            "required": true,
            "schema": {
              "format": "uuid",
              "title": "Product Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "file",
            "required": true,
            "schema": {
              "title": "File",
              "type": "string"
            }
          }
        ],
        "responses": {
          "302": {
            "description": "На превью WebP в хранилище"
          },
          "404": {
            "description": "Нет фото"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          },
          "503": {
            "description": "`photo_processing` — превью ещё строится, `Retry-After`"
          }
        },
        "summary": "Photo",
        "tags": [
          "module:rental"
        ]
      }
    },
    "/api/modules/rental/site/ping": {
      "get": {
        "description": "Проверка подключения плагина: аккаунт, валюта, языки текстов, время заезда и выезда.",
        "operationId": "ping_api_modules_rental_site_ping_get",
        "parameters": [
          {
            "description": "IP посетителя сайта",
            "in": "header",
            "name": "x-type-visitor-ip",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "IP посетителя сайта",
              "title": "X-Type-Visitor-Ip"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SiteInfo"
                }
              }
            },
            "description": "Successful Response"
          },
          "400": {
            "description": "`api_key_misplaced` — ключ в query, cookie или теле"
          },
          "401": {
            "description": "`api_key_invalid` — ключ не принят (причина — в журнале сервера)"
          },
          "403": {
            "description": "`scope_missing` — нет права `rental:site`; `scope_unavailable` — модуль выключен"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          },
          "429": {
            "description": "`too_many_attempts`, `Retry-After`"
          }
        },
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "summary": "Ping",
        "tags": [
          "module:rental"
        ]
      }
    },
    "/api/modules/rental/site/prices": {
      "get": {
        "description": "Цена и доступность всех объектов на даты — фильтр каталога «цена за выбранные даты».",
        "operationId": "prices_api_modules_rental_site_prices_get",
        "parameters": [
          {
            "in": "query",
            "name": "check_in",
            "required": true,
            "schema": {
              "format": "date",
              "title": "Check In",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "check_out",
            "required": true,
            "schema": {
              "format": "date",
              "title": "Check Out",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "guests",
            "required": false,
            "schema": {
              "default": 1,
              "maximum": 100,
              "minimum": 1,
              "title": "Guests",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "group_id",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "format": "uuid",
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Group Id"
            }
          },
          {
            "description": "IP посетителя сайта",
            "in": "header",
            "name": "x-type-visitor-ip",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "IP посетителя сайта",
              "title": "X-Type-Visitor-Ip"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SitePricesOut"
                }
              }
            },
            "description": "Successful Response"
          },
          "400": {
            "description": "`api_key_misplaced` — ключ в query, cookie или теле"
          },
          "401": {
            "description": "`api_key_invalid` — ключ не принят (причина — в журнале сервера)"
          },
          "403": {
            "description": "`scope_missing` — нет права `rental:site`; `scope_unavailable` — модуль выключен"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          },
          "429": {
            "description": "`too_many_attempts`, `Retry-After`"
          }
        },
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "summary": "Prices",
        "tags": [
          "module:rental"
        ]
      }
    },
    "/api/modules/rental/site/quote": {
      "get": {
        "description": "Калькулятор: цена каждой ночи, скидки каталога, итог; нарушения (занято, мин. срок,\nгостей больше максимума). Тот же расчёт, что в CRM.",
        "operationId": "quote_api_modules_rental_site_quote_get",
        "parameters": [
          {
            "in": "query",
            "name": "unit_id",
            "required": true,
            "schema": {
              "format": "uuid",
              "title": "Unit Id",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "check_in",
            "required": true,
            "schema": {
              "format": "date",
              "title": "Check In",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "check_out",
            "required": true,
            "schema": {
              "format": "date",
              "title": "Check Out",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "guests",
            "required": false,
            "schema": {
              "default": 1,
              "maximum": 100,
              "minimum": 1,
              "title": "Guests",
              "type": "integer"
            }
          },
          {
            "description": "IP посетителя сайта",
            "in": "header",
            "name": "x-type-visitor-ip",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "IP посетителя сайта",
              "title": "X-Type-Visitor-Ip"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SiteQuoteOut"
                }
              }
            },
            "description": "Successful Response"
          },
          "400": {
            "description": "`api_key_misplaced` — ключ в query, cookie или теле"
          },
          "401": {
            "description": "`api_key_invalid` — ключ не принят (причина — в журнале сервера)"
          },
          "403": {
            "description": "`scope_missing` — нет права `rental:site`; `scope_unavailable` — модуль выключен"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          },
          "429": {
            "description": "`too_many_attempts`, `Retry-After`"
          }
        },
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "summary": "Quote",
        "tags": [
          "module:rental"
        ]
      }
    },
    "/api/modules/rental/site/units": {
      "get": {
        "description": "Все неархивные объекты с текстами на `lang`, фото по постоянным ссылкам, удобствами и\nбазовой ценой. `updated_at` — версия для кэша плагина.",
        "operationId": "units_api_modules_rental_site_units_get",
        "parameters": [
          {
            "description": "Язык текстов; нет текста — румынский",
            "in": "query",
            "name": "lang",
            "required": false,
            "schema": {
              "default": "ro",
              "description": "Язык текстов; нет текста — румынский",
              "enum": [
                "ro",
                "en",
                "ru"
              ],
              "title": "Lang",
              "type": "string"
            }
          },
          {
            "description": "IP посетителя сайта",
            "in": "header",
            "name": "x-type-visitor-ip",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "IP посетителя сайта",
              "title": "X-Type-Visitor-Ip"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SiteUnitsOut"
                }
              }
            },
            "description": "Successful Response"
          },
          "400": {
            "description": "`api_key_misplaced` — ключ в query, cookie или теле"
          },
          "401": {
            "description": "`api_key_invalid` — ключ не принят (причина — в журнале сервера)"
          },
          "403": {
            "description": "`scope_missing` — нет права `rental:site`; `scope_unavailable` — модуль выключен"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          },
          "429": {
            "description": "`too_many_attempts`, `Retry-After`"
          }
        },
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "summary": "Units",
        "tags": [
          "module:rental"
        ]
      }
    },
    "/api/modules/rental/site/units/{unit_id}": {
      "get": {
        "operationId": "unit_api_modules_rental_site_units__unit_id__get",
        "parameters": [
          {
            "in": "path",
            "name": "unit_id",
            "required": true,
            "schema": {
              "format": "uuid",
              "title": "Unit Id",
              "type": "string"
            }
          },
          {
            "description": "Язык текстов; нет текста — румынский",
            "in": "query",
            "name": "lang",
            "required": false,
            "schema": {
              "default": "ro",
              "description": "Язык текстов; нет текста — румынский",
              "enum": [
                "ro",
                "en",
                "ru"
              ],
              "title": "Lang",
              "type": "string"
            }
          },
          {
            "description": "IP посетителя сайта",
            "in": "header",
            "name": "x-type-visitor-ip",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "IP посетителя сайта",
              "title": "X-Type-Visitor-Ip"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SiteUnit"
                }
              }
            },
            "description": "Successful Response"
          },
          "400": {
            "description": "`api_key_misplaced` — ключ в query, cookie или теле"
          },
          "401": {
            "description": "`api_key_invalid` — ключ не принят (причина — в журнале сервера)"
          },
          "403": {
            "description": "`scope_missing` — нет права `rental:site`; `scope_unavailable` — модуль выключен"
          },
          "404": {
            "description": "`not_found` — нет объекта или он в архиве"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          },
          "429": {
            "description": "`too_many_attempts`, `Retry-After`"
          }
        },
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "summary": "Unit",
        "tags": [
          "module:rental"
        ]
      }
    }
  }
}
