{
  "openapi": "3.1.0",
  "info": {
    "title": "HotelOne Agent API",
    "version": "1.0.0",
    "summary": "Search and book independent hotels from AI assistants and agents.",
    "description": "Find HotelOne hotels, check live availability and prices, and book. The same operations are available as an MCP server at https://hotelone.site/api/mcp.\n\nBooking flow: searchHotels → checkAvailability → createBookingLink (the guest opens the pre-filled checkout and confirms; the default) — or requestBooking when the guest can’t open a link (the hotel confirms), or createBooking with an API key (confirmed at once, paid at the hotel).\nAlways confirm the hotel, room, dates, guests and total with the guest before requestBooking or createBooking.\nSeveral room types in one booking (for example 2 King rooms and a Twin): pass items, each roomTypeId with its rooms, instead of roomTypeId and rooms. guests is the whole party.\n\nDates are YYYY-MM-DD; prices are in each hotel’s currency (`currency`, ISO 4217) and include its taxes and fees. Only createBooking needs an API key (`Authorization: Bearer ho_live_…`), which hotel owners create in the console under AI assistants.\nRate limits: 120 requests a minute per IP (600 with an API key); booking requests 10 an hour per IP; bookings 60 an hour per key; booking lookups 20 an hour per IP.",
    "contact": {
      "name": "HotelOne",
      "url": "https://hotelone.site/assistants",
      "email": "hello@hotelone.site"
    },
    "termsOfService": "https://hotelone.site/about"
  },
  "servers": [
    {
      "url": "https://hotelone.site",
      "description": "HotelOne"
    }
  ],
  "tags": [
    {
      "name": "Hotels",
      "description": "Find hotels, their details, availability and answers."
    },
    {
      "name": "Booking",
      "description": "Book, request a booking or find one."
    }
  ],
  "paths": {
    "/api/agents/v1/hotels": {
      "get": {
        "operationId": "searchHotels",
        "tags": [
          "Hotels"
        ],
        "summary": "Search hotels",
        "description": "Find hotels by place or name. With checkIn and checkOut, results include live availability and the cheapest price for the stay. Start here.",
        "security": [],
        "parameters": [
          {
            "name": "query",
            "in": "query",
            "required": false,
            "description": "A hotel name or what the guest wants, e.g. \"saltwater inn\", \"ocean view\", \"sauna\" or \"motel\". Ranks hotels by matching words in name, type, description and amenities; small typos are fine",
            "schema": {
              "type": "string",
              "maxLength": 100
            }
          },
          {
            "name": "location",
            "in": "query",
            "required": false,
            "description": "Where the guest wants to stay: city, state, zip or area, e.g. \"Santa Cruz, CA\"",
            "schema": {
              "type": "string",
              "maxLength": 100
            }
          },
          {
            "name": "checkIn",
            "in": "query",
            "required": false,
            "description": "Arrival date (YYYY-MM-DD). With checkOut, results carry live availability and prices",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
            }
          },
          {
            "name": "checkOut",
            "in": "query",
            "required": false,
            "description": "Departure date (YYYY-MM-DD), after checkIn; at most 30 nights",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
            }
          },
          {
            "name": "guests",
            "in": "query",
            "required": false,
            "description": "Total guests in the party (1–16)",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 16,
              "default": 2
            }
          },
          {
            "name": "rooms",
            "in": "query",
            "required": false,
            "description": "Rooms needed (1–9)",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 9,
              "default": 1
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum hotels to return (1–20)",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 20,
              "default": 8
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Matching hotels, available and cheapest first.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SearchResult"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input or a rule failed (dates in the past, too many guests…). The message says how to fix it.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Wait for Retry-After seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/agents/v1/hotels/{propertyId}": {
      "get": {
        "operationId": "getHotel",
        "tags": [
          "Hotels"
        ],
        "summary": "Hotel details",
        "description": "Description, address, phone, amenities, policies, room types with starting prices, photos and the hotel’s own answers to common questions.",
        "security": [],
        "parameters": [
          {
            "name": "propertyId",
            "in": "path",
            "required": true,
            "description": "Hotel id from searchHotels.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The hotel.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HotelDetails"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input or a rule failed (dates in the past, too many guests…). The message says how to fix it.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Unknown or unlisted hotel.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Wait for Retry-After seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/agents/v1/hotels/{propertyId}/availability": {
      "get": {
        "operationId": "checkAvailability",
        "tags": [
          "Hotels"
        ],
        "summary": "Check availability",
        "description": "Live availability and exact prices (in the hotel’s currency) for every room type at one hotel. Pick an option that is available and fits the party, then create a booking link with its room_type_id.",
        "security": [],
        "parameters": [
          {
            "name": "propertyId",
            "in": "path",
            "required": true,
            "description": "Hotel id from searchHotels.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64
            }
          },
          {
            "name": "checkIn",
            "in": "query",
            "required": true,
            "description": "Arrival date (YYYY-MM-DD)",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
            }
          },
          {
            "name": "checkOut",
            "in": "query",
            "required": true,
            "description": "Departure date (YYYY-MM-DD), after checkIn; stays are at most 30 nights",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
            }
          },
          {
            "name": "guests",
            "in": "query",
            "required": false,
            "description": "Total guests in the party (1–16)",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 16,
              "default": 2
            }
          },
          {
            "name": "rooms",
            "in": "query",
            "required": false,
            "description": "Rooms needed (1–9)",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 9,
              "default": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Room types with availability and prices.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Availability"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input or a rule failed (dates in the past, too many guests…). The message says how to fix it.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Unknown or unlisted hotel.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Wait for Retry-After seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/agents/v1/hotels/{propertyId}/answers": {
      "get": {
        "operationId": "askHotel",
        "tags": [
          "Hotels"
        ],
        "summary": "Ask the hotel",
        "description": "Answers a guest’s question (parking, pets, breakfast, Wi-Fi, policies, getting there…) from the hotel’s own saved answers. Pass question or topic. If nothing matches, offer the hotel’s phone — don’t guess.",
        "security": [],
        "parameters": [
          {
            "name": "propertyId",
            "in": "path",
            "required": true,
            "description": "Hotel id from searchHotels.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64
            }
          },
          {
            "name": "question",
            "in": "query",
            "required": false,
            "description": "The guest’s question in their own words, e.g. \"Is parking free?\" or \"can I bring my dog\"",
            "schema": {
              "type": "string",
              "maxLength": 300
            }
          },
          {
            "name": "topic",
            "in": "query",
            "required": false,
            "description": "A topic key from the hotel’s answers (e.g. \"policies\", \"amenities\", \"contact\") to get that answer directly",
            "schema": {
              "type": "string",
              "maxLength": 80
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The best matching answers, or the topics the hotel has answers for.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HotelAnswers"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input or a rule failed (dates in the past, too many guests…). The message says how to fix it.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Unknown or unlisted hotel.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Wait for Retry-After seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/agents/v1/booking-links": {
      "post": {
        "operationId": "createBookingLink",
        "tags": [
          "Booking"
        ],
        "summary": "Get a pre-filled booking link",
        "description": "The fastest way to book: a checkout link with the hotel, room, dates, party (and optionally the guest’s details) filled in. Give it to the guest with the summary; they confirm in one tap. Holds nothing by itself.",
        "security": [],
        "x-openai-isConsequential": false,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "propertyId": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 64,
                    "description": "Hotel id from searchHotels"
                  },
                  "roomTypeId": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 64,
                    "description": "room_type_id from checkAvailability (or use items for several room types)"
                  },
                  "checkIn": {
                    "type": "string",
                    "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                    "description": "Arrival date (YYYY-MM-DD)"
                  },
                  "checkOut": {
                    "type": "string",
                    "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                    "description": "Departure date (YYYY-MM-DD), after checkIn; stays are at most 30 nights"
                  },
                  "guests": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 16,
                    "default": 2,
                    "description": "Total guests in the party (1–16)"
                  },
                  "rooms": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 9,
                    "default": 1,
                    "description": "Rooms needed (1–9)"
                  },
                  "items": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "roomTypeId": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 64,
                          "description": "room_type_id from checkAvailability"
                        },
                        "rooms": {
                          "type": "integer",
                          "minimum": 1,
                          "maximum": 9,
                          "description": "Rooms of this type (1–9)"
                        }
                      },
                      "required": [
                        "roomTypeId",
                        "rooms"
                      ],
                      "additionalProperties": false
                    },
                    "minItems": 1,
                    "maxItems": 4,
                    "description": "To book several room types together (for example 2 King rooms and a Twin), list each with its room count instead of roomTypeId and rooms. The party (guests) is shared across them. At most 4 room types and 9 rooms in all."
                  },
                  "guest": {
                    "type": "object",
                    "properties": {
                      "name": {
                        "type": [
                          "string",
                          "null"
                        ],
                        "maxLength": 120,
                        "description": "Guest’s full name, to pre-fill checkout"
                      },
                      "email": {
                        "type": [
                          "string",
                          "null"
                        ],
                        "format": "email",
                        "maxLength": 200,
                        "description": "Guest’s email, to pre-fill checkout"
                      },
                      "phone": {
                        "type": [
                          "string",
                          "null"
                        ],
                        "maxLength": 40,
                        "description": "Guest’s phone, to pre-fill checkout"
                      }
                    },
                    "additionalProperties": false,
                    "description": "Optional details the checkout page pre-fills"
                  }
                },
                "required": [
                  "propertyId",
                  "checkIn",
                  "checkOut"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The link and a summary with the total.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BookingLink"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input or a rule failed (dates in the past, too many guests…). The message says how to fix it.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Unknown or unlisted hotel.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Wait for Retry-After seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/agents/v1/booking-requests": {
      "post": {
        "operationId": "requestBooking",
        "tags": [
          "Booking"
        ],
        "summary": "Send a booking request to the hotel",
        "description": "For guests who can’t open a link: the hotel team confirms with the guest and sends a link to finish booking. Nothing is booked until then. Needs a full name and an email or phone. Confirm the details with the guest first.",
        "security": [],
        "x-openai-isConsequential": true,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "propertyId": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 64,
                    "description": "Hotel id from searchHotels"
                  },
                  "roomTypeId": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 64,
                    "description": "room_type_id from checkAvailability (or use items for several room types)"
                  },
                  "checkIn": {
                    "type": "string",
                    "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                    "description": "Arrival date (YYYY-MM-DD)"
                  },
                  "checkOut": {
                    "type": "string",
                    "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                    "description": "Departure date (YYYY-MM-DD), after checkIn; stays are at most 30 nights"
                  },
                  "guests": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 16,
                    "default": 2,
                    "description": "Total guests in the party (1–16)"
                  },
                  "rooms": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 9,
                    "default": 1,
                    "description": "Rooms needed (1–9)"
                  },
                  "items": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "roomTypeId": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 64,
                          "description": "room_type_id from checkAvailability"
                        },
                        "rooms": {
                          "type": "integer",
                          "minimum": 1,
                          "maximum": 9,
                          "description": "Rooms of this type (1–9)"
                        }
                      },
                      "required": [
                        "roomTypeId",
                        "rooms"
                      ],
                      "additionalProperties": false
                    },
                    "minItems": 1,
                    "maxItems": 4,
                    "description": "To book several room types together (for example 2 King rooms and a Twin), list each with its room count instead of roomTypeId and rooms. The party (guests) is shared across them. At most 4 room types and 9 rooms in all."
                  },
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120,
                    "description": "Guest’s full name"
                  },
                  "email": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "email",
                    "maxLength": 200,
                    "description": "Email for the booking link (email or phone is required)"
                  },
                  "phone": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 40,
                    "description": "Callback number (email or phone is required)"
                  },
                  "notes": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 500,
                    "description": "Special requests, if any"
                  }
                },
                "required": [
                  "propertyId",
                  "checkIn",
                  "checkOut",
                  "name"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The request was sent to the hotel.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BookingRequest"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input or a rule failed (dates in the past, too many guests…). The message says how to fix it.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Unknown or unlisted hotel.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Wait for Retry-After seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/agents/v1/bookings": {
      "post": {
        "operationId": "createBooking",
        "tags": [
          "Booking"
        ],
        "summary": "Book now (pay at the hotel)",
        "description": "Makes a confirmed booking paid at the hotel and emails the guest. Needs an API key with booking access for that hotel. Confirm hotel, room, dates, guests, total and the guest’s name and email first.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-openai-isConsequential": true,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "propertyId": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 64,
                    "description": "Hotel id from searchHotels"
                  },
                  "roomTypeId": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 64,
                    "description": "room_type_id from checkAvailability (or use items for several room types)"
                  },
                  "checkIn": {
                    "type": "string",
                    "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                    "description": "Arrival date (YYYY-MM-DD)"
                  },
                  "checkOut": {
                    "type": "string",
                    "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                    "description": "Departure date (YYYY-MM-DD), after checkIn; stays are at most 30 nights"
                  },
                  "guests": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 16,
                    "default": 2,
                    "description": "Total guests in the party (1–16)"
                  },
                  "rooms": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 9,
                    "default": 1,
                    "description": "Rooms needed (1–9)"
                  },
                  "items": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "roomTypeId": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 64,
                          "description": "room_type_id from checkAvailability"
                        },
                        "rooms": {
                          "type": "integer",
                          "minimum": 1,
                          "maximum": 9,
                          "description": "Rooms of this type (1–9)"
                        }
                      },
                      "required": [
                        "roomTypeId",
                        "rooms"
                      ],
                      "additionalProperties": false
                    },
                    "minItems": 1,
                    "maxItems": 4,
                    "description": "To book several room types together (for example 2 King rooms and a Twin), list each with its room count instead of roomTypeId and rooms. The party (guests) is shared across them. At most 4 room types and 9 rooms in all."
                  },
                  "guest": {
                    "type": "object",
                    "properties": {
                      "name": {
                        "type": "string",
                        "minLength": 3,
                        "maxLength": 120,
                        "description": "Guest’s first and last name"
                      },
                      "email": {
                        "type": "string",
                        "format": "email",
                        "maxLength": 200,
                        "description": "Guest’s own email: the confirmation goes there"
                      },
                      "phone": {
                        "type": [
                          "string",
                          "null"
                        ],
                        "maxLength": 40,
                        "description": "Guest’s phone, if given"
                      }
                    },
                    "required": [
                      "name",
                      "email"
                    ],
                    "additionalProperties": false,
                    "description": "The guest the booking is for"
                  },
                  "notes": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 1000,
                    "description": "Special requests, passed to the hotel"
                  }
                },
                "required": [
                  "propertyId",
                  "checkIn",
                  "checkOut",
                  "guest"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The confirmed booking.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Booking"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input or a rule failed (dates in the past, too many guests…). The message says how to fix it.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No API key, or the key is unknown or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key can’t book at this hotel, or the email can’t be used.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Unknown or unlisted hotel.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "The room was just taken.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Wait for Retry-After seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/agents/v1/bookings/{code}": {
      "get": {
        "operationId": "findBooking",
        "tags": [
          "Booking"
        ],
        "summary": "Find a booking",
        "description": "Looks up a booking by confirmation code and the guest’s last name: status, hotel, room, dates, the free-change deadline and how to change or cancel.",
        "security": [],
        "parameters": [
          {
            "name": "code",
            "in": "path",
            "required": true,
            "description": "Confirmation code.",
            "schema": {
              "type": "string",
              "minLength": 4,
              "maxLength": 20
            }
          },
          {
            "name": "lastName",
            "in": "query",
            "required": true,
            "description": "Guest’s last name as booked",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 60
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The booking.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FoundBooking"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input or a rule failed (dates in the past, too many guests…). The message says how to fix it.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No booking matches that code and last name.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Wait for Retry-After seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "description": "What went wrong, written for people and models."
          },
          "message": {
            "type": "string",
            "description": "Same as error."
          },
          "code": {
            "type": "string",
            "description": "BAD_REQUEST, VALIDATION, NOT_FOUND, CONFLICT, FORBIDDEN, UNAUTHORIZED, INVALID_API_KEY, API_KEY_REQUIRED, RATE_LIMITED, INTERNAL…"
          },
          "details": {
            "type": "object",
            "description": "Extra detail, e.g. validation issues or retryAfterSeconds."
          }
        },
        "required": [
          "error",
          "code"
        ]
      },
      "HotelSummary": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Hotel id (propertyId) for the other operations."
          },
          "name": {
            "type": "string"
          },
          "city": {
            "type": "string"
          },
          "state": {
            "type": "string"
          },
          "tagline": {
            "type": [
              "string",
              "null"
            ]
          },
          "photo": {
            "type": [
              "string",
              "null"
            ],
            "description": "Main photo URL.",
            "format": "uri"
          },
          "fromPricePerNight": {
            "type": [
              "number",
              "null"
            ],
            "description": "Lowest base nightly price among room types that fit the party."
          },
          "currency": {
            "type": "string",
            "description": "The hotel’s ISO 4217 currency, e.g. USD or EUR",
            "pattern": "^[A-Z]{3}$"
          },
          "maxGuestsPerRoom": {
            "type": "integer"
          },
          "fitsParty": {
            "type": "boolean",
            "description": "A room type sleeps the party in the requested number of rooms."
          },
          "available": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "With dates: a fitting room type is free every night. Null without dates."
          },
          "cheapestNightly": {
            "type": "number",
            "description": "With dates, when available: cheapest fitting average nightly price per room."
          },
          "stayTotal": {
            "type": "number",
            "description": "With dates, when available: that option’s total for the whole stay and all rooms."
          },
          "cheapestRoomTypeId": {
            "type": "string",
            "description": "With dates, when available: that option’s room type id."
          },
          "url": {
            "type": "string",
            "description": "The hotel’s booking page (stay pre-filled when dates were given).",
            "format": "uri"
          }
        },
        "required": [
          "id",
          "name",
          "city",
          "state",
          "currency",
          "fitsParty",
          "available",
          "url"
        ]
      },
      "SearchResult": {
        "type": "object",
        "properties": {
          "hotels": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/HotelSummary"
            }
          },
          "matched": {
            "type": "integer",
            "description": "Hotels that matched before the limit."
          },
          "stay": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "checkIn": {
                "type": "string",
                "description": "Arrival",
                "format": "date"
              },
              "checkOut": {
                "type": "string",
                "description": "Departure",
                "format": "date"
              },
              "nights": {
                "type": "integer"
              },
              "guests": {
                "type": "integer"
              },
              "rooms": {
                "type": "integer"
              }
            },
            "required": [
              "checkIn",
              "checkOut",
              "nights",
              "guests",
              "rooms"
            ]
          },
          "note": {
            "type": "string",
            "description": "Only when results are not exact matches (closest places, or the place without the query words): what to tell the person."
          },
          "places": {
            "type": "array",
            "description": "Only when no hotel is in the place asked for: every town with HotelOne hotels, e.g. \"Santa Cruz, CA\".",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "hotels",
          "matched",
          "stay",
          "note",
          "places"
        ]
      },
      "HotelDetails": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "type": {
            "type": [
              "string",
              "null"
            ],
            "description": "Hotel, Motel, Inn, B&B, Boutique…"
          },
          "tagline": {
            "type": [
              "string",
              "null"
            ]
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "address": {
            "type": "string"
          },
          "phone": {
            "type": "string"
          },
          "email": {
            "type": [
              "string",
              "null"
            ]
          },
          "amenities": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "check_in": {
            "type": "string",
            "description": "e.g. \"from 3:00 PM\""
          },
          "check_out": {
            "type": "string",
            "description": "e.g. \"by 11:00 AM\""
          },
          "cancellation": {
            "type": "string"
          },
          "room_types": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                },
                "sleeps": {
                  "type": "integer"
                },
                "from_price_per_night": {
                  "type": "number"
                },
                "amenities": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                },
                "description": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              },
              "required": [
                "id",
                "name",
                "sleeps",
                "from_price_per_night",
                "amenities",
                "description"
              ]
            }
          },
          "currency": {
            "type": "string",
            "description": "The hotel’s ISO 4217 currency, e.g. USD or EUR",
            "pattern": "^[A-Z]{3}$"
          },
          "photos": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uri"
            }
          },
          "skills": {
            "type": "array",
            "description": "The hotel’s own answers (FAQs, amenities, policies, rooms, contact).",
            "items": {
              "type": "object",
              "properties": {
                "key": {
                  "type": "string"
                },
                "title": {
                  "type": "string"
                },
                "answer": {
                  "type": "string"
                }
              },
              "required": [
                "key",
                "title",
                "answer"
              ]
            }
          },
          "url": {
            "type": "string",
            "format": "uri"
          }
        },
        "required": [
          "id",
          "name",
          "address",
          "phone",
          "amenities",
          "check_in",
          "check_out",
          "cancellation",
          "room_types",
          "currency",
          "photos",
          "skills",
          "url"
        ]
      },
      "Availability": {
        "type": "object",
        "properties": {
          "stay": {
            "type": "string",
            "description": "e.g. \"Fri, Oct 23 to Sun, Oct 25, 2 nights, 2 guests\""
          },
          "currency": {
            "type": "string",
            "description": "The hotel’s ISO 4217 currency, e.g. USD or EUR",
            "pattern": "^[A-Z]{3}$"
          },
          "options": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "room_type_id": {
                  "type": "string",
                  "description": "Use with booking links, requests and bookings."
                },
                "name": {
                  "type": "string"
                },
                "sleeps": {
                  "type": "integer"
                },
                "fits_party": {
                  "type": "boolean"
                },
                "available": {
                  "type": "boolean"
                },
                "rooms_left": {
                  "type": "integer"
                },
                "average_per_night": {
                  "type": [
                    "number",
                    "null"
                  ],
                  "description": "Room price per room per night, in `currency`"
                },
                "total": {
                  "type": [
                    "number",
                    "null"
                  ],
                  "description": "Whole stay and all rooms, taxes and fees included, in `currency`"
                }
              },
              "required": [
                "room_type_id",
                "name",
                "sleeps",
                "fits_party",
                "available",
                "rooms_left",
                "average_per_night",
                "total"
              ]
            }
          }
        },
        "required": [
          "stay",
          "currency",
          "options"
        ]
      },
      "HotelAnswers": {
        "type": "object",
        "properties": {
          "hotel": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "phone": {
                "type": "string"
              },
              "email": {
                "type": [
                  "string",
                  "null"
                ]
              }
            },
            "required": [
              "id",
              "name",
              "phone",
              "email"
            ]
          },
          "answers": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "key": {
                  "type": "string",
                  "description": "Topic key"
                },
                "title": {
                  "type": "string"
                },
                "answer": {
                  "type": "string"
                }
              },
              "required": [
                "key",
                "title",
                "answer"
              ]
            }
          },
          "topics": {
            "type": "array",
            "description": "Only when nothing matched: every topic the hotel has answers for.",
            "items": {
              "type": "object",
              "properties": {
                "key": {
                  "type": "string"
                },
                "title": {
                  "type": "string"
                }
              },
              "required": [
                "key",
                "title"
              ]
            }
          },
          "note": {
            "type": "string",
            "description": "Only when nothing matched: what to tell the guest."
          }
        },
        "required": [
          "hotel",
          "answers"
        ]
      },
      "BookingLink": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "description": "The pre-filled checkout. The guest opens it, checks the details and confirms.",
            "format": "uri"
          },
          "summary": {
            "type": "object",
            "properties": {
              "hotel": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string"
                  },
                  "name": {
                    "type": "string"
                  }
                },
                "required": [
                  "id",
                  "name"
                ]
              },
              "roomType": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string"
                  },
                  "name": {
                    "type": "string"
                  },
                  "sleeps": {
                    "type": "integer"
                  }
                },
                "required": [
                  "id",
                  "name",
                  "sleeps"
                ]
              },
              "checkIn": {
                "type": "string",
                "description": "Arrival",
                "format": "date"
              },
              "checkOut": {
                "type": "string",
                "description": "Departure",
                "format": "date"
              },
              "nights": {
                "type": "integer"
              },
              "guests": {
                "type": "integer"
              },
              "rooms": {
                "type": "integer"
              },
              "averageNightly": {
                "type": "number",
                "description": "Room price per room per night, in `currency`"
              },
              "total": {
                "type": "number",
                "description": "Whole stay, all rooms, taxes and fees included, in `currency`"
              },
              "currency": {
                "type": "string",
                "description": "The hotel’s ISO 4217 currency, e.g. USD or EUR",
                "pattern": "^[A-Z]{3}$"
              },
              "roomsLeft": {
                "type": "integer"
              },
              "items": {
                "type": "array",
                "description": "Every room type in the booking (one entry unless it mixes room types).",
                "items": {
                  "type": "object",
                  "properties": {
                    "roomType": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "name": {
                          "type": "string"
                        },
                        "sleeps": {
                          "type": "integer"
                        }
                      },
                      "required": [
                        "id",
                        "name",
                        "sleeps"
                      ]
                    },
                    "rooms": {
                      "type": "integer"
                    },
                    "guests": {
                      "type": "integer"
                    },
                    "total": {
                      "type": "number",
                      "description": "Whole stay, these rooms, taxes and fees included, in `currency`"
                    },
                    "roomsLeft": {
                      "type": "integer"
                    }
                  },
                  "required": [
                    "roomType",
                    "rooms",
                    "guests",
                    "total",
                    "roomsLeft"
                  ]
                }
              }
            },
            "required": [
              "hotel",
              "roomType",
              "checkIn",
              "checkOut",
              "nights",
              "guests",
              "rooms",
              "averageNightly",
              "total",
              "currency",
              "roomsLeft",
              "items"
            ]
          },
          "expiresNote": {
            "type": "string"
          }
        },
        "required": [
          "url",
          "summary",
          "expiresNote"
        ]
      },
      "BookingRequest": {
        "type": "object",
        "properties": {
          "saved": {
            "type": "boolean",
            "const": true
          },
          "reference": {
            "type": "string",
            "description": "Request reference for the guest."
          },
          "quoted_total": {
            "type": [
              "number",
              "null"
            ],
            "description": "Taxes and fees included, in `currency`"
          },
          "currency": {
            "type": "string",
            "description": "The hotel’s ISO 4217 currency, e.g. USD or EUR",
            "pattern": "^[A-Z]{3}$"
          },
          "say": {
            "type": "string",
            "description": "What to tell the guest."
          }
        },
        "required": [
          "saved",
          "reference",
          "quoted_total",
          "currency",
          "say"
        ]
      },
      "Booking": {
        "type": "object",
        "properties": {
          "bookingId": {
            "type": "string"
          },
          "code": {
            "type": "string",
            "description": "Confirmation code for the guest."
          },
          "status": {
            "type": "string",
            "const": "CONFIRMED"
          },
          "total": {
            "type": "number",
            "description": "Taxes and fees included, priced by the server, in `currency`"
          },
          "currency": {
            "type": "string",
            "description": "The hotel’s ISO 4217 currency, e.g. USD or EUR",
            "pattern": "^[A-Z]{3}$"
          },
          "paymentStatus": {
            "type": "string",
            "const": "PAY_AT_PROPERTY"
          },
          "hotel": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "name"
            ]
          },
          "roomType": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "name"
            ]
          },
          "checkIn": {
            "type": "string",
            "description": "Arrival",
            "format": "date"
          },
          "checkOut": {
            "type": "string",
            "description": "Departure",
            "format": "date"
          },
          "nights": {
            "type": "integer"
          },
          "guests": {
            "type": "integer"
          },
          "rooms": {
            "type": "integer"
          },
          "items": {
            "type": "array",
            "description": "Every room type booked, each its own reservation at the hotel under the same confirmation code (one entry unless it mixes room types).",
            "items": {
              "type": "object",
              "properties": {
                "bookingId": {
                  "type": "string"
                },
                "roomType": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "sleeps": {
                      "type": "integer"
                    }
                  },
                  "required": [
                    "id",
                    "name",
                    "sleeps"
                  ]
                },
                "rooms": {
                  "type": "integer"
                },
                "guests": {
                  "type": "integer"
                },
                "total": {
                  "type": "number",
                  "description": "Taxes and fees included, in `currency`"
                },
                "roomsLeft": {
                  "type": "integer"
                }
              },
              "required": [
                "bookingId",
                "roomType",
                "rooms",
                "guests",
                "total",
                "roomsLeft"
              ]
            }
          },
          "manage": {
            "type": "string",
            "description": "How the guest changes or cancels (through the hotel, with the confirmation code)."
          },
          "confirmationEmailSent": {
            "type": "boolean"
          }
        },
        "required": [
          "bookingId",
          "code",
          "status",
          "total",
          "currency",
          "paymentStatus",
          "hotel",
          "roomType",
          "checkIn",
          "checkOut",
          "nights",
          "guests",
          "rooms",
          "items",
          "manage",
          "confirmationEmailSent"
        ]
      },
      "FoundBooking": {
        "type": "object",
        "properties": {
          "found": {
            "type": "boolean",
            "const": true
          },
          "code": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "description": "PENDING, CONFIRMED, CHECKED_IN, CHECKED_OUT, CANCELLED, NO_SHOW…"
          },
          "hotel": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "phone": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "name",
              "phone"
            ]
          },
          "room": {
            "type": "string"
          },
          "checkIn": {
            "type": "string",
            "description": "Arrival",
            "format": "date"
          },
          "checkOut": {
            "type": "string",
            "description": "Departure",
            "format": "date"
          },
          "nights": {
            "type": "integer"
          },
          "guests": {
            "type": "integer"
          },
          "rooms": {
            "type": "integer"
          },
          "items": {
            "type": [
              "array",
              "null"
            ],
            "description": "Several room types booked under this code: each with its rooms, guests and status. Null for one room type.",
            "items": {
              "type": "object",
              "properties": {
                "room": {
                  "type": "string"
                },
                "rooms": {
                  "type": "integer"
                },
                "guests": {
                  "type": "integer"
                },
                "status": {
                  "type": "string"
                }
              },
              "required": [
                "room",
                "rooms",
                "guests",
                "status"
              ]
            }
          },
          "freeChangesUntil": {
            "type": [
              "string",
              "null"
            ],
            "description": "e.g. \"3:00 PM on Thu, Oct 22\"; null once passed."
          },
          "manage": {
            "type": "string"
          },
          "bookingUrl": {
            "type": [
              "string",
              "null"
            ],
            "description": "The guest’s booking page (they sign in to change or cancel). Null for direct bookings made with an API key: follow manage instead.",
            "format": "uri"
          }
        },
        "required": [
          "found",
          "code",
          "status",
          "hotel",
          "room",
          "checkIn",
          "checkOut",
          "nights",
          "guests",
          "rooms",
          "items",
          "freeChangesUntil",
          "manage",
          "bookingUrl"
        ]
      }
    },
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "ho_live_…",
        "description": "A HotelOne API key. Hotel owners create keys in the HotelOne console under AI assistants. Only needed for createBooking; with any valid key the rate limits are higher."
      }
    }
  }
}