Skip to content
FX-Port/Docs
GuidesAPI referenceChangelog
Get API keys
  • Overview
  • Error object

Search

  • Geo searchPOST
  • Locations and coordinatesGET
  • Name searchGET
  • Name search (JSON body)POST

Hotel content

  • Cards of many hotelsPOST
  • One hotel, for its pagePOST
  • Raw hotel documentsPOST

Rates and booking

  • Rates of a hotelPOST
  • Pre-book a ratePOST
  • BookPOST

After booking

  • VoucherGET
  • CancelPOST

Objects

  • Hotel mini
  • Hotel full

Hotels ยท Search

Geo search: hotels around a point

Geo search: finds and prices the hotels around a point for a stay.

POST/api/v1/hotels/search_advanced

Requires an API key with Read permission; a Read+Write key works too.

Send latitude, longitude and radius (meters, required) with the dates, the guests and the residency; the coordinates of a place come from the location search. The same call searches one hotel when you send hotel_id instead. The answer has two parts that you join by hotel id: hotels_details[] holds the MINI card of each hotel (identity, place, photos, amenities, no rates) and hotels_pricing holds the price of the cheapest rate of each hotel for the whole stay. Call get_rates for the rooms, meals and cancellation terms of the hotel the user picks. Hotels that are priced but whose content FX-Port has not cached yet are in missing_hotel_ids: read each one with get_hotel_info. The answer is always one JSON body: stream=true and Accept: text/event-stream are ignored for API keys. There is no pagination: a 5 km radius around a big city can return 1,800 hotels and 8 MB, so keep the radius to what the screen needs. A search answers at most 5,000 hotels: when there are more the answer says truncated and how many were found. A geo search takes 4 to 20 seconds, a search of one hotel less than a second. Identical searches of your agency that arrive at the same moment are merged into one supplier call; each caller still gets its own request_id and headers. Do not send currency. A value written in another well-defined way is read and reported in warnings (coerced_value): a number as text, a date with a midnight time, a sub-territory residency, a radius outside 100 to 70,000 meters, which is moved to the nearest bound. What cannot be read keeps its error code. In the sandbox the search runs on real hotels and prices, but only the supplier test hotels can be booked.

