Booking

The Book API books a departure of a package for your travellers. It checks the rooms, travellers, seats and price, blocks the seats, and returns a provisional booking with a booking code. TravClan later confirms the booking and assigns a final booking code.

Request Path Parameters

ParameterTypeRequiredDescription
codeStringYesPackage ID, the same code used for Package Details, e.g. fdljkyw.

Request Body Parameters

Send every field. Use [] when nothing was chosen.

ParameterTypeRequiredDescription
departure_codeStringYesdepartures[].code of the selected departure.
buyer_booking_referenceStringYesYour own unique reference for this booking. TravClan uses it to match the booking when sending the final booking code.
occupancyArray of ObjectsYesOne item per room. See occupancy[].
hotelsArray of StringsYeshotels[].code of every included hotel stay.
hotel_upgradesArray of ObjectsYesOne item per chosen hotel upgrade. See hotel_upgrades[].
sightseeingsArray of StringsYessightseeings[].sightseeing.code of the included activities.
sightseeing_addon_codesArray of StringsYesaddons[].code of each optional activity chosen.
transfersArray of StringsYestransfers[].transfer.code of the included transfers.
transfer_addon_codesArray of StringsYestransfers[].addons[].code of each transfer upgrade chosen.
flightsArray of StringsYesflights[].code of the included flights.
flight_origin_addon_codesArray of StringsYesflights[].outbound.origin_addons[].code of the start city chosen.
total_amountNumberYesThe total price you calculate room by room, including upgrades and add-ons. It must match the current price.
currencyStringYesdepartures[].currency of the selected departure, e.g. INR.

occupancy[]

Add one item per room. Every room needs at least one adult and must fit the departure's max_occupancy (DOUBLE = 2 people, TRIPLE = 3; one extra infant is allowed with 2 or more adults). Send the age of every child and infant.

ParameterTypeRequiredDescription
num_of_adultsIntegerYesAdults in the room.
child_with_bed_agesArray of IntegersYesAge of each child with a bed.
child_without_bed_agesArray of IntegersYesAge of each child without a bed.
infant_agesArray of IntegersYesAge of each infant.

hotel_upgrades[]

Add one item for each hotel stay the traveller upgrades. Keep the included stay's code in hotels as well.

ParameterTypeRequiredDescription
base_hotel.codeStringYesThe included stay being replaced, hotels[].code.
upgrade_hotel.codeStringYesThe upgrade chosen, hotels[].upgrades[].code.
🚧

Traveller details are not sent here

The Book API does not take traveller names or documents. Send them to your ACM (account manager) with the same buyer_booking_reference.

Sample Request

Two rooms with one add-on of each kind. The codes are placeholders; use the codes from the Package Details response.

curl --request POST 'https://holidays-volt-sandbox.travclan.com/api/v1/fixed-departure/listings/{code}/book' \
  --header 'Accept: application/json' \
  --header 'Content-Type: application/json' \
  --header 'x-api-key: Bearer <API_KEY>' \
  --data '{
  "departure_code": "fddxxxx",
  "buyer_booking_reference": "BUY-12345",
  "occupancy": [
    {
      "num_of_adults": 2,
      "child_with_bed_ages": [
        8
      ],
      "child_without_bed_ages": [],
      "infant_ages": []
    },
    {
      "num_of_adults": 1,
      "child_with_bed_ages": [],
      "child_without_bed_ages": [
        4
      ],
      "infant_ages": [
        1
      ]
    }
  ],
  "hotels": [
    "fhsstay1",
    "fhsstay2"
  ],
  "hotel_upgrades": [
    {
      "base_hotel": {
        "code": "fhsstay1"
      },
      "upgrade_hotel": {
        "code": "fhsupg1"
      }
    }
  ],
  "sightseeings": [
    "ssxxxx1",
    "ssxxxx2"
  ],
  "sightseeing_addon_codes": [
    "fsaxxxx"
  ],
  "transfers": [
    "fdtxxxx1",
    "fdtxxxx2"
  ],
  "transfer_addon_codes": [
    "ftaxxxx"
  ],
  "flights": [
    "flsxxxx1"
  ],
  "flight_origin_addon_codes": [
    "foaxxxx"
  ],
  "total_amount": 136500,
  "currency": "INR"
}'

