Table of Contents

Create Voyage Booking

See Booking flow for the end-to-end lifecycle.

Endpoint: /bookings/create/voyage-only/{:sessionId}

METHOD: POST

Creates a held booking for the chosen voyage within an existing voyage-only search session. Reserves the selected cabin(s) and any vehicle slots requested at search time, and surfaces any mandatory addons that are automatically included.

Path Parameters

Name Type Required Description
sessionId string (UUID) Yes Session returned by /search/voyages. Must be voyage-only.

Query Parameters

Name Type Required Description
user_key string Yes Unique key associated with the calling agency.

Request Body

Field Type Required Description
departureDate string (date-time) Yes Voyage departure timestamp. Must match results[].departureDate from the originating search and be in the future.
cabinMix array of objects Yes One entry per cabin to reserve. Total guestIds across cabins must not exceed 9, must all be unique, and must each appear as a guest in the search.
cabinMix[].code string Yes Cabin grade code from the search response. Must be available on the selected voyage.
cabinMix[].guestIds array of numbers Yes Passenger IDs (from the search) assigned to this cabin. Must contain at least one passenger of type: "ADULT" or type: "SENIOR" and not exceed the grade's maximumOccupancy.

Example

Request

curl --location '{:apiBase}/bookings/create/voyage-only/{:sessionId}?user_key=abcdef' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer XXXXXXXX' \
--data '{
    "departureDate": "2026-05-11T18:15:00",
    "cabinMix": [
        {
            "code": "DECK",
            "guestIds": [1]
        }
    ]
}'

Response

{
    "vehicles": [
        {
            "type": "CAR",
            "guestId": 1
        }
    ],
    "addons": [
        {
            "code": "WIFI",
            "guests": [1],
            "isMandatory": true
        }
    ],
    "excursions": [],
    "supplementalTours": [],
    "priceBreakdown": {
        "totalPrice": 249.0,
        "cabins": [
            {
                "code": "DECK",
                "guests": [
                    {
                        "guestId": 1,
                        "price": 106.0
                    }
                ]
            }
        ],
        "addons": [
            {
                "code": "WIFI",
                "guests": [
                    {
                        "guestId": 1,
                        "price": 70
                    }
                ]
            }
        ],
        "excursions": [],
        "supplementalTours": [],
        "vehicles": [
            {
                "code": "CAR",
                "guest": {
                    "guestId": 1,
                    "price": 73.0
                }
            }
        ]
    },
    "sessionId": "f91c02b2-f22a-42c9-80b7-e3ef591ef0e0",
    "market": "US",
    "currency": "USD",
    "departureDate": "2026-05-11T18:15:00",
    "arrivalDate": "2026-05-12T10:55:00",
    "departurePort": "TOS",
    "arrivalPort": "HVG",
    "shipCode": "KH",
    "embarkationNotification": [
        {
            "locale": "en",
            "value": "Boarding opens 60 minutes before departure. Please be at the terminal in good time."
        },
        {
            "locale": "nb-NO",
            "value": "Ombordstigning åpner 60 minutter før avgang. Vær ved terminalen i god tid."
        }
    ],
    "guests": [
        {
            "id": 1,
            "type": "ADULT"
        }
    ],
    "cabins": [
        {
            "id": 1,
            "code": "DECK",
            "cabinType": "Inside",
            "cabinNumber": null,
            "guests": [
                1
            ]
        }
    ]
}

Fields

