Development Environment • Version in Testing
Perlatours Booking API
Comprehensive documentation for the Perlatours Booking API, detailing endpoints, data models, and authentication requirements.
Available Endpoints
dev.api.perlatours.comBooking API
Complete booking flow from search to cancellation
/Booking/Search/Booking/Prebook/Booking/Book/Booking/GetBooking/Booking/CancelInventory Endpoints
Access to hotel inventory data and system catalogs
/Inventory/GetHotels/Inventory/GetMealPlans/Inventory/GetRoomTypes/Inventory/GetRoomAmenities/Inventory/GetHotelTypes/Inventory/GetHotelCategories/Inventory/GetHotelChains/Inventory/Markets/Inventory/Nationalities/Inventory/Currencies/Inventory/Languages/Inventory/AllCountries/Inventory/AllCurrencies/Inventory/AllLanguages/Inventory/BookingFlowStatusesAuthentication
Authentication is required to access all endpoints in this API. Clients must include a valid authentication token (JWT Bearer) in the Authorization header of their requests.
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...Postman Collection
Download the complete Postman collection with all endpoints configured and ready to use.
Quick instructions:
Download → Import to Postman → Configure your token → Test endpoints!
Changelog
Recent updates and improvements to the Perlatours API.
The pvpRequired field was already present in actual API responses (visible in logs and sample payloads) but was not documented. It is now in the OptionPrice model and in every Search, Prebook, Book, GetBooking and surcharge example.
New Field
pvpRequired(bool) — when true, the agency must display pvpAmount to the end customer (rate fixed by the provider); when false, pvpAmount is a reference value and the agency may apply its own markup on top of netAmount
Significant documentation improvements, new error codes and rate limiting sections, and AI-assisted integration guide.
New Sections
- Complete Error Codes section with categories (Validation, Auth, System, Business, Connector, Rate Limit)
- Rate Limiting documentation with headers (X-RateLimit-Limit, X-RateLimit-Remaining, Retry-After)
- AI Integration Guide — copyable prompt for Claude Code or any AI coding assistant
Documentation Improvements
- Explanation of two response patterns: paginated (GetHotels) vs direct array (catalogs)
- All inventory response examples now show the full CommonRs wrapper
- Date validation rules documented (checkIn must be future, checkOut must be after checkIn)
- PVP sandbox warning (may return 0 in test environments)
- Cancel endpoint now documents the price field with penalty details
- hotelIds accepts both numbers and strings
Naming Clarifications
RoomAmenities— covers all room characteristics, not just amenitiesHotelTypes— covers all accommodation types (apartments, villas, resorts, etc.)HotelCategories— general categories applicable to any accommodation type
Added new descriptive fields across all booking operations to provide human-readable names alongside IDs.
Search Response
accommodations.name- Accommodation nameoptions.mealPlanName- Meal plan namerooms.name- Room namerooms.roomTypeId- Room type identifier
Prebook, Book & GetBooking Responses
hotelId,hotelName- Hotel identifier and namemealPlanId,mealPlanName- Meal plan identifier and namerooms.name,rooms.roomTypeId- Room details
- Added Inventory API endpoints (Hotels, Meal Plans, Room Types, Room Amenities, Hotel Types, Hotel Categories)
- TravelgateX (TGX) integration support
- Enhanced documentation with data models
- Initial release of Booking API
- Search, Prebook, Book, GetBooking, and Cancel endpoints
- JWT Bearer authentication
Detailed Endpoints
dev.api.perlatours.com/Booking/Search{
"metadata": {
"market": "ES",
"currency": "EUR",
"language": "ES",
"nationality": "ES"
},
"hotelIds": ["163608", "5628"],
"checkIn": "2026-09-01",
"checkOut": "2026-09-05",
"occupancies": [
{
"paxAges": [30, 28]
},
{
"paxAges": [60, 8]
}
],
"mealPlanId": "1",
"refundableOnly": false
}/Booking/Prebook{
"searchToken": "ABCDEF123456"
}/Booking/Book{
"prebookToken": "ZYXWVU987654",
"clientReference": "CLIENT-REF-001",
"holderName": "John",
"holderSurname": "Doe",
"paxes": [
{
"name": "John",
"surname": "Doe",
"age": 30
},
{
"name": "Jane",
"surname": "Doe",
"age": 28
}
],
"remarks": "Special requests: Late check-in"
}/Booking/GetBooking{
"locator": "LOCATOR-123"
}/Booking/GetList{
"filter": {
"updatedAtFrom": "2026-04-15T00:00:00Z",
"updatedAtTo": "2026-05-14T23:59:59Z",
"createdAtFrom": null,
"createdAtTo": null,
"checkInFrom": null,
"checkInTo": null,
"checkOutFrom": null,
"checkOutTo": null,
"status": null,
"statuses": ["BOOKED", "CANCELLED"],
"hotelId": null,
"mealPlanId": null,
"providerReference": null,
"clientReference": null
},
"pageSize": 50,
"pageToken": null,
"sort": "UpdatedAtDesc"
}pageToken; do not parse, reuse as-is./Booking/Cancel{
"locator": "LOCATOR-123"
}Inventory API response patterns
All Inventory API responses extend CommonRs (success, errorCode, errorMessages). There are two different response patterns depending on the endpoint:
GetHotels (paginated)
data contains a PaginatedResponse with nested data:
{ "data": {
"data": [...],
"pageNumber": 1,
"totalRecords": 50
},
"success": true
}Catalogs (direct array)
data directly contains the results array:
{ "data": [
{ "id": "BB", "name": "..." }
],
"language": "ES",
"success": true
}/Inventory/GetHotels{
"pageNumber": 1,
"pageSize": 10,
"usePagination": true,
"ids": [12345, 67890],
"name": "Hotel Example",
"location": "Madrid"
}/Inventory/GetMealPlans{
"ids": ["BB", "HB", "FB"],
"name": "Bed and Breakfast"
}/Inventory/GetRoomTypes{
"ids": ["SGL", "DBL", "TRP"],
"name": "Single Room"
}/Inventory/GetRoomAmenities{
"ids": ["WIFI", "AC", "TV"],
"name": "WiFi"
}/Inventory/GetHotelTypes{
"ids": [1, 2],
"name": "Resort"
}/Inventory/GetHotelCategories{
"ids": [1, 2],
"name": "5 estrellas"
}/Inventory/GetHotelChains{
"ids": [1, 2],
"name": "Perla"
}/Inventory/Markets{
"data": ["ES", "FR", "GB"],
"language": "ES",
"success": true
}/Inventory/Nationalities{
"data": ["ES", "FR", "DE"],
"language": "ES",
"success": true
}/Inventory/Currencies{
"data": ["EUR", "GBP", "USD"],
"language": "ES",
"success": true
}/Inventory/Languages{
"data": ["EN", "ES", "FR"],
"language": "ES",
"success": true
}/Inventory/AllCountries{
"data": ["AF", "AL", "DZ", "AR", "AU", "..."],
"language": "ES",
"success": true
}/Inventory/AllCurrencies{
"data": ["AED", "AFN", "ALL", "AMD", "EUR", "..."],
"language": "ES",
"success": true
}/Inventory/AllLanguages{
"data": ["AF", "AR", "BG", "BN", "EN", "ES", "..."],
"language": "ES",
"success": true
}/Inventory/BookingFlowStatuses{
"data": ["BOOKED", "CANCELLED", "ERROR", "SIMULATED"],
"language": "ES",
"success": true
}Data Models
These models are used across multiple endpoints or nested within other models.
| Field | Type | Required | Description |
|---|---|---|---|
| metadata | SearchMetadata | No | Metadata for the search. |
| hotelIds | List<long> | List<string> | Yes | List of hotel IDs to search. Accepts both numeric (163608) and string ("163608") formats. |
| mealPlanId | string | No | Optional meal plan ID to filter results. |
| checkIn | DateOnly | Yes | Check-in date (YYYY-MM-DD). Must be a future date. Returns error if date is in the past. |
| checkOut | DateOnly | Yes | Check-out date (YYYY-MM-DD). Must be after checkIn. Returns error if before or equal to checkIn. |
| occupancies | List<Occupancy> | Yes | List of occupancy details for each room requested. |
| refundableOnly | bool | No | Specifies if only refundable options should be returned. Default false. |
Search validations
The API validates input data and returns success: false with a descriptive message if:
checkInis a past date —"checkIn must be a future date"checkOutis before or equal tocheckIn—"checkOut must be after checkIn"- Required fields are missing —
"Required fields: hotelIds, checkIn, ..." - A metadata value (market, currency, language, nationality) is not allowed for your credential —
"Market 'FR' is not allowed for this credential. Allowed markets: ES"
| Field | Type | Required | Description |
|---|---|---|---|
| market | enum (string) | No | Market country code (ISO 3166-1 alpha-2). Must be a string name, not a numeric code. See accepted values in the SearchMetadata section. |
| currency | enum (string) | No | Currency code (ISO 4217 alpha-3). Must be a string name, not a numeric code. See accepted values in the SearchMetadata section. |
| language | enum (string) | No | Language code (ISO 639-1). Must be a string name, not a numeric code. See accepted values in the SearchMetadata section. |
| nationality | enum (string) | No | Guest nationality country code (ISO 3166-1 alpha-2). Must be a string name, not a numeric code. See accepted values in the SearchMetadata section. |
Important: Enum values in metadata
Metadata fields are enums serialized as strings. Only text names are accepted (e.g. "EUR", "ES", "EN"). Numeric codes (e.g. 978, 46) are not valid. If you send a value not allowed for your credential, the API will return success: false with a message indicating the allowed values (e.g. "Market 'FR' is not allowed for this credential. Allowed markets: ES").
To get the accepted values for your credential, query the Inventory API static endpoints:
GET /Inventory/MarketsGET /Inventory/CurrenciesGET /Inventory/LanguagesGET /Inventory/NationalitiesThese endpoints return the values configured for your credential. To see all possible system values, use the AllCountries, AllCurrencies, and AllLanguages endpoints.
| Field | Type | Required | Description |
|---|---|---|---|
| accommodations | List<SearchAccommodationData> | No | List of accommodations matching the search. Required if success. |
| success | bool | Yes | Indicates if the operation was successful. |
| errorMessages | List<string> | No | List of error messages, if any. |
| warningMessages | List<string> | No | List of warning messages, if any. |
| Field | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | The unique identifier for the accommodation. |
| name | string | No | The name of the accommodation. |
| options | List<SearchAccommodationOption> | Yes | List of available options for this accommodation. |
| Field | Type | Required | Description |
|---|---|---|---|
| mealPlanId | string | No | The identifier for the meal plan. |
| mealPlanName | string | No | The name of the meal plan. |
| rooms | List<OptionRoom> | Yes | List of rooms included in this option. |
| price | OptionPrice | Yes | The price details for this option. |
| cancellationPolicy | CancellationPolicy | Yes | The cancellation policy for this option. |
| surcharges | List<OptionSurcharge> | No | List of additional charges for this option. |
| searchToken | string | Yes | Token for prebook operation. |
| Field | Type | Required | Description |
|---|---|---|---|
| searchToken | string | Yes | The search token obtained from a search result option. |
| Field | Type | Required | Description |
|---|---|---|---|
| option | PrebookAccommodationOption | No | Details of the prebooked option. Required if success. |
| success | bool | Yes | Indicates if the operation was successful. |
| errorMessages | List<string> | No | List of error messages, if any. |
| warningMessages | List<string> | No | List of warning messages, if any. |
| Field | Type | Required | Description |
|---|---|---|---|
| hotelId | string | No | The hotel identifier. |
| hotelName | string | No | The name of the hotel. |
| mealPlanId | string | No | The meal plan identifier. |
| mealPlanName | string | No | The name of the meal plan. |
| rooms | List<OptionRoom> | No | List of rooms included in this option. |
| price | OptionPrice | Yes | Price details for the prebooked option. |
| cancellationPolicy | CancellationPolicy | No | Cancellation policy details. |
| surcharges | List<OptionSurcharge> | No | List of additional charges. |
| remarks | string | No | Additional remarks. |
| prebookToken | string | Yes | Token for booking operation. |
| Field | Type | Required | Description |
|---|---|---|---|
| prebookToken | string | Yes | Token obtained from successful prebook operation. |
| clientReference | string | Yes | Client's booking reference. |
| holderName | string | Yes | Main guest's first name. |
| holderSurname | string | Yes | Main guest's last name. |
| paxes | List<BookRqPax> | Yes | List of guest details. If empty list, holder will be first pax and UNDEFINED for the others. |
| remarks | string | No | Additional booking remarks. |
| Field | Type | Required | Description |
|---|---|---|---|
| booking | BookAccommodationOption | No | The confirmed booking with summary data. Required if success. |
| success | bool | Yes | Indicates if the operation was successful. |
| errorMessages | List<string> | No | List of error messages, if any. |
| warningMessages | List<string> | No | List of warning messages, if any. |
| Field | Type | Required | Description |
|---|---|---|---|
| bookingId | Guid | Yes | Unique identifier for the booking. |
| locator | string | Yes | Booking locator for future operations (GetBooking, Cancel). |
| hotelId | string | No | The hotel identifier. |
| hotelName | string | No | The name of the hotel. |
| mealPlanId | string | No | The meal plan identifier. |
| mealPlanName | string | No | The name of the meal plan. |
| price | OptionPrice | Yes | Price details for the booking. |
| status | BookingFlowStatus | Yes | Current status of the booking. |
| rooms | List<BookAccommodationRoom> | Yes | List of booked rooms. |
| remarks | string | No | Additional booking remarks. |
| Field | Type | Required | Description |
|---|---|---|---|
| name | string | No | The name of the room. |
| roomTypeId | string | No | The room type identifier. |
| roomType | string | Yes | Room type identifier. |
| roomAmenityIds | List<string> | No | List of room amenity identifiers. |
| paxes | List<BookAccommodationRoomPax> | Yes | List of guests in the room. |
| Field | Type | Required | Description |
|---|---|---|---|
| age | int | Yes | Guest's age. |
| name | string | Yes | Guest's first name. |
| surname | string | Yes | Guest's last name. |
| Field | Type | Required | Description |
|---|---|---|---|
| locator | string | Yes | The booking locator to cancel. |
| Field | Type | Required | Description |
|---|---|---|---|
| status | BookingFlowStatus | Yes | Indicates booking status. |
| price | CancelOptionPrice? | No | Cancellation cost. Null if no penalty applies. |
| success | bool | Yes | Indicates if the operation was successful. |
| errorMessages | List<string> | No | List of error messages, if any. |
| warningMessages | List<string> | No | List of warning messages, if any. |
| Field | Type | Required | Description |
|---|---|---|---|
| netAmount | decimal | Yes | Cancellation penalty amount. |
| currency | string | No | Currency code (ISO 4217). |
Note: Cancellation in sandbox environment
In the sandbox environment, all test bookings are refundable. The price field may be null or contain netAmount of 0.00, as no real penalties are generated. This is expected behavior. In production, if the cancellation is made outside the free cancellation period, price will contain the actual penalty cost.
| Field | Type | Required | Description |
|---|---|---|---|
| paxAges | List<int> | Yes | List of ages for each guest. |
| Field | Type | Required | Description |
|---|---|---|---|
| netAmount | decimal | Yes | The net price amount. |
| pvpAmount | decimal | Yes | The public selling price (PVP). In sandbox/test environments this value may be 0, as test providers do not return real PVP prices. In production it reflects the actual provider selling price. |
| currency | string | Yes | Currency code (ISO 4217). |
| pvpRequired | bool | Yes | Indicates whether the public selling price (pvpAmount) is mandatory for the agency. When true, the agency must display pvpAmount as the price to the end customer (the rate is contractually fixed by the provider). When false, pvpAmount is a reference value and the agency may apply its own markup on top of netAmount. |
Note: PVP in sandbox environment
In the sandbox/test environment, the pvpAmount field may return 0.00 because test providers do not send real PVP prices. This is expected behavior and does not indicate an error. In production, pvpAmount will reflect the actual public selling price from the provider. If you are building a B2C interface, use netAmount as a reference during sandbox testing.
| Field | Type | Required | Description |
|---|---|---|---|
| refundable | bool | Yes | Indicates if the option is refundable under certain conditions. |
| penalties | List<CancellationPolicyPenalty> | No | List of penalties that apply based on cancellation deadlines. Null if none apply. |
| Field | Type | Required | Description |
|---|---|---|---|
| deadline | DateTime | Yes | The date by which cancellation incurs this penalty amount in UTC. |
| amount | decimal | Yes | The penalty amount. |
| Field | Type | Required | Description |
|---|---|---|---|
| type | string | No | The type of surcharge. |
| code | string | No | A code identifying the surcharge. |
| description | string | No | A description of the surcharge. |
| price | OptionPrice | Yes | The price details for the surcharge. |
| mandatory | bool | Yes | Indicates if the surcharge is mandatory. |
| Field | Type | Required | Description |
|---|---|---|---|
| searchToken | string | Yes | The search token obtained from a search result option |
| Field | Type | Required | Description |
|---|---|---|---|
| option | PrebookAccommodationOption | No | Details of the prebooked option. Required if success |
| success | bool | Yes | Indicates if the operation was successful |
| errorMessages | List<string> | No | List of error messages, if any |
| warningMessages | List<string> | No | List of warning messages, if any |
| Field | Type | Required | Description |
|---|---|---|---|
| hotelId | string | No | The hotel identifier |
| hotelName | string | No | The name of the hotel |
| mealPlanId | string | No | The meal plan identifier |
| mealPlanName | string | No | The name of the meal plan |
| rooms | List<OptionRoom> | No | List of rooms included in this option |
| price | OptionPrice | Yes | Price details for the prebooked option |
| cancellationPolicy | CancellationPolicy | No | Cancellation policy details |
| surcharges | List<OptionSurcharge> | No | List of additional charges |
| remarks | string | No | Additional remarks |
| prebookToken | string | Yes | Token for booking operation |
| Field | Type | Required | Description |
|---|---|---|---|
| prebookToken | string | Yes | Token obtained from successful prebook operation |
| clientReference | string | Yes | Client's booking reference |
| holderName | string | Yes | Main guest's first name |
| holderSurname | string | Yes | Main guest's last name |
| paxes | List<BookRqPax> | Yes | List of guest details. If empty list, holder will be first pax and UNDEFINED for the others |
| remarks | string | No | Additional booking remarks |
| Field | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | Guest's first name |
| surname | string | No | Guest's last name (optional) |
| age | int | Yes | Guest's age |
| Field | Type | Required | Description |
|---|---|---|---|
| booking | BookAccommodationOption | No | The confirmed booking with summary data. Required if success |
| success | bool | Yes | Indicates if the operation was successful |
| errorMessages | List<string> | No | List of error messages, if any |
| warningMessages | List<string> | No | List of warning messages, if any |
| Field | Type | Required | Description |
|---|---|---|---|
| bookingId | Guid | Yes | Unique identifier for the booking |
| locator | string | Yes | Booking locator for future operations (GetBooking, Cancel) |
| hotelId | string | No | The hotel identifier |
| hotelName | string | No | The name of the hotel |
| mealPlanId | string | No | The meal plan identifier |
| mealPlanName | string | No | The name of the meal plan |
| price | OptionPrice | Yes | Price details for the booking |
| status | BookingFlowStatus | Yes | Current status of the booking |
| rooms | List<BookAccommodationRoom> | Yes | List of booked rooms |
| remarks | string | No | Additional booking remarks |
| Field | Type | Required | Description |
|---|---|---|---|
| name | string | No | The name of the room |
| roomTypeId | string | No | The room type identifier |
| roomType | string | Yes | Room type identifier |
| roomAmenityIds | List<string> | No | List of room amenity identifiers |
| paxes | List<BookAccommodationRoomPax> | Yes | List of guests in the room |
| Field | Type | Required | Description |
|---|---|---|---|
| age | int | Yes | Guest's age |
| name | string | Yes | Guest's first name |
| surname | string | Yes | Guest's last name |
| Field | Type | Required | Description |
|---|---|---|---|
| locator | string | Yes | The booking locator to retrieve details for |
| Field | Type | Required | Description |
|---|---|---|---|
| booking | BookAccommodationOptionExtended | No | Details of the booking. Required if success |
| success | bool | Yes | Indicates if the operation was successful |
| errorMessages | List<string> | No | List of error messages, if any |
| warningMessages | List<string> | No | List of warning messages, if any |
| Field | Type | Required | Description |
|---|---|---|---|
| locator | string | Yes | Booking locator for future operations |
| hotelId | long | Yes | Hotel identifier |
| hotelName | string | No | The name of the hotel |
| mealPlanId | string | Yes | Meal plan identifier |
| mealPlanName | string | No | The name of the meal plan |
| clientReference | string | Yes | Client's booking reference |
| checkIn | DateOnly | Yes | Check-in date (YYYY-MM-DD) |
| checkOut | DateOnly | Yes | Check-out date (YYYY-MM-DD) |
| holderName | string | Yes | Main guest's name |
| rooms | List<BookAccommodationRoom> | Yes | List of booked rooms |
| price | OptionPrice | Yes | Price details for the booking |
| cancellationPolicy | CancellationPolicy | Yes | Cancellation policy details |
| surcharges | List<OptionSurcharge> | No | List of additional charges |
| remarks | string | No | Additional booking remarks |
| status | BookingFlowStatus | Yes | Current status of the booking |
| Field | Type | Required | Description |
|---|---|---|---|
| locator | string | Yes | The booking locator to cancel |
| Field | Type | Required | Description |
|---|---|---|---|
| status | BookingFlowStatus | Yes | Indicates booking status |
| success | bool | Yes | Indicates if the operation was successful |
| errorMessages | List<string> | No | List of error messages, if any |
| warningMessages | List<string> | No | List of warning messages, if any |
Error Codes & Rate Limits
HTTP error codes, error response format, and rate limiting policies.
The Search endpoint is rate-limited per credential using a fixed window of 1 second. The limit is configured by the Perlatours team for each client credential — contact us to know or adjust your assigned rate. Requests that exceed the limit receive an HTTP 429 response.
| Applies to | POST /Booking/Search |
| Window | 1 second (fixed window) |
| Limit | Assigned per credential by Perlatours (contact us for your current limit) |
| Rejection response | HTTP 429 |
| Response headers | X-RateLimit-Limit, X-RateLimit-Remaining, Retry-After |
Headers in every response:
| Header | Description |
|---|---|
| X-RateLimit-Limit | Your request limit per window |
| X-RateLimit-Remaining | Remaining requests in the current window |
| Retry-After | Seconds to wait before retrying (only in 429 responses) |
429 response example:
{
"success": false,
"errorMessages": [
"The request limit for this credential has been exceeded."
]
}All error responses follow the CommonRs format:
{
"success": false,
"errorCode": "VALIDATION_ERROR",
"errorMessages": [
"The provided data is not valid"
],
"warningMessages": null
}| Field | Type | Description |
|---|---|---|
| success | bool | Always false for error responses |
| errorCode | string? | System error code (e.g. "VALIDATION_ERROR") |
| errorMessages | string[]? | List of descriptive error messages |
| warningMessages | string[]? | List of warnings (may be present even in successful responses) |
All error responses use this standard format, including JSON validation errors (missing fields, wrong types). Error messages are descriptive and do not expose internal system details.
Example: { "success": false, "errorMessages": ["Missing required field: locator"] }
Validation (1000-1999)
Invalid request data, missing fields, invalid enums.
Authentication (2000-2999)
Invalid credentials, expired tokens, insufficient permissions.
System (3000-3999)
Internal errors, database errors, timeouts.
Business (4000-4999)
Booking not found, no availability, already cancelled.
Connector (5000-5999)
Provider connection errors, invalid provider responses.
Integration (6000-6999)
Internal service communication errors.
Resource (7000-7999)
Resource not found, already exists, locked.
Rate Limiting (8000-8999)
Rate limit exceeded, too many requests.
| Code | Meaning | When it occurs |
|---|---|---|
200 | OK | Request processed successfully |
400 | Bad Request | Invalid request data, missing fields or incorrect values |
401 | Unauthorized | Missing, invalid or expired JWT token |
403 | Forbidden | Insufficient permissions for the requested operation |
404 | Not Found | Resource not found (booking, hotel, credential) |
409 | Conflict | Booking already cancelled or already confirmed |
429 | Too Many Requests | Rate limit exceeded (Search only) |
500 | Internal Server Error | Internal system error |
Inventory API
Access to hotel inventory data including hotels, meal plans, room types, and more.
dev.api.perlatours.com/InventoryInventory Data Models
These models are used across multiple endpoints or nested within other models.
| Field | Type | Required | Description |
|---|---|---|---|
| pageNumber | int | No | Page number for pagination. Default: 1 |
| pageSize | int | No | Number of items per page. Default: 10, Max: 100 |
| usePagination | bool | No | Whether to use pagination. Default: false |
| ids | List<long> | No | List of hotel IDs to filter by |
| name | string | No | Hotel name to search for (partial match) |
| location | string | No | Hotel location to search for (partial match) |
| Field | Type | Required | Description |
|---|---|---|---|
| id | long | Yes | Unique identifier for the hotel |
| giataId | long | Yes | GIATA identifier for the hotel |
| name | string | Yes | Hotel name |
| latitude | double | Yes | Hotel latitude coordinate |
| longitude | double | Yes | Hotel longitude coordinate |
| companyId | long? | No | Associated company ID |
| categoryId | long? | No | Hotel category ID |
| typeId | long? | No | Hotel type ID |
| address | string? | No | Hotel address |
| countryId | CommonCountry? | No | Country where the hotel is located |
| location | string? | No | City or location name |
| postalCode | string? | No | Postal code |
| phone | string? | No | Hotel phone number |
| fax | string? | No | Hotel fax number |
string? | No | Hotel email address | |
| website | string? | No | Hotel website URL |
| includedMarkets | List<CommonCountry>? | No | Markets where the hotel is available |
| excludedMarkets | List<CommonCountry>? | No | Markets where the hotel is not available |
| isActive | bool | Yes | Whether the hotel is active |
| Field | Type | Required | Description |
|---|---|---|---|
| data | IEnumerable<T> | Yes | Collection of items for the current page |
| pageNumber | int | Yes | Current page number |
| pageSize | int | Yes | Number of items per page |
| totalPages | int | Yes | Total number of pages |
| totalRecords | int | Yes | Total number of records |
| hasPreviousPage | bool | Yes | Whether there is a previous page |
| hasNextPage | bool | Yes | Whether there is a next page |
| Field | Type | Required | Description |
|---|---|---|---|
| ids | List<string>? | No | List of meal plan IDs to filter by |
| name | string? | No | Meal plan name to search for (partial match) |
| Field | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | Unique identifier for the meal plan |
| name | string | Yes | Meal plan name |
| Field | Type | Required | Description |
|---|---|---|---|
| ids | List<string>? | No | List of room type IDs to filter by |
| name | string? | No | Room type name to search for (partial match) |
| Field | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | Unique identifier for the room type |
| name | string | Yes | Room type name |
| Field | Type | Required | Description |
|---|---|---|---|
| ids | List<string>? | No | List of room amenity IDs to filter by |
| name | string? | No | Room amenity name to search for (partial match) |
| Field | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | Unique identifier for the room amenity |
| name | string | Yes | Room amenity name |
| Field | Type | Required | Description |
|---|---|---|---|
| ids | List<long>? | No | List of hotel type IDs to filter by |
| name | string? | No | Hotel type name to search for (partial match) |
| Field | Type | Required | Description |
|---|---|---|---|
| id | long | Yes | Unique identifier for the hotel type |
| name | string | Yes | Hotel type name |
| Field | Type | Required | Description |
|---|---|---|---|
| ids | List<long>? | No | List of hotel category IDs to filter by |
| name | string? | No | Hotel category name to search for (partial match) |
| Field | Type | Required | Description |
|---|---|---|---|
| id | long | Yes | Unique identifier for the hotel category |
| name | string | Yes | Hotel category name |
| Field | Type | Required | Description |
|---|---|---|---|
| ids | List<long>? | No | List of hotel chain IDs to filter by |
| name | string? | No | Hotel chain name to search for (partial match) |
| Field | Type | Required | Description |
|---|---|---|---|
| id | long | Yes | Unique identifier for the hotel chain |
| name | string | Yes | Hotel chain name |
| Field | Type | Required | Description |
|---|---|---|---|
| id | int | Yes | Enum value (numeric) |
| name | string | Yes | Enum name (string) |
AI Integration Assistant
Use this prompt with Claude Code or any AI coding assistant to integrate with our API step by step.
Customize it — describe your system in the designated area so the AI adapts to your architecture.
# Perlatours Booking API — Integration Guide
You are an AI coding assistant helping a developer integrate with the Perlatours Booking API.
Read this entire prompt before starting. Follow each phase in order. Ask clarifying questions when needed.
## Documentation
Full reference: https://developers.perlatours.com
## About the client's system
> ⚠️ IMPORTANT: Replace this block with a description of YOUR system.
> Include: programming language, framework, database, how you handle HTTP calls,
> whether you have an existing booking system, and what your end goal is
> (e.g., "search and book hotels from our travel agency website").
>
> Example:
> "We are a travel agency using Node.js + Express with PostgreSQL.
> We use axios for HTTP calls. We want to let our customers search
> and book hotels through our website. We already have a payment
> system with Stripe."
[DESCRIBE YOUR SYSTEM HERE]
---
## Phase 1: Authentication Setup
**Goal:** Configure JWT Bearer authentication.
- Base URL: `https://api.perlatours.com`
- All requests require header: `Authorization: Bearer <YOUR_JWT_TOKEN>`
- The token is permanent (provided by Perlatours), no refresh flow needed.
- Test it by calling any endpoint — a 401 means the token is invalid.
**Action:** Create a base HTTP client/service in my project that:
1. Sets the base URL
2. Adds the Authorization header to every request
3. Handles common errors (401, 429, 500)
---
## Phase 2: Understand the Response Format
All API responses follow this structure:
```json
{
"success": true,
"errorCode": null,
"errorMessages": [],
"warningMessages": [],
"data": { ... }
}
```
**Important patterns:**
- `success: true` → operation worked, read `data`
- `success: false` → read `errorMessages` for details
- GetHotels returns PAGINATED: `data.data` (array inside pagination object)
- Catalog endpoints (MealPlans, RoomTypes, etc.) return: `data` directly as array
- HTTP 429 = rate limited (Search endpoint only, 1-second fixed window)
**Action:** Create a response parser/wrapper that handles both patterns.
---
## Phase 3: Load Inventory Data (Optional but Recommended)
Before searching, load reference data to understand IDs in search results.
| Endpoint | Method | Path | Body | Returns |
|----------|--------|------|------|---------|
| Hotels | POST | /Inventory/GetHotels | `{ "ids": [163608], "pageNumber": 1, "pageSize": 10 }` | Paginated (data.data) |
| Meal Plans | POST | /Inventory/GetMealPlans | `{ "language": "EN" }` (optional) | Array |
| Room Types | POST | /Inventory/GetRoomTypes | `{ "language": "EN" }` (optional) | Array |
| Room Amenities | POST | /Inventory/GetRoomAmenities | `{ "language": "EN" }` (optional) | Array |
| Hotel Types | POST | /Inventory/GetHotelTypes | `{ "language": "EN" }` (optional) | Array |
| Hotel Categories | POST | /Inventory/GetHotelCategories | `{ "language": "EN" }` (optional) | Array |
| Hotel Chains | POST | /Inventory/GetHotelChains | `{ "language": "EN" }` (optional) | Array |
| Markets | GET | /Inventory/Markets | None | Array |
| Nationalities | GET | /Inventory/Nationalities | None | Array |
| Currencies | GET | /Inventory/Currencies | None | Array |
| Languages | GET | /Inventory/Languages | None | Array |
| All Countries | GET | /Inventory/AllCountries | None | Array |
| All Currencies | GET | /Inventory/AllCurrencies | None | Array |
| All Languages | GET | /Inventory/AllLanguages | None | Array |
| Booking Flow Statuses | GET | /Inventory/BookingFlowStatuses | None | Array |
**Important:** POST endpoints accept an optional JSON body with filters. GET endpoints have no body.
**Action:** Create services/functions to fetch and cache inventory data.
---
## Phase 4: Implement Search
**POST /Booking/Search**
```json
{
"hotelIds": ["163608"],
"checkIn": "2026-09-01",
"checkOut": "2026-09-05",
"occupancies": [
{ "paxAges": [30, 28] }
],
"metadata": {
"market": "ES",
"currency": "EUR",
"language": "EN",
"nationality": "ES"
}
}
```
**Key rules:**
- `occupancies` uses `paxAges` — a flat list of ages per room (e.g. [30, 28] = two adults aged 30 and 28; [35, 8] = one adult + one child age 8)
- `checkIn` must be a future date
- `checkOut` must be after `checkIn`
- `hotelIds` accepts both strings and numbers
- `metadata` values must match your credential's allowed markets/currencies (use inventory endpoints to discover valid values)
- Each result option contains a `searchToken` — save it for the next step
**Response structure:**
```
accommodations[] → options[] → { searchToken, price, rooms[], cancellationPolicy, mealPlanId }
```
**Action:** Implement search and display results. Save `searchToken` from selected option.
---
## Phase 5: Implement Prebook
**POST /Booking/Prebook**
```json
{
"searchToken": "<token from search>"
}
```
**Response:** Returns updated price, cancellation policy, and a `prebookToken`.
- Compare price with search — it may have changed
- Show cancellation policy to the customer before confirming
- Save `prebookToken` for booking
**Action:** Implement prebook flow. Show price confirmation to user.
---
## Phase 6: Implement Book
**POST /Booking/Book**
```json
{
"prebookToken": "<token from prebook>",
"clientReference": "YOUR-REF-001",
"holderName": "John",
"holderSurname": "Smith",
"paxes": [
{ "name": "John", "surname": "Smith", "age": 30 }
],
"remarks": "Late check-in requested"
}
```
**Key rules:**
- `paxes` surname is optional, `name` and `age` are required
- If `paxes` is empty, holder becomes first pax, others are UNDEFINED
- Response includes `locator` — THIS IS THE BOOKING ID for all future operations
- Save the `locator` in your database
**Action:** Implement booking with guest data collection. Store `locator`.
---
## Phase 7: Implement Get Booking
**POST /Booking/GetBooking**
```json
{
"locator": "<booking locator>"
}
```
**Note:** The response uses field name `booking` (not `option` like Book).
**Action:** Implement booking detail retrieval.
---
## Phase 8: Implement Cancel
**POST /Booking/Cancel**
```json
{
"locator": "<booking locator>"
}
```
**Response includes:**
- `status`: "CANCELLED" if successful
- `price`: cancellation penalty cost (null if no penalty)
- `price.netAmount`: penalty amount
- `price.currency`: currency code
**Note:** In sandbox, all bookings are fully refundable (price = null).
In production, check cancellationPolicy deadlines before cancelling.
**Action:** Implement cancellation with penalty display.
---
## Phase 9: Error Handling Checklist
Implement handling for:
- [ ] HTTP 401 → Invalid/expired token
- [ ] HTTP 429 → Rate limited, implement retry with backoff
- [ ] HTTP 400 → Validation error, show errorMessages to developer
- [ ] `success: false` → Business error, show errorMessages to user
- [ ] Network timeouts → Retry with exponential backoff
- [ ] Price changed between Search and Prebook → Show updated price
**Error categories (by errorCode range):**
- 1000-1999: Validation errors
- 2000-2999: Authentication errors
- 4000-4999: Business errors (no availability, already cancelled)
- 5000-5999: Provider/connector errors
- 8000-8999: Rate limit errors
---
## Complete Flow Summary
```
Search (hotelIds, dates, occupancies)
↓ searchToken
Prebook (searchToken)
↓ prebookToken + confirm price
Book (prebookToken, guests, reference)
↓ locator
GetBooking (locator) ← check status anytime
Cancel (locator) ← if needed
```
## Rate Limiting
- Only Search is rate-limited
- Fixed window: 1 request per second (configurable per credential)
- Response headers: X-RateLimit-Limit, X-RateLimit-Remaining, Retry-After