What Book Checks

Before booking, the API checks the request. If any check fails, no booking is made and no seats are blocked.

CheckThe booking fails when
RoomsA room has no adult, or more people than max_occupancy allows.
Minimum adultsThe adults across all rooms are fewer than min_occupancy.
SeatsAdults and children need more seats than total_available. Infants do not take a seat.
Pricetotal_amount does not match the current price for these travellers and selections.

Response Body Structure

Root

KeyTypeDescription
statusInteger200 when the booking is made.
dataObjectThe booking. See data.

data

A 200 response means the seats are blocked and a provisional booking is created. Show "Booking received" with booking_code, your buyer_booking_reference, the trip dates and booking_amount. status is CONFIRMED (the booking is accepted) and internal_booking_status is PENDING until TravClan confirms the booking.

KeyTypeDescription
booking_codeStringProvisional booking ID. Different from the final booking code assigned when TravClan confirms the booking.
listing_codeStringPackage ID.
departure_codeStringDeparture booked.
buyer_booking_referenceStringYour reference, as sent.
travel_start_dateString (YYYY-MM-DD)First day of travel.
travel_end_dateString (YYYY-MM-DD)Last day of travel.
booking_amountNumberAmount booked, in currency.
currencyStringCurrency, e.g. INR.
statusStringCONFIRMED means the booking was accepted and the seats are blocked.
internal_booking_statusStringPENDING until TravClan confirms the booking.
bms_booking_codeString or nullBooking code in Volt's booking system, once created.
booking_remarkStringRemark on the booking.
request_bodyObjectThe request as stored. See data.request_body.
total_availableIntegerSeats left on the departure after this booking.
listingObjectThe package booked, with the same keys as data in the Package Details API.

Sample Response

