Skip to content

TripMaker API Specification

Overview

The TripMaker API provides endpoints for managing trip projects, itineraries, flights, accommodations, activities, other services, exclusions, costs, and PDF generation.

Base Path: /tripmaker

Content Types: - Request: application/json - Response: application/json (or application/pdf for downloads)

Response Format

All endpoints return a TlinqApiResponse object:

{
  "apiStatus": {
    "errorCode": "OK",
    "errorMessage": "Success"
  },
  "apiData": { ... }
}

Date Format: All dates are returned in ISO 8601 format (yyyy-MM-dd'T'HH:mm:ss)


Project Endpoints

POST /tripmaker/project/create

Creates a new trip project.

Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | Yes | User session token | | projectName | string | Yes | Project name | | customerId | integer | No | Customer ID | | startDate | string | No | Start date (yyyy-MM-dd) | | endDate | string | No | End date (yyyy-MM-dd) | | adults | integer | No | Number of adults | | children | integer | No | Number of children | | infants | integer | No | Number of infants |

Request Example:

{
  "session": "user-session-token",
  "projectName": "Smith Family Vacation",
  "customerId": 1001,
  "startDate": "2025-08-15",
  "endDate": "2025-08-25",
  "adults": 2,
  "children": 2,
  "infants": 0
}

Response Structure:

{
  "apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
  "apiData": {
    "projectId": 5001,
    "projectName": "Smith Family Vacation",
    "customerId": 1001,
    "customerName": "John Smith",
    "startDate": "2025-08-15",
    "endDate": "2025-08-25",
    "adults": 2,
    "children": 2,
    "infants": 0,
    "status": "DRAFT",
    "createdBy": 101,
    "createdAt": "2025-06-15T10:30:00",
    "itineraries": []
  }
}


POST /tripmaker/project/list

Lists projects with optional filters.

Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | No | User session token | | customerId | integer | No | Filter by customer | | status | string | No | Filter by status | | fromDate | string | No | Filter from date | | toDate | string | No | Filter to date |

Request Example:

{
  "session": "user-session-token",
  "status": "DRAFT",
  "fromDate": "2025-06-01"
}

Response Structure:

{
  "apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
  "apiData": [
    {
      "projectId": 5001,
      "projectName": "Smith Family Vacation",
      "customerId": 1001,
      "customerName": "John Smith",
      "startDate": "2025-08-15",
      "endDate": "2025-08-25",
      "adults": 2,
      "children": 2,
      "infants": 0,
      "status": "DRAFT",
      "createdAt": "2025-06-15T10:30:00"
    },
    {
      "projectId": 5002,
      "projectName": "Corporate Retreat 2025",
      "customerId": 2001,
      "customerName": "Acme Corp",
      "startDate": "2025-09-01",
      "endDate": "2025-09-05",
      "adults": 20,
      "children": 0,
      "infants": 0,
      "status": "DRAFT",
      "createdAt": "2025-06-16T14:00:00"
    }
  ]
}


POST /tripmaker/project/get

Gets project details by ID.

Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | No | User session token | | projectId | integer | Yes | Project ID |

Request Example:

{
  "session": "user-session-token",
  "projectId": 5001
}

Response Structure:

{
  "apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
  "apiData": {
    "projectId": 5001,
    "projectName": "Smith Family Vacation",
    "customerId": 1001,
    "customerName": "John Smith",
    "customerEmail": "john.smith@example.com",
    "startDate": "2025-08-15",
    "endDate": "2025-08-25",
    "adults": 2,
    "children": 2,
    "infants": 0,
    "status": "DRAFT",
    "createdBy": 101,
    "createdByName": "Agent Jane",
    "createdAt": "2025-06-15T10:30:00",
    "updatedAt": "2025-06-18T09:00:00",
    "itineraries": [
      {
        "itineraryId": 6001,
        "itineraryName": "Option A - Beach Focus",
        "description": "Focus on beach resorts and water activities",
        "totalCost": 5500.00,
        "totalSelling": 7150.00
      },
      {
        "itineraryId": 6002,
        "itineraryName": "Option B - Adventure Focus",
        "description": "Focus on adventure activities and cultural tours",
        "totalCost": 4800.00,
        "totalSelling": 6240.00
      }
    ]
  }
}


POST /tripmaker/project/update

Updates project details.

Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | No | User session token | | projectId | integer | Yes | Project ID | | projectName | string | No | Project name | | startDate | string | No | Start date | | endDate | string | No | End date | | adults | integer | No | Number of adults | | children | integer | No | Number of children | | infants | integer | No | Number of infants | | status | string | No | Project status |

Request Example:

{
  "session": "user-session-token",
  "projectId": 5001,
  "endDate": "2025-08-28",
  "status": "QUOTED"
}

Response Structure:

{
  "apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
  "apiData": {
    "projectId": 5001,
    "projectName": "Smith Family Vacation",
    "endDate": "2025-08-28",
    "status": "QUOTED",
    "updatedAt": "2025-06-18T15:30:00"
  }
}


POST /tripmaker/project/delete

Deletes a project.

Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | No | User session token | | projectId | integer | Yes | Project ID |

Request Example:

{
  "session": "user-session-token",
  "projectId": 5001
}

