openapi: 3.0.0
info:
  title: Kayak Hotels API
  description: |
    Search hotels and other stays on Kayak for a place and dates, with guests, rooms, star, rating, property type, amenity and free cancellation filters, sorting and pages.
    Each property returns its stars, guest rating, location, its price per night and for the whole stay with and without taxes, and the booking offers Kayak lists for it.

    **Cross-linking**: For Google Hotels or Skyscanner prices in the same place, use the Google Hotels API or the Skyscanner Hotels API.
  version: 1.0.0
servers:
  - url: https://www.searchapi.io/api/v1
paths:
  /search:
    get:
      summary: Kayak Hotels Search
      security:
        - ApiKeyAuth: []
        - ApiKeyQuery: []
      parameters:
        - name: engine
          in: query
          required: true
          description: Engine used to retrieve the results.
          schema:
            type: string
            enum: ["kayak_hotels"]
        - name: q
          in: query
          required: true
          description: City, region, neighborhood, landmark, airport or hotel name with at least one letter or digit, searched as the first place Kayak suggests for it. Countries and street addresses are not accepted.
          schema:
            type: string
            maxLength: 100
        - name: check_in_date
          in: query
          required: true
          description: 'Check-in date, from today. Format: YYYY-MM-DD'
          schema:
            type: string
            format: date
        - name: check_out_date
          in: query
          required: true
          description: 'Check-out date, after check_in_date and up to 365 days ahead. Format: YYYY-MM-DD'
          schema:
            type: string
            format: date
        - name: adults
          in: query
          required: false
          description: Number of adults, at least one per room and at most 4 guests per room with the children.
          schema:
            type: integer
            minimum: 1
            maximum: 32
            default: 2
        - name: children_ages
          in: query
          required: false
          description: Comma-separated ages of the children, each from 0 to 17.
          schema:
            type: string
            pattern: '^\s*\d{1,2}\s*(?:,\s*\d{1,2}\s*)*$'
        - name: rooms
          in: query
          required: false
          description: Number of rooms. Prices cover every room and night.
          schema:
            type: integer
            minimum: 1
            maximum: 8
            default: 1
        - name: sort_by
          in: query
          required: false
          description: Order of the properties.
          schema:
            type: string
            enum: ["relevance", "lowest_price", "highest_price", "highest_rating", "distance", "highest_class"]
            default: "relevance"
        - name: hotel_class
          in: query
          required: false
          description: Comma-separated star ratings to keep, from 2 to 5.
          schema:
            type: string
            pattern: '^\s*[2-5]\s*(?:,\s*[2-5]\s*)*$'
        - name: rating
          in: query
          required: false
          description: Lowest guest rating to keep, out of 10.
          schema:
            type: string
            enum: ["6", "7", "8", "9"]
        - name: property_types
          in: query
          required: false
          description: Comma-separated property types to keep.
          schema:
            type: string
            pattern: '^\s*(?:hotel|hostel|motel|inn|resort|bed_and_breakfast|guest_house|aparthotel|apartment|condo|house|villa|cabin|lodge|homestay|campground)\s*(?:,\s*(?:hotel|hostel|motel|inn|resort|bed_and_breakfast|guest_house|aparthotel|apartment|condo|house|villa|cabin|lodge|homestay|campground)\s*)*$'
        - name: amenities
          in: query
          required: false
          description: Comma-separated amenities every property must have, where free_breakfast can be only in a deal for signed-in members that offers leaves out.
          schema:
            type: string
            pattern: '^\s*(?:free_breakfast|free_parking|free_internet|free_airport_shuttle|pay_later|wifi|parking|pool|hot_tub|spa|fitness_center|restaurant|air_conditioning|kitchen|pet_friendly|airport_shuttle|business_center|accessible|ev_charger|non_smoking_rooms|front_desk_24_hours|elevator|adults_only|beachfront|casino|golf|rooftop|terrace)\s*(?:,\s*(?:free_breakfast|free_parking|free_internet|free_airport_shuttle|pay_later|wifi|parking|pool|hot_tub|spa|fitness_center|restaurant|air_conditioning|kitchen|pet_friendly|airport_shuttle|business_center|accessible|ev_charger|non_smoking_rooms|front_desk_24_hours|elevator|adults_only|beachfront|casino|golf|rooftop|terrace)\s*)*$'
        - name: free_cancellation
          in: query
          required: false
          description: Keeps only the properties Kayak lists with a free cancellation offer, which can be a deal for signed-in members that offers leaves out.
          schema:
            type: boolean
        - name: page
          in: query
          required: false
          description: Page of results, with up to 30 properties per page.
          schema:
            type: integer
            minimum: 1
            maximum: 200
            default: 1
      responses:
        '200':
          description: Successful response. A search Kayak answers without properties carries an error.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SearchResponse'
        '400':
          description: Validation Error. There is an issue with query parameters, such as missing required parameters or invalid values.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Authentication Error. The API key is missing or invalid.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: Rate Limit Exceeded. The number of allowed requests has been exceeded. Consider upgrading your plan or waiting for the limit to reset.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Server Error. Internal server error.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '503':
          description: Timeout. We could not retrieve results in 90 seconds.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