{
  "status": 200,
  "data": {
    "booking_code": "fdbjkzn",
    "listing_code": "fdljkkv",
    "departure_code": "fddjky3",
    "buyer_booking_reference": "BUY-12345",
    "travel_start_date": "2026-11-07",
    "travel_end_date": "2026-11-11",
    "booking_amount": 195000,
    "currency": "INR",
    "status": "CONFIRMED",
    "internal_booking_status": "PENDING",
    "bms_booking_code": null,
    "booking_remark": "",
    "request_body": {
      "hotels": [
        "fhsjkkv"
      ],
      "flights": [
        "flsjkkv"
      ],
      "currency": "INR",
      "occupancy": [
        {
          "infant_ages": [],
          "num_of_adults": 2,
          "child_with_bed_ages": [
            8
          ],
          "child_without_bed_ages": []
        },
        {
          "infant_ages": [
            1
          ],
          "num_of_adults": 1,
          "child_with_bed_ages": [],
          "child_without_bed_ages": [
            4
          ]
        }
      ],
      "transfers": [
        "fdtjkkv",
        "fdtjkyi"
      ],
      "sightseeings": [
        "ssgjza1",
        "ssgjzai",
        "ssgjzja",
        "ssgjzjh"
      ],
      "total_amount": 195000,
      "departure_code": "fddjky3",
      "hotel_upgrades": [],
      "domesticChannelId": "travclan-demo-channel",
      "transfer_addon_codes": [],
      "internationalChannelId": "travclan-demo-channel",
      "isHolidaysVoltMerchant": true,
      "buyer_booking_reference": "BUY-12345",
      "sightseeing_addon_codes": [],
      "flight_origin_addon_codes": []
    },
    "total_available": 3,
    "listing": {
      "title": "5N Singapore Getaway | Ex-DEL",
      "code": "fdljkkv",
      "destination_code": "desjkyf",
      "destination_name": "Singapore",
      "description": "<p>Discover the best of…",
      "nights_count": 5,
      "rooms_count": 1,
      "min_pax": 1,
      "star_category": 4,
      "payment_policy": "<p>30% payment at the tim…",
      "cancellation_policy": "<div class=\"min-w-0 lg:…",
      "inclusions": "<ul class=\"space-y-2.5\">…",
      "exclusions": "<ul class=\"space-y-2.5\">…",
      "marketing_prices": {
        "adult": {
          "hotel": 13541.11,
          "flight": 25179.05,
          "land": 7936.51
        },
        "child_with_bed": {
          "hotel": 10155.83,
          "flight": 18884.29,
          "land": 5952.38
        },
        "child_without_bed": {
          "hotel": 8463.19,
          "flight": 15736.9,
          "land": 4960.32
        },
        "infant": {
          "hotel": 1692.64,
          "flight": 3147.38,
          "land": 992.06
        }
      },
      "images": [
        {
          "url": "https://…/singapore-gateway.jpg",
          "is_hero": true
        }
      ],
      "tags": [
        {
          "code": "tgjkkv",
          "name": "Family Friendly"
        }
      ],
      "departures": [
        {
          "code": "fddjky3",
          "source": "TRAVCLAN",
          "travel_start_date": "2026-11-07",
          "travel_end_date": "2026-11-11",
          "booking_start_date": "2026-08-12",
          "booking_end_date": "2026-10-31",
          "total_inventory": 100,
          "total_available": 3,
          "total_booked": 97,
          "adult_price": 40000,
          "infant_price": 5000,
          "child_price_with_bed": 30000,
          "child_price_without_bed": 25000,
          "single_adult_price": 55000,
          "currency": "INR",
          "max_age_child_with_bed": 9,
          "max_age_child_without_bed": 9,
          "max_age_infant": 2,
          "min_occupancy": "DOUBLE",
          "max_occupancy": "TRIPLE"
        }
      ],
      "hotels": [
        {
          "code": "fhsjkkv",
          "hotel": {
            "code": "htjrhf",
            "name": "Holiday Inn Singapore A…",
            "area_code": "arjkrw",
            "area_name": "Singapore",
            "providerReferenceId": 39648221
          },
          "meal_type": "BEDANDBREAKFAST",
          "day_of_trip": 1,
          "rooms": [
            {
              "rooms": [
                {
                  "code": "rmjgqt",
                  "name": "Standard Room",
                  "meal_type": "BEDANDBREAKFAST",
                  "nights_count": 5,
                  "data_source": 1
                }
              ]
            }
          ],
          "proofs": [
            {
              "image_url": "https://…/inn.png",
              "b2b_price": 400,
              "b2c_price": 600,
              "source": "MAKEMYTRIP",
              "remarks": "Hotel Price Comparison"
            }
          ],
          "addons": [
            {
              "code": "fhajkkv",
              "type": "ROOM",
              "description": "Single sofa cum bed",
              "adult_price": 400,
              "infant_price": 100,
              "child_price_with_bed": 200,
              "child_price_without_bed": 150
            }
          ],
          "upgrades": [
            {
              "code": "fhsjkkm",
              "hotel": {
                "code": "htjyuy",
                "name": "One Farrer Hotel",
                "area_code": "arjkrw",
                "area_name": "Singapore",
                "providerReferenceId": 39684174,
                "additional_details": {
                  "images": [],
                  "description": "",
                  "yt_videos": [],
                  "reviews": null,
                  "hero_image": "https://…/47f1880.jpg"
                }
              },
              "meal_type": "BEDANDBREAKFAST",
              "day_of_trip": 1,
              "rooms": [],
              "proofs": [],
              "addons": [],
              "upgrade_adult_price": 500,
              "upgrade_single_adult_price": 500,
              "upgrade_infant_price": 100,
              "upgrade_child_price_with_bed": 200,
              "upgrade_child_price_without_bed": 100
            }
          ]
        }
      ],
      "sightseeings": [
        {
          "sightseeing": {
            "name": "Gardens by the Bay (New…",
            "description": "",
            "code": "ssgjzja",
            "isPopular": false,
            "duration": null,
            "tags": [],
            "coordinates": [],
            "images": [
              {
                "isHero": true,
                "url": "https://…/picture-9.png"
              }
            ],
            "reviews": null
          },
          "type": "SIC",
          "day_of_trip": 1
        }
      ],
      "addons": [
        {
          "code": "fsajkk7",
          "sightseeing": {
            "name": "Marina Bay Sands SkyPar…",
            "description": null,
            "code": "ssgj0z8",
            "isPopular": false,
            "duration": null,
            "tags": [],
            "coordinates": [],
            "images": [],
            "reviews": null
          },
          "type": "PRIVATE",
          "day_of_trip": 1,
          "adult_price": 50,
          "child_price": 40,
          "infant_price": 20
        }
      ],
      "transfers": [
        {
          "transfer": {
            "code": "fdtjkkv",
            "origin": "HAN",
            "origin_type": "AIRPORT",
            "destination": "arjkr6",
            "destination_type": "AREA",
            "transfer_type": "PRIVATE",
            "occupancy": 4,
            "min_pax": 2,
            "unit": "PER_CAB",
            "routes": [
              {
                "origin": "HAN",
                "origin_type": "AIRPORT",
                "destination": "arjkr6",
                "destination_type": "AREA",
                "description": "Transfer from HAN Airp…",
                "transfer_mode": {
                  "code": "ftmjkkm",
                  "name": "4 seater Car",
                  "type": "CAR",
                  "occupancy": 4
                }
              }
            ]
          },
          "addons": []
        }
      ],
      "flights": [
        {
          "code": "flsjkkv",
          "is_primary": true,
          "day_of_trip": 1,
          "origin": "Delhi",
          "destination": "Singapore",
          "journey_type": "ROUND_TRIP",
          "outbound": {
            "origin": "HKT",
            "destination": "BLR",
            "is_refundable": false,
            "stop_count": 0,
            "fare_class": "PUBLISHED",
            "segments": [
              {
                "baggage": {
                  "check_in": {
                    "value": 25,
                    "unit": "KG"
                  },
                  "cabin": {
                    "value": 7,
                    "unit": "KG"
                  }
                },
                "cabin_class": "ECONOMY",
                "airline": {
                  "airline_code": "QP",
                  "airline_name": "Akasa Air",
                  "flight_number": "QP624",
                  "fare_class": "PUBLISHED",
                  "fare_basis": "PUBLISHED"
                },
                "origin": {
                  "airport_code": "HKT",
                  "airport_name": "Phuket Internat…",
                  "terminal_number": "2",
                  "city_code": "HKT",
                  "city_name": "Phuket",
                  "country_name": "Thailand",
                  "timezone": "Asia/Bangkok",
                  "departure_time": "17:00:00"
                },
                "destination": {
                  "airport_code": "BLR",
                  "airport_name": "Kempegowda Inte…",
                  "terminal_number": "2",
                  "city_code": "BLR",
                  "city_name": "Bangalore",
                  "country_name": "India",
                  "timezone": "Asia/Kolkata",
                  "arrival_time": "19:20:00"
                },
                "duration": 260,
                "total_duration": 260,
                "ground_time": 0,
                "stop_over": false,
                "stop_over_point": "",
                "stop_over_duration": 0
              }
            ],
            "origin_addons": []
          },
          "inbound": {
            "origin": "Phuket",
            "destination": "Bombay",
            "is_refundable": false,
            "stop_count": 0,
            "fare_class": "Economy",
            "segments": [],
            "origin_addons": []
          },
          "proofs": [
            {
              "image_url": "https://…/qw.png",
              "b2b_price": 400,
              "b2c_price": 600,
              "source": "MAKEMYTRIP",
              "remarks": "Flight Comparison"
            }
          ]
        }
      ],
      "additional_details": {
        "images": [],
        "description": "",
        "yt_videos": [],
        "reviews": null,
        "hero_image": "https://…/singapore-1.png"
      }
    }
  }
}

Errors

StatusWhen
400Invalid body, occupancy, components, inventory or currency.
401Missing or invalid API key.
404Listing not found, or not bookable for your organisation.
409Prices have changed: total_amount does not match the current price.
500Unexpected error.

How to use: On a 409, data.expected_amount is the current price. Read the package again with the Package Details API, recalculate the total, and show the new price to the traveller before booking again.

{
  "status": 409,
  "message": "Prices have changed",
  "data": {
    "requested_amount": 80000.0,
    "expected_amount": 85000.0,
    "difference": 5000.0,
    "currency": "INR"
  }
}
{
  "success": false,
  "code": 401,
  "message": "Unauthorized"
}

API Reference

https://volt-docs.travclan.com/reference/bookdeparture


Did this page help you?