Response Structure:

{
  "apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
  "apiData": {
    "message": "Project deleted successfully"
  }
}


Itinerary Endpoints

POST /tripmaker/itinerary/create

Creates a new itinerary for a project.

Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | No | User session token | | projectId | integer | Yes | Parent project ID | | itineraryName | string | Yes | Itinerary name | | description | string | No | Description |

Request Example:

{
  "session": "user-session-token",
  "projectId": 5001,
  "itineraryName": "Option A - Beach Focus",
  "description": "Focus on beach resorts and water activities"
}

Response Structure:

{
  "apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
  "apiData": {
    "itineraryId": 6001,
    "projectId": 5001,
    "itineraryName": "Option A - Beach Focus",
    "description": "Focus on beach resorts and water activities",
    "totalCost": 0.00,
    "totalSelling": 0.00,
    "createdAt": "2025-06-15T11:00:00"
  }
}


POST /tripmaker/itinerary/get

Gets itinerary details by ID.

Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | No | User session token | | itineraryId | integer | Yes | Itinerary ID |

Request Example:

{
  "session": "user-session-token",
  "itineraryId": 6001
}

Response Structure:

{
  "apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
  "apiData": {
    "itineraryId": 6001,
    "projectId": 5001,
    "itineraryName": "Option A - Beach Focus",
    "description": "Focus on beach resorts and water activities",
    "totalCost": 5500.00,
    "totalSelling": 7150.00,
    "totalMargin": 1650.00,
    "marginPercentage": 30.0,
    "createdAt": "2025-06-15T11:00:00",
    "updatedAt": "2025-06-18T14:00:00",
    "components": [
      {
        "componentId": 7001,
        "componentType": "FLIGHT",
        "dayNumber": 1,
        "description": "DXB → MLE - Emirates EK652",
        "costPrice": 1200.00,
        "sellingPrice": 1560.00
      },
      {
        "componentId": 7002,
        "componentType": "HOTEL",
        "dayNumber": 1,
        "nights": 10,
        "description": "Maldives Beach Resort - Deluxe Villa",
        "costPrice": 3800.00,
        "sellingPrice": 4940.00
      }
    ]
  }
}


POST /tripmaker/itinerary/list

Lists itineraries for a project.

Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | No | User session token | | projectId | integer | Yes | Project ID |

Request Example:

{
  "session": "user-session-token",
  "projectId": 5001
}

Response Structure:

{
  "apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
  "apiData": [
    {
      "itineraryId": 6001,
      "projectId": 5001,
      "itineraryName": "Option A - Beach Focus",
      "description": "Focus on beach resorts and water activities",
      "totalCost": 5500.00,
      "totalSelling": 7150.00
    },
    {
      "itineraryId": 6002,
      "projectId": 5001,
      "itineraryName": "Option B - Adventure Focus",
      "description": "Focus on adventure activities",
      "totalCost": 4800.00,
      "totalSelling": 6240.00
    }
  ]
}


POST /tripmaker/itinerary/update

Updates itinerary details.

Request Example:

{
  "session": "user-session-token",
  "itineraryId": 6001,
  "itineraryName": "Option A - Beach & Spa Focus",
  "description": "Focus on beach resorts, water activities and spa treatments"
}

Response Structure:

{
  "apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
  "apiData": {
    "itineraryId": 6001,
    "itineraryName": "Option A - Beach & Spa Focus",
    "description": "Focus on beach resorts, water activities and spa treatments",
    "updatedAt": "2025-06-18T16:00:00"
  }
}


POST /tripmaker/itinerary/delete

Deletes an itinerary.

Request Example:

{
  "session": "user-session-token",
  "itineraryId": 6002
}

Response Structure:

{
  "apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
  "apiData": {
    "message": "Itinerary deleted successfully"
  }
}


Flight Management Endpoints

POST /tripmaker/itinerary/add-flight

Adds a flight to an itinerary.

Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | No | User session token | | itineraryId | integer | Yes | Itinerary ID | | flightOffer | object | Yes | Flight offer object from search | | dayNumber | integer | No | Day in itinerary |

Request Example:

{
  "session": "user-session-token",
  "itineraryId": 6001,
  "flightOffer": {
    "offerId": "FL-12345",
    "airline": "Emirates",
    "flightNumber": "EK652",
    "origin": "DXB",
    "destination": "MLE",
    "departureDate": "2025-08-15",
    "departureTime": "08:00",
    "arrivalTime": "12:30",
    "cabinClass": "ECONOMY",
    "price": 1200.00
  },
  "dayNumber": 1
}

Response Structure:

{
  "apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
  "apiData": {
    "componentId": 7001,
    "itineraryId": 6001,
    "componentType": "FLIGHT",
    "dayNumber": 1,
    "airline": "Emirates",
    "flightNumber": "EK652",
    "origin": "DXB",
    "originName": "Dubai International",
    "destination": "MLE",
    "destinationName": "Velana International",
    "departureDate": "2025-08-15",
    "departureTime": "08:00",
    "arrivalTime": "12:30",
    "cabinClass": "ECONOMY",
    "costPrice": 1200.00,
    "sellingPrice": 1560.00,
    "marginType": "PERCENTAGE",
    "marginValue": 30.0
  }
}


