DocumentationMCPCLI

Get started

  • Introduction
  • Quickstart
  • Installation

Search

  • How search works
  • Enabled regions

Reference

  • HTTP API
  • Response schemas
  • Errors & limits

Search

How search works

Search never guesses. A name resolves by a published rule, an ambiguous one is an error that lists the candidates, and every answer says what it covered.

Destinations

A search takes a destination, text, or both. The destination is one of these:

destinationobject

Where to search. A first page needs this or text.

destinationwhen kind: "place_name"

A place named in words, with its country.

destination.namestringrequired

The place name, in any language, e.g. Tokyo or 东京.1–128 chars

destination.countryCodestringrequired

ISO 3166-1 alpha-2 country the place is in, e.g. JP.matches ^[A-Z]{2}$

destination.radiusMetersinteger

Search radius around the destination in meters, 1 to 80000. Left out, the service picks one.1–80000

destinationwhen kind: "place"

A place id from an earlier response.

destination.placeIdstringrequired

placeId from an earlier response.matches ^plc_\d{1,12}$

destination.radiusMetersinteger

Search radius around the destination in meters, 1 to 80000. Left out, the service picks one.1–80000

destinationwhen kind: "point"

A point on the map.

destination.locationobjectrequired

The point, WGS84.

destination.location.latnumberrequired

Latitude, WGS84.-90–90

destination.location.lngnumberrequired

Longitude, WGS84.-180–180

destination.radiusMetersinteger

Search radius around the destination in meters, 1 to 80000. Left out, the service picks one.1–80000

destinationwhen kind: "country"

A whole country.

destination.countryCodestringrequired

ISO 3166-1 alpha-2 country, e.g. JP.matches ^[A-Z]{2}$

destinationwhen kind: "locality"

A locality (hub) listed in an earlier search response.

destination.placeIdstringrequired

placeId of the locality.matches ^plc_\d{1,12}$

destination.radiusMetersinteger

Search radius around the destination in meters, 1 to 80000. Left out, the service picks one.1–80000

Pass a placeId from an earlier answer back as { kind: "place", placeId }, never its name. Place ids stay valid: a place a later release drops still resolves.

Areas and radii

A place covers either its whole area or a radius around it. The answer's destination.scope, center and radiusMeters say which.

PlaceScopeCovers
CountryareaEvery hotel in the country.
Region (province, state)areaEvery hotel in the region, where the region is enabled.
Prefecture-level city (China)areaEvery hotel in the prefecture.
Main islandareaAn island that covers its own land area, such as Bali, Phuket, Hokkaido or Sicily.
Town, neighbourhood, district, small islandradiusA circle around the place, 8,000 m unless radiusMeters says otherwise.
PointradiusA circle around the point, 8,000 m by default.
  • radiusMeters is optional, from 1 to 80,000. On an area it narrows the area to a circle around its center.
  • A radius around a named place stays inside the place's country; a radius around a point does not.
  • The search never widens a radius by itself. When more hotels lie just outside, the answer says so in its counts and notes.
  • A hotel belongs to an area by where it is, worked out once per catalogue update, not by the catalogue's own city or region labels.

How a name resolves

A place_name destination always carries its countryCode. The name is matched exactly against the names and alternate names of places in that country, after Unicode normalization, folding typographic apostrophes, lowercasing and collapsing spaces. Accents, hyphens, apostrophes and periods count: "Köln" and "Cologne" match, "Koln" does not; "St. Moritz" matches, "St Moritz" does not; "Xi'an" and "Xi’an" are the same name.

  1. No match answers destination_not_found.
  2. An area absorbs same-name places inside it: the region "Okinawa" absorbs the island, and "Shanghai" means the whole municipality, starting from the city center (the note area_absorbed says so). An area that isn't city-like doesn't absorb a same-name city of 50,000 people or more: both stay candidates, as with New York State and New York City.
  3. Near-duplicates count as one: same-name towns, neighbourhoods and small islands within 5 km of each other.
  4. One place left is used.
  5. Several left: the most populous is used when it has at least 50,000 people and 100 times the next (the note place_resolved_dominant says so, and otherMatches counts the rest).
  6. Otherwise the answer is destination_ambiguous, with up to 8 candidates, each with its placeId and how many hotels it covers. Ask the user, then search the chosen one as { kind: "place", placeId }.

A region that isn't enabled isn't matched by its name, so the name can still match a town or island of that name.

Localities

A search over an area lists its localities: the 8 towns with the most matching hotels, each gathering the hotels near it. Each has its count in this search, its total anywhere, and up to 3 places it includes ("Mestre, incl. Venice"). Search one as { kind: "locality", placeId }: it returns exactly its total.

A price sort or price filter prices up to 3,000 hotels. Over a radius with more, the nearest are priced and the note pool_limited gives the distance covered. Over an area or text with more, the answer is search_too_broad with the localities to choose from.

Text

text matches whole words in hotel names and addresses, in English and Chinese.

  • Every word must match as written: plurals, accents, spacing and abbreviations matter ("Saint Regis" and "St Regis" differ). Hyphens and apostrophes fold, so Ritz-Carlton matches Ritz Carlton.
  • Chinese follows the index's word segmentation, so part of a word can match unrelated names. Traditional and simplified characters match each other.
  • Use distinctive words: a hotel or brand name, a district or a landmark. Not "hotel", "near", "cheap" or "best". A typo matches nothing.
  • For a country or a city, use a destination rather than text.

Amenity filters take the codes that enough hotels list: parking, wifi, laundry, restaurant, room_service, bar, non_smoking, business_center, pool. A hotel that doesn't list an amenity is left out, though it may still have it (the note amenities_listed_only).

Indicative prices

With a stay, each hotel can carry an indicative price per room and night. It is the hotel supplier's lowest nightly reference price for one unit, converted to USD at a market rate. It doesn't depend on the party or on availability, and it can be above or below the cheapest live offer. It can't be booked: only offers can.

Hotels without an indicative price stay listed with price: null; price sorts put them last, and a price filter leaves them out and counts them. When prices can't be looked up, the search still answers, with pricing.status "unavailable" and the note prices_unavailable.

Counts and notes

Every answer carries coverage: how many hotels matched, how many were priced and had a price, and, where it applies, how many match within the widest radius, without the destination, or with the name taken as text. notes say in English what the counts mean for the next step. Field by field, see the search result.

PreviousInstallationNextEnabled regions

On this page

  • Destinations
  • Areas and radii
  • How a name resolves
  • Localities
  • Text
  • Indicative prices
  • Counts and notes
Fortrip

Opinionated trip planning, built for real itineraries.

Product

  • AI Trip Planner
  • Validator
  • Transport
  • Stays
  • Explore Destinations
  • Agents CLI & MCP

Company

  • About
  • Team
  • Pricing
  • Responsible Travel
  • Contact

Resources

  • Blog
  • News
  • Decision Optimization
  • Itinerary Selection
  • FAQ
  • vs ChatGPT
  • Best AI travel planner
© 2026 FortripAI, Inc.PrivacyTermsBrand Assets
info@fortrip.ai+1-650-272-16121111b South Governors Ave, Dover, DE 19904
Skip to main content
Fortrip Logo
ExplorePlanningPricing
CLIMCPDocs
About UsBlogHotels by CityDecision OptimizationItinerary SelectionNewsFortrip vs. ChatGPTBest AI travel plannerFAQOur TeamResponsible TravelPrivacy PolicyTerms of ServiceContact
Saved