curl https://api.fx-port.com/api/v1/hotels/search_advanced \
  -H "Authorization: Bearer fxp_test_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "latitude": 48.8566,
  "longitude": 2.3522,
  "radius": 1000,
  "checkin": "2026-12-01",
  "checkout": "2026-12-04",
  "residency": "gb",
  "guests": [
    {
      "adults": 2,
      "children": []
    }
  ]
}'
Response200
{
  "environment": "sandbox",
  "search_id": "71498fa9-d3a7-4b6c-81bd-76693be726d1",
  "status": "complete",
  "hotels_details": [
    {
      "id": "hotel_nordbo_2",
      "hid": 10048834,
      "name": "Hotel Nordbo",
      "kind": "Hotel",
      "address": "Vandsovej 13, Nuuk, 3900, Greenland, Nuuk",
      "latitude": 64.17923,
      "longitude": -51.73019,
      "postal_code": null,
      "region": {
        "id": 1359,
        "country_code": "GL",
        "iata": "GOH",
        "name": "Nuuk",
        "type": "City",
        "type_v2": "city"
      },
      "star_rating": 0,
      "images": [
        "https://cdn.worldota.net/t/{size}/content/16/be/16be5aea51c0060686286cf8c886e4e07e1e5dce.jpeg",
        "https://cdn.worldota.net/t/{size}/content/b1/98/b198dca0393650833ee449c3e460b2af85a04dda.jpeg"
      ],
      "serp_filters": [
        "has_parking",
        "has_meal",
        "has_pets"
      ],
      "amenity_groups": [
        {
          "amenities": [
            "24-hour reception",
            "Smoke-free property",
            "Ticket assistance"
          ],
          "non_free_amenities": [],
          "group_name": "General"
        },
        {
          "amenities": [
            "Breakfast",
            "Restaurant"
          ],
          "non_free_amenities": [],
          "group_name": "Meals"
        }
      ]
    },
    {
      "id": "hhe_express",
      "hid": 9168363,
      "name": "HHE Express Hotel",
      "kind": "Hotel",
      "address": "Aqqusinersuaq 14B, Nuuk",
      "latitude": 64.17208,
      "longitude": -51.73649,
      "postal_code": "3900",
      "region": {
        "id": 1359,
        "country_code": "GL",
        "iata": "GOH",
        "name": "Nuuk",
        "type": "City",
        "type_v2": "city"
      },
      "star_rating": 3,
      "images": [
        "https://cdn.worldota.net/t/{size}/content/b5/39/b539a20fd8349ef419e73802ced9a04215155205.JPEG",
        "https://cdn.worldota.net/t/{size}/content/41/97/4197c95a76a3ada2539a0fe169e7e3d7df3e80f9.jpeg"
      ],
      "serp_filters": [
        "has_internet",
        "has_parking"
      ],
      "amenity_groups": [
        {
          "amenities": [
            "24-hour reception",
            "Elevator/lift",
            "Smoke-free property"
          ],
          "non_free_amenities": [],
          "group_name": "General"
        },
        {
          "amenities": [
            "Free Wi-Fi"
          ],
          "non_free_amenities": [],
          "group_name": "Internet"
        }
      ]
    }
  ],
  "processing_status": {
    "total_hotels": 5,
    "cached_hotels": 5,
    "queued_hotels": 0
  },
  "queue_info": {
    "queued_hotel_ids": [],
    "estimated_completion": null
  },
  "timing": {
    "total_duration": 0.84,
    "search_duration": 0.82,
    "cache_check_duration": 0.02
  },
  "hotels_pricing": {
    "hotel_nordbo_2": {
      "exchange_rate": 285,
      "agency_currency": "DZD",
      "agency_commission": 438.68,
      "final_price": 219774.68,
      "b2b_price": 219336
    },
    "hhe_express": {
      "exchange_rate": 285,
      "agency_currency": "DZD",
      "agency_commission": 228.83,
      "final_price": 114639.23,
      "b2b_price": 114410.4
    }
  },
  "missing_hotel_ids": [],
  "missing_hotels_pricing": {}
}
Response200
{
  "environment": "sandbox",
  "search_id": "71498fa9-d3a7-4b6c-81bd-76693be726d1",
  "status": "complete",
  "hotels_details": [
    {
      "id": "test_hotel_do_not_book",
      "hid": 8473727,
      "name": "Test Hotel (Do Not Book) test",
      "kind": "Apartment",
      "address": "Avenida Roble, Frente al Mall Multiplaza, Tegucigalpa",
      "latitude": 14.079872,
      "longitude": -87.21677,
      "postal_code": null,
      "region": {
        "id": 3421,
        "country_code": "HN",
        "iata": "TGU",
        "name": "Tegucigalpa",
        "type": "City",
        "type_v2": "city"
      },
      "star_rating": 0,
      "images": [
        "https://cdn.worldota.net/t/{size}/extranet/b5/d3/b5d3d33394494c68321246882c1bd93a6832dcd5.jpeg",
        "https://cdn.worldota.net/t/{size}/extranet/15/44/15440558c952ec4c3488730d1563dc9e8d25832c.JPEG"
      ],
      "serp_filters": [
        "has_internet",
        "has_parking",
        "has_spa",
        "has_pets",
        "has_jacuzzi",
        "kitchen"
      ],
      "amenity_groups": [
        {
          "amenities": [
            "24-hour reception",
            "Early check-in",
            "Late check-out"
          ],
          "non_free_amenities": [],
          "group_name": "General"
        },
        {
          "amenities": [
            "Concierge services",
            "Dry-cleaning",
            "Shoe shine"
          ],
          "non_free_amenities": [
            "Dry-cleaning",
            "Shoe shine"
          ],
          "group_name": "Services and amenities"
        }
      ]
    }
  ],
  "processing_status": {
    "total_hotels": 1,
    "cached_hotels": 1,
    "queued_hotels": 0
  },
  "queue_info": {
    "queued_hotel_ids": [],
    "estimated_completion": null
  },
  "timing": {
    "total_duration": 0.31,
    "search_duration": 0.3,
    "cache_check_duration": 0.01
  },
  "hotels_pricing": {
    "test_hotel_do_not_book": {
      "exchange_rate": 285,
      "agency_currency": "DZD",
      "agency_commission": 2.97,
      "final_price": 1484.97,
      "b2b_price": 1482
    }
  },
  "missing_hotel_ids": [],
  "missing_hotels_pricing": {}
}
Response200
{
  "environment": "sandbox",
  "search_id": "4a6877dc-96da-4f32-8c1b-4aaed8b60fe4",
  "status": "partial",
  "hotels_details": [
    {
      "id": "hotel_honduras_maya_6",
      "hid": 6329711,
      "name": "Hotel Honduras Maya",
      "kind": "Hotel",
      "address": "Colonia Palmira 3era calle ave, Tegucigalpa",
      "latitude": 14.103492,
      "longitude": -87.19721,
      "postal_code": "11101",
      "region": {
        "id": 3421,
        "country_code": "HN",
        "iata": "TGU",
        "name": "Tegucigalpa",
        "type": "City",
        "type_v2": "city"
      },
      "star_rating": 3,
      "images": [
        "https://cdn.worldota.net/t/{size}/content/1d/67/1d67eefb8685fb4b809624bb4f6c437592722183.JPEG",
        "https://cdn.worldota.net/t/{size}/content/6a/0e/6a0ebfe39089a02e1e6da4a03eb6200047545ba1.JPEG"
      ],
      "serp_filters": [
        "has_internet",
        "has_airport_transfer",
        "has_parking",
        "has_kids",
        "has_pool"
      ],
      "amenity_groups": [
        {
          "amenities": [
            "ATM",
            "Air conditioning",
            "24-hour reception"
          ],
          "non_free_amenities": [],
          "group_name": "General"
        },
        {
          "amenities": [
            "Bridal suite",
            "Room service",
            "Interconnecting rooms available"
          ],
          "non_free_amenities": [],
          "group_name": "Rooms"
        }
      ]
    }
  ],
  "processing_status": {
    "total_hotels": 15,
    "cached_hotels": 14,
    "queued_hotels": 1
  },
  "queue_info": {
    "queued_hotel_ids": [
      "comfort_inn_tegucigalpa"
    ],
    "estimated_completion": "about 9 minutes",
    "estimated_completion_seconds": 541
  },
  "timing": {
    "total_duration": 4.38,
    "search_duration": 4.33,
    "cache_check_duration": 0.05
  },
  "hotels_pricing": {
    "hotel_honduras_maya_6": {
      "exchange_rate": 285,
      "agency_currency": "DZD",
      "agency_commission": 285.14,
      "final_price": 142853.54,
      "b2b_price": 142568.4
    },
    "comfort_inn_tegucigalpa": {
      "exchange_rate": 285,
      "agency_currency": "DZD",
      "agency_commission": 218.75,
      "final_price": 109590.36,
      "b2b_price": 109371.61
    }
  },
  "missing_hotel_ids": [
    "comfort_inn_tegucigalpa"
  ],
  "missing_hotels_pricing": {
    "comfort_inn_tegucigalpa": {
      "exchange_rate": 285,
      "agency_currency": "DZD",
      "agency_commission": 218.75,
      "final_price": 109590.36,
      "b2b_price": 109371.61
    }
  }
}
Response200
{
  "environment": "sandbox",
  "search_id": "0c3f0e0e-1f0b-4f55-a2a6-8d4f2f1d2d11",
  "status": "no_hotels_found",
  "hotels_details": [],
  "processing_status": {
    "total_hotels": 0,
    "cached_hotels": 0,
    "queued_hotels": 0
  },
  "queue_info": {
    "queued_hotel_ids": [],
    "estimated_completion": null
  },
  "timing": {
    "total_duration": 0.24,
    "search_duration": 0.22,
    "cache_check_duration": 0
  }
}

