{
  "openapi": "3.1.0",
  "info": {
    "title": "Channex.io — Properties",
    "version": "0.0.0"
  },
  "tags": [
    {
      "name": "Properties",
      "description": "Manage Properties — the physical premises you sell: hotels, motels, lodges, cabins, chalets, apartments and the like. Each property has its own address and details, so create one property per premises rather than combining several into a single entry."
    }
  ],
  "paths": {
    "/properties": {
      "get": {
        "operationId": "Properties_list",
        "summary": "List properties",
        "description": "List properties. Results are paginated; the `meta` block carries the page, limit, total and ordering. Without `pagination[…]` and `order[…]`, the first 10 properties are returned ordered by title ascending.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Properties.PropertyListParams.title"
          },
          {
            "$ref": "#/components/parameters/Properties.PropertyListParams.city"
          },
          {
            "$ref": "#/components/parameters/Properties.PropertyListParams.country"
          },
          {
            "$ref": "#/components/parameters/Common.Pagination.PaginationParams.page"
          },
          {
            "$ref": "#/components/parameters/Common.Pagination.PaginationParams.limit"
          },
          {
            "$ref": "#/components/parameters/Properties.PropertyListParams.orderTitle"
          },
          {
            "$ref": "#/components/parameters/Properties.PropertyListParams.orderInsertedAt"
          }
        ],
        "responses": {
          "200": {
            "description": "The request has succeeded.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Properties.PropertyListResource"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Common.Pagination.PaginationMeta"
                    }
                  },
                  "description": "JSON:API document wrapping a collection of resources with pagination meta."
                }
              }
            }
          },
          "401": {
            "description": "Authentication credentials are missing or invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Common.Errors.Unauthorized"
                }
              }
            }
          },
          "422": {
            "description": "The request has missing or invalid arguments; `details` lists the messages per argument.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/Common.Errors.InvalidArguments"
                    },
                    {
                      "$ref": "#/components/schemas/Common.Errors.InvalidNestedArguments"
                    }
                  ]
                }
              }
            }
          }
        },
        "tags": [
          "Properties"
        ]
      },
      "post": {
        "operationId": "Properties_create",
        "summary": "Create a property",
        "description": "Create a property. The created property is returned with `201 Created`.",
        "parameters": [],
        "responses": {
          "201": {
            "description": "201 Created response wrapping a resource body.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Properties.PropertyResource"
                    }
                  },
                  "description": "JSON:API document wrapping a single resource."
                }
              }
            }
          },
          "400": {
            "description": "The request body could not be parsed as JSON.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Common.Errors.UnparsableRequest"
                }
              }
            }
          },
          "401": {
            "description": "Authentication credentials are missing or invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Common.Errors.Unauthorized"
                }
              }
            }
          },
          "422": {
            "description": "The request body failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Common.Errors.ValidationError"
                }
              }
            }
          }
        },
        "tags": [
          "Properties"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Properties.PropertyCreateRequest"
              }
            }
          }
        }
      }
    },
    "/properties/options": {
      "get": {
        "operationId": "Properties_options",
        "summary": "List property options",
        "description": "List properties as lightweight options for selectors. Not paginated.",
        "parameters": [],
        "responses": {
          "200": {
            "description": "The request has succeeded.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Properties.PropertyOption"
                      }
                    }
                  },
                  "description": "A plain data-array envelope without pagination — used by reference/dictionary endpoints."
                }
              }
            }
          },
          "401": {
            "description": "Authentication credentials are missing or invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Common.Errors.Unauthorized"
                }
              }
            }
          }
        },
        "tags": [
          "Properties"
        ]
      }
    },
    "/properties/{id}": {
      "get": {
        "operationId": "Properties_read",
        "summary": "Retrieve a property",
        "description": "Retrieve a property by its identifier.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/Common.Scalars.id"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The request has succeeded.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Properties.PropertyResource"
                    }
                  },
                  "description": "JSON:API document wrapping a single resource."
                }
              }
            }
          },
          "401": {
            "description": "Authentication credentials are missing or invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Common.Errors.Unauthorized"
                }
              }
            }
          },
          "404": {
            "description": "The requested resource does not exist.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Common.Errors.NotFound"
                }
              }
            }
          },
          "422": {
            "description": "The request has missing or invalid arguments; `details` lists the messages per argument.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Common.Errors.InvalidArguments"
                }
              }
            }
          }
        },
        "tags": [
          "Properties"
        ]
      },
      "put": {
        "operationId": "Properties_update",
        "summary": "Update a property",
        "description": "Update a property by its identifier. Attributes absent from the request are left unchanged. The updated property is returned.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/Common.Scalars.id"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The request has succeeded.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Properties.PropertyResource"
                    }
                  },
                  "description": "JSON:API document wrapping a single resource."
                }
              }
            }
          },
          "400": {
            "description": "The request body could not be parsed as JSON.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Common.Errors.UnparsableRequest"
                }
              }
            }
          },
          "401": {
            "description": "Authentication credentials are missing or invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Common.Errors.Unauthorized"
                }
              }
            }
          },
          "404": {
            "description": "The requested resource does not exist.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Common.Errors.NotFound"
                }
              }
            }
          },
          "422": {
            "description": "The request has missing or invalid arguments; `details` lists the messages per argument.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/Common.Errors.InvalidArguments"
                    },
                    {
                      "$ref": "#/components/schemas/Common.Errors.ValidationError"
                    }
                  ]
                }
              }
            }
          }
        },
        "tags": [
          "Properties"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Properties.PropertyUpdateRequest"
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "Properties_delete",
        "summary": "Delete a property",
        "description": "Delete a property by its identifier. Deletion is permanent — a removed property cannot be restored.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/Common.Scalars.id"
            }
          },
          {
            "name": "force",
            "in": "query",
            "required": false,
            "description": "Delete the property even when it has connected channels. Without it, a property with at least one channel is refused.",
            "schema": {
              "type": "boolean"
            },
            "explode": false
          }
        ],
        "responses": {
          "200": {
            "description": "The request has succeeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Common.JsonApi.SuccessMessage"
                }
              }
            }
          },
          "401": {
            "description": "Authentication credentials are missing or invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Common.Errors.Unauthorized"
                }
              }
            }
          },
          "404": {
            "description": "The requested resource does not exist.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Common.Errors.NotFound"
                }
              }
            }
          },
          "422": {
            "description": "The request has missing or invalid arguments; `details` lists the messages per argument.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/Common.Errors.InvalidArguments"
                    },
                    {
                      "$ref": "#/components/schemas/Common.Errors.ValidationError"
                    }
                  ]
                }
              }
            }
          }
        },
        "tags": [
          "Properties"
        ]
      }
    }
  },
  "security": [
    {
      "UserApiKeyAuth": []
    }
  ],
  "components": {
    "parameters": {
      "Common.Pagination.PaginationParams.limit": {
        "name": "pagination[limit]",
        "in": "query",
        "required": false,
        "description": "Number of items per page. Maximum is 100.",
        "schema": {
          "$ref": "#/components/schemas/Common.Scalars.positiveInt",
          "maximum": 100
        },
        "explode": false
      },
      "Common.Pagination.PaginationParams.page": {
        "name": "pagination[page]",
        "in": "query",
        "required": false,
        "description": "Page to return, counted from 1.",
        "schema": {
          "$ref": "#/components/schemas/Common.Scalars.positiveInt"
        },
        "explode": false
      },
      "Properties.PropertyListParams.city": {
        "name": "filter[city]",
        "in": "query",
        "required": false,
        "description": "Return only properties in exactly this city.",
        "schema": {
          "type": "string"
        },
        "explode": false
      },
      "Properties.PropertyListParams.country": {
        "name": "filter[country]",
        "in": "query",
        "required": false,
        "description": "Return only properties in this country.",
        "schema": {
          "$ref": "#/components/schemas/Common.Scalars.country"
        },
        "explode": false
      },
      "Properties.PropertyListParams.orderInsertedAt": {
        "name": "order[inserted_at]",
        "in": "query",
        "required": false,
        "description": "Order properties by creation time.",
        "schema": {
          "$ref": "#/components/schemas/Common.Pagination.OrderDirection"
        },
        "explode": false
      },
      "Properties.PropertyListParams.orderTitle": {
        "name": "order[title]",
        "in": "query",
        "required": false,
        "description": "Order properties by title. Applied by default, ascending.",
        "schema": {
          "$ref": "#/components/schemas/Common.Pagination.OrderDirection"
        },
        "explode": false
      },
      "Properties.PropertyListParams.title": {
        "name": "filter[title]",
        "in": "query",
        "required": false,
        "description": "Return only properties with exactly this title.",
        "schema": {
          "type": "string"
        },
        "explode": false
      }
    },
    "schemas": {
      "Authentication.EmbeddedUser": {
        "type": "object",
        "required": [
          "type",
          "id",
          "attributes"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "user"
            ]
          },
          "id": {
            "$ref": "#/components/schemas/Common.Scalars.id"
          },
          "attributes": {
            "$ref": "#/components/schemas/Authentication.EmbeddedUserAttributes"
          }
        },
        "description": "A user embedded in another resource's relationships, carrying identifier, name and email."
      },
      "Authentication.EmbeddedUserAttributes": {
        "type": "object",
        "required": [
          "id",
          "name",
          "email"
        ],
        "properties": {
          "id": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Common.Scalars.id"
              }
            ],
            "description": "User identifier. Mirrors the resource id."
          },
          "name": {
            "type": "string",
            "description": "Display name of the user.",
            "examples": [
              "Channex User"
            ]
          },
          "email": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Common.Scalars.email"
              }
            ],
            "description": "Email address the account is registered with.",
            "examples": [
              "user@channex.io"
            ]
          }
        },
        "description": "Identifier, display name and email address of an embedded user."
      },
      "Common.Errors.InvalidArguments": {
        "type": "object",
        "required": [
          "errors"
        ],
        "properties": {
          "errors": {
            "$ref": "#/components/schemas/Common.Errors.InvalidArgumentsObject"
          }
        },
        "description": "The request has missing or invalid arguments; `details` lists the messages per argument."
      },
      "Common.Errors.InvalidArgumentsObject": {
        "type": "object",
        "required": [
          "code",
          "title",
          "details"
        ],
        "properties": {
          "code": {
            "type": "string",
            "enum": [
              "bad_request"
            ]
          },
          "title": {
            "type": "string",
            "enum": [
              "Bad Request"
            ]
          },
          "details": {
            "type": "object",
            "unevaluatedProperties": {
              "type": "array",
              "items": {
                "type": "string"
              }
            },
            "description": "Maps each invalid argument to the list of validation messages for that argument.",
            "examples": [
              {
                "id": [
                  "can't be blank"
                ]
              }
            ]
          }
        },
        "description": "Error object for invalid request arguments, adding per-argument messages."
      },
      "Common.Errors.InvalidNestedArguments": {
        "type": "object",
        "required": [
          "errors"
        ],
        "properties": {
          "errors": {
            "$ref": "#/components/schemas/Common.Errors.InvalidNestedArgumentsObject"
          }
        },
        "description": "The request has invalid nested arguments; `details` lists the messages per argument within each group."
      },
      "Common.Errors.InvalidNestedArgumentsObject": {
        "type": "object",
        "required": [
          "code",
          "title",
          "details"
        ],
        "properties": {
          "code": {
            "type": "string",
            "enum": [
              "bad_request"
            ]
          },
          "title": {
            "type": "string",
            "enum": [
              "Bad Request"
            ]
          },
          "details": {
            "type": "object",
            "unevaluatedProperties": {
              "type": "object",
              "unevaluatedProperties": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            },
            "description": "Maps each invalid argument group to the invalid arguments inside it and their validation messages.",
            "examples": [
              {
                "pagination": {
                  "limit": [
                    "must be less than or equal to 100"
                  ]
                }
              }
            ]
          }
        },
        "description": "Error object for invalid nested request arguments, adding per-argument messages one level deeper."
      },
      "Common.Errors.NotFound": {
        "type": "object",
        "required": [
          "errors"
        ],
        "properties": {
          "errors": {
            "type": "object",
            "required": [
              "code",
              "title"
            ],
            "properties": {
              "code": {
                "type": "string",
                "enum": [
                  "resource_not_found"
                ]
              },
              "title": {
                "type": "string",
                "enum": [
                  "Resource Not Found"
                ]
              }
            },
            "description": "Shape of a single JSON:API error object: a stable machine code plus a human-readable title."
          }
        },
        "description": "The requested resource does not exist."
      },
      "Common.Errors.Unauthorized": {
        "type": "object",
        "required": [
          "errors"
        ],
        "properties": {
          "errors": {
            "type": "object",
            "required": [
              "code",
              "title"
            ],
            "properties": {
              "code": {
                "type": "string",
                "enum": [
                  "unauthorized"
                ]
              },
              "title": {
                "type": "string",
                "enum": [
                  "Unauthorized"
                ]
              }
            },
            "description": "Shape of a single JSON:API error object: a stable machine code plus a human-readable title."
          }
        },
        "description": "Authentication credentials are missing or invalid."
      },
      "Common.Errors.UnparsableRequest": {
        "type": "object",
        "required": [
          "errors"
        ],
        "properties": {
          "errors": {
            "$ref": "#/components/schemas/Common.Errors.UnparsableRequestObject"
          }
        },
        "description": "The request body could not be parsed as JSON."
      },
      "Common.Errors.UnparsableRequestObject": {
        "type": "object",
        "required": [
          "code",
          "title",
          "details"
        ],
        "properties": {
          "code": {
            "type": "string",
            "enum": [
              "bad_request"
            ]
          },
          "title": {
            "type": "string",
            "enum": [
              "Bad Request"
            ]
          },
          "details": {
            "type": "object",
            "unevaluatedProperties": {
              "type": "string"
            },
            "description": "Maps the part of the request that could not be parsed to the reason.",
            "examples": [
              {
                "body": "malformed JSON"
              }
            ]
          }
        },
        "description": "Error object for an unparsable request body, naming the malformed part."
      },
      "Common.Errors.ValidationError": {
        "type": "object",
        "required": [
          "errors"
        ],
        "properties": {
          "errors": {
            "$ref": "#/components/schemas/Common.Errors.ValidationErrorObject"
          }
        },
        "description": "The request body failed validation."
      },
      "Common.Errors.ValidationErrorObject": {
        "type": "object",
        "required": [
          "code",
          "title",
          "details"
        ],
        "properties": {
          "code": {
            "type": "string",
            "enum": [
              "validation_error"
            ]
          },
          "title": {
            "type": "string",
            "enum": [
              "Validation Error"
            ]
          },
          "details": {
            "type": "object",
            "unevaluatedProperties": {
              "type": "array",
              "items": {
                "type": "string"
              }
            },
            "description": "Maps each invalid field to the list of validation messages for that field.",
            "examples": [
              {
                "field_name": [
                  "can't be blank"
                ]
              }
            ]
          }
        },
        "description": "Error object for a failed validation, adding per-field messages."
      },
      "Common.JsonApi.OptionAttributes": {
        "type": "object",
        "required": [
          "id",
          "title"
        ],
        "properties": {
          "id": {
            "$ref": "#/components/schemas/Common.Scalars.id"
          },
          "title": {
            "type": "string",
            "examples": [
              "My Hotel"
            ]
          }
        },
        "description": "Attributes of a lightweight `/options` item: identifier and display title."
      },
      "Common.JsonApi.SuccessMessage": {
        "type": "object",
        "required": [
          "meta"
        ],
        "properties": {
          "meta": {
            "type": "object",
            "properties": {
              "message": {
                "type": "string",
                "examples": [
                  "Success"
                ]
              }
            },
            "required": [
              "message"
            ]
          }
        },
        "description": "Success response carrying only a meta message (no resource body)."
      },
      "Common.Pagination.OrderDirection": {
        "type": "string",
        "enum": [
          "asc",
          "desc"
        ],
        "description": "Sort direction for list results."
      },
      "Common.Pagination.PaginationMeta": {
        "type": "object",
        "required": [
          "page",
          "limit",
          "total",
          "order_by",
          "order_direction"
        ],
        "properties": {
          "page": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Common.Scalars.positiveInt"
              }
            ],
            "description": "Page returned, counted from 1.",
            "examples": [
              1
            ]
          },
          "limit": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Common.Scalars.positiveInt"
              }
            ],
            "maximum": 100,
            "description": "Number of items per page. At most 100 — requests with `pagination[limit]` above 100 are rejected with `422 Unprocessable Entity`.",
            "examples": [
              10
            ]
          },
          "total": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Common.Scalars.nonNegativeInt"
              }
            ],
            "examples": [
              1
            ]
          },
          "order_by": {
            "type": "string",
            "description": "Field the results are ordered by.",
            "examples": [
              "inserted_at"
            ]
          },
          "order_direction": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Common.Pagination.OrderDirection"
              }
            ],
            "description": "Direction the results are ordered in.",
            "examples": [
              "desc"
            ]
          }
        },
        "description": "Pagination and ordering metadata attached to list responses."
      },
      "Common.Scalars.country": {
        "type": "string",
        "minLength": 2,
        "maxLength": 2,
        "description": "ISO 3166-1 alpha-2 country code.",
        "examples": [
          "GB"
        ]
      },
      "Common.Scalars.currency": {
        "type": "string",
        "minLength": 3,
        "maxLength": 3,
        "description": "ISO 4217 alphabetic currency code. See the `/currencies` endpoint for supported values.",
        "examples": [
          "USD"
        ]
      },
      "Common.Scalars.decimalString": {
        "type": "string",
        "description": "A decimal number as a string, e.g. `100.00`. Every monetary amount the API returns takes this form.",
        "examples": [
          "100.00"
        ]
      },
      "Common.Scalars.email": {
        "type": "string",
        "format": "email"
      },
      "Common.Scalars.id": {
        "type": "string",
        "format": "uuid",
        "examples": [
          "716305c4-561a-4561-a187-7f5b8aeb5920"
        ]
      },
      "Common.Scalars.nonNegativeInt": {
        "type": "integer",
        "format": "int32",
        "minimum": 0
      },
      "Common.Scalars.positiveInt": {
        "type": "integer",
        "format": "int32",
        "minimum": 1
      },
      "Common.Scalars.timezone": {
        "type": "string",
        "description": "Time zone name from the IANA Time Zone Database (the \"tz database\"), published at\nhttps://www.iana.org/time-zones — background at\nhttps://en.wikipedia.org/wiki/Tz_database. See the `/timezones` endpoint for the\nvalues this API accepts.",
        "examples": [
          "Europe/London"
        ]
      },
      "Facilities.Facility": {
        "type": "object",
        "required": [
          "id",
          "category",
          "title"
        ],
        "properties": {
          "id": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Common.Scalars.id"
              }
            ],
            "description": "Unique facility identifier. Mirrors the resource `id`.",
            "examples": [
              "864d91a6-3a40-4098-a880-84b841e11adb"
            ]
          },
          "category": {
            "type": "string",
            "description": "Grouping code the facility belongs to, in lower snake case. The property and\nroom type dictionaries have separate vocabularies: a code valid for one is\nrejected by the other. `filter[category]` takes this value.",
            "examples": [
              "general"
            ]
          },
          "title": {
            "type": "string",
            "description": "Human-readable facility name.",
            "examples": [
              "24-hour front desk"
            ]
          }
        },
        "description": "Attributes of a facility (amenity) available at a property or room type."
      },
      "Facilities.FacilityResource": {
        "type": "object",
        "required": [
          "type",
          "id",
          "attributes"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "facility"
            ]
          },
          "id": {
            "$ref": "#/components/schemas/Common.Scalars.id"
          },
          "attributes": {
            "$ref": "#/components/schemas/Facilities.Facility"
          }
        },
        "description": "A facility resource object (JSON:API), returned by both list and options endpoints."
      },
      "HotelPolicies.EmbeddedHotelPolicy": {
        "type": "object",
        "required": [
          "type",
          "id",
          "attributes"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "hotel_policy"
            ]
          },
          "id": {
            "$ref": "#/components/schemas/Common.Scalars.id"
          },
          "attributes": {
            "$ref": "#/components/schemas/HotelPolicies.EmbeddedHotelPolicyAttributes"
          }
        },
        "description": "A hotel policy embedded in another resource's relationships."
      },
      "HotelPolicies.EmbeddedHotelPolicyAttributes": {
        "type": "object",
        "required": [
          "id",
          "title",
          "pets_policy",
          "smoking_policy",
          "checkin_from_time",
          "checkin_to_time",
          "checkout_from_time",
          "checkout_to_time"
        ],
        "properties": {
          "id": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Common.Scalars.id"
              }
            ],
            "description": "Unique hotel policy identifier.",
            "examples": [
              "cfe101bf-126c-4031-8d73-27739929329a"
            ]
          },
          "title": {
            "type": "string",
            "description": "Hotel policy title.",
            "examples": [
              "Hotel Policy"
            ]
          },
          "pets_policy": {
            "$ref": "#/components/schemas/HotelPolicies.PetsPolicy"
          },
          "smoking_policy": {
            "$ref": "#/components/schemas/HotelPolicies.SmokingPolicy"
          },
          "checkin_from_time": {
            "type": "string",
            "description": "Earliest check-in time (`HH:MM`).",
            "examples": [
              "14:00"
            ]
          },
          "checkin_to_time": {
            "type": "string",
            "description": "Latest check-in time (`HH:MM`).",
            "examples": [
              "23:30"
            ]
          },
          "checkout_from_time": {
            "type": "string",
            "description": "Earliest check-out time (`HH:MM`).",
            "examples": [
              "11:00"
            ]
          },
          "checkout_to_time": {
            "type": "string",
            "description": "Latest check-out time (`HH:MM`).",
            "examples": [
              "12:00"
            ]
          }
        },
        "description": "Attributes of a hotel policy embedded in another resource's relationships."
      },
      "HotelPolicies.PetsPolicy": {
        "type": "string",
        "enum": [
          "allowed",
          "not_allowed",
          "by_arrangements",
          "assistive_only"
        ],
        "description": "Policy towards pets."
      },
      "HotelPolicies.SmokingPolicy": {
        "type": "string",
        "enum": [
          "no_smoking",
          "permitted_areas_only",
          "allowed"
        ],
        "description": "Policy towards smoking."
      },
      "Photos.EmbeddedPhotoWrite": {
        "type": "object",
        "required": [
          "url",
          "kind"
        ],
        "properties": {
          "id": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Common.Scalars.id"
              }
            ],
            "description": "UUID of an existing photo of this parent to update in place or, with `is_removed`, to remove. Omit to attach a new photo. An identifier naming no photo of this parent leaves the list unchanged.",
            "examples": [
              "cc673f90-8d65-498d-9ee7-b4b39f8df3ee"
            ]
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "URL to fetch the image from: the temporary URL returned by the upload endpoint, passed unchanged, or any reachable image URL. The image is copied into Channex storage, and responses carry that copy's URL rather than this one. Required in every entry; an entry without `id` whose URL matches a photo already attached updates that photo.",
            "examples": [
              "https://example.com/temporaryphotos/a66edb22-47da-4da8-bab5-3b6f4056256f.png"
            ]
          },
          "kind": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Photos.PhotoKind"
              }
            ],
            "description": "Kind of photo. Required when attaching or updating a photo; an entry that only removes one may omit it."
          },
          "author": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Photo author, or null.",
            "examples": [
              "John Doe"
            ]
          },
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Photo description, or null.",
            "examples": [
              "Room View"
            ]
          },
          "is_removed": {
            "type": "boolean",
            "description": "Set to `true` to remove the photo named by `id` or `url` from the parent. The photo is deleted and is no longer readable through the Photos resource. Defaults to `false`."
          }
        },
        "description": "A photo in a parent resource's `content.photos` list."
      },
      "Photos.Photo": {
        "type": "object",
        "required": [
          "id",
          "property_id",
          "room_type_id",
          "kind",
          "position",
          "author",
          "description",
          "url"
        ],
        "properties": {
          "id": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Common.Scalars.id"
              }
            ],
            "description": "Unique photo identifier.",
            "examples": [
              "cc673f90-8d65-498d-9ee7-b4b39f8df3ee"
            ]
          },
          "property_id": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Common.Scalars.id"
              }
            ],
            "description": "UUID of the Property the photo belongs to. Cannot be changed after the photo is created.",
            "examples": [
              "52397a6e-c330-44f4-a293-47042d3a3607"
            ]
          },
          "room_type_id": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Common.Scalars.id"
              },
              {
                "type": "null"
              }
            ],
            "description": "UUID of the Room Type the photo belongs to, or null when the photo is attached at property level. Cannot be changed after the photo is created."
          },
          "kind": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Photos.PhotoKind"
              }
            ],
            "description": "Kind of photo: `photo` for the property or room type itself, `ad` for an advertising image, `menu` for a restaurant menu. Defaults to `photo`."
          },
          "position": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Common.Scalars.nonNegativeInt"
              }
            ],
            "description": "Position in the photo list of the property or, for a room type photo, of that room type. Positions run from `0` without gaps and `0` designates the cover photo. On create the photo is inserted at this position, or appended when omitted; on update it is moved there. The other photos shift to keep the positions contiguous, and a value past the end places the photo last.",
            "examples": [
              0
            ]
          },
          "author": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Photo author, or null. An empty string is stored as `null`.",
            "examples": [
              "John Doe"
            ]
          },
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Photo description, or null. An empty string is stored as `null`.",
            "examples": [
              "Room View"
            ]
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "URL of the image as served by Channex. The create response carries a placeholder image URL; once the source image has been fetched and stored, typically within a few seconds, the photo carries the URL of the stored copy — read the photo back to obtain it. A source image that cannot be fetched leaves the placeholder in place.",
            "examples": [
              "https://images.channex.io/1747b751-28c0-47db-742a-40f62a186a00/"
            ]
          }
        },
        "description": "A photo as returned in responses: every attribute is present."
      },
      "Photos.PhotoKind": {
        "type": "string",
        "enum": [
          "photo",
          "ad",
          "menu"
        ],
        "description": "Kind of photo: `photo` for the property or room type itself, `ad` for an advertising image, `menu` for a restaurant menu. Defaults to `photo`."
      },
      "Properties.MinStayType": {
        "type": "string",
        "enum": [
          "both",
          "arrival",
          "through"
        ],
        "description": "Simplified handling of Min Stay restrictions. `both` keeps Min Stay Arrival and Min Stay Through separate. Set `arrival` or `through` when a system works with only one Min Stay type: min stay changes are then accepted under a single `min_stay` key and applied as that type in channel mappings."
      },
      "Properties.Property": {
        "type": "object",
        "required": [
          "id",
          "is_active",
          "expected_removal_date",
          "acc_channels_count",
          "property_category",
          "max_count_of_room_types",
          "max_count_of_rate_plans",
          "max_count_of_occupancies",
          "max_count_of_users",
          "title",
          "currency",
          "email",
          "phone",
          "zip_code",
          "country",
          "state",
          "city",
          "address",
          "longitude",
          "latitude",
          "timezone",
          "property_type",
          "logo_url",
          "website",
          "hotel_policy_id",
          "default_cancellation_policy_id",
          "default_tax_set_id",
          "location_precision",
          "min_stay_type",
          "settings",
          "content"
        ],
        "properties": {
          "id": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Common.Scalars.id"
              }
            ],
            "description": "Unique property identifier.",
            "examples": [
              "716305c4-561a-4561-a187-7f5b8aeb5920"
            ]
          },
          "is_active": {
            "type": "boolean",
            "description": "Whether the property is active.",
            "examples": [
              true
            ]
          },
          "is_demo": {
            "type": "boolean",
            "enum": [
              true
            ],
            "description": "Marks a demo property, pre-filled with sample data.\nPresent on a demo property only — a property created through `POST /properties`\ncarries no such attribute.",
            "examples": [
              true
            ]
          },
          "expected_removal_date": {
            "anyOf": [
              {
                "type": "string",
                "format": "date"
              },
              {
                "type": "null"
              }
            ],
            "description": "Date the property is expected to be removed, or null.",
            "examples": [
              "2026-12-31"
            ]
          },
          "acc_channels_count": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Common.Scalars.nonNegativeInt"
              }
            ],
            "description": "Count of connected channels. Read-only aggregate."
          },
          "property_category": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Properties.PropertyCategory"
              },
              {
                "type": "null"
              }
            ],
            "description": "Classification category of the property, or null when it is not set. Read-only.",
            "examples": [
              "hotel"
            ]
          },
          "max_count_of_room_types": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Common.Scalars.nonNegativeInt"
              }
            ],
            "description": "Maximum number of room types allowed. Read-only limit.",
            "examples": [
              20
            ]
          },
          "max_count_of_rate_plans": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Common.Scalars.nonNegativeInt"
              }
            ],
            "description": "Maximum number of rate plans allowed. Read-only limit.",
            "examples": [
              200
            ]
          },
          "max_count_of_occupancies": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Common.Scalars.nonNegativeInt"
              }
            ],
            "description": "Maximum number of occupancy options allowed. Read-only limit.",
            "examples": [
              8
            ]
          },
          "max_count_of_users": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Common.Scalars.nonNegativeInt"
              }
            ],
            "description": "Maximum number of users allowed. Read-only limit.",
            "examples": [
              20
            ]
          },
          "title": {
            "type": "string",
            "maxLength": 255,
            "description": "Property title, as shown in the system.",
            "examples": [
              "Demo Hotel"
            ]
          },
          "currency": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Common.Scalars.currency"
              }
            ],
            "description": "Default currency for nested entities, and the property's default currency for connected third-party services.",
            "examples": [
              "GBP"
            ]
          },
          "email": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Common.Scalars.email"
              },
              {
                "type": "null"
              }
            ],
            "description": "Contact email. Passed to connected third-party services as the property's contact email. Optional at setup, required before connecting a 3rd-party service."
          },
          "phone": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "maxLength": 32,
            "description": "Contact phone. Digits, spaces, brackets and special characters; max 32 chars. Passed to connected third-party services as the property's contact phone. Optional at setup, required before connecting a 3rd-party service.",
            "examples": [
              "+44 99 9999 9999"
            ]
          },
          "zip_code": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "maxLength": 32,
            "description": "ZIP/postal code (max 32 chars). Part of the contact address passed to connected third-party services. Optional at setup, required before connecting a 3rd-party service.",
            "examples": [
              "XXX XXX"
            ]
          },
          "country": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Common.Scalars.country"
              },
              {
                "type": "null"
              }
            ],
            "description": "Country of the property. ISO 3166-1 alpha-2 country code. Part of the contact address passed to connected third-party services. Optional at setup, required before connecting a 3rd-party service.",
            "examples": [
              "GB"
            ]
          },
          "state": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "maxLength": 255,
            "description": "State/region (max 255 chars). Part of the contact address passed to connected third-party services. Optional at setup, required before connecting a 3rd-party service.",
            "examples": [
              "Wales"
            ]
          },
          "city": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "maxLength": 255,
            "description": "City (max 255 chars). Part of the contact address passed to connected third-party services. Optional at setup, required before connecting a 3rd-party service.",
            "examples": [
              "Cardiff"
            ]
          },
          "address": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "maxLength": 255,
            "description": "Street address (max 255 chars). Part of the contact address passed to connected third-party services. Optional at setup, required before connecting a 3rd-party service.",
            "examples": [
              "123 High Street"
            ]
          },
          "longitude": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "maxLength": 12,
            "description": "Longitude as a decimal string in the range −180..180 (max 7 decimals). Derived from the address when the property is saved without one. Part of the property coordinates passed to connected third-party services. Optional at setup, required before connecting a 3rd-party service.",
            "examples": [
              "-0.2416781"
            ]
          },
          "latitude": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "maxLength": 11,
            "description": "Latitude as a decimal string in the range −90..90 (max 7 decimals). Derived from the address when the property is saved without one. Part of the property coordinates passed to connected third-party services. Optional at setup, required before connecting a 3rd-party service.",
            "examples": [
              "51.5285582"
            ]
          },
          "timezone": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Common.Scalars.timezone"
              },
              {
                "type": "null"
              }
            ],
            "description": "Time zone of the property, or null when it is not set. Sending `null` clears it.\n\nTime zone name from the IANA Time Zone Database (the \"tz database\"), published at\nhttps://www.iana.org/time-zones — background at\nhttps://en.wikipedia.org/wiki/Tz_database. See the `/timezones` endpoint for the\nvalues this API accepts.",
            "examples": [
              "Europe/London"
            ]
          },
          "property_type": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Properties.PropertyType"
              },
              {
                "type": "null"
              }
            ],
            "description": "Type of the property, or null when it is not set. Sending `null` clears it.\n\n**Set this value — it affects billing. Use `hotel` for a hotel and `apartment`\nfor a vacation rental.**"
          },
          "logo_url": {
            "anyOf": [
              {
                "type": "string",
                "format": "uri"
              },
              {
                "type": "null"
              }
            ],
            "description": "URL to the property logo; copied into Channex media storage.",
            "examples": [
              "https://example.com/logo.png"
            ]
          },
          "website": {
            "anyOf": [
              {
                "type": "string",
                "format": "uri"
              },
              {
                "type": "null"
              }
            ],
            "description": "URL to the property website.",
            "examples": [
              "https://example.com"
            ]
          },
          "hotel_policy_id": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Common.Scalars.id"
              },
              {
                "type": "null"
              }
            ],
            "description": "UUID of the property's hotel policy, or null. Sending `null` clears it."
          },
          "default_cancellation_policy_id": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Common.Scalars.id"
              },
              {
                "type": "null"
              }
            ],
            "description": "UUID of the property's default cancellation policy, or null."
          },
          "default_tax_set_id": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Common.Scalars.id"
              },
              {
                "type": "null"
              }
            ],
            "description": "UUID of the property's default tax set, or null."
          },
          "location_precision": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Common.Scalars.nonNegativeInt"
              },
              {
                "type": "null"
              }
            ],
            "description": "Location precision, or null."
          },
          "min_stay_type": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Properties.MinStayType"
              }
            ],
            "description": "Simplified Min Stay restriction handling for the property. Mirrors `settings.min_stay_type`: writing either attribute updates both.",
            "deprecated": true
          },
          "settings": {
            "$ref": "#/components/schemas/Properties.PropertySettings"
          },
          "content": {
            "$ref": "#/components/schemas/Properties.PropertyContent"
          }
        },
        "description": "A property (hotel, apartment, etc.) as returned in responses: every attribute is present."
      },
      "Properties.PropertyCategory": {
        "type": "string",
        "enum": [
          "camping",
          "hotel",
          "vacation_rental"
        ],
        "description": "Classification category of the property."
      },
      "Properties.PropertyContent": {
        "type": "object",
        "required": [
          "description",
          "important_information",
          "photos"
        ],
        "properties": {
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Property description. Null by default.",
            "examples": [
              "A lovely hotel in the city center."
            ]
          },
          "important_information": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Important information, included in booking confirmation emails.",
            "examples": [
              "Check-in from 3 PM. No pets allowed."
            ]
          },
          "photos": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Photos.Photo"
            },
            "description": "Photos attached to the property. A property holds at most 30 of them, counted separately from the photos of its room types. See the Photos resource for the full model and management endpoints."
          }
        },
        "description": "Property content as returned in responses: every field is present."
      },
      "Properties.PropertyContentWrite": {
        "type": "object",
        "properties": {
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Property description. Null by default.",
            "examples": [
              "A lovely hotel in the city center."
            ]
          },
          "important_information": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Important information, included in booking confirmation emails.",
            "examples": [
              "Check-in from 3 PM. No pets allowed."
            ]
          },
          "photos": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Photos.EmbeddedPhotoWrite"
            },
            "description": "Photos to attach to the property. The list is merged into the property's photos rather than replacing them: an entry with a new `url` attaches a photo, an entry carrying `id` updates that photo, and photos the list does not name are kept. Remove a photo through the Photos resource, or by sending its `id` with `is_removed: true`. A property holds at most 30 photos, counted separately from the photos of its room types: a request that would take the count past 30 is refused, while one that does not raise it is accepted even for a property already holding more, and deleting a photo frees its place."
          }
        },
        "description": "Property content accepted on create and update."
      },
      "Properties.PropertyCreate": {
        "type": "object",
        "required": [
          "title",
          "currency"
        ],
        "properties": {
          "title": {
            "type": "string",
            "maxLength": 255,
            "description": "Property title, as shown in the system.",
            "examples": [
              "Demo Hotel"
            ]
          },
          "currency": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Common.Scalars.currency"
              }
            ],
            "description": "Default currency for nested entities, and the property's default currency for connected third-party services.",
            "examples": [
              "GBP"
            ]
          },
          "email": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Common.Scalars.email"
              },
              {
                "type": "null"
              }
            ],
            "description": "Contact email. Passed to connected third-party services as the property's contact email. Optional at setup, required before connecting a 3rd-party service."
          },
          "phone": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "maxLength": 32,
            "description": "Contact phone. Digits, spaces, brackets and special characters; max 32 chars. Passed to connected third-party services as the property's contact phone. Optional at setup, required before connecting a 3rd-party service.",
            "examples": [
              "+44 99 9999 9999"
            ]
          },
          "zip_code": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "maxLength": 32,
            "description": "ZIP/postal code (max 32 chars). Part of the contact address passed to connected third-party services. Optional at setup, required before connecting a 3rd-party service.",
            "examples": [
              "XXX XXX"
            ]
          },
          "country": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Common.Scalars.country"
              },
              {
                "type": "null"
              }
            ],
            "description": "Country of the property. ISO 3166-1 alpha-2 country code. Part of the contact address passed to connected third-party services. Optional at setup, required before connecting a 3rd-party service.",
            "examples": [
              "GB"
            ]
          },
          "state": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "maxLength": 255,
            "description": "State/region (max 255 chars). Part of the contact address passed to connected third-party services. Optional at setup, required before connecting a 3rd-party service.",
            "examples": [
              "Wales"
            ]
          },
          "city": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "maxLength": 255,
            "description": "City (max 255 chars). Part of the contact address passed to connected third-party services. Optional at setup, required before connecting a 3rd-party service.",
            "examples": [
              "Cardiff"
            ]
          },
          "address": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "maxLength": 255,
            "description": "Street address (max 255 chars). Part of the contact address passed to connected third-party services. Optional at setup, required before connecting a 3rd-party service.",
            "examples": [
              "123 High Street"
            ]
          },
          "longitude": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "maxLength": 12,
            "description": "Longitude as a decimal string in the range −180..180 (max 7 decimals). Derived from the address when the property is saved without one. Part of the property coordinates passed to connected third-party services. Optional at setup, required before connecting a 3rd-party service.",
            "examples": [
              "-0.2416781"
            ]
          },
          "latitude": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "maxLength": 11,
            "description": "Latitude as a decimal string in the range −90..90 (max 7 decimals). Derived from the address when the property is saved without one. Part of the property coordinates passed to connected third-party services. Optional at setup, required before connecting a 3rd-party service.",
            "examples": [
              "51.5285582"
            ]
          },
          "timezone": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Common.Scalars.timezone"
              },
              {
                "type": "null"
              }
            ],
            "description": "Time zone of the property, or null when it is not set. Sending `null` clears it.\n\nTime zone name from the IANA Time Zone Database (the \"tz database\"), published at\nhttps://www.iana.org/time-zones — background at\nhttps://en.wikipedia.org/wiki/Tz_database. See the `/timezones` endpoint for the\nvalues this API accepts.",
            "examples": [
              "Europe/London"
            ]
          },
          "property_type": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Properties.PropertyType"
              },
              {
                "type": "null"
              }
            ],
            "description": "Type of the property, or null when it is not set. Sending `null` clears it.\n\n**Set this value — it affects billing. Use `hotel` for a hotel and `apartment`\nfor a vacation rental.**"
          },
          "logo_url": {
            "anyOf": [
              {
                "type": "string",
                "format": "uri"
              },
              {
                "type": "null"
              }
            ],
            "description": "URL to the property logo; copied into Channex media storage.",
            "examples": [
              "https://example.com/logo.png"
            ]
          },
          "website": {
            "anyOf": [
              {
                "type": "string",
                "format": "uri"
              },
              {
                "type": "null"
              }
            ],
            "description": "URL to the property website.",
            "examples": [
              "https://example.com"
            ]
          },
          "hotel_policy_id": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Common.Scalars.id"
              },
              {
                "type": "null"
              }
            ],
            "description": "UUID of the property's hotel policy, or null. Sending `null` clears it."
          },
          "default_cancellation_policy_id": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Common.Scalars.id"
              },
              {
                "type": "null"
              }
            ],
            "description": "UUID of the property's default cancellation policy, or null."
          },
          "default_tax_set_id": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Common.Scalars.id"
              },
              {
                "type": "null"
              }
            ],
            "description": "UUID of the property's default tax set, or null."
          },
          "location_precision": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Common.Scalars.nonNegativeInt"
              },
              {
                "type": "null"
              }
            ],
            "description": "Location precision, or null."
          },
          "min_stay_type": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Properties.MinStayType"
              }
            ],
            "description": "Simplified Min Stay restriction handling for the property. Mirrors `settings.min_stay_type`: writing either attribute updates both.",
            "deprecated": true
          },
          "group_id": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Common.Scalars.id"
              },
              {
                "type": "null"
              }
            ],
            "description": "UUID of the group to place the property in. Defaults to the user's Default Group when omitted, and is applied on create only. In responses the group appears under relationships."
          },
          "facilities": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Common.Scalars.id"
            },
            "description": "Property Facility IDs to associate. See the Property Facilities endpoint for the available identifiers. In responses, facilities appear under relationships."
          },
          "settings": {
            "$ref": "#/components/schemas/Properties.PropertySettingsWrite"
          },
          "content": {
            "$ref": "#/components/schemas/Properties.PropertyContentWrite"
          }
        },
        "description": "Property attributes accepted when creating a property. `title` and `currency` are required; every other attribute is optional and falls back to its default."
      },
      "Properties.PropertyCreateRequest": {
        "type": "object",
        "required": [
          "property"
        ],
        "properties": {
          "property": {
            "$ref": "#/components/schemas/Properties.PropertyCreate"
          }
        },
        "description": "Request body accepted when creating a property."
      },
      "Properties.PropertyListRelationships": {
        "type": "object",
        "required": [
          "users",
          "groups"
        ],
        "properties": {
          "users": {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Authentication.EmbeddedUser"
                }
              }
            },
            "required": [
              "data"
            ],
            "description": "Users with access to the property."
          },
          "groups": {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "type": "object",
                  "required": [
                    "type",
                    "id",
                    "attributes"
                  ],
                  "properties": {
                    "type": {
                      "type": "string",
                      "enum": [
                        "group"
                      ]
                    },
                    "id": {
                      "$ref": "#/components/schemas/Common.Scalars.id"
                    },
                    "attributes": {
                      "$ref": "#/components/schemas/Common.JsonApi.OptionAttributes"
                    }
                  },
                  "description": "A lightweight JSON:API resource returned by `/options` endpoints — id + title only, no relationships or pagination."
                }
              }
            },
            "required": [
              "data"
            ],
            "description": "Groups the property belongs to."
          }
        },
        "description": "Relationships of a property in list responses."
      },
      "Properties.PropertyListResource": {
        "type": "object",
        "required": [
          "type",
          "id",
          "attributes",
          "relationships"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "property"
            ]
          },
          "id": {
            "$ref": "#/components/schemas/Common.Scalars.id"
          },
          "attributes": {
            "$ref": "#/components/schemas/Properties.Property"
          },
          "relationships": {
            "$ref": "#/components/schemas/Properties.PropertyListRelationships"
          }
        },
        "description": "A property as returned by the list endpoint."
      },
      "Properties.PropertyOption": {
        "type": "object",
        "required": [
          "type",
          "id",
          "attributes"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "property"
            ]
          },
          "id": {
            "$ref": "#/components/schemas/Common.Scalars.id"
          },
          "attributes": {
            "$ref": "#/components/schemas/Properties.PropertyOptionAttributes"
          }
        },
        "description": "A lightweight property option for selectors — no relationships or pagination."
      },
      "Properties.PropertyOptionAttributes": {
        "type": "object",
        "required": [
          "id",
          "title",
          "is_owner",
          "currency",
          "min_stay_type",
          "property_type_group",
          "group_ids"
        ],
        "properties": {
          "id": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Common.Scalars.id"
              }
            ],
            "description": "Unique property identifier.",
            "examples": [
              "716305c4-561a-4561-a187-7f5b8aeb5920"
            ]
          },
          "title": {
            "type": "string",
            "description": "Property title, as shown in the system.",
            "examples": [
              "Demo Hotel"
            ]
          },
          "is_owner": {
            "type": "boolean",
            "description": "Whether the current user owns the property.",
            "examples": [
              true
            ]
          },
          "currency": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Common.Scalars.currency"
              }
            ],
            "description": "Default currency of the property.",
            "examples": [
              "USD"
            ]
          },
          "min_stay_type": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Properties.MinStayType"
              }
            ],
            "description": "Simplified Min Stay restriction handling for the property."
          },
          "property_type_group": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Group the property type belongs to, or null when the property has no type.",
            "examples": [
              "hotel"
            ]
          },
          "group_ids": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Common.Scalars.id"
            },
            "description": "UUIDs of the groups the property belongs to."
          }
        },
        "description": "Attributes of a property `/options` item."
      },
      "Properties.PropertyRelationships": {
        "type": "object",
        "required": [
          "users",
          "groups",
          "facilities",
          "hotel_policies",
          "cancellation_policies",
          "tax_sets"
        ],
        "properties": {
          "users": {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Authentication.EmbeddedUser"
                }
              }
            },
            "required": [
              "data"
            ],
            "description": "Users with access to the property."
          },
          "groups": {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "type": "object",
                  "required": [
                    "type",
                    "id",
                    "attributes"
                  ],
                  "properties": {
                    "type": {
                      "type": "string",
                      "enum": [
                        "group"
                      ]
                    },
                    "id": {
                      "$ref": "#/components/schemas/Common.Scalars.id"
                    },
                    "attributes": {
                      "$ref": "#/components/schemas/Common.JsonApi.OptionAttributes"
                    }
                  },
                  "description": "A lightweight JSON:API resource returned by `/options` endpoints — id + title only, no relationships or pagination."
                }
              }
            },
            "required": [
              "data"
            ],
            "description": "Groups the property belongs to."
          },
          "facilities": {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Facilities.FacilityResource"
                }
              }
            },
            "required": [
              "data"
            ],
            "description": "Facilities associated with the property."
          },
          "hotel_policies": {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/HotelPolicies.EmbeddedHotelPolicy"
                }
              }
            },
            "required": [
              "data"
            ],
            "description": "Hotel policies associated with the property."
          },
          "cancellation_policies": {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "type": "object",
                  "required": [
                    "type",
                    "id",
                    "attributes"
                  ],
                  "properties": {
                    "type": {
                      "type": "string",
                      "enum": [
                        "cancellation_policy"
                      ]
                    },
                    "id": {
                      "$ref": "#/components/schemas/Common.Scalars.id"
                    },
                    "attributes": {
                      "$ref": "#/components/schemas/Common.JsonApi.OptionAttributes"
                    }
                  },
                  "description": "A lightweight JSON:API resource returned by `/options` endpoints — id + title only, no relationships or pagination."
                }
              }
            },
            "required": [
              "data"
            ],
            "description": "Cancellation policies associated with the property."
          },
          "tax_sets": {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "type": "object",
                  "required": [
                    "type",
                    "id",
                    "attributes"
                  ],
                  "properties": {
                    "type": {
                      "type": "string",
                      "enum": [
                        "tax_set"
                      ]
                    },
                    "id": {
                      "$ref": "#/components/schemas/Common.Scalars.id"
                    },
                    "attributes": {
                      "$ref": "#/components/schemas/Common.JsonApi.OptionAttributes"
                    }
                  },
                  "description": "A lightweight JSON:API resource returned by `/options` endpoints — id + title only, no relationships or pagination."
                }
              }
            },
            "required": [
              "data"
            ],
            "description": "Tax sets associated with the property."
          }
        },
        "description": "Relationships of a single property: the list blocks plus the facilities, policies and tax sets of the property."
      },
      "Properties.PropertyResource": {
        "type": "object",
        "required": [
          "type",
          "id",
          "attributes",
          "relationships"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "property"
            ]
          },
          "id": {
            "$ref": "#/components/schemas/Common.Scalars.id"
          },
          "attributes": {
            "$ref": "#/components/schemas/Properties.Property"
          },
          "relationships": {
            "$ref": "#/components/schemas/Properties.PropertyRelationships"
          }
        },
        "description": "A property as returned by the single-property endpoints."
      },
      "Properties.PropertySettings": {
        "type": "object",
        "required": [
          "allow_availability_autoupdate_on_confirmation",
          "allow_availability_autoupdate_on_modification",
          "allow_availability_autoupdate_on_cancellation",
          "min_stay_type",
          "state_length",
          "cut_off_time",
          "cut_off_days",
          "max_day_advance",
          "min_price",
          "max_price"
        ],
        "properties": {
          "allow_availability_autoupdate_on_confirmation": {
            "type": "boolean",
            "description": "Decrease availability on new bookings. Effectively read-only — cannot be set to `false`. Always equal to `true`."
          },
          "allow_availability_autoupdate_on_modification": {
            "type": "boolean",
            "description": "Increase/decrease availability on booking modification. Default is `false`, which is the recommended setting."
          },
          "allow_availability_autoupdate_on_cancellation": {
            "type": "boolean",
            "description": "Decrease availability on booking cancellation. Default is `false`, which is the recommended setting."
          },
          "min_stay_type": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Properties.MinStayType"
              }
            ],
            "description": "Simplified Min Stay restriction handling for the property."
          },
          "state_length": {
            "type": "integer",
            "format": "int32",
            "minimum": 100,
            "maximum": 730,
            "description": "Length of the inventory table in days (100-730). Default is 500.",
            "examples": [
              500
            ]
          },
          "cut_off_time": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Cut-off time in 30-minute steps, e.g. `\"00:00:00\"`, or null when no cut-off is set. At this time each day, availability is closed for today plus `cut_off_days`.",
            "examples": [
              "00:00:00"
            ]
          },
          "cut_off_days": {
            "anyOf": [
              {
                "type": "integer",
                "format": "int32"
              },
              {
                "type": "null"
              }
            ],
            "minimum": 0,
            "maximum": 30,
            "description": "Number of days closed by the cut-off task (0-30), or null when no cut-off is set.",
            "examples": [
              0
            ]
          },
          "max_day_advance": {
            "anyOf": [
              {
                "type": "integer",
                "format": "int32"
              },
              {
                "type": "null"
              }
            ],
            "description": "Max number of days open for sale, or null. Applying this overwrites availability with 0 beyond the window; the overwritten values are only recoverable through a full sync.",
            "examples": [
              365
            ]
          },
          "min_price": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Common.Scalars.decimalString"
              },
              {
                "type": "null"
              }
            ],
            "description": "Minimum price per property, or null. Prices below it are raised to it.",
            "examples": [
              "100.00"
            ]
          },
          "max_price": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Common.Scalars.decimalString"
              },
              {
                "type": "null"
              }
            ],
            "description": "Maximum price per property, or null. Prices above it are lowered to it.",
            "examples": [
              "300.00"
            ]
          }
        },
        "description": "Property-level settings as returned in responses: every setting is present."
      },
      "Properties.PropertySettingsWrite": {
        "type": "object",
        "properties": {
          "allow_availability_autoupdate_on_confirmation": {
            "type": "boolean",
            "description": "Decrease availability on new bookings. Effectively read-only — cannot be set to `false`. Always equal to `true`."
          },
          "allow_availability_autoupdate_on_modification": {
            "type": "boolean",
            "description": "Increase/decrease availability on booking modification. Default is `false`, which is the recommended setting."
          },
          "allow_availability_autoupdate_on_cancellation": {
            "type": "boolean",
            "description": "Decrease availability on booking cancellation. Default is `false`, which is the recommended setting."
          },
          "min_stay_type": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Properties.MinStayType"
              }
            ],
            "description": "Simplified Min Stay restriction handling for the property."
          },
          "state_length": {
            "type": "integer",
            "format": "int32",
            "minimum": 100,
            "maximum": 730,
            "description": "Length of the inventory table in days (100-730). Default is 500.",
            "examples": [
              500
            ]
          },
          "cut_off_time": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Cut-off time in 30-minute steps, e.g. `\"00:00:00\"`, or null when no cut-off is set. At this time each day, availability is closed for today plus `cut_off_days`.",
            "examples": [
              "00:00:00"
            ]
          },
          "cut_off_days": {
            "anyOf": [
              {
                "type": "integer",
                "format": "int32"
              },
              {
                "type": "null"
              }
            ],
            "minimum": 0,
            "maximum": 30,
            "description": "Number of days closed by the cut-off task (0-30), or null when no cut-off is set.",
            "examples": [
              0
            ]
          },
          "max_day_advance": {
            "anyOf": [
              {
                "type": "integer",
                "format": "int32"
              },
              {
                "type": "null"
              }
            ],
            "description": "Max number of days open for sale, or null. Applying this overwrites availability with 0 beyond the window; the overwritten values are only recoverable through a full sync.",
            "examples": [
              365
            ]
          },
          "min_price": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Common.Scalars.decimalString"
              },
              {
                "$ref": "#/components/schemas/Common.Scalars.nonNegativeInt"
              },
              {
                "type": "null"
              }
            ],
            "description": "Minimum price per property: a decimal string like `\"100.00\"`, an integer in the currency's minor units (`10000` for 100.00 USD), or null. Prices below it are raised to it.",
            "examples": [
              "100.00"
            ]
          },
          "max_price": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Common.Scalars.decimalString"
              },
              {
                "$ref": "#/components/schemas/Common.Scalars.nonNegativeInt"
              },
              {
                "type": "null"
              }
            ],
            "description": "Maximum price per property: a decimal string like `\"300.00\"`, an integer in the currency's minor units (`30000` for 300.00 USD), or null. Prices above it are lowered to it.",
            "examples": [
              "300.00"
            ]
          }
        },
        "description": "Property-level settings accepted on create and update."
      },
      "Properties.PropertyType": {
        "type": "string",
        "enum": [
          "apart_hotel",
          "apartment",
          "boat",
          "camping",
          "capsule_hotel",
          "chalet",
          "country_house",
          "farm_stay",
          "guest_house",
          "holiday_home",
          "holiday_park",
          "homestay",
          "hostel",
          "hotel",
          "inn",
          "lodge",
          "motel",
          "resort",
          "riad",
          "ryokan",
          "tent",
          "villa"
        ],
        "description": "Type of property. Affects billing — set `hotel` for hotels or `apartment` for vacation rentals."
      },
      "Properties.PropertyUpdate": {
        "type": "object",
        "properties": {
          "title": {
            "type": "string",
            "maxLength": 255,
            "description": "Property title, as shown in the system.",
            "examples": [
              "Demo Hotel"
            ]
          },
          "currency": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Common.Scalars.currency"
              }
            ],
            "description": "Default currency for nested entities, and the property's default currency for connected third-party services.",
            "examples": [
              "GBP"
            ]
          },
          "email": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Common.Scalars.email"
              },
              {
                "type": "null"
              }
            ],
            "description": "Contact email. Passed to connected third-party services as the property's contact email. Optional at setup, required before connecting a 3rd-party service."
          },
          "phone": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "maxLength": 32,
            "description": "Contact phone. Digits, spaces, brackets and special characters; max 32 chars. Passed to connected third-party services as the property's contact phone. Optional at setup, required before connecting a 3rd-party service.",
            "examples": [
              "+44 99 9999 9999"
            ]
          },
          "zip_code": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "maxLength": 32,
            "description": "ZIP/postal code (max 32 chars). Part of the contact address passed to connected third-party services. Optional at setup, required before connecting a 3rd-party service.",
            "examples": [
              "XXX XXX"
            ]
          },
          "country": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Common.Scalars.country"
              },
              {
                "type": "null"
              }
            ],
            "description": "Country of the property. ISO 3166-1 alpha-2 country code. Part of the contact address passed to connected third-party services. Optional at setup, required before connecting a 3rd-party service.",
            "examples": [
              "GB"
            ]
          },
          "state": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "maxLength": 255,
            "description": "State/region (max 255 chars). Part of the contact address passed to connected third-party services. Optional at setup, required before connecting a 3rd-party service.",
            "examples": [
              "Wales"
            ]
          },
          "city": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "maxLength": 255,
            "description": "City (max 255 chars). Part of the contact address passed to connected third-party services. Optional at setup, required before connecting a 3rd-party service.",
            "examples": [
              "Cardiff"
            ]
          },
          "address": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "maxLength": 255,
            "description": "Street address (max 255 chars). Part of the contact address passed to connected third-party services. Optional at setup, required before connecting a 3rd-party service.",
            "examples": [
              "123 High Street"
            ]
          },
          "longitude": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "maxLength": 12,
            "description": "Longitude as a decimal string in the range −180..180 (max 7 decimals). Derived from the address when the property is saved without one. Part of the property coordinates passed to connected third-party services. Optional at setup, required before connecting a 3rd-party service.",
            "examples": [
              "-0.2416781"
            ]
          },
          "latitude": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "maxLength": 11,
            "description": "Latitude as a decimal string in the range −90..90 (max 7 decimals). Derived from the address when the property is saved without one. Part of the property coordinates passed to connected third-party services. Optional at setup, required before connecting a 3rd-party service.",
            "examples": [
              "51.5285582"
            ]
          },
          "timezone": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Common.Scalars.timezone"
              },
              {
                "type": "null"
              }
            ],
            "description": "Time zone of the property, or null when it is not set. Sending `null` clears it.\n\nTime zone name from the IANA Time Zone Database (the \"tz database\"), published at\nhttps://www.iana.org/time-zones — background at\nhttps://en.wikipedia.org/wiki/Tz_database. See the `/timezones` endpoint for the\nvalues this API accepts.",
            "examples": [
              "Europe/London"
            ]
          },
          "property_type": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Properties.PropertyType"
              },
              {
                "type": "null"
              }
            ],
            "description": "Type of the property, or null when it is not set. Sending `null` clears it.\n\n**Set this value — it affects billing. Use `hotel` for a hotel and `apartment`\nfor a vacation rental.**"
          },
          "logo_url": {
            "anyOf": [
              {
                "type": "string",
                "format": "uri"
              },
              {
                "type": "null"
              }
            ],
            "description": "URL to the property logo; copied into Channex media storage.",
            "examples": [
              "https://example.com/logo.png"
            ]
          },
          "website": {
            "anyOf": [
              {
                "type": "string",
                "format": "uri"
              },
              {
                "type": "null"
              }
            ],
            "description": "URL to the property website.",
            "examples": [
              "https://example.com"
            ]
          },
          "hotel_policy_id": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Common.Scalars.id"
              },
              {
                "type": "null"
              }
            ],
            "description": "UUID of the property's hotel policy, or null. Sending `null` clears it."
          },
          "default_cancellation_policy_id": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Common.Scalars.id"
              },
              {
                "type": "null"
              }
            ],
            "description": "UUID of the property's default cancellation policy, or null."
          },
          "default_tax_set_id": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Common.Scalars.id"
              },
              {
                "type": "null"
              }
            ],
            "description": "UUID of the property's default tax set, or null."
          },
          "location_precision": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Common.Scalars.nonNegativeInt"
              },
              {
                "type": "null"
              }
            ],
            "description": "Location precision, or null."
          },
          "min_stay_type": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Properties.MinStayType"
              }
            ],
            "description": "Simplified Min Stay restriction handling for the property. Mirrors `settings.min_stay_type`: writing either attribute updates both.",
            "deprecated": true
          },
          "group_id": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Common.Scalars.id"
              },
              {
                "type": "null"
              }
            ],
            "description": "UUID of the group to place the property in. Defaults to the user's Default Group when omitted, and is applied on create only. In responses the group appears under relationships."
          },
          "facilities": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Common.Scalars.id"
            },
            "description": "Property Facility IDs to associate. See the Property Facilities endpoint for the available identifiers. In responses, facilities appear under relationships."
          },
          "settings": {
            "$ref": "#/components/schemas/Properties.PropertySettingsWrite"
          },
          "content": {
            "$ref": "#/components/schemas/Properties.PropertyContentWrite"
          }
        },
        "description": "Property attributes accepted when updating a property. Every attribute is optional; attributes absent from the request are left unchanged."
      },
      "Properties.PropertyUpdateRequest": {
        "type": "object",
        "required": [
          "property"
        ],
        "properties": {
          "property": {
            "$ref": "#/components/schemas/Properties.PropertyUpdate"
          }
        },
        "description": "Request body accepted when updating a property."
      }
    },
    "securitySchemes": {
      "UserApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "user-api-key",
        "description": "API key for programmatic access, sent in the `user-api-key` header."
      }
    }
  },
  "servers": [
    {
      "url": "https://app.channex.io/api/v1",
      "description": "Production server",
      "variables": {}
    },
    {
      "url": "https://staging.channex.io/api/v1",
      "description": "Staging server",
      "variables": {}
    }
  ]
}
