Skip to content
FX-Port/Docs
GuidesAPI referenceChangelog
Get API keys
  • Introduction
  • Quickstart
  • Security
  • Authentication
  • Environments and Postman
  • Sandbox
  • Conventions and naming
  • Legacy names and twins
  • Errors
  • Rate limits and fair use
  • Streaming search results

Concepts

  • Overview
  • Sandbox testing
  • Mini and full data
  • Guests and rooms
  • Pricing

Search

  • Geo search
  • Locations and coordinates
  • Name search
  • Hotel details

Rates and booking

  • Rates
  • Pre-book
  • Book

After booking

  • Get a booking
  • Voucher
  • Cancel
  • Use these docs with AI

Hotels · Concepts

Hotels API overview

Geo search around a point, name search, hotel content, rates, pre-book, bookings that confirm at once, vouchers and cancellation.

Search, price and book hotels worldwide through one API. Hotel content comes as compact mini cards for result lists and as a full document for the hotel page: Mini and full hotel data.

For a summary of what the API covers, who it is for and how to get access, see the hotel booking API for travel agencies.

The flow: locations → geo search → rates → pre_book → book. Turn a typed city into coordinates, run a geo search (POST /hotels/search_advanced with latitude, longitude and radius) to list the hotels around them with their prices, read the rooms and the cancellation terms of the hotel the user opens, lock the rate and book it. Then read the booking, get the voucher, or cancel. Booking a hotel confirms it: there is no hold or pay-later option for API keys, and your agency is debited as part of the booking, when it is confirmed (the sandbox debits nothing).

In the sandbox you can search and price any hotel, but you can only book the test hotels

A sandbox key searches and prices any hotel on real supplier inventory, but it can book only the supplier's test hotels: test_hotel_do_not_book (every residency: use this one) and test_hotel (residency dz, ru or us only). pre_book on any other hotel answers 409 hotel_not_bookable_in_sandbox and lists the test hotels; book_hotel on it would fail with order_not_found. Every sandbox booking is a real order on the supplier's test contract: cancel it. Sandbox testing has the ids, the date rules and a script that books and cancels.

Your serverHolds the API keyFX-Port APIapi.fx-port.comHotel supplierRateHawk / WorldOTA1 GET /hotels/locations/search2 Coordinates of the destination3 POST /hotels/search_advanced (geo search)4 Mini hotel cards with prices5 POST /hotels/get_hotel_info (hotel page)6 POST /hotels/get_rates7 Rooms, rates, book_hash8 POST /hotels/pre_book9 Locked price, partnerOrderId10 POST /hotels/book_hotel11 Book the room12 GET /bookings/{id}?product=hotels13 Confirmed booking with the voucher
  1. 1Your server to FX-Port API
    GET /hotels/locations/search
  2. 2FX-Port API to Your server
    Coordinates of the destination
  3. 3Your server to FX-Port API
    POST /hotels/search_advanced (geo search)
  4. 4FX-Port API to Your server
    Mini hotel cards with prices
  5. 5Your server to FX-Port API
    POST /hotels/get_hotel_info (hotel page)
  6. 6Your server to FX-Port API
    POST /hotels/get_rates
  7. 7FX-Port API to Your server
    Rooms, rates, book_hash
  8. 8Your server to FX-Port API
    POST /hotels/pre_book
  9. 9FX-Port API to Your server
    Locked price, partnerOrderId
  10. 10Your server to FX-Port API
    POST /hotels/book_hotel
  11. 11FX-Port API to Hotel supplier
    Book the room
  12. 12Your server to FX-Port API
    GET /bookings/{id}?product=hotels
  13. 13FX-Port API to Your server
    Confirmed booking with the voucher

Endpoints

All paths are below https://api.fx-port.com. Read works with any key; Read+Write needs a key with read_write permission (a read key answers 403 read_write_permission_required).