Request

Body

Required, JSON.

latitudenumber

Geo search: the latitude of the center of the search, -90 to 90. Send it with longitude and radius; the coordinates of a place come from the locations search. A number written as text ("48.8566") is read as the number, with a coerced_value warning.

Between -90 and 90.

longitudenumber

Geo search: the longitude of the center, -180 to 180. A number written as text ("2.3522") is read as the number, with a coerced_value warning.

Between -180 and 180.

radiusinteger

Geo search: the radius around the center, in meters, 100 to 70,000. Required for a geo search; there is no default. A value outside the range is moved to the nearest bound and the answer carries a coerced_value warning. A number written as text ("3000") is read as the number, with a coerced_value warning.

Between 100 and 70000.

hotel_idstring

Search one hotel instead of the hotels around a point: its FX-Port id (1 to 128 characters: letters, digits and _ . : -; spaces around it are trimmed). A JSON integer is read as its text, but it is not looked up as the supplier's numeric hid here: send the FX-Port id. When it is sent, latitude, longitude and radius are ignored; a null hotel_id next to latitude and longitude is a geo search.

checkinstringrequired

Check-in date, YYYY-MM-DD: from yesterday (for time zones) to 400 days ahead. A date written with a midnight time (2026-12-01T00:00:00Z) is read as that day, with a coerced_value warning; any other time of day is invalid_date.

