Content Catalog Overview
The Content API provides access to static and semi-static hotel catalog data. Use it to build search filters, display hotel information, and synchronize your local catalog.
What is Content API?
The Content API serves catalog data that doesn't change frequently:
- Hotels – Hotel information, descriptions, amenities, media, and geo enrichment (canonical city, country, closest destinations, region)
- Rooms – Room types, descriptions, images, occupancy details
- Destinations – Cities, regions, airports with hierarchical structure
- Boards – Meal plans (RO, BB, HB, FB, AI)
- Categories – Hotel categories and classifications
Hotel responses include location enrichment when available: countryName, canonicalCityPlaceId, region, closestDestinations (e.g. city and region names), locationPath (breadcrumb like "Madrid, Community of Madrid, Spain"), and optional POI distances (airport, beach, train station).
How this fits with live booking
Use Content API for what to show in your UI and filters; use Booking API for prices and reservations. See Key concepts — Static vs transactional data for the canonical explanation.
Content Structure
Content Catalog
├── Hotels
│ ├── Basic info (name, description, location)
│ ├── Amenities, media, rooms
│ ├── Geo enrichment (canonical city, country, region, closest destinations)
│ └── Optional: POI distances, locationPath, imageBaseUrl
├── Rooms
│ ├── Description, images, occupancy, bed configuration
├── Destinations
│ ├── Hierarchical structure (country → region → city)
│ └── Geographic coordinates
├── Boards
│ └── Meal plan definitions
└── Categories
└── Hotel classifications
Hotel endpoints
POST /content/hotels/v1/hotels– List or get hotels by query (connection, codes, destination, etc.). Preferscopeoverqueryfor filters.POST /content/hotels/v1/hotels/by-base-codes– Get hotel content by Bundleport base codes (e.g. for mapping/base-code–based UIs). Supports preferred content source and multiple sources per hotel.POST /content/hotels/v1/hotels/filter– Filter hotel codes by criteria (canonical city, country, categories, boards, nearby, etc.) with keyset pagination. Use before availability search to reduce payload.
Common use cases
1. Build search filters
Load destinations and boards (and optionally categories) from Content API on a schedule—e.g. nightly or weekly—and populate dropdowns. Keep this data separate from live availability: users still need a Booking API search for current price and inventory.
2. Display hotel information
For a hotel detail page, fetch hotel content by code (or base code) from Content API. Show descriptions, amenities, media, and enriched location fields. When the user picks dates, run availability with hotel codes from your cached catalog or from filter endpoints.
3. Pre-filter before availability
Use POST /content/hotels/v1/hotels/filter (or equivalent list endpoints) to obtain a bounded set of hotel codes for a destination or policy. Pass those codes in criteria.hotels on availability to reduce payload and latency. See Hotels.
4. Synchronize a local catalog
A local mirror lets you serve fast hotel pages and filters without hitting Content API on every HTTP request. Typical shape:
- Bootstrap – Run a full pass per
connectionCode(or per environment) using list endpoints that return a continuation token. Persisttokenhandling in one worker so retries stay idempotent. - Normalize – Store stable primary keys (
hotelCode, base codes, provider codes) and keep raw JSON or a subset of fields you render in the UI; attachupdatedAtor audit fields when the API exposes them. - Refresh – Schedule nightly or weekly full re-syncs for static-heavy objects (destinations, boards) and shorter TTLs for hotels if you show amenities or media that change often. Prefer incremental updates (only changed IDs) when you have audit or “since” APIs.
- Failure modes – If a page fails mid-run, resume from the last persisted token or restart with
token: nulland de-duplicate in your DB. Never assume tokens survive process restarts—treat them as ephemeral (see Pagination with Tokens below).
Optional implementation sketch:
// Initial sync - get all hotels (pseudo-code; adapt to your client)
let token = null;
let allHotels = [];
do {
const result = await getHotels({
query: { maxSize: 1000 },
token,
});
allHotels.push(...result.hotels.hotels);
token = result.hotels.token;
} while (token);
// Store in local database
await syncHotelsToDatabase(allHotels);
Filtering and Pagination
All content endpoints support:
- Filtering by connection code - Get content for specific providers
- Filtering by codes - Get specific hotels, rooms, destinations
- Pagination - Use tokens for large result sets
- Max size - Limit number of results per request
Example: Filtered query (prefer scope)
{
"scope": {
"connectionCode": "CONN_1",
"hotelCodes": ["12345", "67890"],
"maxSize": 50
},
"token": null
}
Use scope as the preferred field for filters; query is supported for backwards compatibility. When connectionCode is set, the provider is resolved automatically (use X-Environment: test or prod as needed).
Pagination with Tokens
Content API uses token-based pagination:
// First page
const page1 = await getHotels({
query: { maxSize: 100 },
token: null,
});
// Next page
const page2 = await getHotels({
query: { maxSize: 100 },
token: page1.hotels.token, // Use token from previous response
});
// Continue until token is null
Important:
- Tokens are valid for 4 minutes
- Tokens are tied to the original query criteria
- If query changes, start with a new token (null)
Best Practices
1. Cache Content Data
// Cache destinations for 24 hours
const destinations = await cache.get('destinations', async () => {
return await getDestinations({ query: {} });
}, { ttl: 24 * 60 * 60 * 1000 }); // 24 hours
2. Incremental Sync
// Sync only changed content
const auditHistory = await getScopeAuditHistory({
contentType: 'hotel',
contentID: '12345',
limit: 100,
});
// Update only changed hotels
for (const record of auditHistory.auditRecords) {
if (record.action === 'updated') {
await syncHotel(record.contentID);
}
}
3. Batch Requests
// Get multiple hotels in one request
const hotels = await getHotels({
query: {
hotelCodes: ['12345', '67890', '11111'],
maxSize: 100,
},
});
Endpoints
| Endpoint | Description |
|---|---|
| Hotels | List/get hotels; pagination with token |
| Hotels by base codes | Get content by Bundleport base codes |
| Hotel filter | Filter hotel codes (geo, categories, boards, etc.) |
| Rooms | Room types and details |
| Destinations | Locations and hierarchy |
| Boards | Meal plans |
| Categories | Hotel categories |
Next Steps
- Hotels Catalog – Access hotel information, by-base-codes, and filter
- Rooms Catalog – Get room type details
- Content API Reference – Full request/response schemas and parameters