POST /tripmaker/itinerary/get-flights

Gets all flights in an itinerary.

Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | No | User session token | | itineraryId | integer | Yes | Itinerary ID |

Request Example:

{
  "session": "user-session-token",
  "itineraryId": 6001
}

Response Structure:

{
  "apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
  "apiData": [
    {
      "componentId": 7001,
      "componentType": "FLIGHT",
      "dayNumber": 1,
      "airline": "Emirates",
      "flightNumber": "EK652",
      "origin": "DXB",
      "destination": "MLE",
      "departureDate": "2025-08-15",
      "departureTime": "08:00",
      "arrivalTime": "12:30",
      "cabinClass": "ECONOMY",
      "costPrice": 1200.00,
      "sellingPrice": 1560.00
    },
    {
      "componentId": 7005,
      "componentType": "FLIGHT",
      "dayNumber": 11,
      "airline": "Emirates",
      "flightNumber": "EK653",
      "origin": "MLE",
      "destination": "DXB",
      "departureDate": "2025-08-25",
      "departureTime": "14:00",
      "arrivalTime": "18:30",
      "cabinClass": "ECONOMY",
      "costPrice": 1200.00,
      "sellingPrice": 1560.00
    }
  ]
}


POST /tripmaker/itinerary/remove-flight

Removes a flight from an itinerary.

Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | No | User session token | | flightId | integer | Yes | Flight component ID |

Request Example:

{
  "session": "user-session-token",
  "flightId": 7001
}

Response Structure:

{
  "apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
  "apiData": {
    "message": "Flight removed successfully"
  }
}


Accommodation Management Endpoints

POST /tripmaker/accommodation/search

Searches for accommodations via Amadeus.

Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | No | User session token | | cityCode | string | Yes | City IATA code | | checkInDate | string | Yes | Check-in date (yyyy-MM-dd) | | checkOutDate | string | Yes | Check-out date (yyyy-MM-dd) | | adults | integer | Yes | Number of adults | | roomQuantity | integer | No | Number of rooms |

Request Example:

{
  "session": "user-session-token",
  "cityCode": "MLE",
  "checkInDate": "2025-08-15",
  "checkOutDate": "2025-08-25",
  "adults": 2,
  "roomQuantity": 1
}

Response Structure:

{
  "apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
  "apiData": [
    {
      "offerId": "HO-98765",
      "hotelId": "MLEBEACH",
      "hotelName": "Maldives Beach Resort",
      "chainCode": "XX",
      "starRating": 5,
      "address": "North Male Atoll, Maldives",
      "latitude": 4.1755,
      "longitude": 73.5093,
      "roomType": "Deluxe Villa",
      "boardType": "ALL_INCLUSIVE",
      "price": {
        "total": 3800.00,
        "currency": "USD",
        "perNight": 380.00
      },
      "amenities": ["Pool", "Spa", "Restaurant", "Beach Access", "Water Sports"]
    },
    {
      "offerId": "HO-98766",
      "hotelId": "MLEPALM",
      "hotelName": "Palm Paradise Resort",
      "starRating": 4,
      "address": "South Male Atoll, Maldives",
      "roomType": "Beach Bungalow",
      "boardType": "HALF_BOARD",
      "price": {
        "total": 2500.00,
        "currency": "USD",
        "perNight": 250.00
      }
    }
  ]
}


POST /tripmaker/itinerary/add-accommodation

Adds accommodation to an itinerary.

Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | No | User session token | | itineraryId | integer | Yes | Itinerary ID | | hotelOffer | object | Yes | Hotel offer from search | | dayNumber | integer | No | Day in itinerary | | nights | integer | No | Number of nights |

Request Example:

{
  "session": "user-session-token",
  "itineraryId": 6001,
  "hotelOffer": {
    "offerId": "HO-98765",
    "hotelId": "MLEBEACH",
    "hotelName": "Maldives Beach Resort",
    "roomType": "Deluxe Villa",
    "boardType": "ALL_INCLUSIVE",
    "price": 3800.00
  },
  "dayNumber": 1,
  "nights": 10
}

Response Structure:

{
  "apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
  "apiData": {
    "componentId": 7002,
    "itineraryId": 6001,
    "componentType": "HOTEL",
    "dayNumber": 1,
    "nights": 10,
    "hotelName": "Maldives Beach Resort",
    "roomType": "Deluxe Villa",
    "boardType": "ALL_INCLUSIVE",
    "checkIn": "2025-08-15",
    "checkOut": "2025-08-25",
    "costPrice": 3800.00,
    "sellingPrice": 4940.00,
    "marginType": "PERCENTAGE",
    "marginValue": 30.0
  }
}


POST /tripmaker/itinerary/get-accommodations

Gets all accommodations in an itinerary.

Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | Yes | User session token | | itineraryId | integer | Yes | Itinerary ID |

Request Example:

{
  "session": "user-session-token",
  "itineraryId": 6001
}

Response Structure:

