Welcome to Juniper's OCTO API documentation.
This documentation details Juniper's implementation of the OCTO API specifications (specifications that are based on the OCTO standard, while accounting for the capabilities and data that it is required on the Juniper system), meant for buyers looking to establish an API connectivity with suppliers that use the Juniper booking engine. For details on the integration process, kindly refer to our Getting Started section.
Our OCTO API implementation consists of a set of core functionalities, each of them having a set of endpoints available for use, and here we would like to offer you a brief overview of each of these functionalities:
OCTO uses Bearer authentication. To authenticate requests, an API key must be sent as a Bearer token in the Authorization header of your request:
Authorization: Bearer {access_token}
Given that Juniper operates with the use of credentials, through this endpoint, you will be able to generate a temporary access token that will allow you to access the rest of the requests of the API.
For further information on the actual endpoint, kindly refer to:
List of available products for purchase.
Either you have a database of products that you need to map to products returned in this API, or you choose to import the product list from this endpoint to your system.
This module consists on the following set of endpoints:
Retrieval of product availability, the first step required prior to performing a sale.
This module consists on the following set of endpoints:
To consolite a reservation, you will first need to check for availability (Availability Check), and then to confirm the reservation (Booking Confirmation).
This module consists on the following set of endpoints:
Resources that may come in handy for the development of the integration:
Available Postman Collection that may help you kick of the implementation of your API integration:
For internal use only. Configurations and requirements that must be complied with internally for the wellbeing of the integration.
A set of HTTP headers must be set when making a request to OCTO API. These can include standard HTTP headers, OCTO API headers and custom Juniper headers.
| Header | Required | Description |
|---|---|---|
Authorization |
Required | Your Authorization Bearer token. Generated through the Authentication endpoint. |
Content-Type |
Required | Required for all POST requests. This must be application/json. |
Content-Length |
Required | Required for all POST requests. This must be calculated dynamically for the request. |
Accept-Language |
Optional | This conforms to the regular HTTP specifications for the language. When requested, it will attempt to provide the contents in the requested language while, if unavailable, it will keep providing you with results in the system's default language. |
Currency |
Optional | TBD |
OCTO will respond to every request with either a 200 OK if everything went ok or 400 Bad Request if it didn't. In the case of the 400 Bad Request the response body will look like this:
{
"error": "UNAUTHORIZED",
"errorMessage": "Invalid credentials."
}
You will always receive error and errorMessage which are defined as:
| Field | Description |
|---|---|
error |
The error code. A table of possible error codes is shown below. |
errorMessage |
A human-readable error message will be provided here. |
Depending on the error code we also may pass additional fields which can make it easier to understand what's wrong with your request.
Below is a list of the error codes and a description of what each means.
| Code | Description |
|---|---|
MISSING_ADDITIONAL_FIELDS |
Missing additional required fields: {0} |
ALLOTMENT_ERROR |
Allotment changed. |
BOOKING_ALREADY_CANCELED |
Booking already canceled |
BOOKING_HAS_DIFFERENT_AGENCY |
The booking was made by a different agency. |
BOOKING_HAS_DIFFERENT_PRODUCT_TYPES |
Booking has different product types. |
BOOKING_ID_EXPIRED |
Booking id has expired. |
BOOKING_IS_BLOCKED |
Booking is blocked. |
BOOKING_NOT_ALLOWED |
Booking not allowed. |
BOOKING_NOT_FOUND |
Booking not found. |
CALENDAR_NOT_FOUND |
Calendar not found. |
CANCEL_NOT_POSSIBLE |
Booking cannot be canceled. |
CANCEL_NOT_POSSIBLE_PAST_DATE |
Booking cannot be canceled after the date. |
CAN_NOT_BOOK |
Booking not allowed. |
ERROR_QUANTITY_UNIT |
Units '{0}' have different quantity and contacts. |
EXCEEDED_PREPAYMENT_LIMIT |
Exceeded prepayment limit. |
EXTERNAL_CONNECTIONS_ERROR |
Error in external connections. |
FORBIDEEN |
Access denied by IP. |
INVALID_DATES |
Past dates are not allowed. |
INVALID_GRANT_TYPE |
Invalid value supplied for grant_type: value must be 'client_credentials'. |
INVALID_OPTION_ID |
The optionId was invalid or missing. |
INVALID_PAYMENT_TYPE |
Invalid payment type. |
INVALID_PICKUP |
Invalid pickup point: Not found. |
INVALID_PRODUCT_ID |
The productId was invalid or missing. |
INVALID_UNIT_ID |
The unitId was invalid or missing. |
INVALID_TOKEN |
The next token provided is invalid. |
INVALID_UPDATE |
No se puede actualizar una reserva pasada. |
IP_NOT_REGISTERED |
The IP {0} does not have permission to access. |
MISSING_FIELDS |
Missing fields: [{0}] |
BOOK_MODIFICATION_NOT_ALLOWED |
Booking cannot be modified. |
NOT_BOOKABLE |
Booking not allowed or not available. |
NO_AVAIL_FOUND |
No avail found. |
MULTIPLE_AVAILABILITY_ID |
Only one availabilityId is permitted. |
TARIFICATION_ERROR |
Price or allotment check was not possible. |
UNAUTHORIZED |
Invalid or missing authentication token. |
BAD_HEADER |
Bad header request: "{0}" |
MISSING_REQUIRED_FIELDS |
Missing required fields: {0} |
BOOKING_UNKNOWN_ERROR |
Unknown booking error. |
REQUIRED_FIELD_ERROR_MSG |
Required field error: {0} |
INVALID_START_DATE |
Start date must be greater or equal to end date. |
INVALID_AVAILABILITY_ID |
Missing or invalid availabilityId in the request. |
INVALID_FIELD |
Invalid field: {0} |
PRODUCT_NOT_FOUND |
Product not found. |
Here you will be able to find listed all of the endpoints that have been implemented for the OCTO API use.
| Name | Method | Description |
|---|---|---|
| Authentication | POST |
Generate a temporary access token that will allow you to access the rest of the requests of the API. |
| Get Products | GET |
Returns a list of Products and associated details. |
| Get Product | GET |
Returns a single Product and associated details for a given Product ID. |
| Availability Calendar | POST |
Returns availability for a given Product & Option as a single object per day. Optimized to be queried for large date ranges and to populate an availability calendar. |
| Availability Check | POST |
Returns availability for a given Product & Option as a single object per start time (or day). You have to perform this step to retrieve an bookingId required for Bookings. |
| Booking Confirmation | POST |
Confirms a reservation, making it ready to be used. |
| Booking Cancellation | POST |
Cancels your booking. You can only cancel a booking if booking.cancellable is TRUE, and is within the booking cancellation cut-off window. |
| Get Booking | GET |
Returns the status and details of your existing booking. |
And next we will proceed to detail each of them:
POST https://xml-uat.bookingengine.es/webservice/octo/authentication
Generate a temporary access token that will allow you to access the rest of the requests of the API.
client_id string required
Credential username
client_secret string required
Credential password
grant_type string required
Credential type. As of the moment, only client_credentials is supported. Example: client_credentials
POST /webservice/octo/authentication HTTP/1.1
Content-Type: application/json
Host: xml-uat.bookingengine.es
Content-Length: 103
{
"client_id": "username",
"client_secret": "password",
"grant_type": "client_credentials"
}
{
"access_token": "U2duNDExMzc1czA6UC5ZTU1MVFM0UVNxa2hxeHFzRjhEYTMxc3luTEJodjgzMDR0cSt0bVJ0T29Hd09Ycy9WOEJwNWJZVmFlOVZMRTFqVjkrSlBqbVJ5cFJNaGxjT1c2Tm43dz09",
"token_type": "Bearer",
"expires_in": 3600
}
A description of each of the keys is given below:
| Field | Description |
|---|---|
| access_token | Access token that you would use for the authentication of the subsequent requests |
| token_type | Token type: Bearer |
| expires_in | Seconds on which the token will expire. As of the moment, this is a fixed value of 60 minutes |
GET https://xml-uat.bookingengine.es/webservice/octo/products
List all the products available for sale
destinationId string optional
The destination id to filter the products by
nextToken string optional
Token of the next page. To be sent when there is a nextToken present on your response (which will imply that there is still more data available).
GET /webservice/octo/products?destinationID=15011 HTTP/1.1
Authorization: Bearer U2duNDExMzc1czA6UC5ZTU1MVFM0UVNxa2hxeHFzRjhEYTMxc3luTEJodjgzMDR0cSt0bVJ0T29Hd09Ycy9WOEJwNWJZVmFlOVZMRTFqVjkrSlBqbVJ5cFJNaGxjT1c2Tm43dz09
Host: xml-uat.bookingengine.es
{
"destinationID": 15011,
"results": [
{
"id": "AKSkrnflyoG4GgB_aJL1X2Y",
"internalName": "Ticket Test Service",
"locale": "en",
"availabilityType": "START_TIME",
"type": "Tickets",
"media": [
],
"classifications": [
{
"id": 2,
"name": "Tickets"
}
],
"options": [
{
"id": "37",
"internalName": "Prueba Tipo",
"availabilityLocalStartTimes": [
"09:30"
]
}
]
},
{
"id": "AIUKumUt8CqUakw6mEfhH6c",
"internalName": "Excursión Coves del Drach",
"locale": "en",
"availabilityType": "START_TIME",
"type": "Tours",
"label": "Test Label",
"media": [
{
"src": "https://juniper-uat.bookingengine.es/images/upload/Bus_anfibio.jpg",
"type": "IMAGE",
"rel": "COVER"
}
],
"classifications": [
{
"id": 1,
"name": "Excursions"
},
{
"id": 3,
"name": "Test Classification"
}
],
"options": [
{
"id": "3",
"internalName": "Ticket with concert",
"availabilityLocalStartTimes": [
"10:15"
]
},
{
"id": "4",
"internalName": "Entrance",
"availabilityLocalStartTimes": [
"10:00"
]
}
]
},
{
"id": "ALbo1f84aRf5EJwRkb1bnuw",
"internalName": "Best Escape Rooms Ocimax",
"locale": "en",
"availabilityType": "START_TIME",
"type": "Tours",
"label": "Test Label",
"pricingFrom": {
"retail": 2125,
"currency": "EUR",
"currencyPrecision": 2,
"pricingPer": "UNIT"
},
"media": [
{
"src": "https://juniper-uat.bookingengine.es/images/upload/Services/bero_main.jpg",
"type": "IMAGE",
"rel": "COVER"
}
],
"classifications": [
{
"id": 2,
"name": "Tickets"
}
],
"options": [
{
"id": "5",
"internalName": "La Egipcia",
"availabilityLocalStartTimes": [
"10:15"
]
},
{
"id": "6",
"internalName": "La Medieval",
"availabilityLocalStartTimes": [
"10:00"
]
}
]
},
{
"id": "AIgbDa35IJI1aWH3ABIK2mU",
"internalName": "Palma Center Sightseeing With Transfer",
"locale": "en",
"availabilityType": "START_TIME",
"type": "Tours",
"media": [
],
"classifications": [
{
"id": 2,
"name": "Tickets"
}
],
"options": [
{
"id": "42",
"internalName": "Palma Center Sightseeing",
"availabilityLocalStartTimes": [
"10:15"
]
}
]
},
{
"id": "AFLAitq9XtR10A_WIfcz93g",
"internalName": "Test with additional fields",
"locale": "en",
"availabilityType": "START_TIME",
"type": "Regular",
"media": [
],
"classifications": [
{
"id": 1,
"name": "Excursions"
},
{
"id": 2,
"name": "Tickets"
}
],
"options": [
{
"id": "61",
"internalName": "La Test",
"availabilityLocalStartTimes": [
"18:15"
]
}
]
}
]
}
A description of each of the keys is given below:
| Field | Description |
|---|---|
| nextToken | Token of the next page, to be sent on the next products request. Having the nextToken property available in the response, will imply that there is still more data available. |
| destinationID | The destination id for which the results are for (when searching for a destination id). |
| results | Array of results in question. |
| id | The id used for checking for availability and creating bookings for the product. |
| internalName | Product name. |
| locale | Language code indicating what language this product content is in. |
| type | Product type. |
| label | Product label. |
| redemptionMethod | How the voucher can be redeemed. |
| pricingFrom | Pricing from option. |
| pricingFrom[].pricingPer | Identify if the price is per unit or per booking. |
| pricingFrom[].retail | Sales price. |
| pricingFrom[].currency | Currency code. |
| pricingFrom[].currencyPrecision | Currency precision. |
| media | Media available for the product. |
| media[].src | Media source/link. |
| media[].type | Media type. Possible values: • IMAGE • VIDEO • IMAGE360 |
| media[].rel | Media relationship. Possible values: • COVER • GALLERY |
| classifications | Product classifications. |
| classifications[].id | Classifications id. |
| classifications[].name | Classifications name. |
| options | Product options. |
| options[].id | The id that identifies this option, it is only unique within the product. |
| options[].internalName | Option name. |
| options[].availabilityLocalStartTimes | Array of all of the possible start times of the option. |
| options[].duration | The duration that the activity will take. |
GET https://xml-uat.bookingengine.es/webservice/octo/products/:id
Get details on a specific product id
id string required
The product id.
GET /webservice/octo/products/AIUKumUt8CqUakw6mEfhH6c%3d HTTP/1.1
Accept-Language: en
Authorization: Bearer U2duNDExMzc1czA6UC5ZTU1MVFM0UVNxa2hxeHFzRjhEYTMxc3luTEJodjgzMDR0cSt0bVJ0T29Hd09Ycy9WOEJwNWJZVmFlOVZMRTFqVjkrSlBqbVJ5cFJNaGxjT1c2Tm43dz09
Host: xml-uat.bookingengine.es
{
"id": "AIUKumUt8CqUakw6mEfhH6c",
"internalName": "Excursión Coves del Drach",
"locale": "en",
"types": [
"Tours"
],
"label": "Test Label",
"shortDescription": "Excursion to Drach Caves, stunning natural scenery, carved by nature through the centuries",
"description": "<p>Located on Mallorca's east coast the caves are without doubt one of the island's most outstanding tourist attractions, extending for almost 2,400 metres and including internal heights of 25 metres above the cave floor.<br /><br />Hidden within the caves is Lake Martel, considered to be one of the largest subterranean lakes in the world, (177 metres long and 30 metres wide) on which there are daily performances of classical music featuring pieces by Caballero, Chopin, Offenbach, ...<br /><br />After the concert one can take a short boat trip on the lake. The unequalled beauty of the caves is further enhanced by the lightning planned and set in place by the engineer Carlos Buigas.<br /><br /></p>",
"availabilityType": "START_TIME",
"media": [
{
"src": "https://juniper-uat.bookingengine.es/images/upload/Bus_anfibio.jpg",
"type": "IMAGE",
"rel": "COVER"
}
],
"ecofriendly": false,
"petfriendly": false,
"accessible": false,
"classifications": [
{
"id": 1,
"name": "Excursions"
},
{
"id": 3,
"name": "Test Classification"
}
],
"inclusions": [
],
"exclusions": [
],
"options": [
{
"id": "3",
"internalName": "Ticket with concert",
"AvailabilityLocalStartTimes": [
"10:15"
],
"durationAmount": 1,
"durationUnit": "Days",
"shortDescription": "<div id=\"cuerpo_contenido\">\n<div><span class=\"negro\">The</span> concert on Lake Martel has been a feature since 1935 and is comprised of four pieces of classical music:</div>\n<ul>\n<li>Alborada gallega (Gallician sunrise) » Caballero</li>\n<li>Plaisir D'amour » Martini</li>\n<li>Tristesse Studio 3 Opus 10 » Chopín</li>\n<li>Barcarola, from the \"Tales of Hoffmann\" » Offenbach</li>\n</ul>\nThis concert is live, played by a quartet of two violins, cello and harmonium, and lasts 10 minutes.</div>\n<p>?</p>",
"voucherRemarks": "observations",
"additionalRemarks": "Additional remarks",
"languages": [
"en",
"es"
],
"media": [
],
"pickupAvailable": true,
"pickupRequired": false,
"pickupLocations": [
{
"id": "149",
"title": "APARTAMENTOS ALLSUN PIL-LARI PLAYA",
"hour": "00:00:00",
"place": {
"latitude": 39.526624,
"longitude": 2.7343799,
"postalAddress": {
"addressLocality": "Palma de Mallorca",
"addressRegion": "Majorca",
"addressCountry": "Spain"
}
}
}
]
},
{
"id": "4",
"internalName": "Entrance",
"AvailabilityLocalStartTimes": [
"10:00"
],
"durationAmount": 1,
"durationUnit": "Days",
"shortDescription": "Service option description",
"voucherRemarks": "Voucher remarks",
"additionalRemarks": "Additional remarks",
"media": [
{
"src": "https://juniper-uat.bookingengine.es/images/upload/-cuevas.jpg",
"type": "IMAGE",
"rel": "COVER"
}
],
"pickupAvailable": true,
"pickupRequired": false,
"pickupLocations": [
{
"id": "149",
"title": "APARTAMENTOS ALLSUN PIL-LARI PLAYA",
"hour": "01:15:00",
"place": {
"latitude": 39.526624,
"longitude": 2.7343799,
"postalAddress": {
"addressLocality": "Palma de Mallorca",
"addressRegion": "Majorca",
"addressCountry": "Spain"
}
}
}
]
}
]
}
A description of each of the keys is given below:
| Field | Description |
|---|---|
| id | The id used for checking for availability and creating bookings for the product. |
| location | Information about where the activity is located. |
| location[].zoneId | Internal zone id. |
| location[].title | Zone name. |
| location[].postalAddress | Zone address. |
| postalAddress[].addressLocality | Address locality. |
| postalAddress[].addressRegion | Address region. |
| postalAddress[].addressCountry | Address country. |
| internalName | Product name. |
| locale | Language code indicating what language this product content is in. |
| types | Product type. |
| label | Product label. |
| shortDescription | Short description. |
| description | Long description. |
| importantInformation | Important information. |
| pricingFrom | Pricing from option. |
| pricingFrom[].pricingPer | Identify if the price is per unit or per booking. |
| pricingFrom[].retail | Sales price. |
| pricingFrom[].currency | Currency code. |
| pricingFrom[].currencyPrecision | Currency precision. |
| redemptionMethod | How the voucher can be redeemed. |
| media | Media available for the product. |
| media[].src | Media source/link. |
| media[].type | Media type. Possible values: • IMAGE • VIDEO • IMAGE360 |
| media[].rel | Media relationship. Possible values: • COVER • GALLERY |
| categoryList | List of services categories. |
| categoryList[].name | Name of the service category. |
| categoryList[].description | Service category description. |
| ecofriendly | If the product is ecofriendly. |
| petfriendly | If the product is petfriendly. |
| accessible | If the product is accessible. |
| classifications | Product classifications. |
| classifications[].id | Classifications id. |
| classifications[].name | Classifications name. |
| options | Product options. |
| options[].id | The id that identifies this option, it is only unique within the product. |
| options[].internalName | Option name. |
| options[].availabilityLocalStartTimes | Array of all of the possible start times of the option. |
| options[].durationAmount | The amount of time that will take the product. |
| options[].durationUnit | The measure of time used by the product. Possible values: • Minutes • Hours • Days |
| options[].shortDescription | Short description. |
| options[].description | Long description. |
| options[].inclusions | Included in that option. |
| options[].exclusions | Excluded in that option. |
| options[].latitude | Location latitude. |
| options[].longitude | Location longitude. |
| options[].voucherRemarks | Booking voucher remarks. |
| options[].additionalRemarks | Additional remarks. |
| options[].languages | List of available languages for this option. |
| options[].galleryImages | List of images available for the option. |
| options[].media | Media available for the option. |
| media[].src | Media source/link. |
| media[].type | Media type. Possible values: • IMAGE • VIDEO • IMAGE360 |
| media[].rel | Media relationship. Possible values: • COVER • GALLERY |
| options[].pickupAvailable | Whether pickup is available for this product. |
| options[].pickupRequired | If true, then a pickup point must be supplied during booking. Otherwise it's optional whether the customer wants to be picked up or not.. |
| options[].pickupLocations | List of all the possible pickup points. Use this list for mapping purposes (if necessary) not all these pickup points are available for every departure. To know which are, check the pickup availability below. |
| pickupLocations[].id | Pickup point id. |
| pickupLocations[].name | Pickup point name. |
| pickupLocations[].latitude | Pickup point latitude. |
| pickupLocations[].longitude | Pickup point longitude. |
| pickupLocations[].country | Pickup point country name. |
| pickupLocations[].hour | Pickup point time. |
POST https://xml-uat.bookingengine.es/webservice/octo/availability/calendar
This endpoint is highly optimised and will return a single object per day. It's designed to be queried for large date ranges and the result is used to populate an availability calendar.
When the end user selects an open date you can call on /availability endpoint to get the bookingId to create the Bookings.
productId string required
The product id. Retrieved from products or product.
optionId string optional
The option id. May be retrieved from product.
localDateStart string required
Start date to query for (YYYY-MM-DD). Example: 2025-05-23
localDateEnd string required
End date to query for (YYYY-MM-DD). Example: 2025-05-24
POST /webservice/octo/availability/calendar HTTP/1.1
Content-Type: application/json
Authorization: Bearer U2duNDExMzc1czA6UC5ZTU1MVFM0UVNxa2hxeHFzRjhEYTMxc3luTEJodjgzMDR0cSt0bVJ0T29Hd09Ycy9WOEJwNWJZVmFlOVZMRTFqVjkrSlBqbVJ5cFJNaGxjT1c2Tm43dz09
Host: xml-uat.bookingengine.es
Content-Length: 117
{
"productId": "AIUKumUt8CqUakw6mEfhH6c%3d",
"localDateStart": "2025-05-23",
"localDateEnd": "2025-05-24"
}
[
{
"optionId": "4",
"name": "Entrance",
"localDate": "2025-12-25",
"localTimeStarts": [
"10:00"
],
"available": true,
"status": "FREESALE",
"capacity": 999,
"unitPricingFrom": [
{
"retail": 2125,
"currency": "EUR",
"currencyPrecision": 2,
"unitId": "Adult",
"unitName": "Adult",
"restrictions": {
"minAge": 13
}
},
{
"retail": 1530,
"currency": "EUR",
"currencyPrecision": 2,
"unitId": "Junior",
"unitName": "Junior",
"restrictions": {
"minAge": 6,
"maxAge": 12
}
},
{
"retail": 1275,
"currency": "EUR",
"currencyPrecision": 2,
"unitId": "Child",
"unitName": "Child",
"restrictions": {
"minAge": 2,
"maxAge": 5
}
}
]
},
{
"optionId": "4",
"name": "Entrance",
"localDate": "2025-12-26",
"localTimeStarts": [
"10:00"
],
"available": true,
"status": "FREESALE",
"capacity": 999,
"unitPricingFrom": [
{
"retail": 2125,
"currency": "EUR",
"currencyPrecision": 2,
"unitId": "Adult",
"unitName": "Adult",
"restrictions": {
"minAge": 13
}
},
{
"retail": 1530,
"currency": "EUR",
"currencyPrecision": 2,
"unitId": "Junior",
"unitName": "Junior",
"restrictions": {
"minAge": 6,
"maxAge": 12
}
},
{
"retail": 1275,
"currency": "EUR",
"currencyPrecision": 2,
"unitId": "Child",
"unitName": "Child",
"restrictions": {
"minAge": 2,
"maxAge": 5
}
}
]
}
]
A description of each of the keys is given below:
| Field | Description |
|---|---|
| optionId | The option id. |
| name | The option name. |
| localDate | The date (in format YYYY-MM-DD). |
| available | A boolean value (true or false) indicating whether you're able to sell tickets. |
| status | The status of that date. Possible values are:AVAILABLE There are availabilities available on this date for sale.FREESALE The availability for this date is free sale.SOLD_OUT This date was available but is now fully sold out.LIMITED This date is available but has less than 50% capacity left.CLOSED This date is closed and not available for sale. |
| vacancies | The available capacity on this day. We cannot give exact vacancies on the calendar endpoint as this endpoint is cached for speed and is only meant to give an indication. |
| capacity | The total capacity on this day. We cannot give exact vacancies on the calendar endpoint as this endpoint is cached for speed and is only meant to give an indication. |
| openingHours | A list of opening hours that the product is open on this day. |
| openingHours[].from | When this product opens (HH:MM). |
| openingHours[].to | When this product closes (HH:MM). |
| basePricing | Base priciding option. |
| basePricing[].retailAmount | Sales price. |
| basePricing[].currency | Currency code. |
| basePricing[].currencyPrecision | Currency precision. |
| unitPricingFrom | Pricing from option. |
| unitPricingFrom[].retail | Sales price. |
| unitPricingFrom[].currency | Currency code. |
| unitPricingFrom[].currencyPrecision | Currency precision. |
| unitPricingFrom[].unitId | Unit id. |
| unitPricingFrom[].unitName | Unit name. |
| unitPricingFrom[].restrictions | Unit restrictions. |
| restrictions[].minAge | Restrictions minimum age. |
| restrictions[].maxAge | Restrictions maximum age. |
POST https://xml-uat.bookingengine.es/webservice/octo/availability
This endpoint is slightly slower as it will return an object for each individual departure time (or day). You have to perform this step to retrieve an bookingId in order to confirm a sale, so if you just want to use this endpoint and skip the calendar endpoint then that's perfectly ok.
productId string required
The product id. Retrieved from products or product.
optionId string required
The option id. Retrieved from product or availability calendar.
localDateStart string required
Start date to query for (YYYY-MM-DD). Example: 2025-05-23
localDateEnd string required
End date to query for (YYYY-MM-DD). Example: 2025-05-24
units object[] required
List of units that you will be asking availability for.
id string required
The unit id.
quantity integer required
The quantity of the unit.
POST /webservice/octo/availability HTTP/1.1
Content-Type: application/json
Authorization: Bearer U2duNDExMzc1czA6UC5ZTU1MVFM0UVNxa2hxeHFzRjhEYTMxc3luTEJodjgzMDR0cSt0bVJ0T29Hd09Ycy9WOEJwNWJZVmFlOVZMRTFqVjkrSlBqbVJ5cFJNaGxjT1c2Tm43dz09
Host: xml-uat.bookingengine.es
Content-Length: 272
{
"productId": "AIUKumUt8CqUakw6mEfhH6c%3d",
"optionId": "4",
"localDateStart": "2025-05-23",
"localDateEnd": "2025-05-24",
"units": [
{
"id": "Adult",
"quantity": 2
},
{
"id": "Child",
"quantity": 1
}
]
}
{
"availabilities": [
{
"bookingId": "n8xL/ikoco+8UyvWDsGLkH1Nmct+HfM1IfrUedm/8A3r3Kzm5jO+2BfMAHWyhjmscDcNDps9vTOKqBukl5P663R6JwMsZezi5zyZYufFjKUHEsMr9OU/A7zZNsOx1hOLWeyc91lyrdIk4JK8mTuO4S/apGLZcETlV4GuNgQ4c1vcxHO0Dyc5dKq1tP+DuvWNDUXyP8OLswCTJRCWe6PzDPPwZKej/TCRhLw1C1c/tQgiYF7NCGfQg7WVso9f9zkPWiNuvpe3h79kqCS23xbiAxIqc17c6emTHr5nsL9WDMFh4Ut+Fh+QJZGFmcBIyoWwMJcJTj1oQWL49rivPvxnnwsWESfJDxFZ2e9qXJvp2VRX/HF6xNjc5IjtRFOmW+GGRHtv7YqgJ/IrGTtWvKXfWXkAUf+VKiqAuNsSazpp9vGYnWFHkAdyiGgfYmTxP6TSZiyZ8UPTtK03xSZE4XnMnA==",
"localDateTimeStart": "2025-12-25T10:00:00Z",
"localDateTimeEnd": "2025-12-25T10:00:00Z",
"allDay": true,
"available": true,
"status": "AVAILABLE",
"utcCutoffAt": "2025-12-23T16:49:48Z",
"pricing": {
"retail": 3825,
"currency": "EUR",
"currencyPrecision": 2,
"net": 3825
},
"cancellationPolicy": {
"firstDayCostCancellation": "2025-12-15T10:00:00Z",
"description": " * Cancelling up to 10 days (included) before the trip: 0 € * Cancelling up to 5 days to 9 days (included) before the trip: 50.00 % of total amount * Cancelling up to 0 days to 4 days (included) before the trip: 100.00 % of total amount",
"policyRules": [
{
"from": 10,
"fixedAmount": 0,
"currencyPrecision": 2
},
{
"from": 5,
"percentageAmount": 50
},
{
"from": 0,
"percentageAmount": 100
}
]
},
"leaderRequiredContactFields": [
"firstName",
"lastName"
],
"requiredFields": [
"pickupLocation.id"
],
"units": [
{
"id": "Adult",
"quantity": 2,
"internalName": "Adult",
"restrictions": {
"minAge": 13
},
"paxCount": 1,
"requiredContactFields": [
],
"additionalRequiredContactFields": [
]
},
{
"id": "Child",
"quantity": 1,
"internalName": "Child",
"restrictions": {
"minAge": 2,
"maxAge": 5
},
"paxCount": 1,
"requiredContactFields": [
],
"additionalRequiredContactFields": [
]
}
],
"pickupLocations": [
{
"id": "149",
"title": "APARTAMENTOS ALLSUN PIL-LARI PLAYA",
"hour": "01:15:00",
"place": {
"latitude": 40,
"longitude": 3,
"postalAddress": {
"addressLocality": "Palma de Mallorca",
"addressRegion": "Majorca",
"addressCountry": "Spain"
}
}
}
],
"additionalRequiredFields": [
]
}
]
}
A description of each of the keys is given below:
| Field | Description |
|---|---|
| availabilities | List of availabilities. |
| availabilities[].id | The availability id. |
| availabilities[].bookingId | The booking id, you will need this when booking. |
| availabilities[].localDateTimeStart | The start time for this availability. |
| availabilities[].localDateTimeEnd | The end time for this availability. |
| availabilities[].allDay | A boolean field indicating whether this is an all day availability and not a fixed departure time. |
| availabilities[].available | A boolean value (true or false) indicating whether you're able to sell tickets. |
| availabilities[].status | The status of that date. Possible values are:AVAILABLE There are availabilities available on this date for sale.FREESALE The availability for this date is free sale.SOLD_OUT This date was available but is now fully sold out.LIMITED This date is available but has less than 50% capacity left.CLOSED This date is closed and not available for sale. |
| availabilities[].vacancies | The available capacity on this day. |
| availabilities[].maxUnits | The total capacity on this day. |
| availabilities[].utcCutoffAt | The maximum DateTime available for the confirmation of the reservation. On UTC format. |
| availabilities[].openingHours | A list of opening hours that the product is open on this day. |
| openingHours[].from | When this product opens (HH:MM). |
| openingHours[].to | When this product closes (HH:MM). |
| availabilities[].pricing | Pricing object. |
| pricing[].retail | Sales price. |
| pricing[].currency | Currency code. |
| pricing[].currencyPrecision | Currency precision. |
| pricing[].net | Net price. |
| availabilities[].cancellationPolicy | Cancellation policy object. |
| cancellationPolicy[].firstDayCostCancellation | Moment on which the product would start incurring into cancellation costs. |
| cancellationPolicy[].description | Textual description of the cancellation policies. |
| cancellationPolicy[].policyRules | Cancellation policy rules. |
| policyRules[].from | Number of days before the check-in date. |
| policyRules[].dateFrom | Indicates the date from which the rule applies. |
| policyRules[].dateTo | Indicates the date to which the rule applies.. |
| policyRules[].fixedAmount | Price value of the rule. |
| policyRules[].percentageAmount | Price percentage of the rule. |
| policyRules[].currencyPrecision | Currency precision. |
| availabilities[].leaderRequiredContactFields | Holder required fields. |
| availabilities[].requiredFields | Required fields. |
| availabilities[].units | List of units. |
| units[].id | Unit id. |
| units[].quantity | Unit quantity. |
| units[].name | Unit name. |
| units[].restrictions | Unit restrictions. |
| restrictions[].minAge | Restrictions minimum age. |
| restrictions[].maxAge | Restrictions maximum age. |
| units[].paxCount | Unit passenger count. |
| units[].requiredContactFields | Unit contact required fields. |
| units[].additionalRequiredContactFields | Unit additional required fields. |
| availabilities[].pickupLocations | Pickup location. |
| pickupLocations[].id | Pickup location id. |
| pickupLocations[].title | Pickup location title. |
| pickupLocations[].hour | Pickup location hour. |
| pickupLocations[].place | Pickup location place. |
| place[].latitude | Pickup location latitude. |
| place[].longitude | Pickup location longitude. |
| place[].postalAddress | Pickup location address. |
| postalAddress[].addressLocality | Pickup location locality. |
| postalAddress[].addressRegion | Pickup location region. |
| postalAddress[].addressCountry | Pickup location country. |
| availabilities[].additionalRequiredFields | Additional required fields. |
POST https://xml-uat.bookingengine.es/webservice/octo/bookings
This endpoint confirms the booking so it's ready to be used.
bookingId string required
The booking id, obtained through an Availability Check request.
units object[] required
List of unit that will be included in the booking.
id string required
Unit id.
quantity string required
Unit quantity.
contacts object[] required
List of contacts.
firstName string required
Contact first name.
lastName string required
Contact last name.
resellerReference string optional
Your own booking reference. Useful for conciliation purposes.
notes string optional
Optional notes for the booking.
contact object[] required
Lead contact information.
title string optional
Lead contact title.
nationalityIso2 string optional
Lead contact nationality. On ISO2 format.
bornDate datetime optional
Lead contact date of birth.
age integer optional
Lead contact age.
firstName string optional
Lead contact first name.
lastName string optional
Lead contact last name.
email string optional
Lead contact email.
phoneNumber string optional
Lead contact phone number.
postalCode string optional
Lead contact postal code.
birthCountry string optional
Lead contact birth country.
residenceCountry string optional
Lead contact residence country.
city string optional
Lead contact city name.
address string optional
Lead contact city address.
documentNumber string optional
Lead contact city document number.
documentExpiration datetime optional
Lead contact city document expiration.
documentExpenditure datetime optional
Lead contact city document expenditure.
additionalRequiredFields string optional
Lead contact additional required fields.
code string required
Additional required field code.
value string required
Additional required field value.
pickupLocation object[] optional
Pickup point.
additionalRequiredFields object[] optional
Additional required fields. May be required for the confirmation of some products.
code string required
Additional required field code.
name string required
Additional required field name.
value string required
Additional required field value.
mandatory boolean required
If the additional required fields will be mandatory.
type string required
Additional required field type. Possible values are: TEXT, BOOL and LIST.
size integer required
Additional required field size.
values object[] required
Additional required field values.
code string required
Value code.
name string required
Value name.
POST /webservice/octo/bookings HTTP/1.1
Content-Type: application/json
Authorization: Bearer U2duNDExMzc1czA6UC5ZTU1MVFM0UVNxa2hxeHFzRjhEYTMxc3luTEJodjgzMDR0cSt0bVJ0T29Hd09Ycy9WOEJwNWJZVmFlOVZMRTFqVjkrSlBqbVJ5cFJNaGxjT1c2Tm43dz09
Host: xml-uat.bookingengine.es
Content-Length: 1242
{
"resellerReference": "YOUR_OWN_REFERENCE_123",
"bookingId": "n8xL/ikoco+8UyvWDsGLkFqHyIdbnB0DW+40Mi9tnVENfiVQr/zS5mFfjJvaW7kQw4M6+QrPj9eqNkjZV77mbymyRqnyA/0z6awqRkB+W+EvfcuCfxvmlx9DlZTSlmpw7wLtLkbRNROnqa9S61BbXnuCeJnRw3U/6zm95fDiolc+6ZAxpvpbV1x0WihYVlKYbqJVZGjjS8RDNhCSOPQVObQi2MHuwSH02eZbGh2ZE4lIc+cAVljK0a9KrSI2zqP/ioMDTmYugncBE4ePkrKLYTwIWJP3J7cO7l4oGYOiVygDPoxZn8dDQbnY7l86hzfp3MD/Q7wnNvvhH3pds4J+GagIPPhwDtuTkCjlDu+schfNe6n97J0WLhS4n0ksFrKeyBnPru6CAs9yzEojxpHJkw==",
"notes": "CUSTOMER COMMENTS",
"contact": {
"firstName": "Holder Name",
"lastName": "Holder Surname",
"phoneNumber": "+34600555999",
"email": "holder@yourdomain.com"
},
"pickupLocation": {
"id": "0"
},
"units": [
{
"id": "Adult",
"quantity": 2,
"contacts": [
{
"firstName": "Holder Name",
"lastName": "Holder Surname"
},
{
"firstName": "Second Passenger Name",
"lastName": "Second Passenger Surname"
}
]
},
{
"id": "Child",
"quantity": 1,
"contacts": [
{
"firstName": "Child Name",
"lastName": "Child Surname"
}
]
}
]
}
{
"bookings": [
{
"type": "SERVICE",
"id": 640424,
"resellerReference": "YOUR_OWN_REFERENCE_123",
"supplierReference": "4KKL1N",
"status": "PAID",
"utcConfirmedAt": "2025-12-23T16:53:03Z",
"productId": "AIUKumUt8CqUakw6mEfhH6c",
"optionId": "4",
"notes": "",
"units": [
{
"id": "Adult",
"internalName": "Adult",
"restrictions": {
"minAge": 13
},
"contacts": [
{
"age": 18,
"firstName": "Holder Name",
"lastName": "Holder Surname",
"additionalRequiredFields": [
]
},
{
"age": 18,
"firstName": "Second Passenger Name",
"lastName": "Second Passenger Surname",
"additionalRequiredFields": [
]
}
]
},
{
"id": "Child",
"internalName": "Child",
"restrictions": {
"minAge": 2,
"maxAge": 5
},
"contacts": [
{
"age": 2,
"firstName": "Child Name",
"lastName": "Child Surname",
"additionalRequiredFields": [
]
}
]
}
],
"cancellable": true,
"cancellationPolicy": {
"firstDayCostCancellation": "2025-12-15T22:00:00Z",
"description": " * Cancelling up to 10 days (included) before the trip: 0 € * Cancelling up to 5 days to 9 days (included) before the trip: 50.00 % of total amount * Cancelling up to 0 days to 4 days (included) before the trip: 100.00 % of total amount",
"policyRules": [
{
"from": 10,
"fixedAmount": 0,
"currencyPrecision": 2
},
{
"from": 5,
"percentageAmount": 50
},
{
"from": 0,
"percentageAmount": 100
}
]
},
"availability": {
"localDateTimeStart": "2025-12-25T10:00:00Z",
"localDateTimeEnd": "2025-12-25T10:00:00Z"
},
"contact": {
"firstName": "Holder Name",
"lastName": "Holder Surname",
"email": "holder@yourdomain.com",
"phoneNumber": "+34600555999",
"postalCode": ""
},
"pricing": {
"retail": 3825,
"currency": "EUR",
"currencyPrecision": 2,
"net": 3825
},
"pickupLocation": {
"id": null,
"title": null,
"hour": "00:00:00",
"place": null
},
"additionalRequiredFields": [
],
"vouchers": [
"http://suppliers.bookingengine.es/voucher/voucher.aspx?idRes=572940&localizador=4KKL1N&securityKey=R14-18-4F-65-91-26-BE-D8-80-D9-45-09-AF-7A-36-61&idioma=en&fromIntranet=13597EC4116EFD64"
],
"internalName": "Excursión Coves del Drach",
"availabilityLocalStartTimes": "10:00",
"media": [
{
"src": "https://juniper-uat.bookingengine.es/images/upload/Bus_anfibio.jpg",
"type": "IMAGE",
"rel": "COVER"
}
]
}
]
}
A description of each of the keys is given below:
| Field | Description |
|---|---|
| bookings | List of bookings. |
| bookings[].type | Product type for the booking. Example: SERVICE. |
| bookings[].id | Supplier id reference.. |
| bookings[].resellerReference | Your own booking reference. |
| bookings[].supplierReference | Supplier booking reference. |
| bookings[].status | The status of the reservation. Possible values are:PAID Booking confirmed and paid.CONFIRMED Booking confirmed.CANCELLED Booking cancelled.PENDING Booking on request.ON_HOLD Booking on hold.ON_REQUEST Booking quotation. |
| bookings[].utcConfirmedAt | The date on which the reservation has been confirmed. On UTC format. |
| bookings[].productId | Product id. |
| bookings[].optionId | Option id. |
| bookings[].notes | Optional notes for the booking. |
| bookings[].units | Units that have been bought. |
| units[].id | Unit id. |
| units[].quantity | Unit quantity. |
| units[].name | Unit name. |
| units[].restrictions | Unit restrictions. |
| restrictions[].minAge | Restrictions minimum age. |
| restrictions[].maxAge | Restrictions maximum age. |
| units[].contacts | Unit contacts. |
| contacts[].age | Unit contact age. |
| contacts[].firstName | Unit contact first name. |
| contacts[].lastName | Unit contact last name. |
| contacts[].additionalRequiredFields | Unit contact additional required fields. |
| bookings[].cancellable | If the booking can be cancelled.. |
| bookings[].cancellationPolicy | Cancellation policy object. |
| cancellationPolicy[].firstDayCostCancellation | Moment on which the product would start incurring into cancellation costs. |
| cancellationPolicy[].description | Textual description of the cancellation policies. |
| cancellationPolicy[].policyRules | Cancellation policy rules. |
| policyRules[].from | Number of days before the check-in date. |
| policyRules[].dateFrom | Indicates the date from which the rule applies. |
| policyRules[].dateTo | Indicates the date to which the rule applies.. |
| policyRules[].fixedAmount | Price value of the rule. |
| policyRules[].percentageAmount | Price percentage of the rule. |
| policyRules[].currencyPrecision | Currency precision. |
| bookings[].availability | Booking related availability information. |
| availability[].localDateTimeStart | The start time for this availability. |
| availability[].localDateTimeEnd | The end time for this availability. |
| availability[].openingHours | A list of opening hours that the product is open on this day. |
| openingHours[].from | When this product opens (HH:MM). |
| openingHours[].to | When this product closes (HH:MM). |
| bookings[].contact | Lead contact information. |
| contact[].firstName | Lead contact first name. |
| contact[].lastName | Lead contact last name. |
| contact[].email | Lead contact email. |
| contact[].phoneNumber | Lead contact phone number. |
| contact[].postalCode | Lead contact postal code. |
| contact[].residenceCountry | Lead contact residence country. |
| bookings[].pricing | Pricing object. |
| pricing[].retail | Sales price. |
| pricing[].currency | Currency code. |
| pricing[].currencyPrecision | Currency precision. |
| pricing[].net | Net price. |
| bookings[].pickupLocations | Pickup location. |
| pickupLocations[].id | Pickup location id. |
| pickupLocations[].title | Pickup location title. |
| pickupLocations[].hour | Pickup location hour. |
| pickupLocations[].place | Pickup location place. |
| place[].latitude | Pickup location latitude. |
| place[].longitude | Pickup location longitude. |
| place[].postalAddress | Pickup location address. |
| postalAddress[].addressLocality | Pickup location locality. |
| postalAddress[].addressRegion | Pickup location region. |
| postalAddress[].addressCountry | Pickup location country. |
| bookings[].additionalRequiredFields | Additional required fields. |
POST https://xml-uat.bookingengine.es/webservice/octo/bookings/:supplierReference/cancel
For cancelling bookings. You can only cancel a booking if booking.cancellable is TRUE, and is within the booking cancellation cut-off window.
supplierReference string required
The supplier reference of the booking.
reason string required
The reason for cancelling the booking.
POST /webservice/octo/bookings/1R1XQF/cancel HTTP/1.1
Content-Type: application/json
Authorization: Bearer U2duNDExMzc1czA6UC5ZTU1MVFM0UVNxa2hxeHFzRjhEYTMxc3luTEJodjgzMDR0cSt0bVJ0T29Hd09Ycy9WOEJwNWJZVmFlOVZMRTFqVjkrSlBqbVJ5cFJNaGxjT1c2Tm43dz09
Host: xml-uat.bookingengine.es
Content-Length: 47
{
"reason": "Reason for the cancellation"
}
{
"bookings": [
{
"type": "SERVICE",
"id": 589506,
"resellerReference": "YOUR_OWN_REFERENCE_123",
"supplierReference": "1R1XQF",
"status": "CANCELLED",
"utcConfirmedAt": "2025-05-15T16:14:08.763Z",
"productId": "AIUKumUt8CqUakw6mEfhH6c",
"optionId": "4",
"notes": "",
"units": [
{
"id": "Adult",
"quantity": 2,
"contacts": [
{
"age": 18,
"firstName": "Holder Name",
"lastName": "Holder Surname",
"additionalRequiredFields": [
]
},
{
"age": 18,
"firstName": "Holder Name",
"lastName": "Holder Surname",
"additionalRequiredFields": [
]
}
]
},
{
"id": "Child",
"quantity": 1,
"contacts": [
{
"age": 2,
"firstName": "Child Name",
"lastName": "Child Surname",
"additionalRequiredFields": [
]
}
]
}
],
"cancellable": true,
"cancellationPolicy": {
"firstDayCostCancellation": "2025-05-13T22:00:00",
"description": " * Cancelando hasta 10 días antes del viaje: 0 € * Cancelando desde 5 días hasta 9 días antes del viaje: 50.00 % de los gastos * Cancelando desde 0 días hasta 4 días antes del viaje: 100.00 % de los gastos",
"policyRules": [
{
"from": 10,
"fixedAmount": 0,
"currencyPrecision": 2
},
{
"from": 5,
"percentageAmount": 50
},
{
"from": 0,
"percentageAmount": 100
}
]
},
"availability": {
"localDateTimeStart": "2025-05-23T10:00:00",
"localDateTimeEnd": "2025-05-23T10:00:00",
"openingHours": [
{
"from": "10:30",
"to": "15:30"
}
]
},
"contact": {
"firstName": "Holder Name",
"lastName": "Holder Surname",
"email": "holder@yourdomain.com",
"phoneNumber": "+34600555999",
"postalCode": ""
},
"pricing": {
"retail": 4023,
"currency": "EUR",
"currencyPrecision": 2,
"net": 4023
},
"additionalRequiredFields": [
]
}
]
}
The structure of this response will be the same one that's provided on the Booking Confirmation endpoint, refer to it's specifications if you would like to be able to review its structure: Booking Confirmation
GET https://xml-uat.bookingengine.es/webservice/octo/bookings/:supplierReference
Fetch the status of an existing booking.
supplierReference string required
The supplier reference of the booking.
GET /webservice/octo/bookings/1R1XQF HTTP/1.1
Authorization: Bearer U2duNDExMzc1czA6UC5ZTU1MVFM0UVNxa2hxeHFzRjhEYTMxc3luTEJodjgzMDR0cSt0bVJ0T29Hd09Ycy9WOEJwNWJZVmFlOVZMRTFqVjkrSlBqbVJ5cFJNaGxjT1c2Tm43dz09
Host: xml-uat.bookingengine.es
{
"bookings": [
{
"type": "SERVICE",
"id": 589506,
"resellerReference": "YOUR_OWN_REFERENCE_123",
"supplierReference": "1R1XQF",
"status": "PAID",
"utcConfirmedAt": "2025-05-15T16:14:08.763Z",
"productId": "AIUKumUt8CqUakw6mEfhH6c",
"optionId": "4",
"notes": "",
"units": [
{
"id": "Adult",
"quantity": 2,
"contacts": [
{
"age": 18,
"firstName": "Holder Name",
"lastName": "Holder Surname",
"additionalRequiredFields": [
]
},
{
"age": 18,
"firstName": "Holder Name",
"lastName": "Holder Surname",
"additionalRequiredFields": [
]
}
]
},
{
"id": "Child",
"quantity": 1,
"contacts": [
{
"age": 2,
"firstName": "Child Name",
"lastName": "Child Surname",
"additionalRequiredFields": [
]
}
]
}
],
"cancellable": true,
"cancellationPolicy": {
"firstDayCostCancellation": "2025-05-13T22:00:00",
"description": " * Cancelando hasta 10 días antes del viaje: 0 € * Cancelando desde 5 días hasta 9 días antes del viaje: 50.00 % de los gastos * Cancelando desde 0 días hasta 4 días antes del viaje: 100.00 % de los gastos",
"policyRules": [
{
"from": 10,
"fixedAmount": 0,
"currencyPrecision": 2
},
{
"from": 5,
"percentageAmount": 50
},
{
"from": 0,
"percentageAmount": 100
}
]
},
"availability": {
"localDateTimeStart": "2025-05-23T10:00:00",
"localDateTimeEnd": "2025-05-23T10:00:00",
"openingHours": [
{
"from": "10:30",
"to": "15:30"
}
]
},
"contact": {
"firstName": "Holder Name",
"lastName": "Holder Surname",
"email": "holder@yourdomain.com",
"phoneNumber": "+34600555999",
"postalCode": ""
},
"pricing": {
"retail": 4023,
"currency": "EUR",
"currencyPrecision": 2,
"net": 4023
},
"additionalRequiredFields": [
]
}
]
}
The structure of this response will be the same one that's provided on the Booking Confirmation endpoint, refer to it's specifications if you would like to be able to review its structure: Booking Confirmation