Hotel API Specification¶
Overview¶
The Hotel API provides endpoints for hotel management, room calendar configuration, accommodation search, and GDS hotel search integration.
Base Path: /hotel
Content Types:
- Request: application/json
- Response: application/json
Response Format¶
All endpoints return a TlinqApiResponse object:
Date Format: All dates are returned in ISO 8601 format (yyyy-MM-dd'T'HH:mm:ss)
Hotel Management Endpoints¶
POST /hotel/listHotels¶
Lists hotels with optional filtering (employees only).
Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | Yes | User session token | | name | string | No | Filter by hotel name (partial match) | | area | string | No | Filter by area | | shDes | string | No | Filter by short description |
Request Example:
Response Structure:
{
"apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
"apiData": [
{
"hotelId": 101,
"name": "Hilton Dubai Downtown",
"shortName": "Hilton Downtown",
"shDes": "5-star luxury hotel in downtown Dubai",
"hotelDesc": "Experience luxury at its finest...",
"productId": 5001,
"direct": true,
"indirect": false,
"country": "UAE",
"stars": 5,
"infant": 2,
"child": 12,
"chkIn": "14:00",
"chkOut": "12:00",
"fees": 50.00,
"feesDesc": "Tourism fee per night",
"terms": "Free cancellation up to 24 hours before check-in",
"area": "Downtown Dubai",
"city": "Dubai",
"release": 3,
"reservationContact": "reservations@hiltondubai.com"
},
{
"hotelId": 102,
"name": "Hilton Dubai Creek",
"shortName": "Hilton Creek",
"shDes": "5-star hotel overlooking Dubai Creek",
"productId": 5002,
"direct": true,
"indirect": false,
"country": "UAE",
"stars": 5,
"area": "Dubai Creek",
"city": "Dubai"
}
]
}
POST /hotel/hotelLookup¶
Searches for hotels by name for autocomplete (employees only).
Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | Yes | User session token | | name | string | No | Partial hotel name |
Request Example:
Response Structure:
{
"apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
"apiData": [
["Marriott Downtown Dubai", 201],
["Marriott Al Jaddaf", 202],
["JW Marriott Marquis", 203]
]
}
POST /hotel/getHotel¶
Retrieves a hotel by ID (employees only).
Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | Yes | User session token | | id | integer | Yes | Hotel ID |
Request Example:
Response Structure:
{
"apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
"apiData": {
"hotelId": 101,
"name": "Hilton Dubai Downtown",
"shortName": "Hilton Downtown",
"shDes": "5-star luxury hotel in downtown Dubai",
"hotelDesc": "Experience luxury at its finest with stunning views of Burj Khalifa...",
"productId": 5001,
"direct": true,
"indirect": false,
"country": "UAE",
"stars": 5,
"infant": 2,
"child": 12,
"chkIn": "14:00",
"chkOut": "12:00",
"fees": 50.00,
"feesDesc": "Tourism fee per night",
"terms": "Free cancellation up to 24 hours before check-in",
"area": "Downtown Dubai",
"city": "Dubai",
"release": 3,
"reservationContact": "reservations@hiltondubai.com"
}
}
POST /hotel/saveHotel¶
Creates or updates a hotel (employees only).
Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | Yes | User session token | | hotel | object | Yes | Hotel data object |
Request Example:
{
"session": "user-session-token",
"hotel": {
"hotelId": null,
"name": "New Luxury Resort",
"shortName": "Luxury Resort",
"shDes": "New 5-star beachfront resort",
"country": "UAE",
"stars": 5,
"infant": 2,
"child": 12,
"chkIn": "15:00",
"chkOut": "11:00",
"area": "Palm Jumeirah",
"city": "Dubai",
"direct": true
}
}
Response Structure:
{
"apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
"apiData": {
"hotelId": 301,
"name": "New Luxury Resort",
"shortName": "Luxury Resort",
"shDes": "New 5-star beachfront resort",
"productId": 6001,
"country": "UAE",
"stars": 5,
"infant": 2,
"child": 12,
"chkIn": "15:00",
"chkOut": "11:00",
"area": "Palm Jumeirah",
"city": "Dubai",
"direct": true,
"indirect": false
}
}
POST /hotel/listHotelRooms¶
Lists rooms for a hotel (employees only).
Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | Yes | User session token | | hotelId | integer | Yes | Hotel ID |
Request Example:
Response Structure:
{
"apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
"apiData": [
{
"roomId": 1001,
"hotelId": 101,
"name": "Deluxe Room",
"roomDesc": "Spacious room with city view",
"maxOccupancy": 3,
"maxAdults": 2,
"extraBed": true,
"bedding": "King or Twin",
"extraBedRequired": false,
"notes": null
},
{
"roomId": 1002,
"hotelId": 101,
"name": "Executive Suite",
"roomDesc": "Luxury suite with separate living area",
"maxOccupancy": 4,
"maxAdults": 2,
"extraBed": true,
"bedding": "King",
"extraBedRequired": false,
"notes": "Includes lounge access"
}
]
}
POST /hotel/saveRoom¶
Creates or updates a hotel room (employees only).
Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | Yes | User session token | | room | object | Yes | Room data object |
Request Example:
{
"session": "user-session-token",
"room": {
"roomId": null,
"hotelId": 101,
"name": "Premium Suite",
"roomDesc": "Luxurious suite with panoramic views",
"maxOccupancy": 4,
"maxAdults": 3,
"extraBed": true,
"bedding": "King",
"extraBedRequired": false
}
}
Response Structure:
{
"apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
"apiData": {
"roomId": 1003,
"hotelId": 101,
"name": "Premium Suite",
"roomDesc": "Luxurious suite with panoramic views",
"maxOccupancy": 4,
"maxAdults": 3,
"extraBed": true,
"bedding": "King",
"extraBedRequired": false
}
}
Calendar & Pricing Endpoints¶
POST /hotel/listRoomCalendar¶
Lists room calendar entries (employees only).
Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | Yes | User session token | | roomId | integer | No | Room ID | | hotelId | integer | No | Hotel ID | | fromDate | string | Yes | Start date (yyyy-MM-dd) | | toDate | string | Yes | End date (yyyy-MM-dd) | | market | string | No | Market code (default: UAE) |
*Either roomId or hotelId must be provided.
Request Example:
{
"session": "user-session-token",
"roomId": 1001,
"fromDate": "2025-07-01",
"toDate": "2025-07-31",
"market": "UAE"
}
Response Structure:
{
"apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
"apiData": [
{
"calendarEntryId": 50001,
"roomId": 1001,
"market": "UAE",
"vendorId": null,
"promo": null,
"bookFrom": "2025-01-01T00:00:00",
"bookTo": "2025-12-31T23:59:59",
"stayDate": "2025-07-01T00:00:00",
"baseRate": 500.00,
"specDayRate": 600.00,
"specialDay": false,
"sdRateType": "ABS",
"adultRate": 50.00,
"adultRateType": "ABS",
"childRate": 25.00,
"childRateType": "ABS",
"extraBedRate": 100.00,
"rateBase": "ROOM",
"mealBase": 1,
"mealSupplements": "BB:30,HB:60,FB:90",
"stopSale": false,
"available": true,
"onRequest": false,
"mlos": 1,
"mlosDesc": "Minimum 1 night",
"sdmlos": 2,
"notes": null,
"adultSdRate": 60.00,
"childSdRate": 30.00
},
{
"calendarEntryId": 50002,
"roomId": 1001,
"market": "UAE",
"stayDate": "2025-07-02T00:00:00",
"baseRate": 500.00,
"specialDay": false,
"available": true
}
]
}
POST /hotel/createRoomCalendar¶
Creates calendar entries for a room (employees only).
Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | Yes | User session token | | template | object | Yes | Calendar entry template | | stayTo | string | Yes | End date for calendar | | specDays | string | Yes | Special day settings (comma-separated weekdays) |
Request Example:
{
"session": "user-session-token",
"template": {
"roomId": 1001,
"market": "UAE",
"stayDate": "2025-08-01",
"bookFrom": "2025-01-01",
"bookTo": "2025-12-31",
"baseRate": 450.00,
"specDayRate": 550.00,
"sdRateType": "ABS",
"adultRate": 50.00,
"adultRateType": "ABS",
"childRate": 25.00,
"childRateType": "ABS",
"extraBedRate": 100.00,
"rateBase": "ROOM",
"mealBase": 1,
"available": true,
"stopSale": false,
"mlos": 1
},
"stayTo": "2025-08-31",
"specDays": "Fri,Sat"
}
Response Structure:
{
"apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
"apiData": [
{
"calendarEntryId": 60001,
"roomId": 1001,
"stayDate": "2025-08-01T00:00:00",
"baseRate": 450.00,
"specialDay": true,
"available": true
},
{
"calendarEntryId": 60002,
"roomId": 1001,
"stayDate": "2025-08-02T00:00:00",
"baseRate": 450.00,
"specialDay": true,
"available": true
}
]
}
POST /hotel/copyRoomCalendar¶
Copies calendar from one room to another (employees only).
Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | Yes | User session token | | fromRoom | integer | Yes | Source room ID | | toRoom | integer | Yes | Target room ID | | market | string | Yes | Market code | | fromDate | string | Yes | Start date | | toDate | string | Yes | End date |
Request Example:
{
"session": "user-session-token",
"fromRoom": 1001,
"toRoom": 1002,
"market": "UAE",
"fromDate": "2025-07-01",
"toDate": "2025-07-31"
}
Response Structure:
{
"apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
"apiData": {
"recordsCopied": 31
}
}
Meal Plan Endpoints¶
POST /hotel/listMealPlans¶
Lists meal plans.
Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | Yes | User session token | | hotelId | integer | No | Hotel ID (for hotel-specific plans) |
Request Example:
Response Structure:
{
"apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
"apiData": [
{
"planId": 1,
"plan": "RO",
"name": "Room Only",
"planDesc": "Accommodation without meals",
"planOrder": 1,
"adultCost": 0.00,
"childCost": 0.00
},
{
"planId": 2,
"plan": "BB",
"name": "Bed & Breakfast",
"planDesc": "Accommodation with breakfast",
"planOrder": 2,
"adultCost": 30.00,
"childCost": 15.00
},
{
"planId": 3,
"plan": "HB",
"name": "Half Board",
"planDesc": "Breakfast and dinner included",
"planOrder": 3,
"adultCost": 60.00,
"childCost": 30.00
},
{
"planId": 4,
"plan": "FB",
"name": "Full Board",
"planDesc": "All meals included",
"planOrder": 4,
"adultCost": 90.00,
"childCost": 45.00
},
{
"planId": 5,
"plan": "AI",
"name": "All Inclusive",
"planDesc": "All meals and beverages included",
"planOrder": 5,
"adultCost": 150.00,
"childCost": 75.00
}
]
}
Search Endpoints¶
POST /hotel/searchAccommodation¶
Searches for available accommodation.
Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | No | User session token | | checkin | string | Yes | Check-in date (dd/MM/yyyy) | | checkout | string | Yes | Check-out date (dd/MM/yyyy) | | adults | integer | Yes | Number of adults | | children | integer | Yes | Number of children | | meals | string | No | Meal plan filter | | area | string | No | Area filter | | market | string | No | Market code | | maxBudget | number | No | Maximum budget | | extraBed | boolean | No | Include extra bed | | hotelId | integer | No | Specific hotel ID | | roomId | integer | No | Specific room ID | | context | string | No | "config" for employee view |
Request Example:
{
"session": "user-session-token",
"checkin": "15/07/2025",
"checkout": "20/07/2025",
"adults": 2,
"children": 1,
"meals": "BB",
"area": "Downtown Dubai",
"market": "UAE",
"maxBudget": 5000
}
Response Structure:
{
"apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
"apiData": {
"input": {
"checkin": "2025-07-15T00:00:00",
"checkout": "2025-07-20T00:00:00",
"adults": 2,
"children": 1,
"market": "UAE",
"area": "Downtown Dubai",
"meals": "BB",
"nights": 5
},
"results": [
{
"hotel": {
"hotelId": 101,
"name": "Hilton Dubai Downtown",
"shortName": "Hilton Downtown",
"stars": 5,
"area": "Downtown Dubai",
"city": "Dubai",
"chkIn": "14:00",
"chkOut": "12:00"
},
"resultSource": "DIRECT",
"rooms": [
{
"roomId": 1001,
"roomName": "Deluxe Room",
"roomDesc": "Spacious room with city view",
"maxOccupancy": 3,
"mealPlan": "BB",
"totalPrice": 3250.00,
"pricePerNight": 650.00,
"currency": "AED",
"available": true,
"onRequest": false
},
{
"roomId": 1002,
"roomName": "Executive Suite",
"roomDesc": "Luxury suite with separate living area",
"maxOccupancy": 4,
"mealPlan": "BB",
"totalPrice": 4500.00,
"pricePerNight": 900.00,
"currency": "AED",
"available": true,
"onRequest": false
}
]
}
]
}
}
Online Hotel Search and Booking¶
These endpoints support dual-mode routing via the searchMode parameter:
- searchMode="online" (default) -- Routes through the OnlineHotelSupplierRegistry to the active online hotel supplier (currently GoGlobal).
- searchMode="contracted" -- Routes to the NTS/EntityFacade for contracted hotel inventory.
POST /hotel/searchCountries¶
Searches GoGlobal static data for countries matching a keyword. Used for the country autocomplete in the hotel search form.
Permissions: guest, agent, admin
Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | No | User session token | | keyword | string | Yes | Country name search keyword (minimum 3 characters recommended) |
Request Example:
Response Structure:
{
"apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
"apiData": [
{ "countryId": 123, "countryName": "United Arab Emirates", "countryCode": "AE" },
{ "countryId": 456, "countryName": "United Kingdom", "countryCode": "GB" },
{ "countryId": 789, "countryName": "United States", "countryCode": "US" }
]
}
Notes:
- Queries the goglobal.country table (populated by StaticDataRefresher).
- Case-insensitive partial match on countryName.
- Returns up to 20 results, ordered by country name.
- If the GoGlobal static data tables are empty, no results will be returned.
POST /hotel/getCities¶
Returns all cities for a given GoGlobal country ID. Used to populate the city dropdown after country selection.
Permissions: guest, agent, admin
Request Body:
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| session | string | No | User session token |
| countryId | long | Yes | GoGlobal country ID (from searchCountries response) |
Request Example:
Response Structure:
{
"apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
"apiData": [
{ "cityId": 1133, "cityName": "Abu Dhabi", "cityCode": "1133" },
{ "cityId": 1218, "cityName": "Dubai", "cityCode": "1218" },
{ "cityId": 1406, "cityName": "Sharjah", "cityCode": "1406" }
]
}
Notes:
- Queries the goglobal.city table (populated by StaticDataRefresher).
- The cityCode value is the GoGlobal city ID (same as cityId), which is used as the cityCode parameter in searchOffers.
- Results are ordered by city name.
POST /hotel/searchOffers¶
Searches hotel offers via the configured online supplier (GoGlobal) or contracted hotel inventory.
Permissions: guest, agent, admin
Request Body:
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| session | string | Yes | User session token |
| searchMode | string | No | "online" (default) or "contracted" |
| hotelIds | string | Conditional | Comma-separated hotel IDs (required for contracted mode) |
| cityCode | string | Conditional | GoGlobal city ID (required for online mode when hotelIds not provided). Obtained from getCities response. |
| checkInDate | string | Yes | Check-in date (yyyy-MM-dd) |
| checkOutDate | string | No | Check-out date (yyyy-MM-dd) |
| adults | integer | Yes | Number of adults |
| children | integer | No | Number of children (default: 0) |
| roomQuantity | integer | No | Number of rooms (default: 1) |
| nationality | string | No | 2-letter country code for pricing nationality (default: "AE"). Mandatory for GoGlobal API — defaults to AE when not provided. |
| currency | string | No | Currency code (default: configured default) |
| paymentPolicy | string | No | Payment policy filter |
| boardType | string | No | Meal plan filter (BB, HB, FB, AI, RO) |
| bestRateOnly | boolean | No | Return best rate only |
| exactDestination | boolean | No | When true, restrict results to the exact city (no nearby cities). GoGlobal default includes nearby cities. |
| sortOrder | integer | No | 1=Price ASC, 2=Price DESC, 3=Name ASC |
Request Example (Online Mode):
{
"session": "user-session-token",
"searchMode": "online",
"cityCode": "1234",
"checkInDate": "2026-03-15",
"checkOutDate": "2026-03-18",
"adults": 2,
"roomQuantity": 1,
"currency": "USD"
}
Response Structure (Online Mode):
{
"apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
"apiData": {
"searchId": "HSRCH-20260315-123456",
"pageId": 1,
"totalRes": 25, // total unique hotels (not individual offers)
"offers": [
{
"offerId": "HSC-2026031500001",
"hotelId": "56789",
"hotelName": "Grand Hotel Dubai",
"cityCode": "1234",
"roomType": "BB",
"roomCategory": "5",
"roomDescription": "DOUBLE OCEAN VIEW",
"boardType": "Bed & Breakfast",
"currencyCode": "USD",
"totalAmount": 450.00,
"available": true,
"checkInDate": "2026-03-15",
"checkOutDate": "2026-03-18",
"cancellationType": "REFUNDABLE",
"cancellationDeadline": "2026-03-13T23:59:59"
}
]
}
}
Notes:
- In online mode, the offerId field contains the GoGlobal HotelSearchCode, which is required for subsequent booking journey operations (valuateOffer, getPriceBreakdown, createBooking).
- The HotelSearchCode is valid for approximately 20 minutes.
- Online mode uses the OnlineHotelSupplierRegistry to resolve the active supplier (GoGlobal).
- Contracted mode uses the EntityFacade with the HotelOffer entity configuration.
- Result grouping: Results are grouped by hotel. The totalRes field represents the total number of unique hotels (not individual room offers). Each hotel may have multiple room offers in the offers array.
- Page size: Configurable via goglobal.hotel.search.pageSize in goglobal-client.xml (default: 20 hotels per page). Use fetchOfferResults to retrieve subsequent pages.
Error Codes:
- NORESULTS -- No hotel availability found
- INVALID_FORMAT -- Date format incorrect
- INVALID_PARAM -- Invalid city code or parameter
- GENERAL -- Unexpected server error
POST /hotel/fetchOfferResults¶
Retrieves the next page of hotel search results from a previously executed search. Results are paginated by hotel — each page returns N hotels with all their room offers.
Permissions: guest, agent, admin
Request Body:
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| session | string | Yes | User session token |
| searchId | string | Yes | Search ID returned from searchOffers |
| page | integer | Yes | Page number to retrieve (1-indexed) |
Request Example:
Response Structure:
{
"apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
"apiData": {
"searchId": "HSRCH-20260315-123456",
"pageId": 2,
"totalRes": 45,
"offers": [
{
"offerId": "HSC-2026031500021",
"hotelId": "67890",
"hotelName": "Marina Hotel Dubai",
"cityCode": "1234",
"roomType": "BB",
"roomCategory": "4",
"roomDescription": "TWIN STANDARD",
"boardType": "Bed & Breakfast",
"currencyCode": "USD",
"totalAmount": 320.00,
"available": true,
"checkInDate": "2026-03-15",
"checkOutDate": "2026-03-18",
"cancellationType": "REFUNDABLE",
"cancellationDeadline": "2026-03-13T23:59:59"
}
]
}
}
Notes:
- The totalRes field represents the total number of unique hotels across all pages.
- Page size is configurable via goglobal.hotel.search.pageSize in goglobal-client.xml (default: 20).
- The offers array contains all room offers for the hotels on the requested page. Multiple offers may share the same hotelId (different room types for the same hotel).
- Search results expire 30 minutes after the initial search.
- Returns empty offers array if the page number exceeds available results.
Error Codes:
- GENERAL -- Unexpected server error
POST /hotel/searchByName¶
Searches hotels by name (autocomplete).
Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | Yes | User session token | | keyword | string | Yes | Search keyword | | countryCode | string | No | Country code filter | | subType | string | No | HOTEL_GDS or HOTEL_LEISURE | | max | integer | No | Maximum results |
Request Example:
Response Structure:
{
"apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
"apiData": [
{
"hotelId": "MARDXB001",
"name": "JW Marriott Marquis Dubai",
"cityCode": "DXB",
"address": "Sheikh Zayed Road, Business Bay",
"rating": 5,
"subType": "HOTEL_GDS"
},
{
"hotelId": "MARDXB002",
"name": "Marriott Downtown Dubai",
"cityCode": "DXB",
"address": "Downtown Dubai",
"rating": 5,
"subType": "HOTEL_GDS"
}
]
}
POST /hotel/getByCity¶
Gets hotels by city code.
Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | Yes | User session token | | cityCode | string | Yes | IATA city code | | radius | integer | No | Search radius | | ratings | string | No | Comma-separated star ratings |
Request Example:
Response Structure:
{
"apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
"apiData": [
{
"hotelId": "HTLDXB001",
"name": "Burj Al Arab",
"cityCode": "DXB",
"address": "Jumeirah Beach Road",
"rating": 5,
"distance": 2.5
},
{
"hotelId": "HTLDXB002",
"name": "Atlantis The Palm",
"cityCode": "DXB",
"address": "Crescent Road, The Palm",
"rating": 5,
"distance": 8.0
}
]
}
Online Hotel Booking Journey¶
The following endpoints implement the hotel booking journey through the online supplier (GoGlobal). They must be called in sequence after an availability search (/hotel/searchOffers), using the HotelSearchCode (returned as offerId in the search results) to identify the selected offer.
Booking Journey Flow:
1. /hotel/searchOffers -- Get available offers (returns offerId / HotelSearchCode), grouped by hotel
2. /hotel/fetchOfferResults -- (Optional) Paginate through additional results
3. /hotel/getHotel (with searchMode="online") -- Get hotel details
4. /hotel/valuateOffer -- Validate pricing and cancellation terms
5. /hotel/getPriceBreakdown -- Get nightly price breakdown
6. /hotel/createBooking -- Create the booking
POST /hotel/getHotel (Online Mode)¶
Retrieves detailed hotel information from the online supplier. When searchMode="online" is specified, the request is routed through the OnlineHotelSupplierRegistry to GoGlobal Operation 61 (Hotel Info Request).
Permissions: guest, agent, admin
Request Body:
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| session | string | Yes | User session token |
| hotelId | string | Yes | GoGlobal hotel ID (from search results hotelId field) |
| searchMode | string | No | "online" to use GoGlobal supplier; omit for contracted |
Request Example:
Response Structure (CHotelInfo):
{
"apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
"apiData": {
"hotelId": "56789",
"hotelName": "Grand Hotel Dubai",
"description": "Luxury 5-star hotel with panoramic views of Burj Khalifa...",
"address": "Sheikh Zayed Road, Downtown Dubai",
"category": "5",
"cityCode": "1218",
"cityName": "Dubai",
"countryCode": "AE",
"facilities": "[{\"name\":\"Swimming Pool\"},{\"name\":\"Spa\"},{\"name\":\"Gym\"}]",
"pictures": "[{\"url\":\"https://images.goglobal.travel/hotels/56789/1.jpg\"}]",
"latitude": 25.2048,
"longitude": 55.2708
}
}
Notes:
- Without searchMode="online", this endpoint retrieves hotel data from the contracted hotel database (NTS) using the id (integer) parameter instead.
- The GoGlobal hotel ID is obtained from the hotelId field in the search results.
- The category field contains the star rating as a string (e.g., "5").
- facilities and pictures are JSON strings; the frontend should parse them.
- Hotel info includes geo-coordinates for map display.
Error Codes:
- NOTFOUND -- Hotel ID not found in GoGlobal database
- GENERAL -- Unexpected server error
POST /hotel/valuateOffer¶
Validates the current price and cancellation terms for a selected hotel offer. This is GoGlobal Operation 9 (Booking Valuation Request). The valuation confirms whether the price has changed since the availability search and returns detailed cancellation policies.
Permissions: agent, admin
Request Body:
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| session | string | Yes | User session token |
| hotelSearchCode | string | Yes | The offerId / HotelSearchCode from search results |
| arrivalDate | string | Yes | Check-in date (yyyy-MM-dd). Required by GoGlobal API v3.16.8. |
| nationality | string | No | 2-letter country code for pricing nationality. Some hotels have nationality-based pricing. |
Request Example:
{
"session": "user-session-token",
"hotelSearchCode": "HSC-2026031500001",
"arrivalDate": "2026-03-15",
"nationality": "AE"
}
Response Structure:
{
"apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
"apiData": {
"offerId": "HSC-2026031500001",
"checkInDate": "2026-03-15",
"totalAmount": 450.00,
"currencyCode": "USD",
"totalTax": 45.00,
"cancellationDeadline": "2026-03-13T23:59:59",
"cancellationType": "REFUNDABLE",
"remarks": "Check-in from 14:00. Late checkout subject to availability.",
"cancellationPolicies": [
{
"id": 1,
"starting": "2026-03-13T00:00:00",
"basedOn": "BOOKINGPRICE",
"mode": "PCT",
"value": 100
}
]
}
}
Response Fields:
| Field | Type | Description |
|-------|------|-------------|
| offerId | string | The HotelSearchCode (unchanged) |
| checkInDate | string | Confirmed arrival date |
| totalAmount | number | Confirmed total price (may differ from search) |
| currencyCode | string | Currency code |
| totalTax | number | Tax amount included in total |
| cancellationDeadline | string | Free cancellation deadline (ISO 8601) |
| cancellationType | string | REFUNDABLE or NON_REFUNDABLE |
| remarks | string | Hotel-specific remarks and conditions |
| cancellationPolicies | array | Detailed cancellation policy rules |
Cancellation Policy Fields:
| Field | Type | Description |
|-------|------|-------------|
| id | integer | Policy sequence ID |
| starting | string | Date/time when policy takes effect |
| basedOn | string | What the penalty is based on (BOOKINGPRICE, FIRSTNIGHT) |
| mode | string | Penalty calculation mode (PCT = percentage, ABS = fixed amount) |
| value | number | Penalty value (percentage or amount depending on mode) |
Error Codes:
- EXPIRED -- Offer expired (HotelSearchCode no longer valid, re-search required)
- GENERAL -- Unexpected server error
POST /hotel/getPriceBreakdown¶
Retrieves the nightly price breakdown per room for a selected offer. This is GoGlobal Operation 14 (Price Breakdown Request). Provides granular pricing detail for each night of the stay.
Permissions: guest, agent, admin
Request Body:
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| session | string | Yes | User session token |
| hotelSearchCode | string | Yes | The offerId / HotelSearchCode from search results |
Request Example:
Response Structure:
{
"apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
"apiData": {
"hotelSearchCode": "HSC-2026031500001",
"rooms": [
{
"roomId": 1,
"nights": [
{ "date": "2026-03-15", "price": 150.00, "currency": "USD" },
{ "date": "2026-03-16", "price": 150.00, "currency": "USD" },
{ "date": "2026-03-17", "price": 150.00, "currency": "USD" }
]
}
]
}
}
Response Fields: | Field | Type | Description | |-------|------|-------------| | hotelSearchCode | string | The HotelSearchCode | | rooms | array | Array of room breakdown objects | | rooms[].roomId | integer | Room sequence number | | rooms[].nights | array | Array of nightly rate objects | | rooms[].nights[].date | string | Night date (yyyy-MM-dd) | | rooms[].nights[].price | number | Price for that night | | rooms[].nights[].currency | string | Currency code |
Notes: - For multi-room bookings, each room has its own breakdown. - Nightly prices may vary (e.g., weekend surcharges). - The sum of nightly prices per room may differ slightly from the total due to rounding.
Error Codes:
- EXPIRED -- Offer expired (HotelSearchCode no longer valid)
- GENERAL -- Unexpected server error
POST /hotel/createBooking¶
Creates a hotel booking for a validated offer. This is GoGlobal Operation 2 (Booking Insert Request). The offer should be valuated first via /hotel/valuateOffer to confirm pricing.
Permissions: agent, admin
Request Body:
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| session | string | Yes | User session token |
| hotelSearchCode | string | Yes | The offerId / HotelSearchCode from search results |
| clientRef | string | No | Agency booking reference (e.g., TQ-BK-2026-0001) |
| title | string | Yes | Lead guest title (MR., MRS., MS., MISS) |
| firstName | string | Yes | Lead guest first name |
| lastName | string | Yes | Lead guest last name |
| email | string | Yes | Contact email address |
| phone | string | No | Contact phone number |
| nationality | string | No | 2-letter guest nationality code (e.g. "AE", "GB") |
| remarks | string | No | Booking remarks / special requests |
| roomGuests | string | No | JSON array of per-room guest arrays for multi-room bookings (see below) |
roomGuests format (JSON string):
[
[
{ "personId": 1, "title": "MR.", "firstName": "John", "lastName": "Smith" },
{ "personId": 2, "title": "MRS.", "firstName": "Jane", "lastName": "Smith" }
],
[
{ "personId": 3, "title": "MR.", "firstName": "Bob", "lastName": "Jones", "age": 10 }
]
]
personId (sequential), title, firstName, lastName, and optional age (for children).
Request Example:
{
"session": "user-session-token",
"hotelSearchCode": "HSC-2026031500001",
"clientRef": "TQ-BK-2026-0001",
"title": "MR.",
"firstName": "John",
"lastName": "Smith",
"email": "john.smith@example.com",
"phone": "+44123456789",
"nationality": "GB",
"remarks": "Late arrival, estimated 22:00"
}
Response Structure:
{
"apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
"apiData": {
"goBookingCode": "GG-123456",
"goReference": "REF-789012",
"bookingStatus": "C",
"totalPrice": 450.00,
"currency": "USD",
"hotelId": "56789",
"hotelName": "Grand Hotel Dubai",
"hotelConfirmation": "HC-GRAND-2026-001",
"clientBookingCode": "TQ-BK-2026-0001"
}
}
Response Fields: | Field | Type | Description | |-------|------|-------------| | goBookingCode | string | GoGlobal booking code (permanent, used for all subsequent operations) | | goReference | string | GoGlobal supplier reference number | | bookingStatus | string | Booking status code (see below) | | totalPrice | number | Confirmed booking price | | currency | string | Currency code | | hotelId | string | GoGlobal hotel ID | | hotelName | string | Hotel name | | hotelConfirmation | string | Hotel's own confirmation number (may be null for RQ bookings) | | clientBookingCode | string | Agency reference code (echoed from request) |
Booking Status Codes:
| Code | Description |
|------|-------------|
| C | Confirmed -- booking is confirmed by the hotel |
| RQ | On Request -- hotel confirmation pending (poll via booking status endpoint) |
| RJ | Rejected -- booking was rejected by the hotel |
Notes:
- A status of C means the booking is immediately confirmed.
- A status of RQ means the hotel needs to confirm; use the booking status endpoint to poll for resolution.
- The goBookingCode is the permanent identifier for cancellation, status check, voucher generation, and amendment operations.
- Room configuration at booking time must match the configuration used during the availability search.
Error Codes:
- EXPIRED -- Offer expired (HotelSearchCode no longer valid, re-search required)
- INVALID_PARAM -- Invalid passenger data or room mismatch
- GENERAL -- Unexpected server error
Data Models¶
CHotel¶
| Field | Type | Description |
|---|---|---|
| hotelId | integer | Unique hotel identifier |
| name | string | Hotel name |
| shortName | string | Short hotel name |
| shDes | string | Short description |
| hotelDesc | string | Full description |
| productId | integer | Associated product ID |
| direct | boolean | Direct contract |
| indirect | boolean | Indirect contract |
| country | string | Country code |
| stars | integer | Star rating |
| infant | integer | Infant age limit |
| child | integer | Child age limit |
| chkIn | string | Check-in time |
| chkOut | string | Check-out time |
| fees | number | Additional fees |
| feesDesc | string | Fee description |
| terms | string | Terms and conditions |
| area | string | Hotel area |
| city | string | City name |
| release | integer | Release days |
| reservationContact | string | Reservation contact |
CHotelRoom¶
| Field | Type | Description |
|---|---|---|
| roomId | integer | Room identifier |
| hotelId | integer | Hotel ID |
| name | string | Room name/type |
| roomDesc | string | Room description |
| maxOccupancy | integer | Maximum guests |
| maxAdults | integer | Maximum adults |
| extraBed | boolean | Extra bed allowed |
| bedding | string | Bedding type |
| extraBedRequired | boolean | Extra bed required |
| notes | string | Room notes |
CRoomCalendarEntry¶
| Field | Type | Description |
|---|---|---|
| calendarEntryId | integer | Entry identifier |
| roomId | integer | Room ID |
| market | string | Market code |
| vendorId | integer | Vendor ID |
| promo | string | Promotion code |
| bookFrom | datetime | Booking window start |
| bookTo | datetime | Booking window end |
| stayDate | datetime | Stay date |
| baseRate | number | Base room rate |
| specDayRate | number | Special day rate |
| specialDay | boolean | Is special day |
| sdRateType | string | Special day rate type (ABS, PCT) |
| adultRate | number | Extra adult rate |
| adultRateType | string | Adult rate type |
| childRate | number | Child rate |
| childRateType | string | Child rate type |
| extraBedRate | number | Extra bed rate |
| rateBase | string | Rate basis (ROOM, PAX) |
| mealBase | integer | Base meal plan ID |
| mealSupplements | string | Meal supplements config |
| stopSale | boolean | Stop sale flag |
| available | boolean | Availability flag |
| onRequest | boolean | On request flag |
| mlos | integer | Minimum length of stay |
| mlosDesc | string | MLOS description |
| sdmlos | integer | Special day MLOS |
| notes | string | Entry notes |
CMealPlan¶
| Field | Type | Description |
|---|---|---|
| planId | integer | Plan identifier |
| plan | string | Plan code (RO, BB, HB, FB, AI) |
| name | string | Plan name |
| planDesc | string | Plan description |
| planOrder | integer | Display order |
| adultCost | number | Adult supplement cost |
| childCost | number | Child supplement cost |
CHotelSearchResult¶
| Field | Type | Description |
|---|---|---|
| input | CHotelSearchInput | Search parameters |
| results | array | Array of CHotelSearchResultItem |
CHotelSearchResultItem¶
| Field | Type | Description |
|---|---|---|
| hotel | CHotel | Hotel details |
| resultSource | string | Result source (DIRECT, GDS) |
| rooms | array | Array of CRoomSearchResult |
CHotelOffer (Online Search/Booking)¶
Used by online hotel search (/hotel/searchOffers with searchMode="online") and booking journey endpoints.
| Field | Type | Description |
|---|---|---|
| offerId | string | Unique offer identifier (GoGlobal HotelSearchCode) |
| type | string | Room type description |
| available | boolean | Availability status |
| hotelId | string | Hotel identifier (GoGlobal hotel code) |
| hotelName | string | Hotel name |
| chainCode | string | Hotel chain code (Amadeus only) |
| cityCode | string | City code / GoGlobal city ID |
| hotelLatitude | number | Hotel latitude |
| hotelLongitude | number | Hotel longitude |
| roomType | string | Room basis / meal plan code (e.g., BB, HB) |
| roomCategory | string | Star rating category code |
| beds | integer | Number of rooms |
| bedType | string | Bed type description |
| roomDescription | string | Full room type description |
| currencyCode | string | 3-letter currency code |
| totalAmount | number | Total stay price |
| baseAmount | number | Base price before taxes |
| cancellationType | string | "NON_REFUNDABLE" or "REFUNDABLE" |
| cancellationDeadline | string | Free cancellation deadline (ISO 8601) |
| cancellationDescription | string | Human-readable cancellation terms |
| boardType | string | Board basis description |
| checkInDate | string | Check-in date |
| checkOutDate | string | Check-out date |
| commission | string | Commission information |
| category | string | Category information |
| description | string | Offer description |
CHotelBookingConfirmation (Booking Response)¶
Returned by /hotel/createBooking for GoGlobal bookings.
| Field | Type | Description |
|---|---|---|
| goBookingCode | string | GoGlobal permanent booking code |
| goReference | string | GoGlobal supplier reference |
| bookingStatus | string | Status: C (confirmed), RQ (on-request), RJ (rejected) |
| totalPrice | number | Confirmed booking price |
| currency | string | Currency code |
| hotelId | string | Hotel identifier |
| hotelName | string | Hotel name |
| hotelConfirmation | string | Hotel's own confirmation number |
| clientBookingCode | string | Agency reference code |
CHotelPriceBreakdown (Price Breakdown Response)¶
Returned by /hotel/getPriceBreakdown.
| Field | Type | Description |
|---|---|---|
| hotelSearchCode | string | The HotelSearchCode identifier |
| rooms | array | Array of room breakdown objects |
Room Breakdown Object: | Field | Type | Description | |-------|------|-------------| | roomId | integer | Room sequence number | | nights | array | Array of nightly rate objects |
Nightly Rate Object: | Field | Type | Description | |-------|------|-------------| | date | string | Night date (yyyy-MM-dd) | | price | number | Price for that night | | currency | string | Currency code |
Hotel Package Endpoints¶
POST /hotel/listPackages¶
List packages, optionally filtering by hotel and/or status. Photos are excluded from list response for performance. Includes hotel name for cross-hotel display.
Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | Yes | User session token | | hotelId | integer | No | Filter by hotel ID (omit for all hotels) | | status | string | No | Filter by status: DRAFT, ACTIVE, RETIRED |
Response: Array of CHotelPackage objects (without photo fields), each including a rooms array and hotelName.
POST /hotel/getPackage¶
Get full package details including rooms and photos.
Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | Yes | User session token | | packageId | integer | Yes | Package ID |
Response: CHotelPackage object with all fields including photos and rooms.
CHotelPackage Object: | Field | Type | Description | |-------|------|-------------| | packageId | integer | Package ID (auto-generated) | | hotelId | integer | Hotel ID | | packageName | string | Package display name | | area | string | Hotel/destination area | | stayFrom | date | Stay validity start | | stayTo | date | Stay validity end | | bookFrom | date | Booking window start | | bookTo | date | Booking window end | | nights | integer | Number of nights | | mealPlan | string | Meal plan code (RO, BB, HB, FB, AIL, AI, AIP) | | maxAdults | integer | Maximum adults | | freeChildren | integer | Number of free children | | freeChildAge | integer | Max age for free children | | discChildren | integer | Number of discounted children | | discChildAge | integer | Max age for discounted children | | description | string | Rich text (HTML) description | | websitePhoto | string | Base64 encoded photo for website | | adPhoto | string | Base64 encoded photo for ad | | brochurePhoto | string | Base64 encoded photo for brochure/PDF | | blackoutDates | string | Comma-separated ISO dates | | status | string | Package status: DRAFT, ACTIVE, RETIRED | | hotelName | string | Hotel name (populated in list responses) | | rooms | array | Array of CHotelPackageRoom objects |
CHotelPackageRoom Object: | Field | Type | Description | |-------|------|-------------| | packageRoomId | integer | Room entry ID | | packageId | integer | Parent package ID | | roomType | string | Room type name (free text) | | pricePerNight | number | Price per night | | priceTotal | number | Total package price | | currencyCode | string | Currency code (AED, USD, EUR) | | sortOrder | integer | Display order |
POST /hotel/savePackage¶
Save a package with rooms atomically. Rooms are replaced entirely on each save.
Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | Yes | User session token | | packageId | integer | No | 0 or null for new package | | hotelId | integer | Yes | Hotel ID | | packageName | string | Yes | Package name | | rooms | array | No | Array of room objects | | (all CHotelPackage fields) | | | See getPackage response |
Response: Saved CHotelPackage object with generated IDs.
POST /hotel/deletePackage¶
Delete a package and all its rooms. Requires admin role.
Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | Yes | User session token | | packageId | integer | Yes | Package ID to delete |
Response: "OK" on success.
POST /hotel/generatePackagePdf¶
Generate a one-page PDF brochure for a package. Company info is loaded from server config (tqpro.company.* properties).
Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | Yes | User session token | | packageId | integer | Yes | Package ID |
Response: | Field | Type | Description | |-------|------|-------------| | pdf | string | Base64-encoded PDF content | | filename | string | Suggested filename |
POST /hotel/copyPackage¶
Copy a package as a new DRAFT (for reactivating retired packages). Copies all fields including rooms, photos, and description. The new package gets status DRAFT.
Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | Yes | User session token | | packageId | integer | Yes | Package ID to copy |
Response: New CHotelPackage object with generated ID and status DRAFT.
POST /hotel/retirePackages¶
Manually trigger retirement of all ACTIVE packages whose stay-to date is in the past. Admin only. (Also runs automatically daily via scheduled job.)
Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | Yes | User session token |
Response: { "retired": <count> }
POST /hotel/packageTemplate¶
Download an Excel template for bulk package import. The workbook contains two sheets: "Packages" (import sheet with data validation dropdowns) and "Hotels" (reference sheet with all hotels from DB for VLOOKUP).
Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | Yes | User session token |
Response: Binary .xlsx file (application/octet-stream).
POST /hotel/importPackages¶
Import packages from an uploaded Excel file. Rows are grouped by (Hotel Name + Package Name). Upserts packages by matching hotelId + packageName. Rooms are merged by room type — existing rooms not in the Excel are preserved.
Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | Yes | User session token | | fileData | string | Yes | Base64-encoded Excel file content |
Response Structure:
{
"apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
"apiData": {
"totalProcessed": 9,
"inserted": 2,
"updated": 1,
"failed": 0,
"errors": []
}
}
Error objects in errors array:
| Field | Type | Description |
|-------|------|-------------|
| rowNumber | integer | Excel row number (1-based) |
| fieldName | string | Field that caused the error |
| errorMessage | string | Human-readable error description |
| rawValue | string | Original cell value |
Limits: 5MB file size, 500 rows max.
POST /hotel/exportHotels¶
Download all configured hotels as an Excel file. Each row represents one hotel with all basic-section fields.
Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | Yes | User session token |
Response: Binary .xlsx file (application/octet-stream, filename hotels.xlsx).
Columns: Hotel Code*, Hotel Name*, Short Name, Country, City, Area, Stars, Direct Contract, Indirect/DMC, Infant Age (up to), Child Age (up to), Check-in Time, Check-out Time, Release Days, Service Fees, Fee Description, Terms & Conditions, Description, Reservation Contact
Data Validations: Area (DXB, AUH, AIN, SHJ, AJM, FUJ, RAK, UAQ), Stars (1–5), Direct/Indirect (Yes/No).
POST /hotel/importHotels¶
Import hotels from an uploaded Excel file. Performs upsert matching by hotel code (shDes, case-insensitive). Existing hotels are updated; new codes are inserted.
Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | Yes | User session token | | fileData | string | Yes | Base64-encoded Excel file content |
Response Structure:
{
"apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
"apiData": {
"totalProcessed": 15,
"inserted": 5,
"updated": 10,
"failed": 0,
"errors": []
}
}
Error objects in errors array:
| Field | Type | Description |
|-------|------|-------------|
| rowNumber | integer | Excel row number (1-based) |
| fieldName | string | Field that caused the error |
| errorMessage | string | Human-readable error description |
| rawValue | string | Original cell value |
Required fields: Hotel Code, Hotel Name. Rows missing either are skipped with an error.
Preserve behavior: When updating an existing hotel, empty Description, Terms, and Reservation Contact cells preserve the existing database values.
Limits: 5MB file size, 500 rows max.
Package Booking Endpoints¶
POST /hotel/booking/create¶
Create a draft booking for a stay package.
Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | Yes | User session token | | packageId | integer | Yes | Package ID | | hotelId | integer | No | Hotel ID | | hotelName | string | No | Hotel name | | checkIn | string | No | Check-in date (yyyy-MM-dd) | | checkOut | string | No | Check-out date (yyyy-MM-dd) | | nights | integer | No | Number of nights | | mealPlan | string | No | Meal plan code | | customerName | string | Yes | Customer full name | | customerEmail | string | Yes | Customer email | | customerPhone | string | No | Customer phone | | odooCustomerId | integer | No | Pre-resolved Odoo customer ID | | passengers | string/array | No | JSON array of passenger objects | | rooms | string/array | No | JSON array of room selection objects | | salePrice | number | No | Total sale price (editable by agent) | | saleCurrency | string | No | Currency code | | notes | string | No | Booking notes |
Passenger object: { "firstName", "lastName", "phone", "email" }
Room selection object: { "roomType", "quantity", "priceTotal", "currencyCode" }
POST /hotel/booking/read¶
Get a single booking by ID.
Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | Yes | User session token | | bookingId | integer | Yes | Booking ID |
POST /hotel/booking/list¶
List bookings with optional filters.
Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | Yes | User session token | | packageId | integer | No | Filter by package | | status | string | No | Filter by status: DRAFT, PENDING_PAYMENT, COMPLETED, CANCELLED |
POST /hotel/booking/update¶
Update booking details. Once status is PENDING_PAYMENT or COMPLETED, only reservationName, confirmationNumber, and notes can be updated.
Request Body: Same as create, with bookingId required.
POST /hotel/booking/checkout¶
Create Odoo quote, generate payment link. Changes booking status from DRAFT to PENDING_PAYMENT.
Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | Yes | User session token | | bookingId | integer | Yes | Booking ID |
Response: Updated CPackageBooking with cartReference, telrPaymentLink, odooQuoteId.
POST /hotel/booking/confirmPayment¶
Manually confirm payment. Creates Odoo invoice, validates, and registers payment. Changes status to COMPLETED.
Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | Yes | User session token | | bookingId | integer | Yes | Booking ID |
POST /hotel/booking/voucher¶
Generate PDF booking voucher with company header, reservation details, rooms, passengers, and confirmation number.
Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | Yes | User session token | | bookingId | integer | Yes | Booking ID |
Response: { "pdf": "base64-encoded-pdf" }
POST /hotel/booking/invoice¶
Download invoice PDF from Odoo.
Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | Yes | User session token | | bookingId | integer | Yes | Booking ID |
Response: { "pdf": "base64-encoded-pdf" }
POST /hotel/booking/sendInvoice¶
Email invoice PDF to the customer.
Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | Yes | User session token | | bookingId | integer | Yes | Booking ID |
Response: "OK"
CPackageBooking Object¶
| Field | Type | Description |
|---|---|---|
| bookingId | integer | Booking ID |
| packageId | integer | FK to package |
| hotelId | integer | FK to hotel |
| hotelName | string | Hotel name |
| checkIn | date | Check-in date |
| checkOut | date | Check-out date |
| nights | integer | Number of nights |
| mealPlan | string | Meal plan code |
| customerName | string | Customer name |
| customerEmail | string | Customer email |
| customerPhone | string | Customer phone |
| odooCustomerId | integer | Odoo customer ID |
| passengers | string | JSON array of passengers |
| rooms | string | JSON array of selected rooms |
| salePrice | number | Total sale price |
| saleCurrency | string | Currency code |
| cartReference | string | Cart/payment reference |
| odooQuoteId | integer | Odoo sale order ID |
| invoiceNumber | string | Odoo invoice number |
| telrPaymentLink | string | Telr payment URL |
| paymentStatus | string | Payment status |
| reservationName | string | Name on hotel reservation |
| confirmationNumber | string | Hotel confirmation number |
| status | string | DRAFT, PENDING_PAYMENT, COMPLETED, CANCELLED |
| agentId | string | Agent user ID |
| notes | string | Booking notes |
| created | datetime | Creation timestamp |
| updated | datetime | Last update timestamp |
Supplier Hotel Import¶
POST /hotel/importFromSupplier¶
Import a hotel from an online supplier (GoGlobal) into the contracted hotels database. Creates or updates a CHotel and its CHotelRoom entries. Duplicate detection uses the supplierHotelId field.
Roles: agent, admin
Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | Yes | User session token | | supplierHotelId | string | Yes | Supplier's hotel ID (e.g. "648898") | | hotelName | string | Yes | Hotel name | | stars | integer | No | Star rating (1-5) | | country | string | No | Country code (e.g. "DE") | | city | string | No | City name | | address | string | No | Hotel address | | description | string | No | Hotel description | | rooms | array | No | Array of room objects |
Room object: | Field | Type | Description | |-------|------|-------------| | name | string | Room type name (e.g. "Deluxe Double") | | bedding | string | Bed type (e.g. "Queen") | | maxOccupancy | integer | Maximum occupancy | | maxAdults | integer | Maximum adults |
Response Data: | Field | Type | Description | |-------|------|-------------| | hotel | object | The created/updated CHotel entity | | hotelId | integer | Hotel ID in the local database | | roomsSaved | integer | Number of rooms created/updated | | created | boolean | True if a new hotel was created | | updated | boolean | True if an existing hotel was updated |
Example Request:
{
"session": "...",
"supplierHotelId": "648898",
"hotelName": "HOTEL-RESTAURANT SCHMACHTENBERGSHOF",
"stars": 3,
"country": "DE",
"city": "ESSEN",
"address": "Schmachtenbergstrasse 157, Essen, DE",
"rooms": [
{ "name": "Deluxe Double", "bedding": "Queen", "maxOccupancy": 2, "maxAdults": 2 },
{ "name": "Standard Single", "bedding": "Single", "maxOccupancy": 1, "maxAdults": 1 }
]
}
Duplicate Detection: If a hotel with the same supplierHotelId already exists, the hotel and its rooms are updated instead of creating a duplicate. The shDes field is set to "GG" + supplierHotelId for new imports.
CDN Media Browser Integration¶
The hotel package edit page (hotel-package-edit.html) integrates the CDN Media Browser for the three photo URL fields: Website Image, Ad Image, and Brochure Image. Each field has a browse button that opens a modal for browsing existing S3 images and uploading new ones.
How It Works¶
Each photo URL input has a browse button with data-cdn-* attributes:
<div class="input-group">
<input type="url" id="url_website" class="form-control form-control-sm photo-url-input" ...>
<button type="button" class="btn btn-outline-secondary btn-sm"
data-cdn-purpose="hotel-photos" data-cdn-allow-upload="true"
data-cdn-target="#url_website">
<i class="bi bi-folder2-open"></i>
</button>
</div>
The cdn-browser.js module auto-binds to these buttons on page load. When clicked, the CDN browser modal opens with:
- Browse tab: Navigate S3 folders under
hotels/photos/, view image thumbnails via CloudFront, select an image - Upload tab: Select a template (Card Header 600x400, Page Banner 1920x400, etc.), drop an image, upload with automatic resize/crop/WebP conversion
On selection or upload, the CDN URL is written to the target input field and a change event is dispatched, triggering the existing image preview update.
Media API Endpoints Used¶
The CDN browser calls the Media API endpoints:
- POST /media/cdn/browse — List folders and images
- POST /media/cdn/upload — Upload with resize/crop/WebP
- POST /media/cdn/templates — Get available image templates
Purpose Configuration¶
The hotel-photos purpose is configured in config/nts-client.xml: