Skip to content

Booking Details API

Authenticated endpoint for retrieving comprehensive booking details including offer, product, and passenger information.

The Booking Details API provides an admin-only endpoint for accessing complete booking information scoped to specific markets and languages.

Authentication: Requires active admin session (web middleware + auth) and admin role.

Base URL Pattern: /api/{market}/{lang}/bookings/{bookingReference}

GET /api/{market}/{lang}/bookings/{bookingReference}

Section titled “GET /api/{market}/{lang}/bookings/{bookingReference}”

Get complete booking details by reference code.

Parameters:

NameInTypeRequiredDescription
marketpathstringYesMarket code (case-insensitive)
langpathstringYesLanguage code (e.g., “en”, “es”, “ca”)
bookingReferencepathstringYesBooking reference code (e.g., “BK-ABC12345”)

Response: 200 OK

{
"data": {
"booking_reference": "BK-ABC12345",
"status": "confirmed",
"status_label": "Confirmed",
"total_amount": "2500.00",
"currency": "EUR",
"currency_symbol": "",
"booked_at": "2024-12-15T10:30:00+00:00",
"number_of_travelers": 2,
"market_code": "es",
"customer_service_phone": "+34 919 49 45 52",
"footer_copyright": "© BY VOLARE SL. Todos los derechos reservados",
"offer": {
"id": 123,
"sku": "ES-5CMB10-CA1-2024-01-15",
"departure_date": "2024-01-15",
"return_date": "2024-01-26",
"trip_days": 12,
"final_price": "1300.00",
"marketing_price_per_pax": "650.00",
"room_type": "double",
"room_type_label": "Double Room",
"departure_airport": {
"iata_code": "BCN",
"name": "Barcelona-El Prat Airport",
"city": "Barcelona"
}
},
"product": {
"id": 10,
"sku": "ES-5CMB10-CA1",
"title": "Tour de Sri Lanka",
"subtitle": "Descobreix l'illa maragda",
"short_description": "Una aventura increible...",
"highlights": ["Sigiriya", "Kandy", "Yala"],
"itinerary": [
{
"day": 1,
"date": "2024-01-15",
"title": "Arrival in Colombo",
"details": "Arrive, meet your host, private transfer to the hotel.",
"image_url": "https://cdn.example.com/itineraries/day1.jpg"
}
],
"hero_image": "https://cdn.example.com/images/sri-lanka.jpg",
"trip_duration_days": 10
},
"passengers": [
{
"id": 1,
"first_name": "John",
"last_name": "Doe",
"full_name": "John Doe",
"age_category": "adult",
"date_of_birth": "1985-03-15",
"is_lead_passenger": true,
"email": "john@example.com",
"phone": "+34612345678"
}
],
"hotels": [
{
"name": "Cinnamon Lodge Habarana",
"city": "Habarana",
"nights": 2,
"check_in": "2024-01-15",
"check_out": "2024-01-17",
"image_urls": ["https://cdn.example.com/hotels/cinnamon.jpg"],
"is_upgrade": false
}
],
"flights": {
"cabin_class": "ECONOMY",
"outbound": {
"date": "2024-01-15",
"departure_time": "10:30",
"arrival_time": "23:45",
"departure_airport": { "iata_code": "BCN", "city": "Barcelona" },
"arrival_airport": { "iata_code": "CMB", "city": "Colombo" },
"segments": [
{
"flight_number": "EK186",
"airline_code": "EK",
"airline_name": "Emirates",
"departure_airport": { "iata_code": "BCN", "city": "Barcelona" },
"arrival_airport": { "iata_code": "DXB", "city": "Dubai" },
"departure_time": "10:30",
"arrival_time": "20:15"
}
],
"stopovers": [
{ "airport": { "iata_code": "DXB", "city": "Dubai" }, "layover_minutes": 120 }
],
"total_duration_minutes": 795
},
"inbound": {
"date": "2024-01-25",
"departure_time": "01:30",
"arrival_time": "12:15",
"departure_airport": { "iata_code": "CMB", "city": "Colombo" },
"arrival_airport": { "iata_code": "BCN", "city": "Barcelona" },
"segments": [],
"stopovers": [],
"total_duration_minutes": 780
}
},
"experiences": [
{
"name": "Visita guiada a la roca de Sigiriya",
"city": "Sigiriya",
"date": "2024-01-16",
"image_url": "https://cdn.example.com/activities/sigiriya.jpg",
"tier": "included"
},
{
"name": "Safari en jeep por el Parque Nacional de Yala",
"city": "Yala",
"date": "2024-01-17",
"image_url": "https://cdn.example.com/activities/yala-safari.jpg",
"tier": "extra"
}
],
"optional_services": [
{
"name": "Traslado privado aeropuerto - hotel",
"description": "Vehículo privado con conductor desde el aeropuerto de Colombo hasta el hotel."
}
]
}
}
{
"message": "Unauthenticated."
}
{
"message": "Access denied. Admin role required."
}

