Quick Start
Make your first Hotel Data API call and build a foundation for integrating room and property data into your application.
Fetch all properties
The /properties endpoint returns all registered hotel properties. This is usually the starting point for any integration.
"color:#c4b5fd">const BASE_URL = "https:">//hotel-data.k3s.ahsm-krakow.com/api/v1";
"color:#c4b5fd">const response = "color:#c4b5fd">await fetch("color:#86efac">`${BASE_URL}/properties`);
"color:#c4b5fd">if (!response.ok) {
"color:#c4b5fd">throw "color:#c4b5fd">new Error("color:#86efac">`API error: ${response.status}`);
}
"color:#c4b5fd">const { data } = "color:#c4b5fd">await response.json();
console.log(data); "color:#6b7280">// Property[]Example response
{
"data": [
{
"id": "apt",
"name": "Aparthotel Stare Miasto",
"slug": "aparthotel-stare-miasto",
"enabled": true,
"total_rooms": 32
},
{
"id": "krw",
"name": "Krowoderska 66B Apartments",
"slug": "krowoderska-66b",
"enabled": true,
"total_rooms": 12
}
]
}Explore room types
Room types define the template for rooms — amenities, size, and category. Filter by property_id, category, has_balcony, and more.
"color:#c4b5fd">const BASE_URL = "https:">//hotel-data.k3s.ahsm-krakow.com/api/v1";
"color:#6b7280">// List all room types for a property
"color:#c4b5fd">const response = "color:#c4b5fd">await fetch("color:#86efac">`${BASE_URL}/room-types?property_id=apt`);
"color:#c4b5fd">const { data: roomTypes } = "color:#c4b5fd">await response.json();
"color:#6b7280">// Find all suites with balconies
"color:#c4b5fd">const suitesWithBalconies = "color:#c4b5fd">await fetch(
"color:#86efac">`${BASE_URL}/room-types?property_id=apt&category=suite&has_balcony=true`
).then((r) => r.json());Example response
{
"data": [
{
"id": "apt-penthouse",
"property_id": "apt",
"name": "Penthouse Suite",
"category": "suite",
"max_guests": 4,
"size_m2": 85,
"has_hot_tub": true,
"has_balcony": true,
"is_duplex": true,
"active": true
}
]
}Look up individual rooms
Individual rooms are physical units within a property. Always pass property_id when fetching a single room — room numbers are not globally unique across properties.
"color:#c4b5fd">const BASE_URL = "https:">//hotel-data.k3s.ahsm-krakow.com/api/v1";
"color:#6b7280">// All rooms on floor 3 at apt
"color:#c4b5fd">const response = "color:#c4b5fd">await fetch(
"color:#86efac">`${BASE_URL}/rooms?property_id=apt&floor=3`
);
"color:#c4b5fd">const { data: rooms } = "color:#c4b5fd">await response.json();
"color:#6b7280">// Single room lookup (property_id is required)
"color:#c4b5fd">const room = "color:#c4b5fd">await fetch(
"color:#86efac">`${BASE_URL}/rooms/301?property_id=apt`
).then((r) => r.json());Example response
{
"data": {
"number": "301",
"property_id": "apt",
"floor": 3,
"room_type_id": "apt-studio",
"active": true,
"room_type": {
"id": "apt-studio",
"name": "Studio",
"max_guests": 2,
"size_m2": 28
}
}
}Production tips
Error handling with retries
Network errors and transient server failures happen. Use exponential backoff to retry safely.
"color:#c4b5fd">async "color:#c4b5fd">function fetchWithRetry(url: string, retries = 3): Promise<Response> {
for ("color:#c4b5fd">let attempt = 0; attempt < retries; attempt++) {
"color:#c4b5fd">try {
"color:#c4b5fd">const response = "color:#c4b5fd">await fetch(url, {
signal: AbortSignal.timeout(10_000), "color:#6b7280">// 10s timeout
});
"color:#6b7280">// Don't retry client errors (4xx)
"color:#c4b5fd">if (response.status >= 400 && response.status < 500) {
"color:#c4b5fd">throw "color:#c4b5fd">new Error("color:#86efac">`Client error ${response.status}`);
}
"color:#c4b5fd">if (!response.ok) {
"color:#c4b5fd">throw "color:#c4b5fd">new Error("color:#86efac">`Server error ${response.status}`);
}
"color:#c4b5fd">return response;
} "color:#c4b5fd">catch (err) {
"color:#c4b5fd">if (attempt === retries - 1) "color:#c4b5fd">throw err;
"color:#6b7280">// Exponential backoff: 1s, 2s, 4s
"color:#c4b5fd">await "color:#c4b5fd">new Promise((r) => setTimeout(r, 1000 * 2 ** attempt));
}
}
"color:#c4b5fd">throw "color:#c4b5fd">new Error("Max retries exceeded");
}Client-side caching
Property and room-type data changes infrequently. Cache responses on the client to reduce latency and server load.
"color:#6b7280">// Cache property list for 5 minutes
"color:#c4b5fd">const CACHE_TTL_MS = 5 * 60 * 1000;
"color:#c4b5fd">const cache = "color:#c4b5fd">new Map<string, { data: unknown; expiresAt: number }>();
"color:#c4b5fd">async "color:#c4b5fd">function fetchCached(url: string): Promise<unknown> {
"color:#c4b5fd">const cached = cache.get(url);
"color:#c4b5fd">if (cached && cached.expiresAt > Date.now()) {
"color:#c4b5fd">return cached.data;
}
"color:#c4b5fd">const response = "color:#c4b5fd">await fetch(url);
"color:#c4b5fd">const data = "color:#c4b5fd">await response.json();
cache.set(url, { data, expiresAt: Date.now() + CACHE_TTL_MS });
"color:#c4b5fd">return data;
}
"color:#6b7280">// Usage
"color:#c4b5fd">const properties = "color:#c4b5fd">await fetchCached("color:#86efac">`${BASE_URL}/properties`);Recommended cache TTLs
| Resource | Suggested TTL |
|---|---|
| Properties | 5 minutes |
| Room Types | 5 minutes |
| Rooms | 2 minutes |
| Summary | 1 minute |
| Issues | 30 seconds |
| Maintenance Schedules | 1 minute |