{
  "apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
  "apiData": {
    "accommodations": [
      {
        "componentId": 7002,
        "componentType": "HOTEL",
        "dayNumber": 1,
        "nights": 10,
        "hotelName": "Maldives Beach Resort",
        "roomType": "Deluxe Villa",
        "boardType": "ALL_INCLUSIVE",
        "checkIn": "2025-08-15",
        "checkOut": "2025-08-25",
        "costPrice": 3800.00,
        "sellingPrice": 4940.00
      }
    ]
  }
}


POST /tripmaker/itinerary/remove-accommodation

Removes accommodation from an itinerary.

Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | Yes | User session token | | accommodationId | integer | Yes | Accommodation ID to remove |

Request Example:

{
  "session": "user-session-token",
  "accommodationId": 7002
}

Response Structure:

{
  "apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
  "apiData": {
    "message": "Accommodation removed successfully"
  }
}


Activity Management Endpoints

POST /tripmaker/activity/search

Searches for activities via Amadeus.

Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | No | User session token | | latitude | number | Yes | Location latitude | | longitude | number | Yes | Location longitude | | radius | integer | No | Search radius (km) |

Request Example:

{
  "session": "user-session-token",
  "latitude": 4.1755,
  "longitude": 73.5093,
  "radius": 50
}

Response Structure:

{
  "apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
  "apiData": [
    {
      "activityId": "ACT-001",
      "amadeusOfferId": "TOUR-12345",
      "activityName": "Sunset Dolphin Cruise",
      "description": "Experience the magical sunset while watching playful dolphins",
      "durationMinutes": 180,
      "price": {
        "amount": 85.00,
        "currency": "USD"
      },
      "category": "WATER_ACTIVITIES",
      "rating": 4.8,
      "reviewCount": 245,
      "images": ["https://example.com/dolphin1.jpg"]
    },
    {
      "activityId": "ACT-002",
      "amadeusOfferId": "TOUR-12346",
      "activityName": "Snorkeling Safari",
      "description": "Explore vibrant coral reefs and marine life",
      "durationMinutes": 240,
      "price": {
        "amount": 120.00,
        "currency": "USD"
      },
      "category": "WATER_ACTIVITIES",
      "rating": 4.9,
      "reviewCount": 380
    }
  ]
}


POST /tripmaker/itinerary/add-activity

Adds activity to an itinerary.

Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | No | User session token | | itineraryId | integer | Yes | Itinerary ID | | activity | object | Yes | Activity data | | dayNumber | integer | No | Day in itinerary | | time | string | No | Time of activity |

Request Example:

{
  "session": "user-session-token",
  "itineraryId": 6001,
  "activity": {
    "activityName": "Sunset Dolphin Cruise",
    "description": "Experience the magical sunset while watching dolphins",
    "durationMinutes": 180,
    "price": 85.00,
    "source": "AMADEUS",
    "amadeusOfferId": "TOUR-12345"
  },
  "dayNumber": 3,
  "time": "16:00"
}

Response Structure:

{
  "apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
  "apiData": {
    "activityId": 8001,
    "itineraryId": 6001,
    "activityDate": "2025-08-17",
    "timePeriod": "Afternoon",
    "activityName": "Sunset Dolphin Cruise",
    "description": "Experience the magical sunset while watching dolphins",
    "durationMinutes": 180,
    "transportIncluded": false,
    "guideIncluded": true,
    "baseCostTotal": 85.00,
    "sellingPrice": 110.50,
    "source": "AMADEUS",
    "amadeusOfferId": "TOUR-12345",
    "displayOrder": 1,
    "createdAt": "2025-06-15T14:00:00"
  }
}


POST /tripmaker/itinerary/get-activities

Gets all activities in an itinerary.

Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | No | User session token | | itineraryId | integer | Yes | Itinerary ID |

Request Example:

{
  "session": "user-session-token",
  "itineraryId": 6001
}

Response Structure:

{
  "apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
  "apiData": [
    {
      "activityId": 8001,
      "itineraryId": 6001,
      "activityDate": "2025-08-17",
      "timePeriod": "Afternoon",
      "activityName": "Sunset Dolphin Cruise",
      "description": "Experience the magical sunset while watching dolphins",
      "durationMinutes": 180,
      "transportIncluded": false,
      "guideIncluded": true,
      "baseCostTotal": 85.00,
      "sellingPrice": 110.50,
      "source": "AMADEUS",
      "displayOrder": 1
    },
    {
      "activityId": 8002,
      "itineraryId": 6001,
      "activityDate": "2025-08-19",
      "timePeriod": "Morning",
      "activityName": "Snorkeling Safari",
      "description": "Explore vibrant coral reefs",
      "durationMinutes": 240,
      "transportIncluded": true,
      "guideIncluded": true,
      "baseCostTotal": 120.00,
      "sellingPrice": 156.00,
      "source": "AMADEUS",
      "displayOrder": 2
    }
  ]
}


POST /tripmaker/itinerary/update-activity

Updates activity details.

Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | Yes | User session token | | activityId | integer | Yes | Activity ID to update | | itineraryId | integer | Yes | Itinerary ID containing the activity | | activityDate | string | No | Activity date (yyyy-MM-dd) | | timePeriod | string | No | Time period (e.g., "Morning", "Afternoon") | | activityName | string | No | Activity name | | description | string | No | Activity description | | durationMinutes | integer | No | Duration in minutes |

