Hotel name search
Find a hotel by name. Partial names and accents are tolerated; typos only when the rest of the name is long enough.
Find a hotel by the name a person types, and get its FX-Port hotel id to use in search_advanced, get_rates and get_hotel_info. The search compares your text with hotel names over every hotel FX-Port knows. It does not price anything and does not need dates.
Permission: Read
Two forms, one search
Use the form that fits your client. They run the same search and return the same answer.
GET /
curl 'https://api.fx-port.com/api/v1/hotels/name-search?query=Sofitel%20Algiers&limit=3&min_score=60' \
-H "Authorization: Bearer fxp_test_YOUR_KEY"POST /
curl https://api.fx-port.com/api/v1/hotels/search-by-name \
-H "Authorization: Bearer fxp_test_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"query": "Sofitel Algiers",
"limit": 3,
"min_score": 60,
"include_location": true,
"include_details": false
}'| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
query | string | Yes | The hotel name or a part of it, 2 to 100 characters. Control characters are removed. | |
limit | integer | No | 10 | Most hits to return, 1 to 100. The POST form caps a larger value at 100 and says so in warnings (coerced_value); the GET form refuses it with 400 invalid_limit. A whole number written as text ("10") is read; zero, a negative number, a fraction or another text is 400 invalid_limit on both forms. |
min_score | number | No | 60 | Lowest match score to return, 0 to 100. A number written as text is read; a number outside that range, or another text, is 400 invalid_min_score. See Reading the score. |
include_location | boolean | No | true | Add the address, city, country code and postal code to each hit. In the POST body the text true or false (also 1, 0, yes, no, on, off) is read, with a coerced_value warning, and null means the default. |
include_details | boolean | No | false | Return the whole stored hotel document of each hit instead of the summary. See Details of each hit: you almost never want it. |
Response
A real answer of the sandbox:
{
"environment": "sandbox",
"query": "Sofitel Algiers",
"results_count": 2,
"search_time": "0.060s",
"hotels": [
{
"id": "sofitel_algiers_hamma_garden",
"name": "Sofitel Algiers Hamma Garden",
"match_score": 83.39,
"match_type": "partial",
"address": "172, rue Hassiba Benbouali, Algiers",
"city": "Algiers",
"country_code": "DZ",
"postal_code": "16014"
},
{
"id": "algiers_hotel",
"name": "Algiers",
"match_score": 76.67,
"match_type": "partial",
"address": "2845 South Las Vegas Boulevard Las Vegas, South Las Vegas Boulevard, Las Vegas",
"city": "Las Vegas",
"country_code": "US",
"postal_code": "89109"
}
]
}| Field | Description |
|---|---|
results_count | How many hotels are in hotels. |
search_time | The time the search itself took, as text with its unit (0.060s). The call takes longer because of the network: 0.2 to 0.8 s in our measurements. |
hotels[].id | The FX-Port hotel id. Send it as hotel_id. |
hotels[].name | The name of the hotel. |
hotels[].match_score | How well the name matches, 0 to 100, two decimals. The hits are sorted by it. |
hotels[].match_type | exact (the whole name), partial (your text is a part of the name, or the name a part of your text) or fuzzy (the text is close to the name but not the same). |
hotels[].address, city, country_code, postal_code | Where the hotel is. postal_code is an empty string when unknown. Absent with include_location=false. |
Reading the score
The score says how close the name is to your text. It does not say that it is the hotel you mean. What the search returned in our probes (sandbox, 2026-11-01):
| You type | Best hit | Score | Type |
|---|---|---|---|
Sofitel Algiers Hamma Garden | Sofitel Algiers Hamma Garden (Algiers, DZ) | 100 | exact |
sofitel algiers hamma garden hotel | the same hotel | 85.59 | partial |
sofitel algirs hamma garden (a typo) | the same hotel | 86.43 | fuzzy |
Hamma Garden (a fragment) | A garden (Sevastopol, RU); the hotel you want is second | 81.67 (80.71) | partial |
sofitel algers (a typo in a short text) | Sofi (Perm, RU): the hotel is not found | 72.14 | partial |
Hilton | many hotels called Hilton, in St Helens, Thanesar, Windsor ... | 100 | exact |
pereme and peremé | the same hits with the same scores (78.33 at best): accents are ignored | 78.33 | partial |
What to do with it:
- Treat a score of 80 or more as a likely match and anything below as a suggestion. In our probes, every hit from 80 up was the hotel we typed, and nearly every hit below was another hotel (
Sofitel Algiersalso finds a hotel calledAlgiersin Las Vegas at 76.67). Raisemin_scoreto 80 to hide the weak ones, or lower it to 50 when you would rather show too much. - Typos are tolerated only when the rest of the text is long enough to carry the match. A typo in a short text finds another hotel.
- Do not book the first hit without showing it. Show the name, the city and the country.
Details of each hit
With include_details=true each hit is the whole stored document of the hotel (snake_case, with images_ext, policy_struct and every room type) plus match_score and match_type, and no city or country_code at the top (they are in region). It is large: 48 KB for one hotel in our measurement (26 KB for the smallest we measured). It is not the shape of any other call, so a client that wants the hotel page should take the id of the hit and call get_hotel_info for that one hotel. For a result list use the summary, or the compact card of Mini and full hotel data.
Good practice
- Debounce a typeahead at about 300 ms and cancel the request in flight. The search engine runs a few searches at a time, and when it is busy the call answers
503withservice_busyand aRetry-Afterof 2 seconds: wait that long and ask again. - The ids are the same in the sandbox and on live, but a hit is not necessarily bookable in the sandbox: see Sandbox testing. The test hotel
test_hotel(Test Hotel (Do Not Book)) is found by name;test_hotel_do_not_bookis not, so use its id as it is written there. - The keys are snake_case and have no camelCase twin.
Errors
| HTTP | Code | Cause |
|---|---|---|
400 | missing_field | query is missing from the POST body (Missing required field: 'query'; errors[0].field is query). |
400 | invalid_query | query is not a text of 2 to 100 characters (POST and GET). |
400 | invalid_limit, invalid_min_score | limit is not a whole number from 1 to 100 (a larger number is capped on the POST form and refused on the GET form), or min_score is not a number from 0 to 100. errors[0].field names it and errors[0].details carries min and max when the number is out of range. |
400 | bad_request | The query is blank, or include_details or include_location of the POST body is not a boolean or one of the texts above (the message names it). |
422 | validation_error | The GET form has no query, or include_details or include_location is not a boolean. |
503 | service_busy | The search engine is busy. Retry after Retry-After seconds. |
401, 403 | The key is missing, wrong or not allowed: Authentication. | |
429 | rate_limit_exceeded | Too many calls: Rate limits. |
A search that finds nothing is not an error: the answer is 200 with results_count: 0 and an empty hotels.