Data Models
This document describes the key data models used throughout Bundleport APIs. For complete schemas, see the API Reference.
Hotel
Represents a hotel property.
interface Hotel {
code: string; // Bundleport hotel code
name: string; // Hotel name
descriptions?: HotelDescription[]; // Multi-language descriptions
category?: string; // Category code
starRating?: number; // 1-5 stars
location: Location; // Address and coordinates
amenities?: Amenity[]; // Hotel amenities
media?: Media[]; // Images and videos
contact?: Contact; // Contact information
providerCode?: string; // Provider identifier
providerHotelCode?: string; // Provider-specific code
destinationCode?: string; // Destination code
boardCodes?: string[]; // Available board types
rooms?: RoomData[]; // Available room types
}
Room
Represents a room type.
interface Room {
code: string; // Bundleport room code
name: string; // Room name
descriptions?: Text[]; // Multi-language descriptions
maxOccupancy: number; // Maximum guests
bedType?: string; // Type of bed
sizeSqM?: number; // Room size in square meters
images?: RoomImage[]; // Room images
occupancy?: Occupancy; // Occupancy details
beds?: Bed[]; // Bed configuration
providerCode?: string; // Provider identifier
providerRoomCode?: string; // Provider-specific code
}
Option
Represents a bookable hotel option from a search.
interface Option {
optionRefId: string; // Unique identifier for this option
hotel: Hotel; // Hotel information
rooms: RoomOption[]; // Room options with pricing
price: Price; // Total price
cancelPolicy?: CancelPolicy; // Cancellation policy
provider: ProviderInfo; // Provider details
}
RoomOption
A specific room option within an Option.
interface RoomOption {
description: string; // Room description
boardCode: string; // Board type (RO, BB, HB, FB, AI)
price: Price; // Room price
cancelPolicy?: CancelPolicy; // Room-specific cancellation policy
occupancyRefId: number; // Reference to occupancy configuration
}
Price
Pricing information with markup and margin details.
There are three independent prices in every response, plus the margin fields that describe your org markup:
interface Price {
currency: string; // ISO 4217 currency code
net: number; // Provider cost (what you pay the supplier)
binding?: boolean; // Provider binding flag (see note below)
suggested?: number; // Provider suggested / minimum selling price
gross?: number; // Provider retail (= suggested, or net if absent)
markupGross: number; // Your selling price = gross + org margin
markupNet: number; // Provider net cost + org margin amount
markupCurrency: string; // Markup currency
markupBinding: boolean; // If markup price must be respected
marginAmount?: number; // Org margin amount (markupGross - gross)
marginPercent?: number; // Effective margin percentage (on gross)
marginType?: string; // "FIXED" or "PERCENTAGE"
breakdown?: PriceBreakdown;
}
The three prices
| Price | Field | Where it comes from |
|---|---|---|
| Cost | net | The provider — what the agency pays the supplier |
| Provider retail | gross / suggested | The provider — recommended / minimum selling price |
| Your selling price | markupGross | gross + the margin your org configures per connection |
net and gross/suggested come straight from the provider. markupGross is
the only price Bundleport computes, by adding your org margin on top of the
provider gross — never on net.
markupGross = gross + orgMargin // PERCENTAGE: gross × (1 + rate); FIXED: gross + amount
marginAmount = markupGross - gross
Price Fields
| Field | Description |
|---|---|
net | Provider cost — what you pay the supplier |
suggested | Provider's suggested or minimum selling price |
gross | Provider retail price (= suggested, or net if the provider sends none) |
markupGross | Your selling price = provider gross + org margin |
marginAmount | Org margin amount (markupGross - gross) |
marginPercent | Effective margin percentage (applied on gross) |
- Customer display: Use
markupGross - Cost calculations: Use
net - Margin analysis: Use
marginAmountandmarginPercent
- No margin configured:
markupGross = grossand aNO_MARKUP_CONFIGUREDwarning is returned. - skipMarkup enabled: When
additionalParams.skipMarkup: "true"is passed,markupGross = gross.
In both cases your selling price is the provider retail price, with no org margin added.
When binding: true, the provider gross/suggested is a minimum selling price:
you must not sell below it. Binding only limits how low you can go — it does not
change how the margin or commission is calculated. Your markupGross (gross +
margin) is always ≥ the binding price, so it stays compliant.
Two ways to read the total
The same total can be split two different ways, depending on what you want to show. They answer different questions, so the two splits do not match each other — only the total is shared.
1. Selling split — what the guest pays, broken into room vs taxes/fees. This is what UIs show in the price breakdown:
Total (gross / suggested) 77.52
├─ Stay amount (room, ex-tax) 69.88 = total − taxes/fees
└─ Taxes and fees 7.64 = sum of included tax/fee surcharges
2. Cost split — what the agency pays vs the provider's own margin. This is the cost view (e.g. the agency-cost tooltip):
Total (gross / suggested) 77.52
├─ Net (your cost) 71.14
└─ Provider margin 6.38 = gross − net (a.k.a. marketing fee)
Stay amount ≠ NetThey live in different splits:
- Stay amount (69.88) is on the selling side, with taxes/fees removed.
- Net (71.14) is the cost side, and still contains its own share of taxes.
They come from subtracting different things from the same total
(total − taxes vs total − provider margin). Any closeness between the two
numbers is a coincidence, not a relationship. There is no "net excluding taxes"
exposed by the provider, so the two breakdowns never reconcile beyond the total.
When the provider sends only a net price (no separate suggested), then
net = gross = suggested, the provider margin is 0, and the cost split
collapses — only the selling split remains.
Markup Configuration
Markups define how prices are adjusted before being returned in API responses.
Markup Types
| Type | Description | Example |
|---|---|---|
PERCENTAGE | Percentage of provider gross | 5% → gross × 1.05 |
FIXED_AMOUNT | Fixed amount added to provider gross | 10€ → gross + 10 |
Markup Priority
When multiple markups exist for a connection, only the highest priority markup is applied:
- Priority field (higher values win)
- Creation date (newer wins if same priority)
Configure only one global markup per connection to ensure consistent pricing across all prices (option price, room prices). Having multiple markups may cause confusion.
Markup Levels
Markups can be configured at different levels:
| Level | Description |
|---|---|
ORGANIZATION | Base level, applies to all bookings |
AGENCY | Mid level, applies to specific agency |
USER | Highest level, personalized for specific user |
Lower levels override higher levels: USER > AGENCY > ORGANIZATION
PriceBreakdown
Detailed price components.
interface PriceBreakdown {
base: number; // Base room price
taxes?: number; // Taxes
fees?: number; // Fees
supplements?: Supplement[]; // Additional charges
discounts?: Discount[]; // Applied discounts
}
Occupancy
Guest configuration.
interface Occupancy {
adults: number; // Number of adults
children?: number; // Number of children
childrenAges?: number[]; // Ages of children (required if children > 0)
total: number; // Total guests (adults + children)
}
Stay
Date range for hotel stay.
interface Stay {
checkIn: string; // Check-in date (YYYY-MM-DD)
checkOut: string; // Check-out date (YYYY-MM-DD)
nights?: number; // Number of nights (calculated)
}
Destination
Location where hotels are located.
interface Destination {
code: string; // Destination code
name: string; // Destination name
type: string; // Type: city, region, airport, etc.
location?: Location; // Geographic location
parent?: string; // Parent destination code
children?: string[]; // Child destination codes
texts?: Text[]; // Multi-language descriptions
}
Location
Geographic location and address.
interface Location {
address?: string; // Street address
city?: string; // City name
state?: string; // State or province
countryCode?: string; // ISO 3166-1 alpha-2 country code
postalCode?: string; // Postal/ZIP code
latitude?: number; // Latitude coordinate
longitude?: number; // Longitude coordinate
}
CancelPolicy
Cancellation policy details.
interface CancelPolicy {
refundable: boolean; // Can be cancelled for free?
cancelPenalties?: CancelPenalty[]; // Penalty rules
description?: string; // Human-readable description
}
interface CancelPenalty {
penaltyType: 'NIGHTS' | 'PERCENT' | 'IMPORT'; // Penalty calculation type
value: number; // Penalty amount
deadline: string; // ISO 8601 deadline (before this date)
currency?: string; // Currency for IMPORT type
}
Booking
A confirmed or pending reservation.
interface Booking {
id: string; // Bundleport booking ID
status: BookingStatus; // Current status
reference: BookingReference; // Booking references
hotel: Hotel; // Hotel information
stay: Stay; // Check-in/check-out dates
rooms: BookingRoom[]; // Booked rooms
holder: Holder; // Booking holder information
price: Price; // Final price
cancelPolicy?: CancelPolicy; // Cancellation policy
remarks?: string[]; // Booking remarks
createdAt: string; // ISO 8601 creation timestamp
updatedAt: string; // ISO 8601 last update timestamp
}
type BookingStatus =
| 'CONFIRMED'
| 'PENDING'
| 'ON_REQUEST'
| 'CANCELLED'
| 'MODIFIED'
| 'FAILED';
BookingReference
References for a booking.
interface BookingReference {
bookingID: string; // Bundleport booking ID
clientReference?: string; // Your internal reference
providerReference?: string; // Provider confirmation number
confirmationNumber?: string; // Hotel confirmation number
}
BookingRoom
A room within a booking.
interface BookingRoom {
description: string; // Room description
boardCode: string; // Board type
paxes: Pax[]; // Guest information
confirmationReference?: string; // Room-specific confirmation
price?: Price; // Room price
}
Holder
Booking holder (main guest).
interface Holder {
name: string; // First name
surname: string; // Last name
email: string; // Email address
phone?: string; // Phone number
nationality?: string; // ISO 3166-1 alpha-2 country code
}
Pax
Guest information.
interface Pax {
name: string; // First name
surname: string; // Last name
age?: number; // Age (for children)
type?: 'ADULT' | 'CHILD'; // Guest type
}
Tracing
Request processing visibility.
interface Tracing {
status: 'OK' | 'PARTIAL' | 'ERROR'; // Overall status
accessSpans: AccessSpan[]; // Per-provider details
processTime?: number; // Processing time in milliseconds
}
interface AccessSpan {
access: string; // Access ID (provider identifier)
status: 'OK' | 'ERROR' | 'TIMEOUT';
hotelsRequested?: number; // Hotels requested from provider
hotelsReturned?: number; // Hotels returned by provider
errorCode?: string; // Error code if status is ERROR
errorDescription?: string; // Error description
processTime?: number; // Provider response time
}
Warning
Non-fatal issue that doesn't prevent request success.
interface Warning {
code: string; // Warning code (e.g., "WARN_CODE_NONE")
description: string; // Human-readable description
connectionCode?: string; // Connection code associated with warning
additionalData?: Record<string, string>; // Additional context data
}
Common Warning Types
| Warning Type | Description |
|---|---|
PARTIAL_RESPONSE | One or more providers failed or timed out |
PRICE_CHANGED | Price changed since search |
NO_MARKUP_CONFIGURED | Connection has no margin; selling price uses provider gross/suggested |
Example warning for no markup configured:
{
"code": "WARN_CODE_NONE",
"description": "No markup configured for connection; selling price uses provider gross/suggested",
"connectionCode": "testb-hbds-1876",
"additionalData": {
"warning_type": "NO_MARKUP_CONFIGURED",
"connection_code": "testb-hbds-1876"
}
}
Error
Error information.
interface Error {
code: string; // Error code
type: 'CLIENT' | 'SERVER'; // Error type
message: string; // Human-readable message
description?: string; // Detailed description
details?: Record<string, any>; // Additional error details
field?: string; // Related field (if applicable)
}
Common Field Types
Text
Multi-language text content.
interface Text {
type?: string; // Text type (description, shortDescription, etc.)
languageCode: string; // ISO 639-1 language code
text: string; // Text content
}
Media
Image or video media.
interface Media {
url: string; // Media URL
mediaType?: 'IMAGE' | 'VIDEO'; // Media type
caption?: string; // Caption
width?: number; // Width in pixels
height?: number; // Height in pixels
orderIndex?: number; // Display order
isPrimary?: boolean; // Is primary image?
}
Amenity
Hotel or room amenity.
interface Amenity {
code: string; // Amenity code
name?: string; // Amenity name
type?: string; // Amenity type/category
description?: string; // Description
}
Next Steps
- API Reference - Complete OpenAPI schemas
- Key Concepts - Understand how these models are used
- Connect Hotels Overview - See models in action