Returned when booking does not exist, or does not belong to requested market/locale.

{
"success": false,
"error": "booking_not_found",
"message": "Booking with reference 'XYZ' not found."
}
{
"success": false,
"error": "language_not_supported",
"message": "Language 'de' is not supported by market 'ES'. Supported languages: es, ca"
}

The flights field is populated from multiple sources in priority order:

PrioritySourceCabin ClassWhen Used
1booking_upsells.flight_search_paramsBUSINESSCustomer upgraded to business class
2booking.flight_selectionECONOMYCustomer selected economy flight during checkout
3dynamic_flight_cache (itinerary_index=1)ECONOMYLegacy fallback for older bookings

The resource handles both enriched format (with nested airport objects containing iata_code and city) and legacy format (plain IATA code strings) for backward compatibility.

Each segment carries both airline_code (IATA code, e.g. EK) and airline_name (full carrier name, e.g. Emirates). airline_name falls back to the code when the full name is unavailable — older economy selections stored before names were captured, or business-upgrade legs whose search params carry no names. Cached economy legs resolve the name from the dynamic_flight_cache_segments.airline_name column.

offer.return_date (YYYY-MM-DD) and offer.trip_days (inclusive day count) are derived from the bound international flight via Offer::getTravelDates() — door-to-door, outbound departure day to return arrival-home day (same source as the booking emails). Both are null when no flight is bound (land-only / pre-flight); the frontend then falls back to the product.trip_duration_days land-tour estimate. product.trip_duration_days (itinerary nights + 1) remains unchanged and can under-report long-haul trips whose return leg spans an extra travel day.

In addition to the booking core fields, the response includes market-aware metadata used by the frontend:

FieldTypeDescription
market_codestringLowercased market code for frontend routing (defaults to es)
customer_service_phonestring | nullMarket customer-service phone number
footer_copyrightstring | nullFooter copyright text, resolved from CmsFooter via the market’s default locale

Each hotel stay groups consecutive nights at the same hotel.

FieldTypeDescription
namestringHotel name
citystring | nullPOI city name
nightsintNumber of nights
check_instringCheck-in date (YYYY-MM-DD)
check_outstringCheck-out date (YYYY-MM-DD)
image_urlsstring[]Full URLs for all hotel images (empty array when none)
is_upgradeboolWhether the stay is a selected hotel upgrade (luxury or grand-luxury tier). The highest purchased tier wins: grand-luxury takes precedence over luxury, which takes precedence over the base selection hotel

product.itinerary is a flat, per-day list — one entry per calendar day, sequential from the offer’s departure date. Each item: { day, date, title, details, image_url }. The tour’s stops (which can span multiple nights) are flattened into individual days: per-day text (title/details) comes from the localized translation, and image_url is resolved from the tour template’s per-day image (day_image), or null when the tour has no image for that day.

These arrays surface the activities and services for the booking:

  • experiences — the tour’s included activities plus the extra activity upsells the customer added at checkout. Each item: { name, city, date, image_url, tier } where tier is included or extra. Included activities are derived from the tour itinerary; extras come from activity upsells. The date is derived from the booking’s departure date plus the activity’s tour day (null when no day is recorded). Entries are ordered chronologically. (A future substitution tier is not yet emitted.)
  • optional_services — transfer upsells only (buildServicesData filters to BookingUpsellType::Transfer). Each item: { name, description }. Travel insurance upsells are intentionally not surfaced here; see Travel Insurance (Intermundial).

Activity and transfer names/descriptions are localized to the market’s default locale.

ComponentFile
Controllerbackend/app/Http/Controllers/Api/BookingController.php
Booking Resourcebackend/app/Http/Resources/BookingDetailsResource.php
Offer Resourcebackend/app/Http/Resources/OfferSummaryResource.php
Passenger Resourcebackend/app/Http/Resources/PassengerSummaryResource.php
Routebackend/routes/api.php (market-scoped routes)