Create an OTA and handle it

Last updated: November 27th, 2020

What will we see in this tutorial?

We won't cover the specific calls for them you can refer to our dynamics reference in the homepage.
Here we will try to give a bit of context about how integrate your OTA as a partner for Octorate using also our APIs.

Register New OTA

Our specialized Entity: The portal

Inside our system, every accommodation connect the OTAs he want to connect.

For your case you will use the both the leverage of our admin api operations to create a new "Portal" entity inside our system.

We will react in a special way afterwards letting you receive content and availability

Workflow

This is a sample of a step-by-step walkthrough required to integrate a connection in octorate.
One time, as Step 0
  1. Call the Portal Create API to create a Portal inside our system, available globally inside our application.
Connection phase
Choose one of these options:
  • (Optionally) Create the first property
  • Accept a connection from a property
  • Start a connection to a property from your side
On the selected property
  1. Create a Portal Connection on this property (it means, please this property have to be connected to this site).
  2. Add your existing rooms / rates / listing / inventory inside this Connection. [Property: Portal Connections -> Create an external product]
  3. Proceed to map the internal Octorate Rooms to your rooms OR ask the user to do though our interface
  4. (Optionally) Implement the json below to receive the inventory from Octorate and subscribe to relative webhook, push the created inventory to Octorate.
  5. (Optionally) Subscribe to the ARI webhook, to receive the changes of the calendar from Octorate
  6. Implements check availability call to make sure that the availability is available in Octorate and Octorate can fulfill your request.
  7. Send the reservations to Octorate
  8. (Optionally) Send the credit card to Octorate.

Dictionary


Let's see some of the basic information we normally store for a connection