MethodPathPermissionWhat it does
GET/api/v1/hotels/locations/searchReadTurn a city, an area or an airport typed by a user into coordinates for the geo search. Search locations
POST/api/v1/hotels/search_advancedReadGeo search: the hotels around a point (or one hotel by id), as mini cards with prices. Geo search
GET / POST/api/v1/hotels/name-search / /api/v1/hotels/search-by-nameReadFind a hotel by name. Hotel name search
POST/api/v1/hotels/search, /api/v1/hotels/detailsReadContent of up to 200 hotels by id, as mini cards or full documents. Mini and full hotel data
POST/api/v1/hotels/get_hotel_infoReadThe full content of one hotel for its page, and the content of a hotel FX-Port does not hold yet. Hotel details
POST/api/v1/hotels/get_ratesReadEvery room and rate of a hotel for a stay, with cancellation terms. Get hotel rates
POST/api/v1/hotels/pre_bookRead+WriteLock the rate you chose. Pre-book a rate
POST/api/v1/hotels/book_hotelRead+WriteBook the locked rate for the guests of each room. Book a hotel
GET/api/v1/bookings/{booking_id}?product=hotelsReadThe status of a booking, with its price and voucher links. Get a hotel booking
GET/api/v1/history?product=hotelsReadThe hotel bookings of your agency, newest first. Booking history
GET/api/v1/hotels/get_voucherReadThe links of the voucher PDFs. Get the hotel voucher
POST/api/v1/hotels/cancel_hotelRead+WriteCancel a confirmed booking. Cancel a hotel booking

The API reference has every field, parameter and error of each call.

The flow, step by step

  1. 1

    Find the place

    locations/search turns a typed city into latitude and longitude, the input of the geo search. name-search finds a hotel by name and gives its id.

  2. 2

    Geo search

    search_advanced is the geo search: send latitude, longitude and a radius (or a hotel_id) with the dates and the guests. It answers the mini cards in hotels_details and the price of each hotel in hotels_pricing. Join them by hotel id. Hotels that have a price but no card are in missing_hotel_ids: see Mini and full hotel data.

  3. 3

    Show the hotel and its rooms

    When the user opens a hotel, call get_hotel_info for its full page and get_rates for its rooms. Each rate has a bookHash and a cancellation schedule.

  4. 4

    Lock the rate

    pre_book with the bookHash re-checks the price with the supplier and answers a partnerOrderId: the id of the booking you are about to make.

  5. 5

    Book

    book_hotel with that id as booking_id, the guests of each room and the contact. It answers pending.

  6. 6

    Wait for the confirmation

    Poll GET /bookings/{booking_id}?product=hotels every 2 seconds until status is confirmed (4 to 14 seconds). FX-Port sends no webhooks.

  7. 7

    Voucher, or cancel

    get_voucher gives the voucher links. cancel_hotel cancels a confirmed booking.

What you carry from one call to the next:

FromYou keepYou send it to
locations/searchlatitude, longitudesearch_advanced (the geo search)
name-search, search_advancedthe hotel idhotel_id of get_rates and get_hotel_info
get_ratesrates[].bookHash (twin book_hash)book_hash of pre_book
pre_bookpartnerOrderId (twin booking_id)booking_id of book_hotel, get_voucher, cancel_hotel and the path of GET /bookings/{booking_id}

Before you start

Base URL and keyhttps://api.fx-port.com/api/v1. A key starting with fxp_test_ works on the sandbox and fxp_live_ on live: Authentication.
PermissionsSearches, content, rates, vouchers and booking reads need Read. pre_book, book_hotel and cancel_hotel need Read+Write.
NamesFields you send are snake_case (hotel_id, book_hash, booking_id). The older spellings (id, hash, partner_order_id, hotelId ...) still work and are answered with a warnings array. Answers keep their keys, mostly camelCase after get_rates, and add snake_case twins of the keys you feed back; ?naming=snake returns snake_case only. See Conventions.
CurrencyPrices come in the currency of your agency, resolved from your key. Never send currency: it is refused. See Hotel pricing.
MoneyThe traveler pays totalPrice; your agency is debited totalPrice - agencyCommission. There is no b2bPrice in the camelCase price blocks.
Stayscheckin and checkout as YYYY-MM-DD, 1 to 30 nights, check-in up to 400 days ahead. Guests and rooms: 9 rooms at most, one { adults, children } object per room.
ValuesA value written in another well-defined way is read, and the answer says so in warnings (coerced_value): a number as text, a date with a midnight time, GB-SCT as residency, a radius outside 100 to 70,000 meters. Only what cannot be read is refused. See Values the API reads for you.
Rate limitsPer key and per minute: 6,000 for searches, rates, content and reads (a booking, a voucher), 1,200 for pre_book, book_hotel and cancel_hotel. Searches also have a ceiling on the calls that run at the same time. Rate limits.
WebhooksNone. Poll the booking.
TimeA search around a point takes 4 to 20 seconds, get_rates 0.5 to 5, pre_book 4 to 5, book_hotel 3 to 6, cancel_hotel 1 to 4. A booking is confirmed 4 to 14 seconds after book_hotel.