Field Type Description
sessionId string (UUID) The booking session this held booking belongs to.
market string Market the booking was created under.
currency string Currency the booking is priced in.
departureDate string (date-time) Voyage departure timestamp.
arrivalDate string (date-time) Voyage arrival timestamp.
departurePort string Departure port code.
arrivalPort string Arrival port code.
shipCode string Ship code (see /refdata/ships).
embarkationNotification array of objects Localized embarkation instruction for the departure port: [{ locale, value }]. null when none applies to this departure.
guests array of objects Passengers on the booking.
guests[].id number Passenger ID (matches the IDs used in cabinMix[].guestIds).
guests[].type string One of ADULT, CHILD, INFANT, SENIOR.
cabins array of objects Cabins reserved.
cabins[].id number Identifies this cabin on the booking. Send it as cabinId when choosing a cabin number.
cabins[].code string Cabin grade code.
cabins[].cabinType string Cabin type (e.g. Inside, Outside, Suite). Categorization above the per-ship cabin grade.
cabins[].cabinNumber string The specific cabin allocated, once one has been chosen via /cabin-numbers. null while the booking holds a guarantee cabin, where the cabin is assigned before departure.
cabins[].guests array of numbers Passenger IDs assigned to this cabin.
vehicles array of objects Vehicle slots reserved. Each vehicle is bound to a passenger; vehicles cannot be added to or removed from the booking after this point.
vehicles[].type string Vehicle category (CAR, MOTORCYCLE).
vehicles[].guestId number Passenger the vehicle is associated with.
addons array of objects Addons currently on the booking. Mandatory addons are auto-included here at create time and must not be re-applied.
addons[].code string Addon code (see /bookings/{:sessionId}/addons to discover available addons for the booking).
addons[].guests array of numbers Passenger IDs the addon applies to.
addons[].isMandatory boolean true for addons auto-included by Hurtigruten; these cannot be removed.
excursions array of objects Excursions currently on the booking. Always present; empty when nothing is applied.
excursions[].code string Excursion code (see /bookings/create/voyage-only/{:sessionId}/excursions).
excursions[].startDate string (date-time) Excursion start timestamp.
excursions[].endDate string (date-time) Excursion end timestamp.
excursions[].isMandatory boolean true when the excursion is bundled and cannot be individually removed. Currently always false on voyage-only bookings — non-removable excursions surface only on package bookings.
excursions[].guests array of numbers Passenger IDs the excursion applies to.
supplementalTours array of objects Supplemental tours (pre- or post-cruise extensions) currently on the booking. Always present; empty when nothing is applied.
supplementalTours[].code string Supplemental-tour code.
supplementalTours[].startDate string (date-time) Tour start timestamp.
supplementalTours[].endDate string (date-time) Tour end timestamp.
supplementalTours[].tourCategory string One of Arrival (pre-cruise) or Departure (post-cruise).
supplementalTours[].isMandatory boolean true when the tour cannot be removed.
supplementalTours[].guests array of numbers Passenger IDs the tour applies to.
supplementalTours[].tourStageSelectableRouteOverrides array of objects Per-stage route overrides chosen for the tour. Empty when no overrides apply.
supplementalTours[].tourStageSelectableRouteOverrides[].tourStageId number Tour-stage identifier.
supplementalTours[].tourStageSelectableRouteOverrides[].departureCode string Override departure port code.
supplementalTours[].tourStageSelectableRouteOverrides[].arrivalCode string Override arrival port code.
priceBreakdown object Price detail. Components sum to priceBreakdown.totalPrice.
priceBreakdown.totalPrice number Total price for the booking in the booking currency.
priceBreakdown.cabins array of objects Per-cabin pricing.
priceBreakdown.cabins[].code string Cabin grade code.
priceBreakdown.cabins[].guests array of objects Per-passenger price for this cabin.
priceBreakdown.cabins[].guests[].guestId number Passenger ID.
priceBreakdown.cabins[].guests[].price number Passenger's portion of the cabin price.
priceBreakdown.addons array of objects Per-addon pricing.
priceBreakdown.addons[].code string Addon code.
priceBreakdown.addons[].guests array of objects Per-passenger price for this addon.
priceBreakdown.addons[].guests[].guestId number Passenger ID.
priceBreakdown.addons[].guests[].price number Passenger's portion of the addon price.
priceBreakdown.excursions array of objects Per-excursion pricing.
priceBreakdown.excursions[].code string Excursion code.
priceBreakdown.excursions[].guests array of objects Per-passenger price for this excursion.
priceBreakdown.excursions[].guests[].guestId number Passenger ID.
priceBreakdown.excursions[].guests[].price number Passenger's portion of the excursion price.
priceBreakdown.supplementalTours array of objects Per-supplemental-tour pricing.
priceBreakdown.supplementalTours[].code string Supplemental-tour code.
priceBreakdown.supplementalTours[].guests array of objects Per-passenger price for this supplemental tour.
priceBreakdown.supplementalTours[].guests[].guestId number Passenger ID.
priceBreakdown.supplementalTours[].guests[].price number Passenger's portion of the supplemental-tour price.
priceBreakdown.vehicles array of objects Per-vehicle pricing.
priceBreakdown.vehicles[].code string Vehicle category.
priceBreakdown.vehicles[].guest.guestId number Passenger the vehicle is bound to.
priceBreakdown.vehicles[].guest.price number Vehicle price.

Errors

See Error model for response-body shapes across status codes.

Status Cause
400 user_key query parameter is missing; the request body fails validation (rules listed below); or the request references a voyage, cabin grade, or passenger that is not in the session.
404 The session does not exist or has expired.
409 A held booking already exists in this session (each session can hold one booking at a time; start a new search for another booking); or the session does not match this endpoint's booking type.

Validation rules. A 400 is returned when any of these rules are not met:

  • cabinMix must be non-empty.
  • Each cabin's code must be non-empty and guestIds must be non-empty, with every guestId > 0.
  • Total guestIds across all cabins must not exceed 9, and every guestId must be unique across the request.
  • departureDate must be in the future and must match a voyage's departure timestamp returned by the originating search.
  • Every guestId and every cabin code must come from the search response.
  • Each cabin's guestIds count must not exceed the cabin grade's maximumOccupancy, and at least one of those passengers must be of type: "ADULT" or type: "SENIOR".
  • Vehicles requested at search time must still be available on the selected voyage in the requested quantity.

Mandatory addons. If the booking includes mandatory addons (for example, on-board Wi-Fi), they appear in addons with isMandatory: true and are already priced into priceBreakdown.totalPrice. Do not call /bookings/{:sessionId}/addons for these — re-applying a mandatory addon is not supported.