Display one to six homes as photo cards with Details and host booking links. A semantic search_properties shows no cards: finish comparing and any detail or price checks first, then call render_properties once with your final choice, best first. Render every home you recommend, even a single one, which opens as its full details. Each call replaces the cards the traveler sees, so never render provisional picks. Also use it for a subset, photos again or a comparison the traveler requests. Pass the structured search arguments the homes came from as searchContext, so explorer refinements keep destination, party and filters; with quoteMode and its dates or flexible bounds, the cards are priced for that stay under the same 2.5-second quote enrichment as search (pending prices finish in the cards). Omit context for unrelated saved homes; cards are then price-free. Rechecks publication before display.
View input schema
{
"type": "object",
"properties": {
"ids": {
"minItems": 1,
"maxItems": 6,
"type": "array",
"items": {
"type": "string",
"minLength": 1,
"maxLength": 160
}
},
"locale": {
"default": "en",
"type": "string",
"enum": [
"en",
"es"
]
},
"searchContext": {
"description": "The structured search arguments the homes came from. Preserves explorer refinements; with quoteMode and its dates or flexible bounds, the shown cards are priced for that stay.",
"type": "object",
"properties": {
"locale": {
"default": "en",
"type": "string",
"enum": [
"en",
"es"
]
},
"quoteMode": {
"description": "Optional price/availability enrichment. exact uses supplied dates and guests; estimate requires estimateWindowStart, estimateWindowEnd, estimateNights and guests for a clearly labeled sample within supplied flexible bounds. Search does not wait for every host or filter unknown homes out.",
"type": "string",
"enum": [
"exact",
"estimate"
]
},
"estimateWindowStart": {
"description": "Earliest sample arrival (YYYY-MM-DD), paired with estimateWindowEnd. Only with quoteMode:estimate. Preserve the traveler's flexible month or date range.",
"type": "string",
"format": "date",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
},
"estimateWindowEnd": {
"description": "Latest sample departure (YYYY-MM-DD), paired with estimateWindowStart. Window must fit estimateNights (required), at most 150 days.",
"type": "string",
"format": "date",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
},
"arrival": {
"type": "string",
"format": "date",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
},
"departure": {
"type": "string",
"format": "date",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
},
"currency": {
"type": "string",
"pattern": "^[A-Z]{3}$",
"description": "Preferred ISO 4217 currency, e.g. USD, EUR or NOK. Rough nightly estimates use approximate conversions (USD by default) when a fresh rate is supported; otherwise retain the host currency. Dated quotes depend on host support: always inspect the returned currency. May be supplied without dates for browsing."
},
"estimateNights": {
"description": "Sample-stay nights, required. Only with quoteMode:estimate.",
"type": "integer",
"minimum": 1,
"maximum": 30
},
"organization": {
"default": "",
"description": "Exact organization slug returned on a property or in get_filters. Restricts results to that organization, across destinations.",
"type": "string",
"maxLength": 160
},
"relatedTo": {
"default": "",
"description": "Published property ID. Find other homes from its organization, same locality first, then region/country and other locations. Excludes the source property. Additional filters still combine with AND.",
"type": "string",
"maxLength": 160
},
"q": {
"default": "",
"description": "Search public property names, locations and approved introduction text.",
"type": "string",
"maxLength": 160
},
"semantic": {
"description": "Rank indexed, eligible homes by text and photo similarity. Does not establish hard facts; no lexical fallback when unavailable.",
"type": "string",
"minLength": 1,
"maxLength": 4000
},
"semanticPreferences": {
"description": "Individual experiential preferences, each copied verbatim from semantic. Interpret the traveler in context: separate requested preferences without adding needs. Keep related words together when they describe one room, view or relationship. These are questions to assess, not property facts; omit for factual-only searches.",
"minItems": 1,
"maxItems": 8,
"type": "array",
"items": {
"type": "string",
"minLength": 1,
"maxLength": 350
}
},
"reassessPropertyIds": {
"minItems": 1,
"maxItems": 4,
"type": "array",
"items": {
"type": "string",
"minLength": 1,
"maxLength": 160
},
"description": "Up to four previously discussed public property IDs to reassess against this semantic request alongside fresh matches. Use when refining or comparing earlier suggestions. This reserves comparison slots only: current factual filters, indexed source ownership and every essential requirement still apply. It does not keep an old recommendation or establish fit. Omit for a new search without earlier candidates to reassess."
},
"semanticRequirements": {
"description": "Essential trip requirements, each copied verbatim from semantic with all relationship and provenance qualifiers. Every one must have source-backed support before a home is returned. Preserve these from the conversation; ordinary preferences belong in semanticPreferences. Omit when no essential experiential requirements were stated. Interpret semanticRequirements as conditions the accommodation or its setting must satisfy. Preserve essential support for the traveler's primary activity and access needs, including when expressed indirectly. Preserve the traveler's complete context in semantic. When the traveler states an explicit offering condition together with their own plans, circumstances or reasons, copy the complete offering condition as the essential; do not create an additional standalone proof obligation for the traveler's plan or circumstance. Keep any context necessary to understand the condition, its scope and relationships. Do not broaden a specific access requirement into proof of every aspect of the trip, and do not drop an actual offering condition because it is motivated by a traveler's circumstances. When a circumstance leaves the required accommodation or access condition ambiguous, ask one short clarifying question before searching; do not submit the circumstance itself as a property-proof requirement. If the offering condition itself is ambiguous, clarify it in the real conversation instead of inventing a stricter condition.",
"minItems": 1,
"maxItems": 8,
"type": "array",
"items": {
"type": "string",
"minLength": 1,
"maxLength": 350
}
},
"place": {
"default": "",
"description": "Place key from the live filter catalog.",
"type": "string",
"maxLength": 240
},
"bounds": {
"default": "",
"description": "Map viewport as south,west,north,east in degrees; keeps homes whose public area center is inside it. West greater than east crosses the antimeridian.",
"type": "string",
"maxLength": 80,
"pattern": "^$|^-?\\d{1,3}(\\.\\d{1,6})?(,-?\\d{1,3}(\\.\\d{1,6})?){3}$"
},
"feature": {
"default": "",
"description": "Collection key from the filter catalog.",
"type": "string",
"enum": [
"",
"private-pools",
"room-for-4",
"room-for-6",
"room-for-8",
"room-for-10",
"2-bedrooms",
"3-bedrooms",
"4-bedrooms",
"pets",
"air-conditioning",
"workspace",
"step-free"
]
},
"geographicArea": {
"default": "",
"description": "Exact geographic area key from get_filters(kind:geography), including continents and subregions. Americas includes North/Central/South America and the Caribbean. north-america includes Northern America, Central America and Caribbean; northern-america is the narrower UN M49 subregion. Filters by public ISO country/territory code; unknown locations never match. Combines with all other filters using AND.",
"type": "string",
"enum": [
"",
"africa",
"northern-africa",
"sub-saharan-africa",
"eastern-africa",
"middle-africa",
"southern-africa",
"western-africa",
"americas",
"latin-america-and-the-caribbean",
"caribbean",
"central-america",
"south-america",
"northern-america",
"asia",
"central-asia",
"eastern-asia",
"south-eastern-asia",
"southern-asia",
"western-asia",
"europe",
"eastern-europe",
"northern-europe",
"southern-europe",
"western-europe",
"oceania",
"australia-and-new-zealand",
"melanesia",
"micronesia",
"polynesia",
"north-america"
]
},
"countries": {
"default": [],
"description": "Explicit union of ISO 3166-1 alpha-2 country/territory codes, e.g. [CR, PA]. A home must match one selected country; combines with geographicArea, country and every other filter using AND. Use available codes from get_filters; never silently substitute a narrower country for an area.",
"maxItems": 249,
"type": "array",
"items": {
"type": "string",
"pattern": "^[A-Z]{2}$"
}
},
"country": {
"default": "",
"description": "Destination country established by the traveler or unambiguous trip context. Ask before choosing a country for an ambiguous place name.",
"type": "string",
"maxLength": 160
},
"region": {
"default": "",
"description": "Published region name. Resolve informal areas such as south of France with get_filters before searching; an invented region label can return no homes.",
"type": "string",
"maxLength": 160
},
"city": {
"default": "",
"description": "Specific destination locality, not a nearby radius. Resolve ambiguous names before choosing a country; use the area tools for nearby discovery.",
"type": "string",
"maxLength": 160
},
"accommodationType": {
"default": "",
"description": "Filter by reviewed accommodation type. Hotel results represent one establishment; guest count requires a quote for one suitable room, never total hotel capacity.",
"type": "string",
"enum": [
"",
"vacation_rental",
"boutique_hotel"
]
},
"guests": {
"description": "Total occupancy, adults plus children. Rentals: minimum sleeping capacity. Boutique hotels: everyone in one room for a one-room quote, priced as adults, with occupancy unconfirmed until that quote succeeds.",
"type": "integer",
"minimum": 1,
"maximum": 100
},
"children": {
"description": "How many of guests are children (under 18). guests stays total occupancy, so it must exceed children; capacity counts everyone. No reader prices child ages yet.",
"type": "integer",
"minimum": 1,
"maximum": 199
},
"childAges": {
"description": "Each child's age at check-out, one entry per child (exactly children entries). Retained and disclosed; the host confirms child rates.",
"maxItems": 199,
"type": "array",
"items": {
"type": "integer",
"minimum": 0,
"maximum": 17
}
},
"minBedrooms": {
"type": "integer",
"minimum": 1,
"maximum": 50
},
"minBathrooms": {
"type": "number",
"minimum": 0.5,
"maximum": 50,
"multipleOf": 0.5
},
"amenities": {
"default": "",
"description": "Comma-separated keys from: air-conditioning, wifi, workspace, parking, pets, kitchen, washer, step-free. Every requested key must be explicitly present. Other details (for example pool heating) belong in semantic preferences or requirements, not invented keys.",
"type": "string",
"maxLength": 240
},
"pool": {
"default": "",
"type": "string",
"enum": [
"",
"present",
"private",
"shared",
"absent"
]
},
"page": {
"default": 1,
"type": "integer",
"minimum": 1,
"maximum": 1000
}
},
"additionalProperties": false
}
},
"required": [
"ids"
],
"additionalProperties": false
}