Concepts

Sandbox testingThe test hotels, what happens with any other hotel, and a script that books and cancels.Mini and full hotel dataCompact cards for lists, the full document for the hotel page, and the hotels that have a price but no card yet.Guests and roomsSeveral rooms, adults, children and their ages, residency and guest names.Hotel pricingWhat each price field means and what your agency is debited.

Errors

Every failed call answers one body, whatever the endpoint: errors[] with a stable code, next to the older keys. Branch on the code: see Errors. The ones you meet in the hotel flow:

HTTPCodeWhat to do
400missing_field, invalid_date, stay_too_long, invalid_guests, invalid_residency ...The request is wrong. A missing required field is missing_field: errors[0].field names it (the current name) and errors[0].details.missing_fields lists all of them when several are missing. Read errors[0].field and message, fix it.
400invalid_statusThe booking is not confirmed: wait, or it is already cancelled.
400rate_not_foundThe rate expired or its price rose: call get_rates again.
403read_write_permission_requiredUse a Read+Write key.
404booking_not_found, pdf_not_foundNo such booking of your agency; or the voucher is not made yet (get_voucher): ask again in 2 seconds.
409hotel_not_bookable_in_sandboxSandbox: book test_hotel_do_not_book.
409duplicate_bookingThe booking exists. Do not call book_hotel again: read its status.
409cached_offer_requiredThe offer of pre_book was not found (older than one hour on live, or locked by another agency): pre_book again.
422supplier_rejected_requestThe supplier refused well formed dates, guests, residency or radius (search_advanced): change them.
429rate_limit_exceededWait for Retry-After, then back off.
502supplier_error, supplier_invalid_response, bad_gatewayThe supplier could not answer, or answered in a form that could not be used. Retry a read with backoff. For book_hotel and cancel_hotel, read the booking first.
503supplier_busy, service_overloadedThe supplier, or the service, is at capacity. The call was refused before anything was sent: nothing was searched, locked, booked or debited. Wait the seconds of Retry-After, then repeat the same call.
503supplier_unavailable, supplier_timeoutThe supplier could not be reached or did not answer. Retry a read with backoff. For cancel_hotel, read the booking first.

A 200 is not always a hotel: get_rates answers 200 with an empty rates when a hotel is unknown, closed, not available for the dates or not available for the residency, and search_advanced answers 200 with no_hotels_found. Check the content of a 200.

What is safe to repeat

CallSafe to repeat?
Locations, name search, search_advanced, content, get_rates, get_voucher, reading a bookingYes.
pre_bookYes: the same rate and the same price_increase_percent within a minute get the same answer.
book_hotelNo. A second call answers 409 duplicate_booking and does not reach the supplier. After a timeout or a 5xx (except 503 supplier_busy, which was refused before anything was sent), read GET /bookings/{booking_id}: if it exists, the booking was made.
cancel_hotelYes after a timeout: a second call settles it, also when the supplier had already cancelled. Once the cancellation is recorded, a further call answers 400 invalid_status.

Questions?

Email the FX-Port developer team at [email protected] for integration help, feature requests, or to report an API error. Quote the request_id of the failed call.

PreviousACD passport uploadsNext Sandbox testing

On this page

  • Endpoints
  • The flow, step by step
  • Before you start
  • Concepts
  • Errors
  • What is safe to repeat
  • Questions?

© 2026 FX-Port

TermsPrivacy[email protected]