Property Name Description
Logo (Icon) Inside our system in many points we show a small icon (that's normally a square) to let the user recognize your portal.
Since the experience will be very ugly otherwise, we ask you this field as mandatory.
Please provide the url to a JPG or PNG image here, we will upload on our server.
Banner Inside the list of portals we show an horizontal rectangle that helps user to recognize your portal
Please provide the url to a JPG or PNG image here, we will upload on our server
Internal Name You can choose an identifier for your connection, should be something without spaces that we will use as ID. You are not allowed to change it after it has been created.
Display Name Please specify the name for your connection here. We will show this to your customer.
Color (Hex) Hexadecimal value (like #c5c5c5) of the color of this connection. Useful for recognize the portal in the calendar of the reservations
calendarValues What kind of values do you are able to handle? Set as null if you don't expect to receive any data or rooms and availability.
ContentMetas What kind of values do you expect to receive from customers as content? We suggest you to enable everything in developing phase and in the tests properties you will see a bug icon with the alt text of the name of the tag that you may want to remove after.
If you leave empty (not null, the key should not compare) in the first POST, we will enable everything. Set array of values to enable content fields, explicitly set as null to disable all content fields.

Create The Portal

In order to receive contents and prices you should add a new Portal inside Octorate.

You should create them according to the info of your site, an example of "Portal", available for all the customers would be "Booking.com".
A point to keep in mind: we suggest to start leaving completely empty in POST the content_metas, we will setup all the content metas as enabled (Content related). If you don't need them you can shut them down setting it as "null".

Subscribe the events

We will notify the informations regarding the connection in the links you provide us.
In order to do it, please subscribe to these events:
CONTENT_PUSH To receive content from Octorate,
PORTAL_SUBSCRIPTION_CALENDAR To receive Prices, Rates and Minstay from our calendar


Inventory and properties

Visibility of the portal

At this stage of development we don't provide a direct connection though our interface, so it's not possible to show an API connection in our connection list.
We will offer this opportunity in future, in that case, we will call your redirect_uri.
You should then create the portal connection from the api side.

Register Portal Connection

When you create the Portal, you will receive a new ID for this portal, you can create a new Portal Connection on each property to allow customer to connect to your service.

Push inventory

If you already have some products or listing inside your inventory you can push your inventory to Octorate.

Refer to our "ARI External Products" API calls to create them.

If you want to map the products with ours, you can either do on your side using the apis, but it's also perfectly fine to ask the user to do it, since we provide an interface to do it.
It's important to create the inventory and do the mapping since we send the availability info only for rooms that have a mapping ended.
At this point the connection is not yet viable. If you think the connection is ok, you can enable the connection from your side pushing the calendar updating and reservation receiving flag to on. This step also can be done on octorate side, so you can skip it.

Receive the inventory

You can also receive the Octorate Inventory. This can be done either reading all the content information available on Octorate OR subscribing to the webhook CONTENT_PUSH. When subscribing to this event, if the portal connection has been created, we will show your connection inside the available connection for the push to the user.
When the user fill the information and ask Octorate to send it, we will send all the details inside one json that you will be able to receive.
Either we will notify there when a room is cancelled.
We know that you might have some restriction on the Content, for this reason in the following section we explain how to reject this content in a way that the user can acknowledge what's going on.
If everything was good, please, reply with status code 200, and create the external product and the mapping. We will by default create an external room with our same room code but you are able to change it.

Validate The Json content.

Page Of Reference: Open the frontend, open a room, inside the room there is a link named "Modify the room for Expedia/Airbnb/Ota...".

We support these type of rejections and params, please follow this table to understand how to reject the information

Please, in case something went wrong, reply with the http status 500 if you don't know how to handle the failure, or 4xx in case you know how

You can provide the complete list of the errors marshalling them as list. I.e. {data:[{...},{...}]}

RejectionType Description Accepted Params Example in frontend Small (complete) example
RejectLength The specified field cannot be validated because doesn't respect the expected length field the label of the field
message the label of the message
type use one of CONTACT, GENERIC, CANC_POLICY, DESCRIPTION, EXTRA, PICTURE, SERVICE, FEE, AMENITY, ROOM, ACCOMMODATION, RATE, RESERVATION, SUBROOMS, REGULATION, RULES, PRODUCT_BENEFIT, CANC_POLICY_DEPOSIT
max (boolean) set true if the value is over the limit, false is below
length the expected length
userProvided what the user have provided (optional)
typeClass set always as RejectLength
(Inside the description content part) The element 'description' should be at least of 400 characters. You have specified only 200. { "userProvided":3, "field":"url", "max":true, "length":300, "message":"labelUrl", "type":"GENERIC", "typeClass":"RejectLength" }
RejectRequired The specified field is required and the user has not given it field the label of the field
message the label of the message
type use one of CONTACT, GENERIC, CANC_POLICY, DESCRIPTION, EXTRA, PICTURE, SERVICE, FEE, AMENITY, ROOM, ACCOMMODATION, RATE, RESERVATION, SUBROOMS, REGULATION, RULES, PRODUCT_BENEFIT, CANC_POLICY_DEPOSIT
The element 'description' is required.
RejectInvalid The content of that field cannot be accepted field the label of the field
message the label of the message
type use one of CONTACT, GENERIC, CANC_POLICY, DESCRIPTION, EXTRA, PICTURE, SERVICE, FEE, AMENITY, ROOM, ACCOMMODATION, RATE, RESERVATION, SUBROOMS, REGULATION, RULES, PRODUCT_BENEFIT, CANC_POLICY_DEPOSIT
The checkin time you have inserted (13.00) is not supported by AppName.
RejectConfiguration The property configuration is not good field the label of the field
message the label of the message
currentValue you can specify here what you were expecting
type use one of CONTACT, GENERIC, CANC_POLICY, DESCRIPTION, EXTRA, PICTURE, SERVICE, FEE, AMENITY, ROOM, ACCOMMODATION, RATE, RESERVATION, SUBROOMS, REGULATION, RULES, PRODUCT_BENEFIT, CANC_POLICY_DEPOSIT
(Usually with content generic/section generic): Please before pushing this listing, configure a valid payment method inside AppName
RejectLang The field in that language, cannot be accepted field the label of the field
lang the code of the language in iso code.
secondary another RejectValue like RejectLength
to describe the field that having the issue. This will be appended to the first text message the label of the message
type use one of CONTACT, GENERIC, CANC_POLICY, DESCRIPTION, EXTRA, PICTURE, SERVICE, FEE, AMENITY, ROOM, ACCOMMODATION, RATE, RESERVATION, SUBROOMS, REGULATION, RULES, PRODUCT_BENEFIT, CANC_POLICY_DEPOSIT
The element 'description' is language EN is not valid. (secondary) The element 'description' should be at least of 400 characters. You have specified only 200 { "field":"$.description.name[it]", "message":"labelDescription", "type":"DESCRIPTION", "lang":"IT", "typeClass":"RejectLang" "secondary": { "typeClass":"RejectLenght", "userProvided":5, "field":"$.description.name[it]", "max":true,"length":200, "message":"labelDescription", "type":"DESCRIPTION" } }
RejectListItem An element to a particular position cannot be accepted (i.e. you can say the 3rd photo is not valid) field the label of the field

message the label of the message

secondary another RejectValue like RejectLength
type use one of
CONTACT, GENERIC, CANC_POLICY, DESCRIPTION, EXTRA, PICTURE, SERVICE, FEE, AMENITY, ROOM, ACCOMMODATION, RATE, RESERVATION, SUBROOMS, REGULATION, RULES, PRODUCT_BENEFIT, CANC_POLICY_DEPOSIT
The 3rd element of the list of fee is not valid.

Availability/Rates webhooks

When you subscribe to the PORTAL_SUBSCRIPTION_CALENDAR event, we will notify all the changes inside our calendar.

We have an optimizer that will group these changes by room and period of dates.

An example of the request we will send you will be like this.


{
"content":"
{
\"data\":[
{
\"id\":225214,
\"name\":\"Apartment 2 pax\",
\"days\":[
{
\"availability\":1,
\"closeToArrival\":true,
\"closeToDeparture\":false,
\"cutOffDays\":0,
\"days\":[
\"2020-12-05\",\"2020-12-06\",\"2020-12-07\",\"2020-12-08\",\"2020-12-09\",\"2020-12-10\",\"2020-12-11\",\"2020-12-12\",\"2020-12-13\",\"2020-12-14\",\"2020-12-15\",\"2020-12-16\",\"2020-12-17\",\"2020-12-18\",\"2020-12-19\",\"2020-12-20\",\"2020-12-21\",\"2020-12-22\",\"2020-12-23\",\"2020-12-24\" ], \"maxStay\":99,
\"minStay\":1,
\"price\":0.00,
\"stopSells\":false
},
{
\"availability\":2,
\"closeToArrival\":true,
\"closeToDeparture\":false,
\"cutOffDays\":0,
\"days\":[
\"2020-11-27\",\"2020-11-28\",\"2020-11-29\",\"2020-11-30\",\"2020-12-01\",\"2020-12-02\",\"2020-12-03\",\"2020-12-04\"],
\"maxStay\":99,
\"minStay\":1,
\"price\":105.00,
\"stopSells\":false
} ] } ] }
",
"createTime":"2020-11-27T18:47:18.19Z[UTC]",
"reference":"77370",
"retry":14,
"subscription":{
"apiMember":359,
"createTime":"2020-11-27T10:43:46Z[UTC]",
"endpoint":"http://localhost:8080/connect/rest/utility/webhooks",
"id":488,
"type":"PORTAL_SUBSCRIPTION_CALENDAR"
},
"type":"PORTAL_SUBSCRIPTION_CALENDAR"
}