Request Example:

{
  "session": "user-session-token",
  "activityId": 8001,
  "itineraryId": 6001,
  "activityDate": "2025-08-18",
  "timePeriod": "Evening",
  "description": "Experience the magical sunset while watching playful dolphins - includes refreshments"
}

Response Structure:

{
  "apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
  "apiData": {
    "activityId": 8001,
    "message": "Activity updated successfully"
  }
}

Error Codes: - NOTFOUND - Activity not found in the itinerary


POST /tripmaker/itinerary/remove-activity

Removes activity from an itinerary.

Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | Yes | User session token | | activityId | integer | Yes | Activity ID to remove |

Request Example:

{
  "session": "user-session-token",
  "activityId": 8001
}

Response Structure:

{
  "apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
  "apiData": {
    "message": "Activity removed successfully"
  }
}


Exclusion Management Endpoints

POST /tripmaker/itinerary/add-exclusion

Adds an exclusion to an itinerary.

Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | No | User session token | | itineraryId | integer | Yes | Itinerary ID | | exclusionText | string | Yes | Exclusion description |

Request Example:

{
  "session": "user-session-token",
  "itineraryId": 6001,
  "exclusionText": "Travel insurance"
}

Response Structure:

{
  "apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
  "apiData": {
    "exclusionId": 9001,
    "itineraryId": 6001,
    "exclusionText": "Travel insurance",
    "displayOrder": 1,
    "createdAt": "2025-06-15T15:00:00"
  }
}


POST /tripmaker/itinerary/get-exclusions

Gets all exclusions for an itinerary.

Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | No | User session token | | itineraryId | integer | Yes | Itinerary ID |

Request Example:

{
  "session": "user-session-token",
  "itineraryId": 6001
}

Response Structure:

{
  "apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
  "apiData": [
    {
      "exclusionId": 9001,
      "itineraryId": 6001,
      "exclusionText": "Travel insurance",
      "displayOrder": 1,
      "createdAt": "2025-06-15T15:00:00"
    },
    {
      "exclusionId": 9002,
      "itineraryId": 6001,
      "exclusionText": "Visa fees",
      "displayOrder": 2,
      "createdAt": "2025-06-15T15:01:00"
    },
    {
      "exclusionId": 9003,
      "itineraryId": 6001,
      "exclusionText": "Personal expenses and tips",
      "displayOrder": 3,
      "createdAt": "2025-06-15T15:02:00"
    }
  ]
}


POST /tripmaker/itinerary/update-exclusion

Updates an exclusion.

Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | Yes | User session token | | exclusionId | integer | Yes | Exclusion ID to update | | exclusionText | string | Yes | Updated exclusion text |

Request Example:

{
  "session": "user-session-token",
  "exclusionId": 9001,
  "exclusionText": "Travel and medical insurance"
}

Response Structure:

{
  "apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
  "apiData": {
    "exclusionId": 9001,
    "message": "Exclusion updated successfully"
  }
}


POST /tripmaker/itinerary/delete-exclusion

Deletes an exclusion.

Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | Yes | User session token | | exclusionId | integer | Yes | Exclusion ID to delete |

Request Example:

{
  "session": "user-session-token",
  "exclusionId": 9003
}

Response Structure:

{
  "apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
  "apiData": {
    "message": "Exclusion deleted successfully"
  }
}


Other Service Management Endpoints

POST /tripmaker/itinerary/add-other-service

Adds an other service to an itinerary. Supports miscellaneous services such as transport, visa processing, meet & greet, etc. Currency conversion is applied automatically if the service currency differs from the local currency.

Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | No | User session token | | itineraryId | integer | Yes | Itinerary ID | | category | string | Yes | Service category (TRANSPORT, VISA, MEET & GREET, OTHERS) | | description | string | Yes | Service description | | serviceDate | string | No | Service date (yyyy-MM-dd) | | serviceTime | string | No | Service time (HH:mm) | | quantity | integer | No | Quantity (default: 1) | | supplierName | string | No | Supplier name | | baseCostTotal | decimal | No | Base cost total (default: 0.00) | | basePriceTotal | decimal | No | Base price total (default: 0.00) | | currency | string | No | Currency code (e.g. USD, AED, EUR) |

Request Example:

{
  "session": "user-session-token",
  "itineraryId": 6001,
  "category": "TRANSPORT",
  "description": "Airport transfer DXB to hotel",
  "serviceDate": "2025-08-15",
  "serviceTime": "14:00",
  "quantity": 1,
  "supplierName": "ABC Transport LLC",
  "baseCostTotal": 45.00,
  "basePriceTotal": 60.00,
  "currency": "AED"
}

Response Structure:

{
  "apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
  "apiData": {
    "otherServiceId": 10001,
    "baseCostTotal": 45.00,
    "basePriceTotal": 60.00,
    "currency": "AED",
    "originalCostTotal": null
  }
}


POST /tripmaker/itinerary/get-other-services

Gets all other services in an itinerary.

Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | No | User session token | | itineraryId | integer | Yes | Itinerary ID |

Request Example:

{
  "session": "user-session-token",
  "itineraryId": 6001
}

Response Structure:

