Integrating 3rd Party Reservation Tools
By: Haozhe Chen
Tags: Api Design, Platform, Self Service, Booking

Modeling and Implementation

Design Principles

When we model the APIs, we are following these principles:

Extensibility : as the business evolves and new requirements are added to the API we would need to add those in a non-breaking way, by being backward compatible with previous integrations.

: as the business evolves and new requirements are added to the API we would need to add those in a non-breaking way, by being backward compatible with previous integrations. Flexibility : The same solution can be adapted to multiple verticals, and it can support experiences on different clients, like mobile and web.

: The same solution can be adapted to multiple verticals, and it can support experiences on different clients, like mobile and web. Agility : We can easily iterate it and test different experiences.

: We can easily iterate it and test different experiences. Simplicity : It is easy to understand, explain, and reason about; since partners implement the spec, its complexity is directly proportional to the cost of the integrations; that is, higher complexity increases time to market; the goal is to reduce it, however.

: It is easy to understand, explain, and reason about; since partners implement the spec, its complexity is directly proportional to the cost of the integrations; that is, higher complexity increases time to market; the goal is to reduce it, however. Performance: We ensure great user experience by having the apps respond quickly to customers’ input.

API Modeling

Different actions possible with the API such as fetching the availability, completing a transaction (booking), updating states, etc. In this article, we are focusing on the availability API and how it supports, drives, and delivers the user experience.

The availability is consumed as a feed that Groupon caches to ensure a low latency interaction for searching and booking a selection. Booking UX is driven by this API to support the cases shown here and much more. Key components are Attributes, Questions, and the Availability itself. More details are below:

Attributes

Attributes are modeled the following way:

These attributes are displayed as selection widgets in the UI to filter the availability. This specification has the following features:

selectionType indicates whether multiple values can be selected by the customer.

indicates whether multiple values can be selected by the customer. category is optional and is indicating a special group of attributes that will have a special treatment in the UI. This can be further extended into new values in the future.

is optional and is indicating a special group of attributes that will have a special treatment in the UI. This can be further extended into new values in the future. writeups are used to provide textual values in different locales that will be displayed to the customer. These can also be extended in the future to add more capabilities in a non-breaking way.

The availability references the attribute values that they apply to, we will show how this works below.

Here is an example that powers the TTD screens above (party size and tour type):

Modeling Customer Inputs

We present additional fields and forms to request information, as questions, which will be associated with the reservation. In order to support a flexible questionnaire, we introduced a question schema.

Based on the type of a field , we generate different components on the client UI. It can be extended if we need more components

of a , we generate different components on the client UI. It can be extended if we need more components Supports client-side validation through constraints such as type , required , pattern , minLength and maxLength

, , , and With the recursive fields , we support nested forms

, we support nested forms Fields can be pre-filled with values

The hint and label are to generate helper text

An example showing how UI form is driven by the API

The Generated UI powered by the API above

Availability Segments

Segments are where availability is defined. It combines time and attributes. Additionally, they override some data if needed such as price and additional questions. This is helpful to model more expensive premium times.

This structure allows for greater flexibility since any specific combination of time and attributes can be specified; the drawback is that by being more specific, lots of data is needed and that is why we are consuming this data as a feed using a background job and caching it in our systems.

Here is an example of an availability segment for an adult entrance using a price override:

Availability Selection

As we have shown so far, the API specification is very flexible and enables different business verticals to operate with Groupon. Unfortunately, it requires a lot of data, since it can detail availability at the time slot level, normally it would require to have the product of all attribute groups times the number of time slots data points. For example, 1 month of availability with 10-time slots per day, 6 party size, 3 tour types, gives us 30*10*6*3 = 5400 segments in the availability feed and this grows as attribute groups are added!

Handling all this data in the client application (booking widget) isn’t very fast, the main problem is to determine the “from price” and available options according to the customer's selections.

In a naive implementation, we would keep a filtered list of segments (which starts with all of them), and each time the customer makes a selection, we keep the segments in the list that match that selection (eg: date matches or they have the corresponding attributed), then compute the from price from that list. Additionally, we need to detect which options aren’t available anymore (eg: after selecting a date and party size, some tours might not be available and need to be disabled).

The problem is compounded by the requirement of showing the “from price” of each visible option (each date of the calendar, each attribute). Note that as the customer is selecting, the “from price” of the next options might change, for example, after selecting 2 Adults and 1 Kid, we calculate the price based on that selection.

To minimize the computations done on the client, some of them are performed on the backend to ensure a great user experience with our product. When the client fetches the availability it gets the data it needs to render all widgets: dates with from prices and availability attributes, as well as the list of all segments.

The initial UI is rendered right away with the data provided by the backend, and while the customer is making their first selection, full availability is processed in a non-blocking way. The client creates a series of hashmaps and lists to make the filtering and each “from price” computation way faster.

As a next step, we are looking at ways to improve our API to see if there are ways to reduce the payload size and chattiness while retaining flexibility.