Introduction
Welcome to the Innstant API! You can use our API to access Innstant’s various API endpoints.
This document is meant for developers with at least some experience in API developments.
For any question, credentials, or request, please contact your account manager at Innstant.
Authentication
There are basically 3 different methods you can choose to use for authentication.
- Persistent Authentication - This method is used when you need a session that expires.
To use this method you send a “login” call with the user details, and get the LoginToken in the response.
This token is your session ID and you can send it instead of sending the account/agent/password on each call, and once it expires you simply get a new session code. - One-off Authentication - This method is used when you don’t need a session, and have the login credentials handy. to use it, you simply send the account/agent/password combination on each call.
- Token Based Authentication - This method is used for searching and booking content on Mishor, but can also be used for all other services.
To use this method you simply save a unique login token for each agent/account combination.
Persistent Authentication
The Persistent authentication method is used to establish a “session” and avoid having to send all the authentication details on each call to the API.
The first phase is to send a login
call with the specific agent login details, and then used to received token to conduct all other calls.
GET https://example.com/login/agent/
Login
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => "https://example.com/login/agent/",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => array(
"aether-application-key: [app-key]",
"aether-account: [account]",
"aether-agent: [agent]",
"aether-customization: [customization]",
"aether-password: [password]",
"cache-control: no-cache"
),
));
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
curl \
-H "aether-application-key: [app-key]" \
-H "aether-account: [account]" \
-H "aether-agent: [agent]" \
-H "aether-customization: [customization]" \
-H "aether-password: [password]" \
-H "cache-control: no-cache" \
https://example.com/login/agent/
Header | Mandatory | Description |
---|---|---|
aether-application-key | Yes | Your unique application key issued by your account manager |
aether-account | Yes | The account that is making the request |
aether-agent | Yes | The agent that is making the request |
aether-password | Yes | The agent that is making the request |
aether-customization | No | The whitelabel domain that is making the request. This is used in cases that require some customization like setting logos or emails, etc. |
The login request returns JSON structured like this:
{
"content": {
"LoginToken": "example12345",
"UserName": "example",
"FirstName": "example",
"LastName": "example",
"AccountID": 12345,
"AgentID": 12345,
"Permissions": {
"12345": {
"PermissionID": 12345,
"PermissionValue": "enabled"
}
},
"AccountLoginName": "example",
"AccountCompanyName": "example",
"AccountCurrencies": {
"EUR": {
"IsDefault": 1,
"Currency": "EUR"
},
"USD": {
"IsDefault": 0,
"Currency": "USD"
}
},
"AgentMeta": {
"AgentID": 1
},
"AccountMeta": {
"AccountID": 1
},
"OnAccounts": [
{
"AccessToken": "$6h$14$.gAH439wmRjrwAVXD98HNOgsNpDczlqm3Jq7KnEd1rVAGv3Fykk1a",
"AccountID": 1,
"LoginName": "example",
"CompanyName": "example",
"Type": "test",
"Status": "enabled",
"Market": "EU",
"Country": "DE",
"City": "Berlin",
"Address": "Some street"
}
],
"ProfileVersion": "dcc81048a744a12345a33bf6728550f700"
},
"status": "done"
}
Then, Once you have the LoginToken
you can send it instead of the full credentials on each call.
Example of using the LoginToken to authenticate
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => "[API endpoint]",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => array(
"aether-application-key: [application-key]",
"aether-customization: [customization]",
"aether-login-token: [login-token]
"cache-control: no-cache"
),
));
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
curl \
-H "aether-application-key: [app-key]" \
-H "aether-customization: [customization]" \
-H "aether-login-token: [login-token]" \
-H "cache-control: no-cache" \
[API endpoint]
Make sure to replace all items in
square brackets []
with the requests’ details.
One-off Authentication
These headers must be sent with every call:
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => "[API endpoint]",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => array(
"aether-application-key: [app-key]",
"aether-account: [account]",
"aether-agent: [agent]",
"aether-customization: [customization]",
"aether-password: [password]",
"cache-control: no-cache"
),
));
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
curl \
-H "aether-application-key: [app-key]" \
-H "aether-account: [account]" \
-H "aether-agent: [agent]" \
-H "aether-customization: [customization]" \
-H "aether-password: [password]" \
-H "cache-control: no-cache" \
[API endpoint]
Make sure to replace all items in
square brackets []
with the requests’ details.
The One-Off authentication method is used in cases you do not want to keep a “session”.
The API expects for all of the above headers to be included in all API requests to the server in a header that looks like the example on the right:
Header | Mandatory | Description |
---|---|---|
aether-application-key | Yes | Your unique application key issued by your account manager |
aether-account | Yes | The account that is making the request |
aether-agent | Yes | The agent that is making the request |
aether-password | Yes | The agent that is making the request |
aether-customization | No | The whitelabel domain that is making the request. This is used in cases that require some customization like setting logos or emails, etc. |
Token based authentication
The Token authentication method is a combination of the 2 previous methods, and is mainly used for searching and booking content through Mishor. However, you can use this method for all of your authentication needs, it’ll work either way.
curl \
-H "aether-application-key: [app-key]" \
-H "aether-access-token: [account]" \
-H "aether-customization: [customization]" \
-H "cache-control: no-cache" \
[API endpoint]
Make sure to replace all items in
square brackets []
with the requests’ details.
The aether-access-token
can be retrieved through the login
method above, and saved locally for all future use. it will not change until you actively change it through the back-office, although Innstant may initiate a rotation of all tokens once every period for security purposes.
Remote login to the Innstant UI
In order to perform a silent login from your UI to the Innstant UI so that your users will not need to enter their credentials, you can use the following method.
Basically, you need to hold the credentials of your agents or users, and send them to the Innstant API.
After we get the data from JSON, we’ll try to login with received credentials. If an attempt fails, we register a new user.
For registration we need all the fields. For login it can be only “email” and “password”. But we recommend sending the whole record each time.
Request
POST https://yourWhitelabelDomain.com/api/remote/login
Remote login request:
{
"firstName": "testName",
"lastName": "testLastName",
"email": "some@email.com",
"phone": "+44 123 456 789"
"password": "test"
}
Attribute | Description |
---|---|
firstName | First name of the agent, required for registration |
lastName | Last name of the agent, required for registration |
email of the agent, required always | |
password | The password of the agent, which is performing the login, required always |
phone | optional |
Response
Remote login response:
{
"auth_key": "$2y$10$GgE9IqVAt9BhRtjKADliWusRknKj0JlLWUZBAnT/OlQM5M0ykv03q",
"url": "http://{WLURL}?auth_key=$2y$10$GgE9IqVAt9BhRtjKADliWusRknKj0JlLWUZBAnT/OlQM5M0ykv03q"
}
In response you are getting an URL and auth_key. You should redirect your user to this URL:
http://{WLURL}?auth_key=$2y$10$GgE9IqVAt9BhRtjKADliWusRknKj0JlLWUZBAnT/OlQM5M0ykv03q
Attribute | Description |
---|---|
auth_key | should be send to url for authorisation |
url | the url to send your user’s browser to. |
Errors
There are two kinds of errors that can be received as a response:
You are trying to login with wrong password or register with existing e-mail:
{
"status": "error",
"errorMessage": "Account with the email first@last.email already exists.",
"errorCode": 500
}
Other errors:
{
"status": "error",
"errorMessage": "The operation was unsuccessful [#205].",
"errorCode": 500
}
Aether
Aether is the full fledged back office system that allows management of the bookings, accounting, setting of accounts and agents, and all other entities in the system.
Currency rates
Request
curl \
-H "aether-application-key: [app-key]" \
-H "aether-account: [account]" \
-H "aether-agent: [agent]" \
-H "aether-customization: [customization]" \
-H "aether-password: [password]" \
-H "cache-control: no-cache" \
https://example.com/currency-rates/get/USD,EUR
Response
{
"content": {
"Status": "done",
"Message": [
{
"FromCurrency": "EUR",
"ToCurrency": "USD",
"Rate": 1.24607
},
{
"FromCurrency": "USD",
"ToCurrency": "EUR",
"Rate": 0.802523
}
],
"ProfileVersion": "xxx"
},
"status": "done"
}
GET https://example.com/currency-rates/get/[comma separated currencies]
Attribute | Description |
---|---|
FromCurrency | 3 letter ISO 4217 currency code |
ToCurrency | 3 letter ISO 4217 currency code |
Rate | Float, value of the currency pair |
Accounting
In order to use the accounting, you will need to use the same authentication methods described above.
Documents
Get Document
Request
curl \
-H "aether-application-key: [app-key]" \
-H "aether-account: [account]" \
-H "aether-agent: [agent]" \
-H "aether-customization: [customization]" \
-H "aether-password: [password]" \
-H "cache-control: no-cache" \
-d '{"ID":22}' \
-X POST
https://example.com/accounting/document/get
Response
{
"content": {
"Accounting": {
"Balance": 30,
"Currency": "USD",
"GrossAmount": 30,
"NetAmount": 30,
"PaymentMethod": "cash",
"Tax": 0
},
"ActionPermissions": {
"AddLine": true,
"Cancel": true,
"Finalize": true,
"Pay": true
},
"Booking": ["35"],
"Covered": [],
"CreateDate": "2018-02-05 15:10:49",
"CreateType": "manual",
"DisplayName": "Sales Order",
"DocumentID": 48,
"DueDate": "2018-02-06 10:20:58",
"From": {
"AccountAlias": "test travel",
"AccountID": 101,
"AccountType": "Account",
"ContactAddress": "test",
"ContactCity": "test",
"ContactEmail": "stest@mail.com",
"ContactName": "testy mctestington"
},
"IssueDate": "2018-02-06 10:20:58",
"LeadName": "TEST TEST",
"LineSubTotals": {
"hotels": 30
},
"Lines": [
{
"Accounting": {
"Amount": 15,
"Conversion": 15,
"Currency": "EUR"
},
"BookingItem": {
"BookingID": "35",
"BookingItemID": 1,
"EndDate": "2018-01-15",
"LeadName": "TEST TEST",
"ServiceType": "hotels",
"StartDate": "2018-01-09"
},
"Details": {
"ItemDescription": "A TEST ROOM IN A FAKE HOTEL",
"ItemName": "hotels Booking",
"LineType": "hotels",
"ProductID": 1,
"Quantity": 1
},
"DocumentID": 48,
"LineID": 42
},
{
"Accounting": {
"Amount": 15,
"Conversion": 15,
"Currency": "EUR"
},
"BookingItem": {
"BookingID": "35",
"BookingItemID": 2,
"EndDate": "2018-01-15",
"LeadName": "TEST TEST",
"ServiceType": "hotels",
"StartDate": "2018-01-09"
},
"Details": {
"ItemDescription": "A TEST ROOM IN A FAKE HOTEL",
"ItemName": "hotels Booking",
"LineType": "hotels",
"ProductID": 2,
"Quantity": 1
},
"DocumentID": 48,
"LineID": 43
}
],
"PaymentDetails": null,
"Payments": [],
"ProfileVersion": "1108c82ffac3914820eee3c4b227299e909e1cd5",
"Reference": "s51",
"Status": "open",
"To": {
"AccountAlias": "jeff travel",
"AccountID": 3,
"AccountType": "Account",
"ContactAddress": "test",
"ContactCity": "test",
"ContactEmail": "N/A",
"ContactName": "N/A"
},
"ToProvider": false,
"Type": "invoice"
},
"status": "done"
}
POST https://example.com/accounting/document/get
Attribute | Description |
---|---|
DocumentID | The ID of this document |
CreateDate | The timestamp of the document creation |
CreateType | How was this document created. possible values are: manual, custom, scenario |
IssueDate | The deciding timestamp of when the document was issue, can be different than the actual creation timestamp |
DueDate | The timestamp stating when the document is due to be covered |
Type | Whether the document is an invoice or a payment. possible values are: invoice, payment |
DisplayName | The category name that the condition of this document falls under. Can be one of the following (Sales Order, Invoice, Receipt, Credit, Refund, Purchase Order, Provider Invoice, Provider Receipt, Provider Credit, Provider Payout, Provider Payment, Provider Refund) |
Status | The status of the document. possible values are: open, finalized, cancelled |
Reference | The reference number generated for this document |
ToProvider | Boolean, indicates the direction of the document. if false it means it’s a client facing document, otherwise it’s provider facing |
LeadName | Name of the lead Pax the document refers to |
From | The Contact element which is issuing the document, see details below |
To | The Contact element which is receiving the document, see details below |
Accounting.NetAmount | The net amount of the document |
Accounting.GrossAmount | The gross amount of the document |
Accounting.Currency | The currency of the document |
Accounting.Tax | Tax value included in the document |
Accounting.Balance | The remaining balance for the document |
ActionsPermissions | See ActionsPermissions section below |
Lines | See the “Get lines” section for details |
LineSubTotals | An array/object of sub-totals regarding the lines, grouped by line type |
Payments | Array of payments that covers this document |
Covered | Array of documents this document covers |
PaymentDetails | See PaymentDetails section below |
Contact element
Note that the contact can be of a Customer or of an account.
Attribute | Description |
---|---|
ContactName | The name of the Customer and/or the account holder |
ContactAddress | The address of the Customer and/or the account holder |
ContactCity | The city of the Customer and/or the account holder |
ContactEmail | The email of the Customer and/or the account holder |
AccountID | The ID of the contact |
AccountType | Whether it’s an “Account” or a “Customer” |
AccountAlias | Name of the account |
ActionsPermissions element
Attribute | Description |
---|---|
Pay | Indicates that a payment can be made to this document |
AddLine | Indicates whether a line could be added to this document |
Finalize | Indicates whether this document is open and can be finalized |
Cancel | Indicates whether this document can be cancelled |
PaymentDetails element
The PaymentDetails can be one of the following:
- Bank Transfer
- Credit Card
- VCC
- Cash
- Cheque
Each of these elements have different structure, and is shown on the “Type” attribute:
Bank Transfer
Attribute | Description |
---|---|
Date | Date of the payment, structure YYYY-MM-DD HH:MM:SS |
Sum | Value of the payment |
Comment | Free text comment |
Type | always “Bank Transfer” |
Reference | Transaction reference, free text |
Credit Card
Attribute | Description |
---|---|
Date | Date of the payment, structure YYYY-MM-DD HH:MM:SS |
Sum | Value of the payment |
Comment | Free text comment |
CardType | the card type used for payment. Free text. |
Last4Digits | last 4 digits of the credit card used for the payment |
VCC
Attribute | Description |
---|---|
Date | Date of the payment, structure YYYY-MM-DD HH:MM:SS |
Sum | Value of the payment |
Comment | Free text comment |
CardType | the card type used for payment. Free text. |
Last4Digits | last 4 digits of the credit card used for the payment |
Cash
Attribute | Description |
---|---|
Date | Date of the payment, structure YYYY-MM-DD HH:MM:SS |
Sum | Value of the payment |
Comment | Free text comment |
Details | Free text |
Cheque
Attribute | Description |
---|---|
Date | Date of the payment, structure YYYY-MM-DD HH:MM:SS |
Sum | Value of the payment |
Comment | Free text comment |
AccountNumber | Number of the account used for payment |
ChequeNumber | Identifier of the Cheque used for payment |
Get Line
Request
curl \
-H "aether-application-key: [app-key]" \
-H "aether-account: [account]" \
-H "aether-agent: [agent]" \
-H "aether-customization: [customization]" \
-H "aether-password: [password]" \
-H "cache-control: no-cache" \
-d '{"ID":44}' \
-X POST
https://example.com/accounting/line/get
Response
{
"content": {
"ActionPermissions": {
"Edit": true,
"Remove": true
},
"ProfileVersion": "347...",
"LineID": 9,
"DocumentID": 6,
"Details": {
"LineType": "Product",
"ProductID": 1,
"ItemName": "dinner",
"ItemDescription": "super awesome delux dinner for 2",
"Quantity": 1
},
"BookingItem": {
"BookingID": null,
"BookingItemID": null,
"ServiceType": null,
"LeadName": null,
"StartDate": null,
"EndDate": null
},
"Accounting": {
"Amount": 100,
"Currency": "EUR",
"Conversion": 125
}
},
"status": "done"
}
This method retrieves document lines.
Attribute | Description |
---|---|
LineID | The ID of the line |
DocumentID | The ID of the document the line belongs to |
ActionPermissions | What can be done with this line, see below |
Details | Line details, see below |
BookingItem | The booking item the line covers, see below |
Accounting | Accounting aspects of the line, see below |
ActionPermissions
Attribute | Description |
---|---|
Edit | boolean, can the line be edited |
Remove | boolean, can the line be removed |
Details
Attribute | Description |
---|---|
LineType | The type of item the line refers to, possible values are: Product, Tax, but it can also be anything the user defines when setting the line. |
ProductID | The product id for the line. Note that this can be any product and not necessarily the booking item id. |
ItemName | The name of the Item the line refers to, free text. |
ItemDescription | Free text description of the item. |
Quantity | How many products does this line covers |
BookingItem
Attribute | Description |
---|---|
BookingID | The booking ID the line covers |
BookingItemID | The booking item ID the line covers |
ServiceType | The service type the line covers |
LeadName | Lead name of the booking |
StartDate | Start date of the booking |
EndDate | End date of the booking |
Accounting
Attribute | Description |
---|---|
Amount | Value of the line |
Currency | Currency of the line |
Conversion | The value of this line converted into the documents default currency |
List Documents
Request
curl \
-H "aether-application-key: [app-key]" \
-H "aether-account: [account]" \
-H "aether-agent: [agent]" \
-H "aether-customization: [customization]" \
-H "aether-password: [password]" \
-H "cache-control: no-cache" \
-d '{"filters":{"FromID": 1},"resultsPerPage": 10,"currentPage": 1}' \
-X POST
https://example.com/accounting/document/list
This method retrieves documents based of filters and pagination.
Attribute | Description |
---|---|
resultsPerPage | Number of results to return per page, max is 50 |
currentPage | Current page |
filters | available filters object, optional, see below for details |
(optional) Request Filters
you can include multiple filters on the request to narrow your search. all filters are optional
Attribute | Description |
---|---|
DocumentIDs | array of document IDs |
FromIDs | array of account IDs the document was issued from |
ToIDs | array of account IDs the document was issued to |
BookingIDs | array of booking IDs the document was issued for |
AgentIDs | array of booking IDs the document was issued by |
CreatedAfter_value | Timestamp, get bookings created after this date, format is: YYYY-MM-DD HH:MM:SS |
CreatedBefore_value | Timestamp, get bookings created before this date, format is: YYYY-MM-DD HH:MM:SS |
IssuedAfter_value | Timestamp, get bookings issued after this date, format is: YYYY-MM-DD HH:MM:SS |
IssuedBefore_value | Timestamp, get bookings issued before this date, format is: YYYY-MM-DD HH:MM:SS |
DueAfter_value | Timestamp, get bookings due after this date, format is: YYYY-MM-DD HH:MM:SS |
DueBefore_value | Timestamp, get bookings due before this date, format is: YYYY-MM-DD HH:MM:SS |
Types | array, possible values are invoice, payment |
PaymentMethods | array, see PaymentDetails for possible values |
Statuses | array, possible values are open, finalized, cancelled |
Currencies | array, list of currencies |
References | array, list of document references |
DisplayNames | array, possible values Sales Order, Invoice, Receipt, Credit, Refund, Purchase Order, Provider Invoice, Provider Receipt, Provider Credit, Provider Payout, Provider Payment, Provider Refund |
Direction | string, possible values Account, Provider, Both |
Response
{
"content": {
"currentPage": 1,
"totalResults": 86,
"resultsPerPage": 10,
"records": [
/*...documents...*/
],
"ProfileVersion": "7efd..."
},
"status": "done"
}
POST https://example.com/accounting/document/list
Attribute | Description |
---|---|
records | a list of document objects as described in the /accounting/document/get method |
Mishor
Introduction
Mishor is an API switch for multiple travel content providers.
Products
Hotels
Flow
The common case usage is quite simple:
- Initiate a search
- Poll to get results
- [optional] poll the same search to get better results providing timestamp of the last poll
- [optional] get the cancellation policy, if it’s not returned as part of the search/poll results
- run a pre-book call
- book
Please note - changing any method of the API requires a new fresh certification.
Search
Request
curl \
-H "aether-application-key: [app-key]" \
-X POST
-d @request-file.json
https://example.com/hotels/search
Request content
{
"client": {
"ip": "1.2.3.4",
"userAgent": "Example User Agent"
},
"currencies": ["USD"],
"customerCountry": "IL",
"customFields": [],
"dates": {
"from": "2018-09-20",
"to": "2018-09-22"
},
"destinations": [
{
"id": 5252,
"type": "location"
}
],
"filters": [],
"pax": [
{
"adults": 2
}
],
"service": "hotels"
}
Request
POST https://example.com/hotels/search
Attribute | Description |
---|---|
client | Information about the client who is running the search. This node is optional, but sending it may provide special rates, for example for mobile users. |
.client/ip | The IP of the end-client |
.client/userAgent | The user agent of the end-client |
currencies | A list of currencies you wish to get your results in. The first currency on the list will be the default currency of the search |
customerCountry | 2 letter ISO code of the customer country running the search. Note: that the same customer country must be used on the booking, and giving a wrong or inaccurate customer country may result in the hotel not honoring the booking. |
customFields | See below |
dates | The from and to dates, format: YYYY-MM-DD |
destinations | The search destinations array |
.destinations/[item]/type | can be either hotel or location |
.destinations/[item]/id | the entity id based on the type |
filters | See below |
pax | See below |
Filters
In order to better fit your needs, the API allows sending filters to include additional content.
All the filters are optional.
Example of a filter in the request
{
"name": "payAtTheHotel",
"value": true
},
{
"name":"showWhenCheckinDateWithin",
"value":8
},
{
"name":"hideWhenCancellationDeadlineWithin",
"value":18
}
Filter | Type | Description |
---|---|---|
payAtTheHotel | bool | Include post-pay content |
onRequest | bool | Include on-request content, which is not immediately confirmed |
showSpecialDeals | bool | Include the special deals offers and descriptions in the response |
getPackageRates | bool | Include rates which mustn’t be sold as-is, but only as part of a package. This feature must be enabled on your account by your account manager |
showRoomDescriptions | bool | Whether to show the rooms descriptions where available |
showRoomBedding | bool | Whether to show the bedding setup for the room |
showRoomCategories | bool | Whether to show the category of the room |
showWhenCheckinDateWithin | int | Show all results regardless of the free cancellation deadline if the arrival date is within the days specified in the filter |
hideWhenCancellationDeadlineWithin | int | Hide results if the deadline for free cancellation is within the days specified in the filter |
Custom Fields
This part is relevant for deep-integrations only, where you have your own suppliers connected via this API and need to pass parameters to specific providers.
An example of such a use-case is a B2B system that wants the agents using the system to collect loyalty points from a specific directly-contracted provider. In order to achieve that, you need to pass the agent credentials for that specific provider during search, and these credentials will be used to contact the provider.
Example of custom fields in the request
{
"customFields": {
"agentId": 1,
"whatever": "shalgon"
}
}
Pax
The pax array specifies the desired room configuration.
Each room is an object and each object consists of adults
and children
, where the children
element is an array with their ages.
For example: in order to search for a room with 1 adult and 2 children ages 12 and 14, you need to create an object that looks like this:
{
“adults”: 1,
“children”: [12,14]
}
Note that different hotels and different channels treat “child” differently, so even if you send a child aged 15, some properties may treat it as an adult while others as a child.
Example of pax in the request
{
"pax": [
{
"adults": 2
},
{
"adults": 1,
"children": [12, 14]
}
]
}
Response
The response will return the results received until the search was completed.
Response
{
"results": [
{
"items": [
{
"name": "Classic Double",
"category": "standard",
"bedding": "double",
"board": "BB",
"hotelId": 3090,
"pax": {
"adults": 2,
"children": []
},
"quantity": {
"min": 1,
"max": 1
}
},
{
"name": "Classic Double",
"category": "standard",
"bedding": "double",
"board": "BB",
"hotelId": 3090,
"pax": {
"adults": 2,
"children": []
},
"quantity": {
"min": 1,
"max": 1
}
}
],
"code": "3090:::BB:5aeffedce7c86:qPo",
"price": {
"amount": 1096.62,
"currency": "USD"
},
"netPrice": {
"amount": 722.25,
"currency": "EUR"
},
"barRate": {
"amount": 631.8,
"currency": "EUR"
},
"confirmation": "immediate",
"payment": "pre",
"packageRate": false,
"commissionable": true,
"cancellation": {
"type": "non-refundable"
}
}
],
"sessionId": "1234",
"status": "done",
"timestamp": 1533640316,
"requestTime": "2018-08-07 14:11:56",
"completed": 100,
"processTime": 530
}
The response is an array of results, each result consists of these attributes:
Attribute | Description |
---|---|
items | An array of items the result id holds. The booking will be made on the result including all the items in it. The prices are only on the result level. |
.item/name | The name of the offered room |
.item/category | The category of the room |
.item/bedding | the bedding type available for this room |
.item/board | the available board for this offer, available list of boards exists in the lookups section |
.item/hotelId | The hotel id, taken from the static data |
.item/pax | the corresponding pax from your search which this result is suitable to |
.item/quantity | min /max availability. how many items of this result can be booked. If the min value is larger than 1, it means you must book at least the minimum quantity of results. Note that the price element in any case is the total price of the minimum quantity of items offered. |
barRate | Price (amount/currency) of the BAR, the price which you are not allowed to sell below on B2C platforms. |
cancellation | See below |
code | The result code, use this for the next steps |
commissionable | boolean, indicates whether you can apply a commission on top of the price or not |
confirmation | immediate or on-request |
netPrice | The net price (amount/currency) of this result |
packageRate | boolean, indicates whether this result can be sold as a stand-alone offer or if it requires to be sold as part of a package |
payment | pre or post , indicates whether this is a pre-paid result or a pay-at-the-hotel result |
price | The gross price of the result |
In addition, there are several other attributes that are of interest:
Attribute | Description |
---|---|
sessionId | The session ID of the search |
status | The status of the search, whether it is done , working , or failed |
timestamp | The server timestamp of the response. this can be used to poll by delta |
requestTime | The request date time in Human readable format |
completed | Integer, percentage of the progress. 0 means no tasks were completed, 100 means all tasks were completed, everything in between in “in process”. Please note this attribute is for Innstant’s internal use only. To check if the search was completed or not please refer only to the status property. |
processTime | Processing time in milliseconds. |
In case of post-payment results, you might get a transaction
node in the response. This node will be returned in case you defined a “transaction fee” markup for this purpose.
This is being used in case the user has to pay a gross amount directly to the hotel, but you still want to collect something for the booking.
Example of a transaction fee in the response
"transactionFee": {
"amount": 25.7,
"currency": "EUR"
}
Cancellation Policy
The cancellation policy is build from frames
.
Each frame
has a start date (from
), end date(to
), and a penalty.
These frames tells you exactly what will be the penalty on each date starting from the booking date until the check-in date.
After the check-in date the cancellation penalty should be assumed as 100%.
Poll
Request
curl \
-H "aether-application-key: [app-key]" \
-X POST
-d @request-file.json
https://example.com/hotels/poll[/timestamp]
Request content
{
"client": {
"ip": "1.2.3.4",
"userAgent": "Example User Agent"
},
"currencies": ["USD"],
"customerCountry": "IL",
"customFields": [],
"dates": {
"from": "2018-09-20",
"to": "2018-09-22"
},
"destinations": [
{
"id": 5252,
"type": "location"
}
],
"filters": [],
"pax": [
{
"adults": 2
}
]
}
Request
POST https://example.com/hotels/poll[/timestamp]
The poll request & response are identical to the search request & response with the exception of the endpoint.
You can send as many polls as you like until the status in the response is working
. Once it finishes, the status changes to done
and this means no new results will show up in your next poll.
Check out the Flow
chapter in the beginning to get a better understanding of this method.
You can add an optional timestamp
to the URL, the timestamp must be the one returned in the previous search/poll response in order to get the details.
If you do not send the timestamp
in the URL, you will get ALL results every time.
Note that the search and poll requests must be identical.
Progress
Request
curl \
-H "aether-application-key: [app-key]" \
-X POST
-d @request-file.json
https://example.com/hotels/progress
Request content
{
"client": {
"ip": "1.2.3.4",
"userAgent": "Example User Agent"
},
"currencies": ["USD"],
"customerCountry": "IL",
"customFields": [],
"dates": {
"from": "2018-09-20",
"to": "2018-09-22"
},
"destinations": [
{
"id": 5252,
"type": "location"
}
],
"filters": [],
"pax": [
{
"adults": 2
}
]
}
Request
POST https://example.com/hotels/progress
The progress request & response are identical to the search request & response with the exception of the endpoint. This call doesn’t return any results, but status of the search.
You can send as many progress calls as you like until the status in the response is working
. Once it finishes, the status changes to done
and this means you can now use poll
request to grab all of the results.
Check out the Flow
chapter in the beginning to get a better understanding of this method.
Note that the search and progress requests much be identical.
Get cancellation policy
Request content
{
"client": {
"ip": "1.2.3.4",
"userAgent": "Example User Agent"
},
"currencies": ["USD"],
"customerCountry": "IL",
"customFields": [],
"dates": {
"from": "2018-09-20",
"to": "2018-09-22"
},
"destinations": [
{
"id": 5252,
"type": "location"
}
],
"filters": [],
"pax": [
{
"adults": 2
}
]
}
Request
POST http://example.com/hotels/cancellation/[room code]
The request consists of the desired room code (in the url) and the original search (in the request body).
Response
The response is exactly the same as the poll response, but with the cancellation frames in place.
Note that if you searched for multiple rooms and received multiple room codes for a single result, you MUST send multiple calls in order to get the cancellation policy for each separate code.
Pre-Book
Request content
{
"services": [
{
"searchCodes": [
{
"code": "17512:standard:double:BB:5c06a3747437b$118h120U",
"pax": [
{
"adults": 2,
"children": []
}
]
},
{
"code": "17512:standard:double:BB:5c06a378bbb90$118h120U",
"pax": [
{
"adults": 1,
"children": []
}
]
}
],
"searchRequest": {
"currencies": ["USD"],
"customerCountry": "IL",
"dates": {
"from": "2018-05-04",
"to": "2018-05-05"
},
"destinations": [
{
"id": 5252,
"type": "location"
}
],
"filters": [
{
"name": "payAtTheHotel",
"value": true
}
],
"pax": [
{
"adults": 2
},
{
"adults": 1
}
],
"service": "hotels"
}
}
]
}
Request
POST http://example-booking.com/pre-book
Note that this request is being send to a different domain than the one used for searching
Element | Description |
---|---|
searchCodes | The result codes you are planning to book. you can send as many search codes as you like in this array. |
.code | the code from the result |
.pax | the pax related to the specific code |
searchRequest | the original, unchanged, search request |
Response
Response content
{
"content": {
"PaymentMethods": [
{
"methodDescription": "",
"methodName": "account_credit",
"paymentSettings": {
"creditCardForm": false,
"requiredFields": []
},
"status": "disabled"
},
{
"methodDescription": "",
"methodName": "enett",
"paymentSettings": {
"creditCardForm": false,
"requiredFields": [
{
"enettId": "test"
}
]
},
"status": "enabled"
},
{
"methodDescription": "",
"methodName": "credit_card",
"paymentSettings": {
"creditCardForm": true,
"requiredFields": []
},
"status": "enabled"
}
],
"Services": {
"hotels": [
{
"barRate": {
"amount": 690,
"currency": "EUR"
},
"cancellation": {
"frames": [
{
"from": "2018-05-21",
"penalty": {
"amount": 0,
"currency": "USD"
},
"to": "2018-06-18"
},
{
"from": "2018-06-18",
"penalty": {
"amount": 247.71,
"currency": "EUR"
},
"to": "2018-06-21"
}
],
"type": "fully-refundable"
},
"code": "33823:standard:double:BB:5afd296a87736$33823:standard:double:BB:5afd296a87775$qPo",
"commissionable": true,
"confirmation": "immediate",
"items": [
{
"bedding": "double",
"board": "BB",
"boardName": "Breakfast Continental",
"category": "standard",
"hotel": {
"address": "Via Marghera 15/17",
"city": "Rome",
"fax": null,
"latitude": "41.90224110705",
"longitude": "12.503670528531",
"name": "Hotel Corot",
"phone": "+39644700900",
"rating": "3",
"zip": "00185"
},
"hotelId": 33823,
"name": "Standard Double or Twin Room",
"pax": {
"adults": 2,
"children": []
},
"quantity": {
"max": 1,
"min": 1
},
"remarks": {
"general": "this is a remark that should be shown to the customer"
}
},
{
"bedding": "double",
"board": "BB",
"boardName": "Breakfast Continental",
"category": "standard",
"hotel": {
"address": "Via Marghera 15/17",
"city": "Rome",
"fax": null,
"latitude": "41.90224110705",
"longitude": "12.503670528531",
"name": "Hotel Corot",
"phone": "+39644700900",
"rating": "3",
"zip": "00185"
},
"hotelId": 33823,
"name": "Standard Double or Twin Room",
"pax": {
"adults": 2,
"children": []
},
"quantity": {
"max": 1,
"min": 1
},
"remarks": {
"general": "this is a remark that should be shown to the customer <b>including HTML</b>"
}
}
],
"netPrice": {
"amount": 788.77,
"currency": "EUR"
},
"packageRate": false,
"paymentMethod": "direct",
"price": {
"amount": 1196.4,
"currency": "USD"
},
"surcharges": [],
"requestCode": "319229:standard:double:RO:4bf3d2665b474$119yo",
"token": "65DDBED2"
}
]
}
},
"status": "done"
}
Element | Description |
---|---|
PaymentMethods | The acceptable payment methods for this booking |
.methodName | the name of the payment method. a standard integration will use account_credit or credit_card . |
.methodDescription | additional description of the method, for example if the method is a saved credit card token on the account, the description can say something like “Credit card ending with 1234” |
.status | whether this option is enabled for this booking |
.paymentSettings | specific settings for the payment method |
..creditCardForm | boolean, specifies if you need to show the credit card form to the user |
..requiredFields | key/value array of objects, consists of required fields to request from the user. for example the enett agent id in case of enett payment integration |
Services | The services that are about to be booked |
.hotels | an array of hotel rooms that are about to be booked |
..barRate | The minimum price (amount/currency) that can be shown on B2C website |
..cancellation | The cancellation policies, see the search response for details |
..code | The room code |
..commissionable | Whether or not you can add commission to the final price |
..confirmation | immediate or on-request |
..items | a collection of items |
..item.bedding | The offered bedding configuration |
..item.board | The offered board code |
..item.board | The offered board name |
..item.category | The offered room category |
..item.hotel | The hotel information. Note that it is mandatory to show the hotel information received in this response to the user prior to them making the booking, and use this information on the voucher issued to the user. It is NOT allowed to use the information from the static data. |
..item.hotelId | The booked hotel ID |
..item.name | The booked room name. Note that it is mandatory to show the room name received in this response to the user prior to them making the booking, and show this information on the voucher issued to the user. It is NOT allowed to use the information from the search response. |
..item.pax | The pax suitable for this room |
..item.quantity | See the search response for details |
..item.remarks | object that includes keys and free text remarks received from the hotel. the default key is called general , and additional keys may be included in certain cases. Note that is is mandatory to show these remarks to the user before the booking and it is also mandatory to put them on the voucher. |
..netPrice | The net price (amount/currency) of the booking, i.e. the amount that you need to pay the provider |
..packageRate | if true, this offer cannot be sold as a stand-alone booking, and the price must never be shown to the user without it being bundled as a package with other products. |
..payment | pre or post |
..price | The gross price (amount/currency) of the booking, i.e. the amount you charge your customer |
..requestCode | the code you sent in the request. this is used in case the result changed due to price or availability. it is for your use only and should not be sent in further requests. |
..token | the booking token you will have to send in order to make the actual booking |
..warnings | optional node, returned only in case of price or availability change |
"warnings": [
{
"code": 2100,
"message": "Your item is not available under the originally requested price, please review the selected alternative or go back to select another result."
}
]
Book
Request
POST http://example-booking.com/book
Note that this request is being send to a different domain than the one used for searching
{
"creditCard": {
"cardNumber": "4111 1111 1111 1111",
"cvc": "555",
"expiry": {
"month": "12",
"year": "2019"
},
"name": {
"first": "Yogi",
"last": "Berra"
}
},
"customer": {
"birthDate": "1975-09-14",
"contact": {
"address": "housington 66",
"city": "cityngton",
"country": "NL",
"email": "test@example.com",
"phone": "555-4433222",
"state": "N/A",
"zip": "88776"
},
"name": {
"first": "Yogi",
"last": "Berra"
},
"title": "M"
},
"paymentMethod": {
"methodName": "account_credit"
},
"reference": {
"agency": "my agency reference",
"voucherEmail": "test@example.com"
},
"services": [
{
"bookingRequest": [
{
"code": "3742:::RO:5acb6bcf725bf:qPo",
"pax": [
{
"adults": [
{
"contact": {
"address": "housington 66",
"city": "cityngton",
"country": "NL",
"email": "test@example.com",
"phone": "555-4433222",
"state": "N/A",
"zip": "88776"
},
"lead": true,
"name": {
"first": "Yogi",
"last": "Berra"
},
"title": "M"
},
{
"name": {
"first": "Mona",
"last": "Lisa"
},
"title": "F"
}
]
}
],
"token": "1515BEE8"
}
],
"searchRequest": {
"currencies": ["USD"],
"customerCountry": "NL",
"dates": {
"from": "2018-05-04",
"to": "2018-05-05"
},
"destinations": [
{
"id": 5252,
"type": "location"
}
],
"filters": [
{
"name": "payAtTheHotel",
"value": true
}
],
"pax": [
{
"adults": 2,
"children": []
}
],
"service": "hotels"
}
}
]
}
Element | Description |
---|---|
creditCard | In case you are paying with a credit card, you need to send all relevant details |
customer | The customer details of the customer that is making the booking. It doesn’t have to be the same details as the travelers |
payment | how are you going to pay for the booking. this value must be one of the options returned in the pre-book |
.method | one of: “credit_card”, “account_credit”, or “enett” |
.securePaymentUrl | in case the payment method is credit_card , you need to supply a URL where to send the user after the payment process. |
reference | your references |
.agency | free text of your agency reference, i.e. your internal booking id |
.voucherEmail | an email address to send the voucher to |
services | this array of elements consists of the desired items you want to book. Each element contains 2 sub-elements: the original search request, and the booking request. |
.searchRequest | the original search request |
.bookingRequest | this element will contain the guest information and the payment details. |
..code | The result code you wish to book, this code comes from the search/poll response |
..token | the token from the pre-book call |
..pax | The pax configuration array for the booked properties. Each element in the array is a booked room |
…adults | the details of the adults in the room |
….name | first /last names of the guest |
….title | M for male, F for female (for children - see below) |
….lead | boolean, set to true if this is the lead pax. each booking must have one lead. do not set this flag on more than one. |
….contact | contact details of the lead pax, can be different than the customer on the booking. |
In case you want to send a booking request for children, the child element must include another attribute called “birthDate” with a date value in the format YYYY-MM-DD. It is important to note that the age of the children is calculated based on the booking date.
Example of a children node:
“children”: [
{
”birthDate”: “2014-04-20”
”name”: {
”first”: “test”,
”last”: “test”
},
”title”: “C”
}
]
Please ensure the “birthDate” attribute is present and correctly formatted to prevent any issues during the booking process.
Response
Response content
{
"content": {
"bookingID": "1000255",
"customer": {
"birthDate": "1985-01-01",
"contact": {
"address": "housington 66",
"city": "cityington",
"country": "NL",
"email": "test@example.com",
"phone": "555-4433222",
"state": "N/A",
"zip": "88776"
},
"name": {
"first": "Yogi",
"last": "Berra"
},
"title": "M"
},
"netPrice": {
"amount": 55.2,
"currency": "EUR"
},
"payment": {
"method": "account_credit",
"clearingState": null,
"paymentStatus": "unpaid"
},
"price": {
"amount": 60.72,
"currency": "EUR"
},
"services": [
{
"cancellation": {
"frames": [
{
"from": "2018-05-13",
"penalty": {
"amount": 60.72,
"currency": "EUR"
},
"to": "2018-07-17"
}
],
"type": "refundable"
},
"code": "10666:standard:double:BB:5af95d6668163:qPo",
"hotel": {
"address": "Via San Lino Papa 35",
"city": "Rome",
"fax": null,
"latitude": "41.919755493726",
"longitude": "12.420943826437",
"name": "Hotel Pineta Palace",
"phone": "+3963013800",
"rating": "4",
"room": {
"bedding": "double",
"board": "BB",
"boardName": null,
"category": "standard",
"name": "Economy Double or Twin Room",
"token": "9179F6DB"
},
"zip": "00167"
},
"itemId": 1,
"netPrice": {
"amount": 55.2,
"currency": "EUR"
},
"pax": [
{
"adults": [
{
"birthDate": "1985-01-01",
"contact": {
"address": "housington 66",
"city": "cityington",
"country": "NL",
"email": "test@example.com",
"phone": "555-4433222",
"state": "N/A",
"zip": "88776"
},
"lead": true,
"name": {
"first": "Yogi",
"last": "Berra"
},
"title": "M"
},
{
"birthDate": "1985-01-01",
"lead": false,
"name": {
"first": "Mona",
"last": "Lisa"
},
"title": "F"
}
],
"children": []
}
],
"price": {
"amount": 60.72,
"currency": "EUR"
},
"quantity": 1,
"remarks": "<br>\r\n. 1 double bed, 2 single beds. Economy Double or Twin Room. <p><b>Know Before You Go</b> <br /><ul> <li>All guests, including children, must be present at check-in and show their government-issued photo ID card or passport.</li> <li>Cash transactions at this property cannot exceed EUR 2999.99, due to national regulations. For further details, please contact the property using information in the booking confirmation. </li> <li>One child 3 years old or younger stays free when occupying the parent or guardian's room, using existing bedding. </li> </ul></p><p><b>Fees</b> <br /><p>The following fees and deposits are charged by the property at time of service, check-in, or check-out. </p> <ul> <li>Self parking fee: EUR 8 per day</li> </ul> <p>The above list may not be comprehensive. Fees and deposits may not include tax and are subject to change. </p></p><p><b>Mandatory Fees and Taxes</b> <br /><p>You'll be asked to pay the following charges at the property:</p> <ul><li>A tax is imposed by the city: EUR 6 per person, per night, up to 10 nights. This tax does not apply to children under 10 years of age. </li></ul> <p>We have included all charges provided to us by the property. However, charges can vary, for example, based on length of stay or the room you book. </p></p>. -This booking is non-amendable, If you need to make an amendment, please cancel and re-book for the new dates or room type.. Breakfast Buffet. 1 double bed, 2 single beds. Economy Double or Twin Room. <p><b>Know Before You Go</b> <br /><ul> <li>All guests, including children, must be present at check-in and show their government-issued photo ID card or passport.</li> <li>Cash transactions at this property cannot exceed EUR 2999.99, due to national regulations. For further details, please contact the property using information in the booking confirmation. </li> <li>One child 3 years old or younger stays free when occupying the parent or guardian's room, using existing bedding. </li> </ul></p><p><b>Fees</b> <br /><p>The following fees and deposits are charged by the property at time of service, check-in, or check-out. </p> <ul> <li>Self parking fee: EUR 8 per day</li> </ul> <p>The above list may not be comprehensive. Fees and deposits may not include tax and are subject to change. </p></p><p><b>Mandatory Fees and Taxes</b> <br /><p>You'll be asked to pay the following charges at the property:</p> <ul><li>A tax is imposed by the city: EUR 6 per person, per night, up to 10 nights. This tax does not apply to children under 10 years of age. </li></ul> <p>We have included all charges provided to us by the property. However, charges can vary, for example, based on length of stay or the room you book. </p></p>. -This booking is non-amendable, If you need to make an amendment, please cancel and re-book for the new dates or room type.. Breakfast Buffet",
"service": "hotels",
"status": "confirmed",
"supplier": {
"reference": "BG66666GZSPL"
}
}
],
"status": "confirmed"
},
"status": "done"
}
Most of the details are a reflection of the data sent by you. the following details are of notice:
Element | Description |
---|---|
bookingID | The Innstant system booking ID |
payment | The payment options used in the booking |
.method | The payment method used |
.clearingState | In case a credit card was used, the clearing state tells you if the booking was charged or just authorized. possible values are enrollment , authorization , payment and pre-payment |
.paymentStatus | paid or unpaid |
services.supplier.reference | the supplier reference that should appear on the voucher |
Understanding the different statuses on the bookings response
We return 3 status attributes as part of the book
response, each of them has a different purpose.
In order to know if a specific service within the booking was confirmed - you must check the individual statuses on each service in the booking.
Element | Description |
---|---|
status | message status - tells you if there was a communication error |
content.status | the booking status |
content.services.status | status of each service in the booking |
Possible status values
Element | Description |
---|---|
confirmed | The booking/item was confirmed |
initialized | The booking/item started the booking process |
partially_confirmed | The booking was only partially confirmed, you must check each item to make sure which one was not confirmed |
failed | The booking/item failed to confirm |
error | There was an error during the booking process |
cancelled | The booking/item was cancelled |
pending_cancellation | The booking/item was not cancelled yet but is waiting to be cancelled |
on_request | The booking/item is pending the provider approval or rejection |
rejected | The booking/item was rejected |
unknown | ¯_(ツ)_/¯ |
Recoverable errors
In some cases you’ll get a “recoverable error”. This can happen if there is already a booking on that hotel for the same guest, if the price changed, or if the processing commission is too high (if you’re using the processing feature).
The response will have the error code a70x or a21xx (i.e. a702, a2100, etc) and it can be recovered by calling the endpoint: /complete-booking/
with the content:
{"completeCode":"a702","paymentSettings":{"paymentAmount":"net","paymentDate":"billing-terms","transactionFeeCharge":true},"bookingID":xx1234}
Element | Description |
---|---|
completeCode | The recoverable error code you received in the initial booking response |
paymentSettings | the same paymentSettings node you sent in the booking request |
bookingID | the booking ID from the initial booking response |
Cancel
Request content
{
"BookingID": 1234,
"CancelReason": "The dog is sick",
"Force": false,
"IsManual": false
}
Request
POST https://example.com/booking-cancel
Attribute | Description |
---|---|
BookingID | The booking ID you would like to cancel |
CancelReason | The reason for the cancellation, can be left blank |
Force | Should the booking be cancelled in any case, without calling the provider - USE FALSE UNLESS YOU KNOW WHAT YOU ARE DOING |
IsManual | Is the booking being cancelled by a human request or by an automated process |
Response
Response content
{
"content": {
"Status": "done",
"Warnings": []
},
"status": "done"
}
Attribute | Description |
---|---|
content.Status | Was the cancellation successful (done ) or unsuccessful (error ) |
content.Warnings | This array will be returned only if force cancellation was used |
Booking Details
Request
GET https://example.com/booking-details/[booking-id]
Attribute | Description |
---|---|
BookingID | The booking ID you would like to get details for |
Response
The response is the same as booking response
Events
Flow
The common case usage is quite simple:
- Initiate a search
- get results
- [optional] poll the same search to get better results
- get details (times)
- [optional] get the cancellation policy, if it’s not returned as part of the search/poll results
- run a pre-book call
- book
Search
Request
curl \
-H "aether-application-key: [app-key]" \
-X POST
-d @request-file.json
https://example.com/events/search
Request content
{
"client": {
"ip": "1.2.3.4",
"userAgent": "Example User Agent"
},
"currencies": ["USD"],
"customerCountry": "IL",
"customFields": [],
"dates": {
"from": "2018-09-20",
"to": "2018-09-22"
},
"destinations": [
{
"id": 5252,
"type": "location"
}
],
"pax": [
{
"adults": 2
}
]
}
Request
POST https://example.com/events/search
Attribute | Description |
---|---|
client | Information about the client who is running the search. This node is optional, but sending it may provide special rates, for example for mobile users. |
.client/ip | The IP of the end-client |
.client/userAgent | The user agent of the end-client |
currencies | A list of currencies you wish to get your results in. The first currency on the list will be the default currency of the search |
customerCountry | 2 letter ISO code of the customer country running the search. Note: that the same customer country must be used on the booking, and giving a wrong or inaccurate customer country may result in the venue not honoring the booking. |
customFields | See below |
dates | The from and to dates, format: YYYY-MM-DD |
destinations | The search destinations array |
.destinations/[item]/type | can be location only |
.destinations/[item]/id | the entity id based on the type |
filters | See below |
pax | See below |
Custom Fields
This part is relevant for deep-integrations only, where you have your own suppliers connected via this API and need to pass parameters to specific providers.
An example of such a use-case is a B2B system that wants the agents using the system to collect loyalty points from a specific directly-contracted provider. In order to achieve that, you need to pass the agent credentials for that specific provider during search, and these credentials will be used to contact the provider.
Example of custom fields in the request
{
"customFields": {
"agentId": 1,
"whatever": "shalgon"
}
}
Pax
The pax array specifies the desired room configuration.
Each room is an object and each object consists of adults
and children
, where the children
element is an array with their ages.
For example: in order to search for a room with 1 adult and 2 children ages 12 and 14, you need to create an object that looks like this:
{
“adults”: 1,
“children”: [12,14]
}
Note that different suppliers and different channels treat “child” differently, so even if you send a child aged 15, some properties may treat it as an adult while others as a child.
Example of pax in the request
{
"pax": [
{
"adults": 2
},
{
"adults": 1,
"children": [12, 14]
}
]
}
Response
The response will return the results received until the search was completed.
Response
{
"timestamp": 1561875522,
"requestTime": "2019-06-30 06:18:42",
"status": "done",
"completed": 100,
"sessionId": "x:y:z",
"processTime": 113,
"results": [
{
"price": {
"amount": 176.08,
"currency": "EUR"
},
"netPrice": {
"amount": 145.38,
"currency": "EUR"
},
"barRate": null,
"confirmation": "immediate",
"paymentType": "pre",
"packageRate": false,
"commissionable": true,
"providers": [
{
"id": "1nb9ff34gferb435bv",
"name": "example"
}
],
"specialOffers": [],
"items": [
{
"name": "Colosseum Express private Tour - skip the line tickets!",
"categories": [
{
"id": 3,
"name": "Cultural & Theme Tours"
},
{
"id": 21,
"name": "Private & Custom Tours"
},
{
"id": 18,
"name": "Family Friendly"
},
{
"id": 14,
"name": "Walking & Biking Tours"
}
],
"images": ["https://example.com/directory/image.jpg"],
"thumbnail": "https://example.com/directory/thumbnail.jpg",
"locations": ["Roma, Italy"],
"duration": "60 to 90 minutes",
"reviews": {
"rating": 0,
"count": 0
},
"description": "Learn the history of Rome. <br>Immerse yourself in the imperial Rome and learn all about the gladiators fighting in the Roman Colosseum and the emperors who decided their fates.<br>Tickets: included.<br>Duration: up to 1h30 hours.<br>Meeting Point: Largo Gaetana Agnesi above metro stop “Colosseum”.<br>Features: Professional Certified Guides, Skip the Line and Save Time, Private Tours"
}
],
"cancellation": {
"type": "fully-refundable",
"frames": [
{
"from": "2019-06-30 00:00:00",
"to": "2019-09-09 23:59:59",
"penalty": {
"amount": 0,
"currency": "EUR"
}
},
{
"from": "2019-09-09 00:00:00",
"to": "2019-09-12 23:59:59",
"penalty": {
"amount": 176.08,
"currency": "EUR"
}
}
]
},
"code": "1234abcd"
}
]
}
The response is an array of results, each result consists of these attributes:
Attribute | Description |
---|---|
items | An array of items the result id holds. The booking will be made on the result including all the items in it. The prices are only on the result level. |
.item/name | The name of the offered event |
.item/categories | The categories of the events |
.item/images | array of images of the event |
.item/thumbnail | thumbnail image of the event |
.item/locations | locations of the event |
.item/duration | duration of the event |
.item/reviews | object of 2 fields: “rating” and “count” |
.item/description | description of the event |
barRate | Price (amount/currency) of the BAR, the price which you are not allowed to sell below on B2C platforms. |
cancellation | See below |
code | The result code, use this for the next steps |
commissionable | boolean, indicates whether you can apply a commission on top of the price or not |
confirmation | immediate or on-request |
netPrice | The net price (amount/currency) of this result |
packageRate | boolean, indicates whether this result can be sold as a stand-alone offer or if it requires to be sold as part of a package |
payment | pre or post , indicates whether this is a pre-paid result or a pay-at-the-venue result |
price | The gross price of the result |
In addition, there are several other attributes that are of interest:
Attribute | Description |
---|---|
sessionId | The session ID of the search |
status | The status of the search, whether it is done , working , or failed |
timestamp | The server timestamp of the response. this can be used to poll by delta |
requestTime | The request date time in Human readable format |
completed | Integer, percentage of the progress. 0 means no tasks were completed, 100 means all tasks were completed, everything in between in “in process”. Please note this attribute is for Innstant’s internal use only. To check if the search was completed or not please refer only to the status property. |
processTime | Processing time in milliseconds. |
In case of post-payment results, you might get a transaction
node in the response. This node will be returned in case you defined a “transaction fee” markup for this purpose.
This is being used in case the user has to pay a gross amount directly to the venue, but you still want to collect something for the booking.
Example of a transaction fee in the response
"transactionFee": {
"amount": 25.7,
"currency": "EUR"
}
Cancellation Policy
The cancellation policy is build from frames
.
Each frame
has a start date (from
), end date(to
), and a penalty.
These frames tells you exactly what will be the penalty on each date starting from the booking date until the check-in date.
After the check-in date the cancellation penalty should be assumed as 100%.
Poll
Request
curl \
-H "aether-application-key: [app-key]" \
-X POST
-d @request-file.json
https://example.com/events/poll[/timestamp]
Request content
{
"client": {
"ip": "1.2.3.4",
"userAgent": "Example User Agent"
},
"currencies": ["USD"],
"customerCountry": "IL",
"customFields": [],
"dates": {
"from": "2018-09-20",
"to": "2018-09-22"
},
"destinations": [
{
"id": 5252,
"type": "location"
}
],
"filters": [],
"pax": [
{
"adults": 2
}
]
}
Request
POST https://example.com/events/poll[/timestamp]
The poll request & response are identical to the search request & response with the exception of the endpoint.
You can send as many polls as you like until the status in the response is working
. Once it finishes, the status changes to done
and this means no new results will show up in your next poll.
Check out the Flow
chapter in the beginning to get a better understanding of this method.
You can add an optional timestamp
to the URL, the timestamp must be the one returned in the previous search/poll response in order to get the deltas.
If you do not send the timestamp
in the URL, you will get ALL results every time.
Note that the search and poll requests much be identical.
Get cancellation policy
Request content
{
"client": {
"ip": "1.2.3.4",
"userAgent": "Example User Agent"
},
"currencies": ["USD"],
"customerCountry": "IL",
"customFields": [],
"dates": {
"from": "2018-09-20",
"to": "2018-09-22"
},
"destinations": [
{
"id": 5252,
"type": "location"
}
],
"filters": [],
"pax": [
{
"adults": 2
}
]
}
Request
POST http://example.com/events/cancellation/[event code]
The request consists of the desired event code (in the url) and the original search (in the request body).
Response
The response is exactly the same as the poll response, but with the cancellation frames in place.
Details/Times
Request content
{
"client": {
"ip": "1.2.3.4",
"userAgent": "Example User Agent"
},
"currencies": ["USD"],
"customerCountry": "IL",
"customFields": [],
"dates": {
"from": "2018-09-20",
"to": "2018-09-22"
},
"destinations": [
{
"id": 5252,
"type": "location"
}
],
"filters": [],
"pax": [
{
"adults": 2
}
]
}
Request
POST http://example.com/events/details/[event code]
The request consists of the desired event code (in the url) and the original search (in the request body).
Response
"timestamp": 1561875573,
"requestTime": "2019-06they s-30 06:19:33",
"status": "done",
"completed": 100,
"sessionId": "x:y:z",
"processTime": 1900,
"error": {
"code": 2100,
"message": "Price has changed. Please try to book another item or confirm new result price"
},
"results": [
{
"price": {
"amount": 158.45,
"currency": "EUR"
},
"netPrice": {
"amount": 130.83,
"currency": "EUR"
},
"barRate": {
"amount": 163.8,
"currency": "EUR"
},
"confirmation": "on request",
"paymentType": "pre",
"packageRate": false,
"commissionable": true,
"providers": [],
"specialOffers": [],
"items": [
{
"name": "Villa Borghese Bike Tour in Rome",
"categories": [
{
"id": 14,
"name": "Walking & Biking Tours"
},
{
"id": 11,
"name": "Tours & Sightseeing"
}
],
"images": [
"https://example.com/directory/image.jpg"
],
"thumbnail": "https://example.com/directory/thumbnail.jpg",
"locations": [
"Roma, Italy"
],
"duration": "3 hours",
"reviews": {
"rating": 5,
"count": 3
},
"description": "Unforgettable guided bike tour in Villa Borghese, Rome's most important monumental Villa (complex of gardens), house of the superb art collection of Cardinal Scipione Borghese, nephew of Pope Paul V and patron of painter Caravaggio and architect and sculptor Bernini.",
"remarks": {
"returnDetails": "Returns to original departure point<br />",
"inclusions": "Italian espresso coffee, Bottled water, Local guide, Use of bicycle, Use of helmet",
"exclusions": "Food and drinks, Entrance fees (If you want to visit the inside of the Borghese Gallery or the Bio Park, please specify when booking), Entry/Admission - Villa Borghese, Entry/Admission - Museo Pietro Canonica, Entry/Admission - Silvano Toti Globe Theatre Roma, Entry/Admission - The San Carlino Gran Teatro Dei Piccoli",
"general": "Confirmation will be received within 48 hours of booking, subject to availability<br>\\r\\nA minimum of 2 persons per booking is required<br>\\r\\nIf you want to visit the inside of the Borghese Gallery or the Bio Park, please specify when booking",
"termsAndConditions": null
},
"times": [
{
"id": "xxx",
"date": "2019-09-14",
"time": "10:00 AM",
"type": "departure",
"location": "Via del Fiume, 7, 00186 Roma RM, Italy<br />"
}
],
"dispatchOptions": [
{
"id": "yyy",
"type": "print",
"price": {
"amount": 0,
"currency": "USD"
},
"description": "You can present either a paper or an electronic voucher for this activity."
}
]
}
],
"cancellation": {
"type": "fully-refundable",
"frames": [
{
"from": "2019-06-30 00:00:00",
"to": "2019-09-09 23:59:59",
"penalty": {
"amount": 0,
"currency": "EUR"
}
},
{
"from": "2019-09-09 00:00:00",
"to": "2019-09-12 23:59:59",
"penalty": {
"amount": 158.45,
"currency": "EUR"
}
}
]
},
"code": "zzzxxcc1"
},
...
]
}
The response is exactly the same as the poll response, but has several additional fields.
Attribute | Description |
---|---|
.item/remarks | [If exists] important information about the event |
.item/times | List of available times for specific event. See description below |
.item/dispatchOptions | List of available dispatch options. See description below |
Description of time object:
Attribute | Description |
---|---|
.time/id | Id of specific time option, will be used on next steps |
.time/date | Date of the event |
.time/time | Time of the event |
.time/type | Type of this time option. Available types: departure or return |
.time/location | Location of the event |
Description of dispatchOption object:
Attribute | Description |
---|---|
.dispatchOption/id | Id of specific dispatch option, will be used on booking stage |
.dispatchOption/type | Type of this dispatch option. Available types: print , collect , post |
.dispatchOption/price | Price of specific dispatch option. Will be added to total price |
.dispatchOption/description | Description of the dispatch option |
Pre-Book
Request content
{
"services": [
{
"searchRequest": {
"destinations": [
{
"id": 5252,
"type": "location"
}
],
"dates": {
"from": "2019-09-14",
"to": "2019-09-17"
},
"customerCountry": "IL",
"pax": [
{
"adults": 2
}
],
"currencies": ["EUR"],
"filters": [],
"service": "events"
},
"searchCodes": [
{
"code": "1234Jk$156",
"options": [
{
"name": "time",
"value": "aaabbbccc1"
}
],
"pax": [
{
"adults": 2,
"children": []
}
]
}
]
}
]
}
Request
POST http://example-booking.com/pre-book
Note that this request is being send to a different domain than the one used for searching
Element | Description |
---|---|
searchCodes | The result codes you are planning to book. you can send as many search codes as you like in this array. |
.code | the code from the result |
.pax | the pax related to the specific code |
.options | the time value you wish to book |
searchRequest | the original, unchanged, search request |
Response
Response content
{
"content": {
"ImmediateCharge": false,
"LoyaltyPoints": [],
"PaymentDueDate": "2019-09-09",
"PaymentMethods": [
{
"methodDescription": "",
"methodName": "account_credit",
"paymentSettings": {
"creditCardForm": false,
"requiredFields": []
},
"status": "enabled"
},
{
"methodDescription": "",
"methodName": "credit_card",
"paymentSettings": {
"creditCardForm": true,
"requiredFields": []
},
"status": "enabled"
}
],
"ProfileVersion": "111",
"Services": {
"events": [
{
"barRate": {
"amount": 231,
"currency": "EUR"
},
"cancellation": {
"frames": [
{
"from": "2019-07-15 00:00:00",
"penalty": {
"amount": 0,
"currency": "EUR"
},
"to": "2019-09-09 23:59:59"
},
{
"from": "2019-09-09 00:00:00",
"penalty": {
"amount": 92.25,
"currency": "EUR"
},
"to": "2019-09-12 23:59:59"
}
],
"type": "fully-refundable"
},
"code": "zaq123",
"commissionable": true,
"confirmation": "immediate",
"items": [
{
"categories": [
{
"id": "14",
"name": "Walking & Biking Tours"
},
{
"id": "11",
"name": "Tours & Sightseeing"
}
],
"description": "Explore Rome on a relaxed bike tour with a guide, discovering sights like Castel Sant'Angelo, Piazza Navona, the Pantheon, Trevi Fountain, the Spanish Steps, and the Colosseum. <br>Biking is a great way to soak up the atmosphere of this historical city.",
"dispatchOptions": [
{
"description": "You can present either a paper or an electronic voucher for this activity.",
"id": "5ecf17ca",
"price": {
"amount": 0,
"currency": "EUR"
},
"type": "print"
}
],
"duration": "4 hours",
"images": ["https://example.com/image.jpg"],
"locations": ["Rome, Italy"],
"name": "Highlights of Rome Bike Tour",
"questions": [
{
"id": "1",
"message": "Enter your date of birth.",
"options": [],
"required": true,
"subTitle": "(e.g. 20 October 1970)",
"title": "Date of Birth",
"type": "free text"
},
{
"id": "2",
"message": "For safety reasons you must enter the height of all passengers. Please indicate inches or centimetres.",
"options": [],
"required": true,
"subTitle": "(eg. 5'2\", 158cm etc)",
"title": "Passenger Heights",
"type": "free text"
}
],
"remarks": {
"exclusions": "Food and drinks, unless specified, Alcoholic drinks (available to purchase), Gratuities",
"general": "Confirmation will be received at time of booking<br>\\r\\nChildren must be accompanied by an adult",
"inclusions": "Use of bike, Local guide",
"returnDetails": "Returns to original departure point",
"termsAndConditions": "For a full refund, cancel at least 24 hours in advance of the start date of the experience."
},
"reviews": {
"count": 15,
"rating": 5
},
"thumbnail": "https://example.com/thumbnail.jpg",
"times": [
{
"id": "23456z",
"location": "Central Rome",
"time": "9:45 AM",
"type": "departure"
}
]
}
],
"netPrice": {
"amount": 92.25,
"currency": "EUR"
},
"netPriceInClientCurrency": {
"amount": 92.25,
"currency": "EUR"
},
"packageRate": false,
"paymentMethod": "direct",
"price": {
"amount": 92.25,
"currency": "EUR"
},
"priceWithoutTax": {
"amount": 92.25,
"currency": "EUR"
},
"requestCode": "vvv555",
"surcharges": [],
"taxAmount": null,
"token": "BBBCCC123",
"transactionFee": {
"amount": 0,
"currency": "EUR"
},
"warnings": [
{
"code": 2100,
"message": "Your item is not available under the originally requested price, please review the selected alternative or go back to select another result."
}
]
}
]
}
},
"status": "done"
}
Element | Description |
---|---|
PaymentMethods | The acceptable payment methods for this booking |
.methodName | the name of the payment method. a standard integration will use account_credit or credit_card . |
.methodDescription | additional description of the method, for example if the method is a saved credit card token on the account, the description can say something like “Credit card ending with 1234” |
.status | whether this option is enabled for this booking |
.paymentSettings | specific settings for the payment method |
..creditCardForm | boolean, specifies if you need to show the credit card form to the user |
..requiredFields | key/value array of objects, consists of required fields to request from the user. for example the enett agent id in case of enett payment integration |
Services | The services that are about to be booked |
.events | an array of events that are about to be booked |
..barRate | The minimum price (amount/currency) that can be shown on B2C website |
..cancellation | The cancellation policies, see the search response for details |
..code | The event code |
..commissionable | Whether or not you can add commission to the final price |
..confirmation | immediate or on-request |
..items | a collection of items |
..item.categories | name and id of the taxonomy categories |
..item.description | free text description |
..item.dispatchOptions | see below |
..item.duration | The estimated duration of the event |
..item.images | an array of image URLs |
..item.locations | an array of location strings where the event is taking place |
..item.name | The event name |
..item.questions | see below |
..item.remarks | an array of remarks with key/value |
..item.reviews | the quantity (count) and value (rating) of the reviews for the event |
..item.thumbnail | a URL of a thumbnail image |
..item.times | see below |
..netPrice | The net price (amount/currency) of the booking, i.e. the amount that you need to pay the provider |
..netPriceInClientCurrency | normalized amount to the currency you requested |
..packageRate | if true, this offer cannot be sold as a stand-alone booking, and the price must never be shown to the user without it being bundled as a package with other products. |
..payment | pre or post |
..price | The gross price (amount/currency) of the booking, i.e. the amount you charge your customer |
..priceWithoutTax | the gross price minus the tax amount |
..requestCode | the code you sent in the request. this is used in case the result changed due to price or availability. it is for your use only and should not be sent in further requests. |
..surcharges | if there are any additional surcharges applied to the price |
..taxAmount | the amount of the tax, if applicable |
..token | the booking token you will have to send in order to make the actual booking |
..transactionFee | any additional fee that may apply for the cost of processing the transaction |
..warnings | optional node, returned only in case of price or availability change |
Description of dispatchOptions
object. Different methods might have additional costs (like snail-mail or a courier service):
Attribute | Description |
---|---|
.description | free text description of the dispatch option |
.id | the id of the option, you’ll need to use it for booking |
.price | the (additional) price of the dispatch option, can be 0 |
.type | the type of the option. can be print , collect , or post |
Description of questions
object. It is mandatory to show the questions to the end-user, collect the answers from them, and send them as part of the booking requests.
Attribute | Description |
---|---|
.id | the id of the question |
.message | the question text |
.options | if the answers should be limited to the set described in this element |
.required | if mandatory |
.subTitle | description of the question (example, explanation, etc.) |
.title | the title of the question |
.type | can be free text , one , or multiple |
Description of times
object.
Attribute | Description |
---|---|
.id | the id of the time option |
.location | the location of the time, free text, usually describes the location of the option |
.time | the time of the event, timezone is always the local time |
.type | can be departure or return |
"warnings": [
{
"code": 2100,
"message": "Your item is not available under the originally requested price, please review the selected alternative or go back to select another result."
}
]
Book
Request
POST http://example-booking.com/book
Note that this request is being send to a different domain than the one used for searching
{
"creditCard": {
"cardNumber": "4111 1111 1111 1111",
"cvc": "555",
"expiry": {
"month": "12",
"year": "2019"
},
"name": {
"first": "Yogi",
"last": "Berra"
}
},
"customer": {
"birthDate": "1975-09-14",
"contact": {
"address": "housington 66",
"city": "cityngton",
"country": "NL",
"email": "test@example.com",
"phone": "555-4433222",
"state": "N/A",
"zip": "88776"
},
"name": {
"first": "Yogi",
"last": "Berra"
},
"title": "M"
},
"paymentMethod": {
"methodName": "account_credit"
},
"reference": {
"agency": "my agency reference",
"voucherEmail": "test@example.com"
},
"services": [
{
"bookingRequest": [
{
"code": "kuegkrug398y3:222$fjfjfj",
"options": [
{
"name": "time",
"value": "5bfdcf5b"
},
{
"name": "dispatch",
"value": "5ecf17ca"
},
{
"name": "questions",
"value": [
{
"id": "1",
"value": "20 October 1970"
},
{
"id": "2",
"value": "10 meter"
}
]
}
],
"pax": [
{
"adults": [
{
"contact": {
"address": "housington 66",
"city": "cityngton",
"country": "NL",
"email": "test@example.com",
"phone": "555-4433222",
"state": "N/A",
"zip": "88776"
},
"lead": true,
"name": {
"first": "Yogi",
"last": "Berra"
},
"title": "M"
},
{
"name": {
"first": "Mona",
"last": "Lisa"
},
"title": "F"
}
]
}
],
"token": "1515BEE8"
}
],
"searchRequest": {
"currencies": ["USD"],
"customerCountry": "NL",
"dates": {
"from": "2018-05-04",
"to": "2018-05-05"
},
"destinations": [
{
"id": 5252,
"type": "location"
}
],
"filters": [],
"pax": [
{
"adults": 2,
"children": []
}
],
"service": "events"
}
}
]
}
Element | Description |
---|---|
creditCard | In case you are paying with a credit card, you need to send all relevant details |
customer | The customer details of the customer that is making the booking. It doesn’t have to be the same details as the travelers |
payment | how are you going to pay for the booking. this value must be one of the options returned in the pre-book |
.method | one of: credit_card , account_credit , or enett |
.securePaymentUrl | in case the payment method is credit_card , you need to supply a URL where to send the user after the payment process. |
reference | your references |
.agency | free text of your agency reference, i.e. your internal booking id |
.voucherEmail | an email address to send the voucher to |
services | this array of elements consists of the desired items you want to book. Each element contains 2 sub-elements: the original search request, and the booking request. |
.searchRequest | the original search request |
.bookingRequest | this element will contain the guest information and the payment details. |
..code | The result code you wish to book, this code comes from the search/poll response |
..token | the token from the pre-book call |
..pax | The pax configuration array for the booked properties. Each element in the array is a booked room |
…adults | the details of the adults in the room |
….name | first /last names of the guest |
….title | M for male, F for female (for children - see below) |
….lead | boolean, set to true if this is the lead pax. each booking must have one lead. do not set this flag on more than one. |
….contact | contact details of the lead pax, can be different than the customer on the booking. |
..options | the relevant options you’d like to book. always include time and dispatch with the relevant values. if there are questions, you need to send the id and values of the answers. |
In case you want to send a booking request for children, the child element must include another attribute called “birthDate” with a date value in the format YYYY-MM-DD.
Example of a children node:
“children”: [
{
”birthDate”: “2014-04-20”
”name”: {
”first”: “test”,
”last”: “test”
},
”title”: “C”
}
]
Response
Response content
{
"content": {
"bookingID": 12345,
"bookingDate": "2019-07-16",
"status": "confirmed",
"customer": {
"title": "MR",
"name": {
"first": "john",
"last": "smith"
},
"birthDate": "1986-01-01",
"contact": {
"country": "DE",
"state": "N/A",
"address": "123 somestreet",
"city": "somecity",
"phone": "123456789",
"zip": "1234567",
"email": "you@example.com"
},
"create": false
},
"price": {
"amount": 96.86,
"currency": "EUR"
},
"netPrice": {
"amount": 96.86,
"currency": "EUR"
},
"taxAmount": null,
"services": [
{
"event": {
"name": "Highlights of Rome Bike Tour",
"categories": [
{
"id": "14",
"name": "Walking & Biking Tours"
},
{
"id": "11",
"name": "Tours & Sightseeing"
}
],
"images": ["https://example.com/media/image.jpg"],
"thumbnail": "https://example.com/media/thumbnail.jpg",
"locations": ["Rome, Italy"],
"duration": "4 hours",
"reviews": {
"rating": 5,
"count": 15
},
"description": "Explore Rome on a relaxed bike tour with a guide, discovering sights like Castel Sant'Angelo, Piazza Navona, the Pantheon, Trevi Fountain, the Spanish Steps, and the Colosseum. <br>Biking is a great way to soak up the atmosphere of this historical city."
},
"dispatchOption": {
"id": "5ecf17ca",
"type": "print",
"price": {
"amount": 0,
"currency": "EUR"
},
"description": "You can present either a paper or an electronic voucher for this activity.",
"details": null,
"voucherURL": "https://example.com//voucher.ext?1234567890"
},
"time": {
"id": "5bfdcf5b",
"time": "9:45 AM",
"type": "departure",
"location": "Central Rome",
"remarks": {
"address": "Via dei Mille 8 ROMA",
"directions": "Meet your guide at our office: Via dei Mille 8 ROMA"
}
},
"answers": [
{
"id": "1",
"title": "Date of Birth",
"value": "20 October 1988"
},
{
"id": "2",
"title": "Passenger Heights",
"value": "1 meter"
}
],
"itemId": 1,
"service": "events",
"startDate": "2019-09-14",
"endDate": "2019-09-17",
"paymentType": "pre",
"quantity": 1,
"code": "1234$abcd",
"status": "confirmed",
"supplier": {
"reference": "1234:abcd:t$yy5"
},
"price": {
"amount": 96.86,
"currency": "EUR"
},
"taxAmount": null,
"netPrice": {
"amount": 96.86,
"currency": "EUR"
},
"cancellation": {
"type": "fully-refundable",
"frames": [
{
"from": "2019-07-16 00:00:00",
"to": "2019-09-09 23:59:59",
"penalty": {
"amount": 0,
"currency": "EUR"
}
},
{
"from": "2019-09-09 00:00:00",
"to": "2019-09-12 23:59:59",
"penalty": {
"amount": 96.86,
"currency": "EUR"
}
}
]
},
"pax": [
{
"adults": [
{
"lead": true,
"title": "MR",
"name": {
"first": "test",
"last": "test"
},
"birthDate": "1986-01-01",
"contact": {
"country": "IL",
"state": "N/A",
"address": "N/A",
"city": "",
"phone": "N/A",
"zip": "N/A",
"email": "someone@example.com"
}
},
{
"lead": false,
"title": "MR",
"name": {
"first": "john",
"last": "smith"
},
"birthDate": "1986-01-01",
"contact": {
"country": "IL",
"state": "N/A",
"address": "N/A",
"city": "",
"phone": "N/A",
"zip": "N/A",
"email": "someone@example.com"
}
}
],
"children": []
}
],
"remarks": {
"returnDetails": "Returns to original departure point",
"inclusions": "Use of bike, Local guide",
"exclusions": "Food and drinks, unless specified, Alcoholic drinks (available to purchase), Gratuities",
"general": "Confirmation will be received at time of booking<br>\\r\\nChildren must be accompanied by an adult",
"termsAndConditions": "For a full refund, cancel at least 24 hours in advance of the start date of the experience."
}
}
],
"payment": {
"method": "credit_card",
"clearingState": null,
"paymentStatus": "paid"
},
"options": {
"emails": ["confirmation_email"]
},
"reference": {
"agency": "",
"voucherEmail": ""
},
"ProfileVersion": "1234"
},
"status": "done"
}
Most of the details are a reflection of the data sent by you. the following details are of notice:
Element | Description |
---|---|
bookingID | The Innstant system booking ID |
payment | The payment options used in the booking |
.method | The payment method used |
.clearingState | In case a credit card was used, the clearing state tells you if the booking was charged or just authorized. possible values are enrollment , authorization , payment and pre-payment |
.paymentStatus | paid or unpaid |
services.supplier.reference | the supplier reference that should appear on the voucher |
services.dispatchOption | details about the voucher |
Understanding the different statuses on the bookings response
We return 3 status attributes as part of the book
response, each of them has a different purpose.
In order to know if a specific service within the booking was confirmed - you must check the individual statuses on each service in the booking.
Element | Description |
---|---|
status | message status - tells you if there was a communication error |
content.status | the booking status |
content.services.status | status of each service in the booking |
Possible status values
Element | Description |
---|---|
confirmed | The booking/item was confirmed |
initialized | The booking/item started the booking process |
partially_confirmed | The booking was only partially confirmed, you must check each item to make sure which one was not confirmed |
failed | The booking/item failed to confirm |
error | There was an error during the booking process |
cancelled | The booking/item was cancelled |
pending_cancellation | The booking/item was not cancelled yet but is waiting to be cancelled |
on_request | The booking/item is pending the provider approval or rejection |
rejected | The booking/item was rejected |
unknown | ¯_(ツ)_/¯ |
Cancel
Request content
{
"BookingID": 1234,
"CancelReason": "The dog is sick",
"Force": false,
"IsManual": false
}
Request
POST https://example.com/booking-cancel
Attribute | Description |
---|---|
BookingID | The booking ID you would like to cancel |
CancelReason | The reason for the cancellation, can be left blank |
Force | Should the booking be cancelled in any case, without calling the provider - USE FALSE UNLESS YOU KNOW WHAT YOU ARE DOING |
IsManual | Is the booking being cancelled by a human request or by an automated process |
Respone
Response content
{
"content": {
"Status": "done",
"Warnings": []
},
"status": "done"
}
Attribute | Description |
---|---|
content.Status | Was the cancellation successful (done ) or unsuccessful (error ) |
content.Warnings | This array will be returned only if force cancellation was used |
Booking Details
Request
GET https://example.com/booking-details/[booking-id]
Attribute | Description |
---|---|
BookingID | The booking ID you would like to get details for |
Response
The response is the same as booking response
Lookups
Board Codes
Board Code | Description |
---|---|
RO | Room Only |
BB | Breakfast |
HB | Half Board |
FB | Full Board |
AI | All Inclusive |
FAQ
Q: How many adults and children can accommodate a single room?
A: 1-4 adults, 0-4 children
Q: Which ages are considered as children?
A: Each provider treats it differently, but usually guests are counted as children if their ages are between 0 and 16
Q: What is the min/max length of stay (in nights) allowed in a search request?
A: 1 to 30 nights
Q: Is it possible to send more than one hotel code in the same request?
A: Yes, this feature is supported. You can send max 250 hotel codes per request
Q: Is it possible to send more than one destination code in the same request?
A: No, this feature will be supported in the future
Q: I get an error in the search response: “”Invalid Request! Make sure it’s a valid JSON and has allowed values as described in documentation””
A: Make sure you included the header Content-Type: application/json
, and that your search dates are in the future.
Q: I get a status: “working” in search response, but no results
A: You need to send at least one Poll request in order to get results.
Q: How many polls do I have to send in order to get all the results?
A: Depends on your preferred timeout. We work with many providers, some are faster than others and return results in a few seconds, while the slower ones require more time.
The polling mechanism allows you to decide how much time you want to keep polling. The first results will be received in 3 to 5 seconds, and you’ll be able to get new ones by keeping polling every 3 seconds until you decide to stop.
Q: When searching for multiple rooms, can I select which items I want to book from the different results?
A: No. Each of the result objects in the results array has the exact number of rooms to match your search criteria, and should be booked as a whole, using the result code.
Q: For how long are the search results bookable?
A: Every search session is valid for 30 minutes. If more than 30 minutes have passed, the results are no longer bookable, and you’ll have to run a new search.
Q: I get an error message in pre-book/book response
A: Make sure that you try to book the search results within 30 minutes from initial search. In addition, verify that your booking matches your search criteria exactly: same nationality, number of guests, number of rooms, children ages, etc.
Q: Are all the fields in the customer object mandatory?
A: Yes. And without a proper country code that matches the one in search request, the booking will probably fail. As for the other fields, if you don’t have the customer’s phone number or zip, for example, you can send “N/A”, but the fields must be included.
Q: Why do I get an “on_request” booking status even though I’ve excluded on-request in my search filters?
A: Even though the result you got has not been classified as “on request” when you first initiated the search, its status may change on the provider end by the time you make the booking. In such cases, it is mandatory to run the booking-details request to verify it’s status at least once a day until the status is changed to either confirmed or rejected. If the status does not change after 5 working days, it is mandatory to contact customer support and verify the status manually.
Q: I get empty results when the second request with the same parameters is sent
A: To avoid this please make sure that you send the first poll request without a timestamp. The timestamp should be used only in the second poll.
Q: Do you have passenger name restrictions?
A: Yes. First and last name should contain alphabetic characters only and be at least one character. Empty names, no white space or special characters allowed. Please only use the letters a-z, A-Z (Latin alphabet).
Static Data
Introduction
The static data is accessible via a web service or by downloading data in a CSV file. The data is updated constantly, so make sure to update it at least once a week.
In order to access the static data, you will need to send a valid application key in the request header.
Please note: It is not permitted to use static data dynamically. This means you must download the static data and keep it updated on your side.
Methods
Countries
Request
curl \
-H "aether-application-key: [app-key]" \
https://example.com/countries
Response
[
{
"continent": "Europe",
"id": "AD",
"name": "Andorra",
"region": "Southern Europe",
"regions": [
{
"code": "AN",
"name": "Andorra la Vella"
},
{
"code": "EE",
"name": "Escaldes-Engordany"
}
]
},
{
"continent": "Europe",
"id": "AL",
"name": "Albania",
"region": "Southern Europe",
"regions": [
{
"code": "TR",
"name": "Tirane"
}
]
},
...
]
GET https://example.com/countries
Attribute | Description |
---|---|
id | ISO Alpha-2 country code |
name | The name of the country |
continent | Name of the continent |
region | The region within the continent |
regions | a collection of provinces or regions within the country |
Destinations
Request
curl \
-H "aether-application-key: [app-key]" \
https://example.com/destinations/AL
Response
[
{
"countryid": "AL",
"id": "6069",
"lat": "41.3275459",
"lon": "19.8186982",
"name": "Tirana",
"seoname": "tirana",
"type": "city"
},
...
]
GET https://example.com/destinations/[country code]
Attribute | Description |
---|---|
countryid | ISO Alpha-2 country code |
id | a numeric value, the id of the specific location |
name | The name of the destination |
type | the type of the destination, whether it’s a city, a region, etc. |
seoname | a url-safe slug of the destination name |
lat | Latitude of the destination |
lon | Longitude of the destination |
Hotels by IDs
Request
curl \
-H "aether-application-key: [app-key]" \
https://example.com/hotels/1,2,3
Response
[
{
"id":"1111",
"name":"Example Hotel",
"address":"123 main street",
"status":"1",
"zip":"12345",
"phone":"+66 666 666666",
"fax":"+66 666 666667",
"lat":"66.6666",
"lon":"77.777",
"seoname":"example-hotel",
"stars":"4",
"destinations":[
{
"destinationId":"666",
"type": "city"
},
{
"destinationId":"84533",
"type": "zone"
}
],
"mainImageId":"666",
"images":[
{
"id":"666",
"width":"375",
"height":"250",
"title":"External View",
"url":"0\/0\/666.png"
},
...
],
"description":"The Example is a superbly decorated 4 star place setting new standards. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."
},
...
]
GET https://example.com/hotels/[hotels id list]
The hotel ids should be separated by a comma, and the limit is up to 500 hotel ids per request.
Attribute | Description |
---|---|
id | a numeric value, the id of the specific hotel |
name | The name of the hotel |
seoname | a url-safe slug of the destination name |
lat | Latitude of the destination |
lon | Longitude of the destination |
status | The status of the hotel, 0 means disabled, all other positive values means active. |
address | the physical address of the hotel |
zip | zip code |
phone | phone number |
fax | fax number |
stars | the number of stars |
description | free text description. for translations, see translations |
destinations | a collection of destination ids and types the hotel belongs to. see destinations |
images | see the images section |
mainImageId | the main image id of the hotel. the image details will be part of the images collection. |
Hotels Diff Since
Request
curl \
-H "aether-application-key: [app-key]" \
https://example.com/hotels-diff/2018-01-01
Response
[
"1142",
"30087",
...
]
GET https://example.com/hotels-diff/[timestamp]
This method returns the hotel ids of only hotels that changed since the timestamp in the request.
Currencies
Request
curl \
-H "aether-application-key: [app-key]" \
https://example.com/currencies
Response
[
{
"currencyId": "EUR",
"name": "Euro",
"sign": "€",
"active": "1"
},
{
"currencyId": "USD",
"name": "United States Dollars",
"sign": "$",
"active": "1"
}
]
GET https://example.com/currencies
Attribute | Description |
---|---|
currencyId | 3 letter ISO 4217 currency code |
name | The name of the currency |
sign | Sign, if any |
active | boolean, 1 is active, 0 is disabled |
Markets
Request
curl \
-H "aether-application-key: [app-key]" \
https://example.com/markets
Response
[
{
"marketId":"26",
"title":"Western Europe",
"countries":[
"AT",
"BE",
"CH",
"DE",
"FR",
"LI",
"LU",
"MC",
"NL"
]
},
...
]
GET https://example.com/markets
Attribute | Description |
---|---|
marketId | numeric id |
title | The name of the market |
countries | ISO Alpha-2 country code collection of countries participating in this market |
Airlines
Request
curl \
-H "aether-application-key: [app-key]" \
https://example.com/airlines
Response
[
{
"iata": "BD",
"name": "bmi",
"alt_name": "bmi British Midland",
"icao": "BMA",
"country": "United Kingdom"
},
...
]
GET https://example.com/airlines
Attribute | Description |
---|---|
iata | iata code (2 letter code) |
name | The name of the airline |
alt_name | alternative name, more descriptive |
icao | icao code of the airline (3 letter code) |
country | Country of origin |
Facilities
24h reception
accessibility
air condition
babysitting
bar
beach
beauty salon
concierge
conference room
gym
hair dryer
internet
kids pool
laundry services
minibar
nightclub
no smoking
outdoor pool
parking lot
pets friendly
radio
refrigerator
restaurant
room service
safe
sauna
solarium
spa
tv
tv channels (satellite)
bikes
bath
free newspaper
coffee/tea
currency exchange
water sports
bidet
free internet
iron
surcharge airport shuttle
surcharge baby friendly
surcharge babysitting
heated pool
indoor pool
pool
baby friendly
ball sport
diving
free street parking
game room
gift shop
golf course
kitchen
library
newspaper
ping pong
pool bar
squash
tennis court
winter sport
airport shuttle
free bikes
kids club
water park
free airport shuttle
hot tub
surcharge bikes
onsite parking lot
surcharge laundry services
surcharge room service
coffee shop
free shuttle to beach
free kids club
video games
iron services
surcharge shuttle to casino
free baby friendly
mini market
pool table
casino
surcharge valet parking
tv channels (cable)
valet parking
atm
surcharge internet
surcharge street parking
surcharge newspaper
free coffee/tea
free long term parking
free truck parking
surcharge shuttle to train
tv channels (digital)
shared bathroom
free near gym
surcharge pets friendly
surcharge parking lot
surcharge shuttle to beach
truck parking
near gym
bbq
surcharge beach
shared lounge
free minibar
fireplace
surcharge kids club
surcharge shuttle to shopping
free gym
free safe
surcharge spa
board games
electric vehicle charge station
surcharge safe
bowling
surcharge truck parking
onsite atm
surcharge coffee/tea
boating
surfing
street parking
surcharge shuttle to ferry
karaoke
free onsite parking lot
free shuttle to train
beach bar
free valet parking
free babysitting
free conference room
free parking lot
surcharge beauty salon
surcharge long term parking
surcharge shuttle to theme park
surcharge shuttle to cruise
scenic view
onsite beach
free beauty salon
free solarium
onsite golf course
free shuttle to theme park
free shuttle to cruise
free shuttle to ferry
onsite spa
free shuttle to casino
adults only
surcharge shuttle to ski
surcharge minibar
free pets friendly
onsite mini market
onsite water sports
free shuttle to shopping
near nightclub
free water park
lockers
free shuttle to ski
onsite tennis court
shared kitchen
shuttle to ski
surcharge conference room
surcharge pool
surcharge gym
free spa
onsite video games
surcharge solarium
surcharge golf course
shared bath
surcharge water park
halal
free laundry services
near golf course
shuttle to beach
kosher
surcharge sauna
free currency exchange
near beach
near spa
free sauna
near tennis court
onsite winter sport
sea view
near water sports
surcharge air condition
free pool
surcharge onsite parking lot
surcharge tennis court
surcharge pool table
free accessibility
long term parking
surcharge tv channels (cable)
free beach
near restaurant
onsite conference room
surcharge iron
free game room
netflix
surcharge winter sport
surcharge hair dryer
surcharge refrigerator
onsite diving
surcharge video games
onsite restaurant
surcharge ping pong
onsite bikes
surcharge tv channels (satellite)
surcharge accessibility
surcharge iron services
onsite bbq
surcharge kitchen
surcharge bath
surcharge tv
near beauty salon
onsite coffee/tea
free air condition
near atm
near outdoor pool
near casino
surcharge radio
near surfing
free heated pool
free refrigerator
near parking lot
free no smoking
near winter sport
near diving
near bbq
surcharge near parking lot
halal food
kosher food
onsite boating
near boating
Static Data Download
There is an option to download a CSV file with the static data instead of using API.
To download static data in CSV file please use the following endpoint:
https://static-data-console.innstant-servers.com/static-files/download
Images
{
"images":[
{
"id":"100511",
"width":"500",
"height":"500",
"title":"Double Bed",
"url":"0\/100\/100511.png"
},
...
]
}
Attribute | Description |
---|---|
id | a numeric value, the id of the specific image |
width | width in pixels |
height | height in pixels |
title | textual title for the image. Note that it can be empty. |
url | the url of the image |
To create the full URI, use the following structure:
https://cdn-images.innstant-servers.com/[max-width]x[max-height]/[image-url]
For example:
https://cdn-images.innstant-servers.com/500x500/0/100/100511.jpg
Errors
Search Errors
Code | Description |
---|---|
m400 | Bad Request – Your request sucks |
m401 | Unauthorized – Your API key is wrong |
m404 | Required service and/or method not found. Refer to documentation to see available endpoints |
m405 | Method not allowed! Refer to documentation to see allowed methods |
m777 | Unexpected infrastructure failure! Please contact us at api@innstant.com |
m1001 | Invalid Request! Make sure it’s a valid JSON and has allowed values as described in documentation |
m1003 | Entity id and/or type is wrong! Please contact us at api@innstant.com |
m1004 | Unexpected internal error occurred. Please contact us at api@innstant.com |
m1010 | Unexpected internal error occurred. Please contact us at api@innstant.com |
m1011 | Unexpected internal error occurred. Please contact us at api@innstant.com |
m1012 | Unexpected internal error occurred. Please contact us at api@innstant.com |
m1013 | Unexpected internal error occurred. Please contact us at api@innstant.com |
m1014 | Unexpected internal error occurred. Please contact us at api@innstant.com |
m1015 | Unexpected internal error occurred. Please contact us at api@innstant.com |
m1016 | Unexpected internal error occurred. Please contact us at api@innstant.com |
m1020 | Unexpected internal error occurred. Please contact us at api@innstant.com |
m1021 | Unexpected internal error occurred. Please contact us at api@innstant.com |
m1100 | Wrong account setup. Please contact your account manager for more details |
m1101 | Wrong account setup. Please contact your account manager for more details |
m1200 | No data found for requested plugin. Please check your spelling |
m1201 | Account does not exist. Please contact your account manager |
m1202 | Supplier does not exist. Please contact your account manager |
m1203 | Agent does not exist. Please contact your account manager |
m1210 | Unexpected internal error occurred. Please contact us at api@innstant.com |
m2000 | Unexpected supplier response. Please contact us at api@innstant.com |
m2001 | Unexpected supplier response. Please contact us at api@innstant.com |
m2100 | Unexpected supplier response. Please contact us at api@innstant.com |
m2101 | Unexpected supplier response. Please contact us at api@innstant.com |
m2102 | Unexpected supplier response. Please contact us at api@innstant.com |
Login errors
Code | Description |
---|---|
a0 | Uncategorized error |
a100 | Missing login details |
a101 | Invalid login information |
a102 | Invalid password |
a103 | Invalid account status |
a104 | Invalid agent status |
a105 | Account disabled |
a106 | Agent disabled |
a107 | Invalid login details |
a108 | Invalid API key |
a109 | Missing API key |
a110 | API key disabled |
a111 | Bad agent configuration |
a112 | Missing access token |
System errors
Code | Description |
---|---|
a201 | Missing account ID |
a202 | Missing agent ID |
a203 | Invalid parameter |
a204 | Invalid account setup |
a205 | General error |
a206 | Missing whitelabel ID |
a208 | Access storage error |
Permission error
Code | Description |
---|---|
a300 | Permission error |
Booking errors
Code | Description |
---|---|
a400 | Missing booking item |
a401 | Booking not found |
a402 | Payment method not supported |
a403 | Account balance error |
a404 | Provider failure |
a405 | Booking expired |
a406 | Invalid 3D secure token |
a407 | Invalid markup |
a408 | Cancellation failed |
a409 | Broad on request |
a410 | Missing customer email |
a414 | Room is unavailable |
Processing errors
Code | Description |
---|---|
a500 | Missing processing credentials |
a501 | No processing account set |
Accounting errors
Code | Description |
---|---|
a600 | Duplicate document |
a601 | Document save error |
Payment errors
Code | Description |
---|---|
a700 | Payment authorize is not supported for this interface |
a701 | Missing amount |
a702 | Booking already exists (recoverable) |
Warnings
Code | Description |
---|---|
a2100 | Price change (recoverable) |
a2101 | Board change (recoverable) |
a2102 | Cancellation policy change (recoverable) |
a2103 | Result code change (recoverable) |