{
  "apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
  "apiData": {
    "otherServices": [
      {
        "otherServiceId": 10001,
        "itineraryId": 6001,
        "category": "TRANSPORT",
        "description": "Airport transfer DXB to hotel",
        "serviceDate": "2025-08-15",
        "serviceTime": "14:00",
        "quantity": 1,
        "supplierName": "ABC Transport LLC",
        "baseCostTotal": 45.00,
        "basePriceTotal": 60.00,
        "currency": "AED",
        "originalCostTotal": null,
        "createdAt": "2025-06-15T15:00:00"
      },
      {
        "otherServiceId": 10002,
        "itineraryId": 6001,
        "category": "VISA",
        "description": "Tourist visa processing",
        "serviceDate": null,
        "serviceTime": null,
        "quantity": 2,
        "supplierName": null,
        "baseCostTotal": 150.00,
        "basePriceTotal": 200.00,
        "currency": "AED",
        "originalCostTotal": null,
        "createdAt": "2025-06-15T15:05:00"
      }
    ]
  }
}


POST /tripmaker/itinerary/update-other-service

Updates an other service. Uses read-modify-write pattern — only provided fields are updated.

Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | No | User session token | | otherServiceId | integer | Yes | Other service ID to update | | itineraryId | integer | Yes | Itinerary ID | | category | string | No | Service category | | description | string | No | Service description | | serviceDate | string | No | Service date (yyyy-MM-dd) | | serviceTime | string | No | Service time (HH:mm) | | quantity | integer | No | Quantity | | supplierName | string | No | Supplier name | | baseCostTotal | decimal | No | Base cost total | | basePriceTotal | decimal | No | Base price total | | currency | string | No | Currency code |

Request Example:

{
  "session": "user-session-token",
  "otherServiceId": 10001,
  "itineraryId": 6001,
  "baseCostTotal": 50.00,
  "basePriceTotal": 65.00
}

Response Structure:

{
  "apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
  "apiData": {
    "otherServiceId": 10001,
    "message": "Other service updated successfully"
  }
}


POST /tripmaker/itinerary/remove-other-service

Removes an other service from an itinerary.

Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | No | User session token | | otherServiceId | integer | Yes | Other service ID to remove |

Request Example:

{
  "session": "user-session-token",
  "otherServiceId": 10001
}

Response Structure:

{
  "apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
  "apiData": {
    "message": "Other service removed successfully"
  }
}


Cost Management Endpoints

POST /tripmaker/cost/get-breakdown

Gets cost breakdown for an itinerary.

Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | No | User session token | | itineraryId | integer | Yes | Itinerary ID |

Request Example:

{
  "session": "user-session-token",
  "itineraryId": 6001
}

Response Structure:

{
  "apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
  "apiData": {
    "itineraryId": 6001,
    "components": [
      {
        "componentId": 7001,
        "componentType": "FLIGHT",
        "description": "DXB → MLE - Emirates EK652",
        "costPrice": 1200.00,
        "marginType": "PERCENTAGE",
        "marginValue": 30.0,
        "marginAmount": 360.00,
        "sellingPrice": 1560.00
      },
      {
        "componentId": 7002,
        "componentType": "HOTEL",
        "description": "Maldives Beach Resort - 10 nights",
        "costPrice": 3800.00,
        "marginType": "PERCENTAGE",
        "marginValue": 30.0,
        "marginAmount": 1140.00,
        "sellingPrice": 4940.00
      },
      {
        "componentId": 8001,
        "componentType": "ACTIVITY",
        "description": "Sunset Dolphin Cruise",
        "costPrice": 85.00,
        "marginType": "PERCENTAGE",
        "marginValue": 30.0,
        "marginAmount": 25.50,
        "sellingPrice": 110.50
      }
    ],
    "totalCost": 5085.00,
    "totalMargin": 1525.50,
    "totalSelling": 6610.50,
    "overallMarginPercentage": 30.0,
    "currency": "USD"
  }
}


POST /tripmaker/cost/update-margin

Updates margin for a component.

Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | No | User session token | | componentId | integer | Yes | Component ID | | marginType | string | Yes | "PERCENTAGE" or "FIXED" | | marginValue | number | Yes | Margin value |

Request Example:

{
  "session": "user-session-token",
  "componentId": 7001,
  "marginType": "PERCENTAGE",
  "marginValue": 25.0
}

Response Structure:

{
  "apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
  "apiData": {
    "componentId": 7001,
    "costPrice": 1200.00,
    "marginType": "PERCENTAGE",
    "marginValue": 25.0,
    "marginAmount": 300.00,
    "sellingPrice": 1500.00,
    "message": "Margin updated successfully"
  }
}


POST /tripmaker/cost/override-price

Overrides price for a component.

Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | No | User session token | | componentId | integer | Yes | Component ID | | overridePrice | number | Yes | New selling price |

Request Example:

{
  "session": "user-session-token",
  "componentId": 7002,
  "overridePrice": 5000.00
}

Response Structure:

{
  "apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
  "apiData": {
    "componentId": 7002,
    "costPrice": 3800.00,
    "sellingPrice": 5000.00,
    "effectiveMargin": 31.58,
    "priceOverridden": true,
    "message": "Price override applied successfully"
  }
}