checkoutstringrequired

Check-out date, YYYY-MM-DD, after checkin. A stay is 1 to 30 nights. A midnight time is read as in checkin.

guestsarray of objectrequired

The rooms: one {adults, children} object per room, 1 to 9 rooms.

ShowHide 2 attributes
adultsintegerrequired

Number of adults in the room, 1 to 6. A number written as text ("2") is read as the number, with a coerced_value warning.

Between 1 and 6.

childrenarray of integer

One entry per child of the room: the age at check-in. [] or omitted when there is none. At most 4 children per room.

residencystring

Residency of the guests, a two-letter ISO 3166-1 country code (gb, dz, fr). A sub-territory code of the website's nationality list (GB-SCT, USPR, ES-XCI, PT-MA, BQ-SA ...) is read as its country, with a coerced_value warning: send the 2-letter country. Some rates exist for some residencies only. Not defaulted: always send it.

languagestring

Language of the supplier's answer, such as en, fr or zh_CN. A longer tag (zh-Hans-CN, es-419, sr-Latn-RS) is read as the supplier's code, with a coerced_value warning. The hotel content in the answer is English whatever you send.

Default en.

idstringdeprecated

Legacy name, still accepted. Use hotel_id instead.

The hotel id, in its older spelling. Use hotel_id.

hotelIdstringdeprecated

Legacy name, still accepted. Use hotel_id instead.

The hotel id, in its older spelling. Use hotel_id.

checkinDatestringdeprecated

Legacy name, still accepted. Use checkin instead.

The check-in date, in an older spelling. Use checkin.

checkin_datestringdeprecated

Legacy name, still accepted. Use checkin instead.

The check-in date, in an older spelling. Use checkin.

check_instringdeprecated

Legacy name, still accepted. Use checkin instead.

The check-in date, in an older spelling. Use checkin.

checkoutDatestringdeprecated

Legacy name, still accepted. Use checkout instead.

The check-out date, in an older spelling. Use checkout.

checkout_datestringdeprecated

Legacy name, still accepted. Use checkout instead.

The check-out date, in an older spelling. Use checkout.

check_outstringdeprecated

Legacy name, still accepted. Use checkout instead.

The check-out date, in an older spelling. Use checkout.

Response

200The hotels that are available, with their mini cards and prices. status tells how many have content; an empty hotels_details with no_hotels_found means no hotel is available for the request (also the case when a hotel exists but not for this residency). The examples are real answers of the sandbox: a geo search around Nuuk, a search of one hotel, a geo search around Tegucigalpa where one priced hotel has no card yet, and an empty answer.