components:
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: Authorization
      description: 'Use Bearer authentication. Format: "Bearer YOUR_API_KEY"'
    ApiKeyQuery:
      type: apiKey
      in: query
      name: api_key
      description: Pass API key as query parameter
  schemas:
    SearchResponse:
      type: object
      required: [search_metadata, search_parameters]
      properties:
        search_metadata:
          $ref: '#/components/schemas/SearchMetadata'
        search_parameters:
          $ref: '#/components/schemas/SearchParameters'
        search_information:
          $ref: '#/components/schemas/SearchInformation'
        properties:
          type: array
          description: Properties on the requested page, in the order asked for.
          items:
            $ref: '#/components/schemas/Property'
        pagination:
          $ref: '#/components/schemas/Pagination'
        error:
          type: string
          description: Message explaining why the search has no properties.
    SearchMetadata:
      type: object
      required: [status, created_at]
      properties:
        id:
          type: string
          description: "Unique identifier for the search request"
        status:
          type: string
          description: "Status of the search request"
        created_at:
          type: string
          format: date-time
          description: "Timestamp when the search was created"
        request_time_taken:
          type: number
          description: "Time taken to make the request in seconds"
        parsing_time_taken:
          type: number
          description: "Time taken to parse the results in seconds"
        total_time_taken:
          type: number
          description: "Total time taken for the search in seconds"
        request_url:
          type: string
          description: "Kayak URL for this search"
        html_url:
          type: string
          description: "URL to view HTML results"
        json_url:
          type: string
          description: "URL to view JSON results"
    SearchParameters:
      type: object
      required: [engine, q, check_in_date, check_out_date]
      properties:
        engine:
          type: string
          description: Engine used for the search.
        q:
          type: string
          description: Place or hotel searched.
        check_in_date:
          type: string
          description: Check-in date.
        check_out_date:
          type: string
          description: Check-out date.
        adults:
          type: integer
          description: Number of adults.
        children_ages:
          type: string
          description: Ages of the children.
        rooms:
          type: integer
          description: Number of rooms.
        sort_by:
          type: string
          description: Order of the properties.
        hotel_class:
          type: string
          description: Star ratings kept.
        rating:
          type: string
          description: Lowest guest rating kept.
        property_types:
          type: string
          description: Property types kept.
        amenities:
          type: string
          description: Amenities every property has.
        free_cancellation:
          type: boolean
          description: Whether only properties offering free cancellation are kept.
        page:
          type: integer
          description: Page of results.
    SearchInformation:
      type: object
      required: [total_results]
      properties:
        total_results:
          type: integer
          description: Number of properties matching the search.
        destination:
          $ref: '#/components/schemas/Destination'
        check_in_date:
          type: string
          description: Check-in date Kayak searched.
        check_out_date:
          type: string
          description: Check-out date Kayak searched.
        nights:
          type: integer
          description: Number of nights searched.
        currency:
          type: string
          description: Currency of every price.
    Destination:
      type: object
      properties:
        name:
          type: string
          description: Full name of the place searched.
        city:
          type: string
          description: City of the place searched.
        country:
          type: string
          description: Country of the place searched.
        country_code:
          type: string
          description: Two-letter code of the country.
    Property:
      type: object
      required: [position, property_id, title, link]
      properties:
        position:
          type: integer
          description: Position of the property on the page, starting at 1.
        property_id:
          type: string
          description: Kayak's id for the property.
        title:
          type: string
          description: Name of the property.
        link:
          type: string
          description: Kayak page of the property for the dates and guests searched.
        type:
          type: string
          description: Type of property, such as Hotel or Inn.
        extracted_hotel_class:
          type: integer
          description: Star rating of the property.
        rating:
          type: number
          description: Guest rating out of 10.
        max_rating:
          type: integer
          description: Highest possible guest rating.
        rating_word:
          type: string
          description: Word Kayak gives the guest rating, such as Very good.
        reviews:
          type: integer
          description: Number of guest reviews behind the rating.
        neighborhood:
          type: string
          description: Neighborhood of the property.
        city:
          type: string
          description: City of the property.
        distance:
          type: string
          description: Distance of the property from the city center or from the place searched.
        gps_coordinates:
          $ref: '#/components/schemas/GpsCoordinates'
        description:
          type: string
          description: Description of the property.
        phone:
          type: string
          description: Phone number of the property.
        website:
          type: string
          description: Website of the property.
        amenities:
          type: array
          description: Amenities of the property.
          items:
            type: string
        images:
          type: array
          description: Photos of the property.
          items:
            $ref: '#/components/schemas/Image'
        price_per_night:
          $ref: '#/components/schemas/Price'
        total_price:
          $ref: '#/components/schemas/Price'
        offers:
          type: array
          description: Booking sites offering the property, in Kayak's order, without deals only signed-in members can see.
          items:
            $ref: '#/components/schemas/Offer'
    Offer:
      type: object
      required: [source, total_price, is_free_cancellation, has_free_breakfast, is_private_deal, is_member_rate]
      properties:
        source:
          type: string
          description: Booking site offering the property.
        logo:
          type: string
          description: Logo of the booking site.
        price_per_night:
          $ref: '#/components/schemas/Price'
        total_price:
          $ref: '#/components/schemas/Price'
        tracking_link:
          type: string
          description: Kayak link that sends the traveller on to book the offer on the booking site.
        is_free_cancellation:
          type: boolean
          description: Whether the offer can be cancelled for free.
        has_free_breakfast:
          type: boolean
          description: Whether the offer includes breakfast.
        is_private_deal:
          type: boolean
          description: Whether the offer is a private deal of the booking site.
        is_member_rate:
          type: boolean
          description: Whether the offer is a rate for members of the booking site.
    Price:
      type: object
      required: [extracted_price, extracted_price_before_taxes]
      properties:
        extracted_price:
          type: number
          description: Price including taxes and fees, for every room searched.
        extracted_price_before_taxes:
          type: number
          description: Price before taxes and fees, for every room searched.
    Image:
      type: object
      properties:
        thumbnail:
          type: string
          description: Thumbnail of the photo.
        original:
          type: string
          description: Full-size photo.
    GpsCoordinates:
      type: object
      required: [latitude, longitude]
      properties:
        latitude:
          type: number
          description: Latitude of the property.
        longitude:
          type: number
          description: Longitude of the property.
    Pagination:
      type: object
      required: [current]
      properties:
        current:
          type: integer
          description: Current page.
        total_pages:
          type: integer
          description: Number of pages of results.
        next:
          type: integer
          description: Next page.
    ErrorResponse:
      type: object
      required: [error]
      properties:
        error:
          type: string
          description: Error message describing what went wrong