POST /tripmaker/cost/apply-global-margin

Applies global margin to all components.

Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | No | User session token | | itineraryId | integer | Yes | Itinerary ID | | marginType | string | Yes | "PERCENTAGE" or "FIXED" | | marginValue | number | Yes | Margin value |

Request Example:

{
  "session": "user-session-token",
  "itineraryId": 6001,
  "marginType": "PERCENTAGE",
  "marginValue": 25.0
}

Response Structure:

{
  "apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
  "apiData": {
    "itineraryId": 6001,
    "componentsUpdated": 5,
    "totalCost": 5085.00,
    "totalMargin": 1271.25,
    "totalSelling": 6356.25,
    "marginType": "PERCENTAGE",
    "marginValue": 25.0,
    "message": "Global margin applied to all components"
  }
}


PDF Generation Endpoints

Both PDF types (quotation and brochure) use externalized HTML templates loaded from TLINQ_HOME/templates/tripmaker/. If no external template is found, the system falls back to classpath-bundled defaults. This allows layout customization without rebuilding.

Template File Purpose
Quotation pdf-quotation-template.html Client-facing pricing document
Brochure pdf-brochure-template.html AI-generated travel brief (no prices)

POST /tripmaker/pdf/generate

Generates PDF quotation. Includes flights, accommodations, activities, other services, a chronological trip schedule, exclusions, and a cost summary.

Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | No | User session token | | itineraryId | integer | Yes | Itinerary ID | | templateId | integer | No | PDF template ID | | includeBreakdown | boolean | No | Include cost breakdown |

Request Example:

{
  "session": "user-session-token",
  "itineraryId": 6001,
  "templateId": 1,
  "includeBreakdown": true
}

Response Structure:

{
  "apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
  "apiData": {
    "pdfId": "PDF-2025-12345",
    "itineraryId": 6001,
    "fileName": "SmithFamilyVacation_OptionA.pdf",
    "fileSize": 245678,
    "generatedAt": "2025-06-18T16:30:00",
    "expiresAt": "2025-06-25T16:30:00",
    "downloadUrl": "/tripmaker/pdf/download/PDF-2025-12345"
  }
}


POST /tripmaker/pdf/download

Downloads PDF quotation.

Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | No | User session token | | pdfId | string | Yes | PDF document ID |

Response: Returns PDF file as binary stream with Content-Disposition header.


POST /tripmaker/pdf/email

Emails PDF quotation.

Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | No | User session token | | pdfId | string | Yes | PDF document ID | | recipientEmail | string | Yes | Recipient email | | subject | string | No | Email subject | | message | string | No | Email message |

Request Example:

{
  "session": "user-session-token",
  "pdfId": "PDF-2025-12345",
  "recipientEmail": "john.smith@example.com",
  "subject": "Your Maldives Vacation Quote",
  "message": "Dear Mr. Smith,\n\nPlease find attached our proposed itinerary for your family vacation to the Maldives.\n\nBest regards,\nTravel Team"
}

Response Structure:

{
  "apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
  "apiData": {
    "emailSent": true,
    "recipientEmail": "john.smith@example.com",
    "sentAt": "2025-06-18T16:45:00",
    "message": "Quote emailed successfully"
  }
}


POST /tripmaker/pdf/get-status

Gets PDF generation status.

Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | No | User session token | | pdfId | string | Yes | PDF document ID |

Request Example:

{
  "session": "user-session-token",
  "pdfId": "PDF-2025-12345"
}

Response Structure:

{
  "apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
  "apiData": {
    "pdfId": "PDF-2025-12345",
    "status": "READY",
    "fileName": "SmithFamilyVacation_OptionA.pdf",
    "fileSize": 245678,
    "generatedAt": "2025-06-18T16:30:00",
    "expiresAt": "2025-06-25T16:30:00",
    "downloadCount": 2,
    "emailedTo": ["john.smith@example.com"]
  }
}


POST /tripmaker/pdf/generate-brochure

Generates a travel brochure PDF combining the AI-generated travel brief with the trip schedule. The brochure is strictly a "travel story" document — no prices or cost information are included.

Request Body: | Field | Type | Required | Description | |-------|------|----------|-------------| | session | string | No | User session token | | itineraryId | integer | Yes | Itinerary ID | | aiBrief | object | Yes | AI brief data (headline, narrative, areas, sights, practical info) |

Request Example:

{
  "session": "user-session-token",
  "itineraryId": 6001,
  "aiBrief": {
    "headline": "Bali: Island of Gods",
    "timing_score": 4,
    "timing_explanation": "Great weather for beach and culture",
    "narrative": "Bali offers a rich tapestry of experiences...",
    "areas": [
      { "name": "Ubud", "description": "Cultural heart of Bali", "highlights": ["Rice terraces", "Monkey Forest"] }
    ],
    "sights": [
      { "name": "Tanah Lot Temple", "description": "Iconic sea temple", "duration": "2 hours", "best_time": "Sunset" }
    ],
    "activities": [
      { "name": "Surfing in Kuta", "description": "Beginner-friendly waves", "duration": "3 hours" }
    ],
    "practical": {
      "visa": "Visa on arrival for most nationalities",
      "currency": "Indonesian Rupiah (IDR)",
      "transport": "Scooter rental or private driver",
      "safety": "Generally safe for tourists",
      "etiquette": "Dress modestly at temples",
      "connectivity": "Good WiFi in tourist areas",
      "health": "Drink bottled water only"
    }
  }
}

