Table of Contents

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 every Rate_* value (see the Currency field), 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 omit market entirely.

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 /voyages once per day, shortly after 07:00 CEST, and replace your local copy wholesale.
  • Fetch /ships and /ports far less often — they are static reference data that changes rarely (a new ship, a renamed port). Refreshing weekly, or whenever you see an unknown ShipCode / 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:

  1. Ship — look up ShipCode "FN" in /ships where shipId == "FN"MS Fridtjof Nansen, with specs, deck plans and gallery.
  2. Cabin grade — for the priced category "I2", find the cabinGrades[] entry with code == "I2" inside that ship's cabinCategories[] → title, size, amenities, images.
  3. Ports — resolve "USOME" and "CAVAN" in /ports → display names and countries for the embarkation/debarkation ports.
  4. PricingRate_Dbl is the per-guest rate when two share the cabin; Rate_Sgl is the price for a single traveller occupying it alone (null if not offered). Both are in Currency (GBP here). 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.