Reply with 200 if you have processed correctly the request

Reply anything except 200, if you're not able to process the request. We will retry the call at least one time if you don't provide 5xx status codes.

Please be aware: You must reply in short times, otherwise we will consider the http request as failed. So don't do anything time expensive here, but if requires more than some minutes, schedule it asynchronously.


Reservation Management

Before making the new Reservation

In order to prevents overbooking we have developed an endpoint that we will check in that exact moment if the calendar is open for the given Octorate Product - Checkin Date - Checkout Date.

Please use that endpoint otherwise we won't consider the analysis of an overbooking.

Either if the customer has enabled a super special calendar params, that you cannot actually support, we will reject the call in this case, but this is the behavior expected since the property has denied this date. If you ask the PM to improve the booking experience you can ask the PM to not use these params.


What kinds of params our calendar supports?

You can see them opening the calendar, clicking a day. A window will popup, check also the "advanced params".

You can either check them by the values supported when creating a new portals, inside our documentation (check the model of the portal)


Create a new Reservation

Creating a reservations doesn't have any special recommendations.

Remember only that if you want the reservations appear with your logo, specify your channel ID to registered as yours.

Cancelling reservations is an action that's expected to be done on your side.


Payments and Credit card Management

We follow strict security requirements for credit cards (PSD2 european normative), so we cannot directly take credit cards. You can check the addCard method to get an idea, but you will need to contact us to accredit you in the secure channel


Checklist

To go live we expect you to...

  • been able to register a new portal inside Octorate
  • been able to create a new portal connection for that user
  • You can either a) create at least one new external portal room and the relative mapping b) support receiving a push from our side
  • show us that you can handle prices and availability incoming
  • creating a new reservation