Overview
The HotelifyPMS API allows you to integrate with our property management system to check room availability, create reservations, and manage bookings programmatically.
Base URL
https://your-domain.com/api/v1Content Type
application/jsonAvailable Endpoints
/availability/reservations/reservations/reservations/:id/reservations/:id/pdf/reservations/:id/reservations/:idAuthentication
All API requests require authentication using an API key. You can create and manage API keys from the Settings > API Keys page in your dashboard.
Request Headers
# Using Authorization header (recommended)
curl -X GET "https://your-domain.com/api/v1/availability" \
-H "Authorization: Bearer htl_your_api_key_here"
# Or using X-API-Key header
curl -X GET "https://your-domain.com/api/v1/availability" \
-H "X-API-Key: htl_your_api_key_here"Keep your API keys secure
Never expose your API keys in client-side code or public repositories. Use environment variables and server-side requests only.
API Key Permissions
| Permission | Description | Endpoints |
|---|---|---|
read | Read-only access | GET endpoints |
write | Create and modify resources | POST, PATCH, DELETE endpoints |
Rate Limits
API requests are rate-limited to ensure fair usage and system stability. The default limit is 60 requests per minute per API key.
Rate Limit Headers
| Header | Description |
|---|---|
X-RateLimit-Limit | Maximum requests per minute |
X-RateLimit-Remaining | Remaining requests in current window |
X-RateLimit-Reset | Time when the rate limit resets |
Error Handling
The API returns consistent error responses with helpful error codes and messages.
Error Response Format
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Missing required fields: checkIn, checkOut",
"details": {
"missingFields": ["checkIn", "checkOut"]
}
},
"meta": {
"requestId": "req_abc123def456",
"timestamp": "2026-01-10T12:00:00.000Z"
}
}Error Codes
| Code | HTTP Status | Description |
|---|---|---|
MISSING_API_KEY | 401 | No API key provided |
INVALID_API_KEY | 401 | Invalid or unknown API key |
INSUFFICIENT_PERMISSIONS | 403 | API key lacks required permission |
RATE_LIMIT_EXCEEDED | 429 | Too many requests |
VALIDATION_ERROR | 400 | Invalid request parameters |
NOT_FOUND | 404 | Resource not found |
NO_AVAILABILITY | 409 | No rooms available for dates |
Check Availability
/availabilityReturns available room types with pricing for the specified date range and guest count.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
checkIn | string | Check-in date (YYYY-MM-DD) | |
checkOut | string | Check-out date (YYYY-MM-DD) | |
adults | integer | — | Number of adults (default: 2) |
children | integer | — | Number of children (default: 0) |
childAges | array | — | Ages of children for pricing |
roomTypeId | uuid | — | Filter to specific room type |
Example Request
curl -X GET "https://your-domain.com/api/v1/availability?checkIn=2026-02-15&checkOut=2026-02-18&adults=2&children=1&childAges=[8]" \
-H "Authorization: Bearer htl_your_api_key"Example Response
{
"success": true,
"data": {
"searchParams": {
"checkIn": "2026-02-15",
"checkOut": "2026-02-18",
"nights": 3,
"adults": 2,
"children": 1,
"childAges": [8]
},
"availability": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Deluxe Double Room",
"nameBg": "Двойна стая Делукс",
"description": "Spacious room with mountain view",
"roomDetails": {
"sizeSqm": 35,
"totalBeds": 2,
"bedConfiguration": [
{
"type": "king",
"name": "King Bed",
"nameBg": "Голямо легло",
"count": 1,
"maxAdults": 2,
"maxChildren": 1
}
],
"amenities": [
{ "id": "a1", "name": "Free WiFi", "nameBg": "Безплатен WiFi", "category": "connectivity", "icon": "wifi" },
{ "id": "a2", "name": "Air Conditioning", "nameBg": "Климатик", "category": "comfort", "icon": "air-conditioning" },
{ "id": "a3", "name": "Minibar", "nameBg": "Минибар", "category": "amenity", "icon": "minibar" }
]
},
"capacity": {
"maxAdults": 2,
"maxChildren": 2,
"maxOccupancy": 4,
"baseOccupancy": 2
},
"imageUrl": "https://example.com/room.jpg",
"availableRooms": 5,
"ratePlans": [
{
"id": "660e8400-e29b-41d4-a716-446655440001",
"name": "Bed & Breakfast",
"mealPlan": {
"code": "BB",
"name": "Bed & Breakfast",
"nameBg": "Нощувка и закуска",
"description": "Start your day with our rich buffet breakfast",
"includes": ["Buffet breakfast", "Coffee & tea all day"],
"breakfast": {
"type": "buffet",
"time": "07:00-10:00",
"location": "Main Restaurant"
},
"lunch": null,
"dinner": null,
"serviceTimes": "Breakfast: 07:00-10:00"
},
"pricing": {
"baseRoomRate": 300.00,
"additionalAdultCharge": 0,
"additionalChildCharge": 52.50,
"pricePerNight": 117.50,
"totalPrice": 352.50,
"currency": "EUR"
}
}
]
}
],
"totalRoomTypes": 1
},
"meta": {
"requestId": "req_abc123def456",
"timestamp": "2026-01-10T12:00:00.000Z"
}
}Meal Plan Object
Each rate plan includes detailed meal plan information with the following structure:
| Field | Type | Description |
|---|---|---|
code | string | Meal plan code (RO, BB, HB, FB, AI) |
name | string | Meal plan name in English |
nameBg | string | Meal plan name in Bulgarian |
description | string | null | Description of what's included |
includes | string[] | Array of included items/services |
breakfast | object | null | Breakfast details: type, time, location |
lunch | object | null | Lunch details: type, time, location |
dinner | object | null | Dinner details: type, time, location |
serviceTimes | string | null | Human-readable service times summary |
Room Details Object
Each room type includes detailed information about the room:
| Field | Type | Description |
|---|---|---|
sizeSqm | number | null | Room size in square meters |
totalBeds | number | Total number of beds in the room |
bedConfiguration | array | Array of bed types with count and capacity |
amenities | array | Room amenities (WiFi, AC, TV, etc.) |
Bed Configuration Object
| Field | Type | Description |
|---|---|---|
type | string | Bed type code (king, queen, twin, single, sofa) |
name | string | Bed name in English |
nameBg | string | null | Bed name in Bulgarian |
count | number | Number of this bed type in the room |
maxAdults | number | Maximum adults this bed can accommodate |
maxChildren | number | Maximum children this bed can accommodate |
Create Reservation
/reservationsCreates a new reservation with the specified details. Requires write permission.
Request Body
{
"checkIn": "2026-02-15",
"checkOut": "2026-02-18",
"roomTypeId": "550e8400-e29b-41d4-a716-446655440000",
"ratePlanId": "660e8400-e29b-41d4-a716-446655440001",
"rooms": 1,
"adults": 2,
"children": 1,
"childAges": [8],
"guest": {
"firstName": "John",
"lastName": "Doe",
"email": "john.doe@example.com",
"phone": "+359888123456",
"nationality": "BG",
"address": {
"street": "123 Main Street",
"city": "Sofia",
"postalCode": "1000",
"country": "BG"
}
},
"specialRequests": "Late check-in around 22:00",
"externalReference": "PARTNER-BOOKING-123"
}Example Response
{
"success": true,
"data": {
"reservation": {
"id": "770e8400-e29b-41d4-a716-446655440002",
"confirmationNumber": "API-LXYZ123-AB",
"status": "confirmed",
"paymentStatus": "pending",
"checkIn": "2026-02-15",
"checkOut": "2026-02-18",
"nights": 3,
"roomsBooked": 1,
"roomType": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Deluxe Double Room",
"nameBg": "Двойна стая Делукс",
"maxOccupancy": 4,
"baseOccupancy": 2
},
"ratePlan": {
"id": "660e8400-e29b-41d4-a716-446655440001",
"name": "Bed & Breakfast",
"mealPlan": {
"code": "BB",
"name": "Bed & Breakfast",
"nameBg": "Нощувка и закуска",
"description": "Start your day with our rich buffet breakfast",
"includes": ["Buffet breakfast", "Coffee & tea all day"],
"breakfast": { "type": "buffet", "time": "07:00-10:00", "location": "Main Restaurant" }
},
"rateCategory": { "name": "Standard", "isRefundable": true, "discountPercentage": 0 }
},
"guest": {
"id": "880e8400-e29b-41d4-a716-446655440003",
"firstName": "John",
"lastName": "Doe",
"email": "john.doe@example.com",
"phone": "+359888123456",
"nationality": "BG"
},
"guests": { "adults": 2, "children": 1, "childAges": [8], "total": 3 },
"pricing": {
"baseRoomRate": 300.00,
"pricePerNight": 100.00,
"additionalAdultCharge": 0,
"additionalChildCharge": 52.50,
"childCharges": [{ "age": 8, "percentage": 50, "charge": 52.50 }],
"totalAmount": 352.50,
"paidAmount": 0,
"balanceDue": 352.50,
"currency": "EUR",
"dailyRates": [
{ "date": "2026-02-15", "rate": 100.00 },
{ "date": "2026-02-16", "rate": 100.00 },
{ "date": "2026-02-17", "rate": 100.00 }
]
},
"specialRequests": "Late check-in around 22:00",
"externalReference": "PARTNER-BOOKING-123",
"source": "api",
"createdAt": "2026-01-10T12:00:00.000Z"
},
"hotel": {
"name": "Hotel Pirin SKI & SPA",
"phone": "+359896699009",
"email": "sales@hotelpirin.com",
"address": "Tsar Simeon 68, Bansko 2770",
"checkInTime": "14:00",
"checkOutTime": "11:00"
},
"links": {
"self": "/api/v1/reservations/770e8400-e29b-41d4-a716-446655440002",
"confirmationLink": "/api/v1/reservations/770e8400-e29b-41d4-a716-446655440002/confirmation-link",
"pdf": "/api/v1/reservations/770e8400-e29b-41d4-a716-446655440002/pdf"
}
},
"meta": {
"requestId": "req_def456ghi789",
"timestamp": "2026-01-10T12:00:00.000Z"
}
}Get Reservation
/reservations/:idRetrieves detailed information about a specific reservation by ID or confirmation number.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
id | string | Reservation UUID or confirmation number |
Example Request
# By UUID
curl -X GET "https://your-domain.com/api/v1/reservations/770e8400-e29b-41d4-a716-446655440002" \
-H "Authorization: Bearer htl_your_api_key"
# By confirmation number
curl -X GET "https://your-domain.com/api/v1/reservations/API-LXYZ123-AB" \
-H "Authorization: Bearer htl_your_api_key"Search Reservations
/reservationsSearch reservations with various filters and pagination support.
Query Parameters
| Parameter | Type | Description |
|---|---|---|
confirmationNumber | string | Search by confirmation number |
guestEmail | string | Filter by guest email |
guestName | string | Search by guest name |
checkInFrom | string | Filter by check-in date (from) |
checkInTo | string | Filter by check-in date (to) |
status | string | Filter by status |
externalReference | string | Filter by external reference |
limit | integer | Results per page (max: 100) |
offset | integer | Pagination offset |
Example Request
curl -X GET "https://your-domain.com/api/v1/reservations?checkInFrom=2026-02-01&checkInTo=2026-02-28&status=confirmed&limit=20" \
-H "Authorization: Bearer htl_your_api_key"Example Response
{
"success": true,
"data": {
"reservations": [
{
"id": "770e8400-e29b-41d4-a716-446655440002",
"confirmationNumber": "API-LXYZ123-AB",
"status": "confirmed",
"paymentStatus": "pending",
"checkIn": "2026-02-15",
"checkOut": "2026-02-18",
"nights": 3,
"guests": {
"adults": 2,
"children": 1,
"childAges": [8]
},
"roomsRequested": 1,
"roomType": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Deluxe Double Room",
"nameBg": "Двойна стая Делукс"
},
"guest": {
"id": "880e8400-e29b-41d4-a716-446655440003",
"firstName": "John",
"lastName": "Doe",
"email": "john.doe@example.com"
},
"pricing": {
"totalAmount": 352.50,
"paidAmount": 0,
"balance": 352.50,
"currency": "EUR"
},
"createdAt": "2026-01-10T12:00:00.000Z"
}
],
"pagination": {
"total": 42,
"limit": 20,
"offset": 0,
"hasMore": true
}
},
"meta": {
"requestId": "req_ghi789jkl012",
"timestamp": "2026-01-10T12:00:00.000Z"
}
}Download PDF
/reservations/:id/pdfGenerate and download a confirmation PDF for a specific reservation. The PDF includes hotel details, reservation dates, guest information, room details, and pricing.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
id | string | Reservation UUID or confirmation number |
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
format | string | binary | Output format: binary (direct download) or base64 (JSON with base64 encoded PDF) |
Example Request
# Download PDF directly (binary)
curl -X GET "https://your-domain.com/api/v1/reservations/API-LXYZ123-AB/pdf" \
-H "Authorization: Bearer htl_your_api_key" \
-o confirmation.pdf
# Get PDF as base64 JSON
curl -X GET "https://your-domain.com/api/v1/reservations/API-LXYZ123-AB/pdf?format=base64" \
-H "Authorization: Bearer htl_your_api_key"Response (binary format)
application/pdfattachment; filename="Confirmation-API-LXYZ123-AB.pdf"Response (base64 format)
{
"success": true,
"data": {
"filename": "Confirmation-API-LXYZ123-AB.pdf",
"contentType": "application/pdf",
"base64": "JVBERi0xLjQKMSAwIG9iago8PAovVHlwZSAvQ2F0YWxvZw..."
},
"meta": {
"requestId": "req_pdf123abc456",
"timestamp": "2026-01-10T12:00:00.000Z"
}
}PDF Contents
The generated PDF includes: hotel branding, confirmation number, check-in/out dates, room type, meal plan, guest details, pricing summary, payment status, and special requests.
Create Confirmation Link
/reservations/:id/confirmation-linkCreates a secure confirmation URL with an embedded Stripe payment session for deposit collection. The link can be sent to guests via email, allowing them to view their reservation details and pay their deposit online.
Request Body (Optional)
{
"deposit": {
"type": "percentage",
"value": 30,
"currency": "EUR"
},
"expiresIn": 72,
"locale": "en",
"successRedirectUrl": "https://hotelpirin.com/thank-you",
"cancelRedirectUrl": "https://hotelpirin.com/booking-cancelled",
"metadata": {
"source": "email_agent",
"leadId": "uuid-of-lead"
}
}Request Parameters
| Field | Type | Default | Description |
|---|---|---|---|
deposit.type | string | "percentage" | "percentage" or "fixed" |
deposit.value | number | 30 | Amount (0-100 for %, or fixed amount) |
expiresIn | number | 72 | Hours until link expires |
locale | string | "en" | Confirmation page language (en, bg) |
metadata | object | {} | Additional data to attach to payment |
Example Response
{
"success": true,
"data": {
"confirmationUrl": "https://hotelpirin.com/confirm/abc123def456",
"paymentUrl": "https://checkout.stripe.com/pay/cs_live_...",
"expiresAt": "2026-01-24T14:30:00.000Z",
"reservation": {
"confirmationNumber": "HP-2026-001234",
"guestName": "John Doe",
"checkIn": "2026-03-10",
"checkOut": "2026-03-15",
"roomType": "Deluxe Double Room",
"totalAmount": 630.00,
"depositAmount": 189.00,
"currency": "EUR"
}
},
"meta": {
"requestId": "req_abc123",
"timestamp": "2026-01-21T14:30:00.000Z"
}
}Example Usage
curl -X POST "https://api.hotelpirin.com/api/v1/reservations/HP-2026-001234/confirmation-link" \
-H "Authorization: Bearer htl_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"deposit": {"type": "percentage", "value": 30}, "expiresIn": 72}'Cancel Reservation
/reservations/:idImportant
The DELETE endpoint does not permanently delete a reservation. Instead, it changes the reservation status to cancelled and records the cancellation timestamp and reason. This preserves the booking history for auditing and reporting purposes.
Cancel a reservation by ID or confirmation number. The reservation will be marked as cancelled along with all associated room assignments and stays. Open folios will be closed.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
id | string | Reservation UUID or confirmation number |
Request Body (Optional)
| Field | Type | Description |
|---|---|---|
reason | string | Optional reason for cancellation |
Validation Rules
- Cannot cancel a reservation that is already cancelled
- Cannot cancel a reservation that has been checked out
Example Request
curl -X DELETE "https://api.hotelify.com/api/v1/reservations/API-LXYZ123-AB" \
-H "Authorization: Bearer htl_your_api_key" \
-H "Content-Type: application/json" \
-d '{"reason": "Guest requested cancellation"}'Example Response
{
"success": true,
"data": {
"reservation": {
"id": "abc123-def456-ghi789",
"confirmationNumber": "API-LXYZ123-AB",
"status": "cancelled",
"cancelledAt": "2026-01-10T14:30:00.000Z",
"cancellationReason": "Guest requested cancellation"
},
"message": "Reservation cancelled successfully."
},
"meta": {
"requestId": "req_cancel123",
"timestamp": "2026-01-10T14:30:00.000Z"
}
}Need help? Contact us at support@hotelify.com