environmentstring

The environment of the key that made the call: sandbox for fxp_test_ keys, live for fxp_live_ keys. Present in every JSON body.

One of sandbox, live.

request_idstring

The id of the request, also in the X-Request-Id header.

warningsarray of object

Present only when the request used a previous spelling of a field or something the endpoint ignored.

ShowHide 5 attributes
codestring

What the warning is about.

One of deprecated_field, ignored_field, coerced_value, deprecated_value, deprecated_endpoint.

fieldstring

The request field the warning is about.

replacementstring

The name to use instead, for deprecated_* warnings.

messagestring

A sentence that says what happened and what to do.

documentation_urlstring

Where the naming rules are explained.

search_idstring

The id of the search, also in the X-Search-Id header. Quote it to support.

statusstring

complete: every priced hotel has content. partial: some do not (see missing_hotel_ids). cache_miss: none has. no_hotels_found: no hotel is available for the request.

One of complete, partial, cache_miss, no_hotels_found.

hotels_detailsarray of HotelMini

The mini card of each hotel that has cached content. No rates here: the prices are in hotels_pricing.

See the Hotel mini object

processing_statusobject

How many hotels of the search have content.

ShowHide 3 attributes
total_hotelsinteger

Hotels the supplier priced for the search.

cached_hotelsinteger

Of them, the hotels whose content FX-Port holds: they are in hotels_details.

queued_hotelsinteger

Of them, the hotels without cached content that were queued for loading: their ids are in missing_hotel_ids.

queue_infoobject

The hotels without cached content that FX-Port loads in the background.

ShowHide 3 attributes
queued_hotel_idsarray of string

The ids of the hotels whose content was queued for loading (at most 50 per search).

estimated_completionstringnullable

A rough delay until the content is loaded, such as about 9 minutes. null when nothing was queued.

estimated_completion_secondsinteger

The same delay in seconds. Present only when hotels were queued.

timingobject

Where the time of a search went, in seconds.

ShowHide 3 attributes
total_durationnumber

Seconds the whole search took, in FX-Port.

search_durationnumber

Seconds the supplier took to price the hotels.

cache_check_durationnumber

Seconds FX-Port took to read the hotel content.

hotels_pricingobject

The price of the cheapest rate of every priced hotel, by hotel id. Absent when status is no_hotels_found.

missing_hotel_idsarray of string

The ids of the hotels that are priced but have no cached content yet. Get one with get_hotel_info. Absent when status is no_hotels_found.

missing_hotels_pricingobject

The price entry of each hotel of missing_hotel_ids, with the same fields as hotels_pricing.

truncatedboolean

true when the supplier found more hotels than one search answers and the rest was cut off. Present only then: narrow the search.

max_hotelsinteger

The most hotels one search answers. Present with truncated.

total_hotels_foundinteger

How many hotels the supplier found before the cut. Present with truncated.

notestring

A hint about an empty answer, for example that test_hotel has no availability for the residency you sent. Present only when there is one.

Errors

StatusCodeExample message
400stay_too_longA stay can be at most 30 nights ('checkout' is 35 nights after 'checkin').
400missing_fieldMissing required fields for hotel_id search: ['guests']
400missing_fieldMissing required fields for hotel_id search: ['checkin', 'guests']
400bad_requestDo not pass 'currency'. Currency is resolved automatically from the authenticated agency.
400missing_field'radius' (meters) is required for a geo search.
400invalid_radius'radius' must be a whole number of meters.
422supplier_rejected_requestThe hotel supplier rejected the request parameters. Check dates, guests, residency and radius.
503supplier_busyThe supplier is temporarily at capacity; retry after the time given in the Retry-After header.

The shape of the error body depends on the endpoint. See Errors for every shape and code.

Related guides

  • Geo search
  • Mini and full hotel data
  • Guests and rooms
PreviousUpload ACD passport documentsNext Search destinations and get coordinates

ยฉ 2026 FX-Port

TermsPrivacy[email protected]