Response Structure:

{
  "apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
  "apiData": {
    "pdfId": "PDF-2025-12346",
    "itineraryId": 6001,
    "fileName": "SmithFamilyVacation_Brochure.pdf",
    "fileSize": 198432,
    "generatedAt": "2025-06-18T17:00:00",
    "downloadUrl": "/tripmaker/pdf/download/PDF-2025-12346"
  }
}

Brochure Content: - Cover header with destination, dates, traveler details - Timing badge (score and explanation) - Narrative section (AI-generated destination overview) - Recommended areas (cards with highlights) - Sights and activities grid - Chronological trip schedule (same as quotation) - Practical information table


Data Models

CTripProject

Field Type Description
projectId integer Project ID
projectName string Project name
customerId integer Customer ID
customerName string Customer name
startDate date Trip start date
endDate date Trip end date
adults integer Number of adults
children integer Number of children
infants integer Number of infants
status string Project status (DRAFT, QUOTED, ACCEPTED, BOOKED, COMPLETED, CANCELLED)
createdBy integer Creator user ID
createdAt datetime Creation timestamp
updatedAt datetime Last update timestamp
itineraries array List of itineraries

CTripItinerary

Field Type Description
itineraryId integer Itinerary ID
projectId integer Parent project ID
itineraryName string Itinerary name
description string Description
totalCost decimal Total cost
totalSelling decimal Total selling price
totalMargin decimal Total margin amount
marginPercentage decimal Overall margin percentage
createdAt datetime Creation timestamp
updatedAt datetime Last update timestamp
components array List of trip components

CTripComponent

Field Type Description
componentId integer Component ID
itineraryId integer Parent itinerary ID
componentType string Type (FLIGHT, HOTEL, ACTIVITY, OTHER_SERVICE)
dayNumber integer Day in itinerary
description string Component description
costPrice decimal Cost price
sellingPrice decimal Selling price
marginType string Margin type (PERCENTAGE, FIXED)
marginValue decimal Margin value
marginAmount decimal Calculated margin amount
priceOverridden boolean Whether price is manually overridden

CCostBreakdown

Field Type Description
itineraryId integer Itinerary ID
components array Component costs array
totalCost decimal Total cost
totalMargin decimal Total margin
totalSelling decimal Total selling price
overallMarginPercentage decimal Overall margin as percentage
currency string Currency code

CActivity

Field Type Description
activityId integer Activity ID
itineraryId integer Parent itinerary ID
activityDate date Activity date
timePeriod string Time period (MORNING, AFTERNOON, EVENING, FULL_DAY)
activityName string Activity name
description string Activity description
durationMinutes integer Duration in minutes
transportIncluded boolean Whether transport is included
guideIncluded boolean Whether guide is included
baseCostTotal decimal Base cost total
sellingPrice decimal Selling price
source string Source (AMADEUS, MANUAL)
amadeusOfferId string Amadeus offer ID if sourced from Amadeus
displayOrder integer Display order
createdAt datetime Creation timestamp

COtherService

Field Type Description
otherServiceId integer Other service ID
itineraryId integer Parent itinerary ID
category string Service category (TRANSPORT, VISA, MEET & GREET, OTHERS)
description string Service description
serviceDate date Service date
serviceTime string Service time (HH:mm format)
quantity integer Quantity (default: 1)
supplierName string Supplier name
baseCostTotal decimal Base cost total
basePriceTotal decimal Base price total (selling price)
currency string Currency code
originalCostTotal decimal Original cost before currency conversion
createdAt datetime Creation timestamp

CExclusion

Field Type Description
exclusionId integer Exclusion ID
itineraryId integer Parent itinerary ID
exclusionText string Exclusion description text
displayOrder integer Display order
createdAt datetime Creation timestamp

Booking Integration

POST /tripmaker/project/convertToBooking

Converts a TripMaker project in QUOTED status into a BLM booking. The project is set to CLOSED after successful conversion.

Request Body:

Parameter Type Required Description
projectId Integer Yes The TripMaker project ID
itineraryId Integer Yes The itinerary whose cost breakdown defines the service lines

Response: CBooking object with all fields populated, including bookingId, bookingRef, status (ENQUIRY), sourceType (TRIPMAKER), sourceRef (projectId).

Example Request:

{
  "projectId": 15,
  "itineraryId": 42
}

Example Response:

{
  "apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
  "apiData": {
    "bookingId": 101,
    "bookingRef": "TQ-2026-00042",
    "status": "ENQUIRY",
    "customerName": "John Smith",
    "sourceType": "TRIPMAKER",
    "sourceRef": "15",
    "travelStartDate": "2026-05-01",
    "travelEndDate": "2026-05-08"
  }
}

Error Responses: - Project not found → ERR00012 - Project not in QUOTED status → ERR00014 - Itinerary doesn't belong to project → ERR00012

Roles: agent, admin