Flat files V3
Flat files V3 serves HX's product catalogue — bookable voyages with live availability and pricing, plus rich ship and port reference data — as plain JSON over three simple GET endpoints. It is the easiest way to keep a local, queryable copy of HX inventory in sync without orchestrating the full booking flow.
It sits on the same host and behind the same Auth0 authentication as the Seaware API (SwOTA), but instead of posting OTA XML messages you simply GET a path and receive a JSON array.
Note
The voyages file is a daily snapshot of availability and pricing — see Regeneration schedule. For real-time pricing, holds, and bookings, use the Seaware API (SwOTA).
What you get
| Endpoint | File | Contents | Nature |
|---|---|---|---|
/voyages |
Voyages | Available sailings with day-by-day itinerary, cabin grades, and per-occupancy pricing for a market | Dynamic — regenerated daily |
/ships |
Ships | Ship specifications, deck plans, cabin categories and grades, marketing copy | Static reference |
/ports |
Ports | Lookup of port/location codes → country + display name | Static reference |
voyages is the spine: it carries availability, pricing and the codes (ShipCode, Category, DeparturePort, ArrivalPort) that you resolve against the two static reference files. See Tying the data together.
Environment
Production:
https://bookings.sw.travelhx.com
The voyages and ships files are scoped to a market (see The market parameter). The markets available to you depend on your partner agreement.
Credentials
To start using the API, contact our support team via the support portal to have your credentials created. You will receive:
- client_id and client_secret — for Auth0 authentication.
These are the same credentials used for the Seaware API (SwOTA); if you are already integrated with Seaware you can reuse them here.
Authentication
Authentication is identical to the Seaware API: request an Auth0 bearer token with the client_credentials grant, then send it as a Bearer token on every request.
Token endpoint: https://partner-travelhx.eu.auth0.com/oauth/token
Audience: https://partner.travelhx.com/api
curl --request POST \
--url https://partner-travelhx.eu.auth0.com/oauth/token \
--header 'content-type: application/json' \
--data '{
"client_id": "YOUR_CLIENT_ID",
"client_secret": "YOUR_CLIENT_SECRET",
"audience": "https://partner.travelhx.com/api",
"grant_type": "client_credentials"
}'
Response:
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"scope": "application:Partner.WebApi",
"expires_in": 86400,
"token_type": "Bearer"
}
Note
The token is valid for the number of seconds in expires_in. Cache it and reuse it until it is close to expiry rather than requesting a new token per call.
You then attach the token to every request:
curl --location 'https://bookings.sw.travelhx.com/voyages?market=GB' \
--header 'Authorization: Bearer YOUR_ACCESS_TOKEN'
Endpoints
All endpoints are GET and return a JSON array (the response body is the array itself — there is no paging envelope). The full set is returned in a single response.
| Method | Path | market |
Description |
|---|---|---|---|
GET |
/voyages |
Required | Available sailings, itineraries, cabin grades and pricing for the market. |
GET |
/ships |
Required | Ship reference data; market selects the content language. |
GET |
/ports |
Optional | Port/location lookup. Global data — market has no effect. |
Field-level reference for each file:
The market parameter
market is a market code (for example GB) that selects which catalogue you see:
/voyages— required. It determines the currency of everyRate_*value (see theCurrencyfield), the availability and pricing on offer./ships— required. It selects the language of the marketing copy (body, cabin descriptions). The structural data (specs, codes, deck plans) is the same across markets./ports— optional and has no effect; the port lookup is global. You may omitmarketentirely.
Supported markets
market must be one of the codes below. Each market returns its prices in the currency shown. The markets available to you depend on your partner agreement.
| Market | Code | Currency |
|---|---|---|
| United Kingdom | GB |
GBP |
| United States | US |
USD |
| Canada | CA |
CAD |
| Germany | DE |
EUR |
| France | FR |
EUR |
| Switzerland | CH |
CHF |
| Denmark | DK |
DKK |
| Sweden | SE |
SEK |
| Norway | NO |
NOK |
| Australia | AU |
AUD |
# Voyages for the GB market (prices in that market's currency)
curl --location 'https://bookings.sw.travelhx.com/voyages?market=GB' \
--header 'Authorization: Bearer YOUR_ACCESS_TOKEN'
# Ships for the GB market (English copy)
curl --location 'https://bookings.sw.travelhx.com/ships?market=GB' \
--header 'Authorization: Bearer YOUR_ACCESS_TOKEN'
# Ports — global, no market needed
curl --location 'https://bookings.sw.travelhx.com/ports' \
--header 'Authorization: Bearer YOUR_ACCESS_TOKEN'
Regeneration schedule
The voyages file is regenerated daily at 07:00 CEST. Each generation refreshes the latest availability, pricing, and descriptive content.
Recommended cadence:
- Fetch
/voyagesonce per day, shortly after 07:00 CEST, and replace your local copy wholesale. - Fetch
/shipsand/portsfar less often — they are static reference data that changes rarely (a new ship, a renamed port). Refreshing weekly, or whenever you see an unknownShipCode/ port code in voyages, is sufficient.
Important
The voyages snapshot reflects availability and pricing at generation time. Cabin counts and fares can move during the day. Always confirm price and availability with a real-time quote against the Seaware API (SwOTA) before taking payment.
Tying the data together
voyages is the central file. Every voyage carries codes that resolve against the static reference files.
flowchart LR
subgraph daily["Daily snapshot · 07:00 CEST"]
V["<b>/voyages</b><br/>availability · pricing · itinerary"]
end
subgraph ref["Static reference"]
S["<b>/ships</b><br/>specs · cabin grades · decks"]
P["<b>/ports</b><br/>code → country · name"]
end
V -- "ShipCode → shipId" --> S
V -- "categories[].Category → cabinGrades[].code" --> S
V -- "DeparturePort · ArrivalPort → code" --> P
style V fill:#e8f4f8,stroke:#2196F3,stroke-width:2px,color:#000
style S fill:#fff3e0,stroke:#FF9800,color:#000
style P fill:#fff3e0,stroke:#FF9800,color:#000
Join keys
| From (voyages) | To | Meaning |
|---|---|---|
ShipCode |
ships[].shipId |
Which ship operates the sailing (FN, FR, RA, SP, SC). |
categories[].Category |
ships[].cabinCategories[].cabinGrades[].code |
Resolves a priced cabin grade to its full description, size, and amenities. |
DeparturePort, ArrivalPort |
ports[].code |
Resolves embarkation/debarkation port codes to country + name. |
Warning
itinerary[].location is free-text day copy (e.g. "Germany to Quito"), not a port code. Only DeparturePort and ArrivalPort join to the ports file. Do not attempt to resolve itinerary[].location against /ports.
Worked example
A voyage from /voyages?market=GB:
{
"VoyageID": "_@FNALA04-260906",
"DepartureDate": "2026-09-06",
"ArrivalDate": "2026-09-23",
"EmbarkationTime": "2026-09-07T22:00:00",
"DisembarkationTime": "2026-09-23T08:00:00",
"DeparturePort": "USOME",
"ArrivalPort": "CAVAN",
"ShipCode": "FN",
"Name": "Alaska & British Columbia | Inside Passage, Bears and Aleutian Islands | Southbound",
"Description": "18-day all-inclusive Alaska expedition cruise from Seattle to Vancouver",
"Map": "https://images.eu.ctfassets.net/.../FNALA2703_FNALA2608_UK.png",
"Region": "ALASKA",
"Currency": "GBP",
"itinerary": [ /* day-by-day narrative */ ],
"categories": [
{ "Category": "I2", "MaxOccupancy": 2, "Rate_Sgl": "17416.51", "Rate_Dbl": "10244.75", "RateCode": "BESTPRICE" }
]
}
To present this voyage fully:
- Ship — look up
ShipCode"FN"in/shipswhereshipId == "FN"→ MS Fridtjof Nansen, with specs, deck plans and gallery. - Cabin grade — for the priced category
"I2", find thecabinGrades[]entry withcode == "I2"inside that ship'scabinCategories[]→ title, size, amenities, images. - Ports — resolve
"USOME"and"CAVAN"in/ports→ display names and countries for the embarkation/debarkation ports. - Pricing —
Rate_Dblis the per-guest rate when two share the cabin;Rate_Sglis the price for a single traveller occupying it alone (nullif not offered). Both are inCurrency(GBPhere). Confirm with a live quote before payment.
Errors
| Status | Cause | Fix |
|---|---|---|
401 Unauthorized |
Missing, malformed or expired bearer token. | Request a fresh token; ensure the Authorization: Bearer <token> header is present and the audience is correct. |
403 Forbidden |
Token valid but your account is not entitled to the requested market. |
Confirm with your integration manager which markets your agreement covers. |
400 Bad Request |
market missing on /voyages or /ships, or an unknown market code. |
Supply a valid market query parameter. |