Change summary for frontend migration:
docs/frontend-api-change-impact.md
This document lists the APIs required by frontend for:
POST/v1/location/check-cities-by-nameRequest
{
"cityNames": ["Gangtok", "Darjeeling", "Pelling"]
}
Response
{
"message": "SUC_CITY_NAME_CHECKED",
"data": {
"Gangtok": { "id": 101, "name": "Gangtok", "stateName": "Sikkim" },
"Darjeeling": {
"id": 102,
"name": "Darjeeling",
"stateName": "West Bengal"
}
}
}
GET/v1/location/cities/search?name=<text>Response
{
"message": "SUC_CITIES_FETCHED",
"data": [
{ "id": 101, "name": "Gangtok", "state": { "id": 11, "name": "Sikkim" } }
]
}
GET/v1/location/states/search?name=<text>Response
{
"message": "SUC_STATES_FETCHED",
"data": [{ "id": 11, "name": "Sikkim" }]
}
POST/v1/location/cityRequest
{
"name": "Lachung",
"stateId": 11,
"latitude": 27.6892,
"longitude": 88.742
}
Response
{
"message": "SUC_CITY_CREATED",
"data": {
"id": 501,
"name": "Lachung",
"stateId": 11,
"countryId": 1,
"latitude": 27.6892,
"longitude": 88.742
}
}
POST/v1/hotel/check-inventorypriorityHotelNames within category + locationRequest
{
"items": [
{
"category": "standard",
"locationId": 101,
"priorityHotelNames": ["Maple Residency", "Delight The Fortuna"]
},
{
"category": "premium",
"locationId": 101
}
]
}
Response
{
"message": "SUC_HOTEL_INVENTORY_CHECKED",
"data": [
{
"inputIndex": 0,
"matched": true,
"matchType": "priority_name",
"hotel": {
"id": 9001,
"name": "Maple Residency",
"cityId": 101,
"category": "standard",
"address": "MG Road",
"description": "Sample standard hotel",
"starRating": 4,
"checkInTime": "14:00:00",
"checkOutTime": "11:00:00",
"roomType": "Suite"
},
"hotels": [
{
"id": 9001,
"name": "Maple Residency",
"cityId": 101,
"category": "standard",
"address": "MG Road",
"description": "Sample standard hotel",
"starRating": 4,
"checkInTime": "14:00:00",
"checkOutTime": "11:00:00",
"roomType": "Suite"
},
{
"id": 9003,
"name": "Delight The Fortuna",
"cityId": 101,
"category": "standard",
"address": "Central Avenue",
"description": "Sample standard hotel",
"starRating": 4,
"checkInTime": "13:00:00",
"checkOutTime": "10:00:00",
"roomType": "Deluxe"
}
]
},
{
"inputIndex": 1,
"matched": true,
"matchType": "fallback_category_location",
"hotel": {
"id": 9007,
"name": "Lemon Tree",
"cityId": 101,
"category": "premium",
"address": "Hill View",
"description": "Sample premium hotel",
"starRating": 5,
"checkInTime": "14:00:00",
"checkOutTime": "11:00:00",
"roomType": "Suite"
},
"hotels": [
{
"id": 9007,
"name": "Lemon Tree",
"cityId": 101,
"category": "premium",
"address": "Hill View",
"description": "Sample premium hotel",
"starRating": 5,
"checkInTime": "14:00:00",
"checkOutTime": "11:00:00",
"roomType": "Suite"
}
]
}
]
}
GET/v1/hotel/search-inventory?name=<text>&category=<category>&locationId=<id>Response
{
"message": "SUC_HOTELS_FETCHED",
"data": [
{
"id": 9001,
"name": "Maple Residency",
"cityId": 101,
"category": "standard",
"address": "MG Road",
"description": "Sample standard hotel",
"starRating": 4,
"checkInTime": "14:00:00",
"checkOutTime": "11:00:00",
"roomType": "Suite"
}
]
}
POST/v1/hotel/inventorymultipart/form-dataRequest
{
"name": "Delight The Fortuna",
"cityId": 101,
"category": "standard",
"address": "MG Road, Gangtok",
"description": "Comfort stay near city center",
"starRating": 4.5,
"checkInTime": "14:00:00",
"checkOutTime": "11:00:00",
"roomType": 4,
"mediaLinks": [
"https://cdn.example.com/hotels/delight-1.jpg",
"https://cdn.example.com/hotels/delight-2.jpg"
]
}
Required fields:
namecityIdcategoryOptional fields:
addressdescriptionstarRatingcheckInTimecheckOutTimeroomTypemediaLinks (array of image/video URLs to map as hotel media)mediaFile[] (bulk photo upload files; backend uploads to storage and stores generated file names in hotel.hotel_media.file_name)Response
{
"message": "SUC_HOTEL_CREATED",
"data": {
"id": 9010,
"name": "Delight The Fortuna",
"cityId": 101,
"category": "standard",
"address": "MG Road, Gangtok",
"description": null,
"starRating": null,
"checkInTime": null,
"checkOutTime": null,
"roomType": null,
"media": [
{
"id": 30001,
"fileType": 1,
"link": "https://cdn.example.com/hotels/delight-1.jpg"
}
]
}
}
POST/v1/transfer/check-by-nameRequest
{
"items": [{ "name": "Wagon R / Similar" }, { "name": "Innova / Similar" }]
}
Response
{
"message": "SUC_TRANSFER_CHECKED",
"data": [
{
"requestedName": "Wagon R / Similar",
"matched": true,
"transfer": {
"id": 3001,
"vehicleName": "Wagon R / Similar",
"vehicleType": "Car",
"seater": 3,
"description": "Airport and local transfers",
"notes": "Night surcharge excluded",
"isActive": true,
"createdAt": "2026-03-20T10:10:10.000Z",
"updatedAt": "2026-03-20T10:10:10.000Z"
}
},
{
"requestedName": "Innova / Similar",
"matched": false,
"transfer": null
}
]
}
GET/v1/transfer/search?name=<text>Response
{
"message": "SUC_TRANSFERS_FETCHED",
"data": [
{
"id": 3002,
"vehicleName": "Innova / Xylo / Similar",
"vehicleType": "Car",
"seater": 6,
"description": "Airport and local transfers",
"notes": "Night surcharge excluded",
"isActive": true,
"createdAt": "2026-03-20T10:10:10.000Z",
"updatedAt": "2026-03-20T10:10:10.000Z"
}
]
}
POST/v1/transfer/inventorymultipart/form-dataRequest
{
"vehicleType": "Car",
"vehicleName": "Innova / Xylo / Similar",
"seater": 6,
"description": "Airport and local transfers",
"notes": "Night surcharge excluded"
}
Required fields:
vehicleTypevehicleNameOptional fields:
seaterdescriptionnotesmediaFile[] (bulk photo upload files; backend uploads to storage and stores generated file names in transfer.transfer_media.file_name)Response
{
"message": "SUC_TRANSFER_CREATED",
"data": {
"id": 3010,
"vehicleName": "Innova / Xylo / Similar",
"vehicleType": "Car",
"seater": 6,
"description": "Airport and local transfers",
"notes": null,
"isActive": true,
"media": [
{
"id": 40001,
"fileType": 1,
"link": "https://cdn.example.com/transfers/innova-1.jpg"
}
],
"createdAt": "2026-03-20T10:10:10.000Z",
"updatedAt": "2026-03-20T10:10:10.000Z"
}
}
POST/v1/activitymultipart/form-dataNotes:
mediaFile[] upload.activity.activity_media.file_name.POST/v1/itinerary/import-itinerary-fullRequest (shape)
{
"itinerary": { "...": "CreateItineraryDto" },
"transferIds": [3010, 3011],
"hotelIds": [901, 905],
"hotelDayMappings": [
{ "hotelId": 901, "dayOrder": 1 },
{ "hotelId": 905, "dayOrder": 2 }
],
"activities": [
{
"dayOrder": 1,
"title": "Gangtok local sightseeing",
"startTime": "2026-03-20 10:00:00",
"duration": 120,
"description": "MG Road and nearby viewpoints"
},
{
"dayOrder": 2,
"title": "Tsomgo Lake excursion",
"startTime": "2026-03-21 09:30:00"
}
],
"bundlePricing": [
{
"category": "standard",
"plan": "CP",
"extraBedPrice": 4050,
"childWithoutBedPrice": 2100,
"dinnerSupplementPrice": 1950,
"vehiclePricing": [
{
"transferId": 3001,
"capacityMin": 1,
"capacityMax": 3,
"pricePerPerson": 15100
},
{
"transferId": 3002,
"capacityMin": 1,
"capacityMax": 3,
"pricePerPerson": 18400
},
{
"transferId": 3002,
"capacityMin": 4,
"capacityMax": 6,
"pricePerPerson": 12350
}
]
}
]
}
Notes:
hotelIds and transferIds must be existing inventory IDs.activities are created first, then mapped day-wise using dayOrder.activities[].startTime is mandatory.activities[].duration is optional (minutes).hotelIds are mapped itinerary-wise by category + location.hotelDayMappings controls explicit day-wise hotel mapping.hotelDayMappings is omitted, backend falls back to location-based day mapping (maps hotel to all matching city/location days) for backward compatibility.transferIds are mapped itinerary-wise only.check-by-name / search / inventory) to fetch full transfer objects and pick IDs for import payload.vehiclePricing[].transferId is required for bundle pricing rows.vehiclePricing is preferred over capacityPricing.capacityPricing is kept as a backward-compatible fallback shape.Response
{
"message": "SUC_ITN_IMPORTED",
"data": {
"id": 948,
"name": "THE LAST SHANGRI-LA"
}
}
GET /v1/location/cities?search=<text>GET /v1/location/states?search=<text>POST /v1/hotel (full create)POST /v1/transfer (full create)For import-preview UX, prefer the new lightweight check/search endpoints documented above.
tripType, hotel category, and bundle pricing category all use HotelCategoryEnum values: 1=LUXURY, 2=PREMIUM, 3=SUPER_DELUXE, 4=DELUXE, 5=STANDARD.BASIC trip-type behavior is treated as STANDARD in compatibility handling.hotel_transfer and hotel_only, availableCategories in the price-details response always returns all five values [1,2,3,4,5]. Use categoryPerPersonPrices to find which categories have pricing rows.hotel_transfer: selected/default category hotel bundle + primary transfer vehicle slab.hotel_only: selected/default category hotel bundle.transfer_only: primary transfer pricing slabs.activities_only: adultPrice by default.Validation runs only when publishing (not unpublishing). Checked in validatePublishReadiness() (src/modules/itinerary/utils/publish-validation.util.ts).
hotel_transfer (has both hotels and transfers):tripType / effective category must be set (ERR_ITN_PUBLISH_CATEGORY_REQUIRED)ERR_ITN_PUBLISH_HOTEL_PRICING_MISSING)ERR_ITN_PUBLISH_HOTEL_MAPPING_MISSING_FOR_PRICED_CATEGORY)ERR_ITN_PUBLISH_PRIMARY_TRANSFER_REQUIRED)ERR_ITN_PUBLISH_TRANSFER_PRICING_MISSING)hotel_only (has hotels, no transfers):tripType / effective category must be set (ERR_ITN_PUBLISH_CATEGORY_REQUIRED)ERR_ITN_PUBLISH_HOTEL_PRICING_MISSING)ERR_ITN_PUBLISH_HOTEL_MAPPING_MISSING_FOR_PRICED_CATEGORY)transfer_only (no hotels, has transfers):ERR_ITN_PUBLISH_PRIMARY_TRANSFER_REQUIRED)ERR_ITN_PUBLISH_TRANSFER_PRICING_MISSING)activities_only (no hotels, no transfers, has activities):adultPrice must be set in travelerDetails (ERR_ITN_PUBLISH_ACTIVITY_ADULT_PRICE_REQUIRED)