Step 4: Product mapping
The next step after registering your plugin is to map the product counterparts between Bókun extranet and external system. Each product in Bókun can be mapped to one external product only and vice versa.
In order to accomplish mapping, the same product has to exist on both Bókun extranet as well as the plugin side. There are two different API calls, both of which have to be implemented by the Channel manager plugin.
gRPC service interfaces
gRPC-enabled plugins must implement the following API calls:
rpc SearchProducts(SearchProductsRequest) returns (stream io.bokun.inventory.common.api.grpc.BasicProductInfo) {}
The above call (further referred as searchProduct
) may return multiple products, based on search criteria. This only requires basic product information to be supplied.
rpc GetProductById(GetProductByIdRequest) returns (io.bokun.inventory.common.api.grpc.ProductDescription) {}
The above call (further referred as getProductById
) must return extended information about a single product requested.
REST URLs
REST-enabled plugins must implement the following API calls:
POST /product/search
The above call (further referred as searchProducts
) may return multiple products, based on search criteria. This only requires basic product information to be supplied.
POST /product/getById
The above call (further referred as getProductById
) must return extended information about a single product requested.
searchProducts
call
searchProducts
call takes a single SearchProductsRequest
(in gRPC) or SearchProductsRequest
(in REST) as an input parameter and returns a number of BasicProductInfos
as its result.
SearchProductsRequest
/SearchProductRequest
have the following attributes:
Attribute | Mandatory | Notes |
parameters | ✓ | Plugin configuration parameters, as specified in Step 3. plugin configuration |
productName | If specified, result set should only contain products matching given product name (substring match) | |
country | ISO ALPHA-2 country code. If specified, the result set should only contain products from given country | |
city | If specified, result set should only contain products matching given city name (substring match) this product is applicable for. If the product is not applicable to any city, this attribute can be ignored |
If none of {productName, country, city}
are specified, searchProducts
should simply return a list of all available products.
BasicProductInfo
object has the following attributes:
Attribute | Mandatory | Notes |
id | ✓ | Product ID on external system. Must be unique: no other product should return this id. Channel manager will maintain active bimap of external-to-internal references. |
name | ✓ | Product name on the external system |
description | Product description on the external system | |
pricingCategories | ✓ | Product categories (such as Adult, Child, etc.) this product is sold at - as referred by the remote system. Should have at least one element in the collection. |
cities | Should list all cities (plain text format) this product is served at. Only optional if product is not applicable to a city. Multiple entries could be used for multi-city product | |
countries | Should list all countries (ISO ALPHA-2 codes) this product is for. If this product does not refer to any country, the field might remain unset, otherwise mandatory. The most typical case is having one country in the list |
getProductById
call
getProductById
implements retrieval of the most detailed information about a given product. This information is used for the mapping between products as well it could be used as a template for creating a new product in Bókun. This call takes in GetProductByIdRequest
as a parameter and returns ProductDescription
.
GetProductByIdRequest
has the following attributes:
Attribute | Mandatory | Notes |
parameters | ✓ | Plugin configuration parameters, as specified in Step 3. plugin configuration |
externalId | ✓ | Product id on the external system |
ProductDescription
has the following attributes:
Attribute | Mandatory | Notes |
id | ✓ | Product id on the external system. Must correspond to GetProductByIdRequest::externalId as well as BasicProductInfo::id |
name | ✓ | Product name on the external system. Must match BasicProductInfo::name |
description | Product description on the external system. Must match BasicProductInfo::description | |
pricingCategories | ✓ | Product categories (such as Adult, Child, etc.) this product is sold at - as referred by the remote system. Should have at least one element in the collection. Must match BasicProductInfo::pricingCategories |
rates | ✓ | Product rates (such as daily rate, weekly rate, etc.). Even if the remote system does not support the concept of rates, plugin must provide some default/mock rate for mapping |
openingHours (gRPC only), allYearOpeningHours,seasonalOpeningHours | Opening hours when this product is available (similar to ship opening hours). Note that these are not departure times. Note: only one of {allYearOpeningHours, seasonalOpeningHours} may be present but not both. This is enforced in gRPC API by static proto construct; REST may have it enforced in runtime. | |
bookingType | ✓ | If DATE , then this product does not have any start times.
If DATE_AND_TIME , then this product is bookable for certain times within available days.
If PASS , then this product is bookable so that participants could consume this product at any given day (providing ticket is not expired). |
customPickupPlaceAllowed | see notes | Whether customer can be picked up at an arbitrary place, specified during the booking process. Mandatory if meetingType is one of { MEET_ON_LOCATION_OR_PICK_UP , PICK_UP }, otherwise irrelevant/ignored. |
pickupMinutesBefore | see notes | How many minutes somebody should be picked up before the event takes place. Mandatory if meetingType is one of { MEET_ON_LOCATION_OR_PICK_UP , PICK_UP }, otherwise irrelevant/ignored. |
pickupPlaces | see notes | A collection of predefined pick up places, supported by vendor. Mandatory (should have at least one entry) if meetingType is one of { MEET_ON_LOCATION_OR_PICK_UP , PICK_UP } and customPickupPlaceAllowed is false . |
dropoffAvailable | ✓ | Whether drop off is available for this product. |
customDropoffPlaceAllowed | see notes | Whether customer can be dropped off at arbitrary place, specified during the booking process. Mandatory if dropoffAvailable is true, otherwise irrelevant/ignored. |
dropoffPlaces | ✓ | A collection of predefined drop off places, supported by vendor. Mandatory (should have at least one entry) if dropoffAvailable is true and customDropoffPlaceAllowed is false. |
productCategory | ✓ | Currently only experience type of products (aka activities) are supported hence the system expects ACTIVITIES here. |
ticketSupport | ✓ | Should specify what kind of tickets does this integration support (per booking or per person or none). |
countries | Should list all countries (ISO ALPHA-2 codes) this product is for. If this product does not refer to any country, the field might remain unset, otherwise mandatory. The most typical case is having one country in the list. Must match BasicProductInfo::countries | |
cities | Should list all cities (plain text format) this product is served at. Only optional if product is not applicable to a city. Multiple entries could be used for multi-city product. Must match BasicProductInfo::cities | |
startTimes | see notes | Plugin should specify a collection of product start time(s), if bookingType=DATE_AND_TIME . Otherwise ignored |
ticketType | see notes | What kind of tickets does this product generate? Currently supported types:
• QR code
• Data Matrix
• Binary
Mandatory unless ticketSupport is set to TICKETS_NOT_REQUIRED . Binary tickets currently only support application/pdf content type meaning the plugin should send tickets in PDF format |
meetingType | ✓ | How are passengers arriving to the event (are they picked up or should arrive independently)? |
enforcedLeadPassengerFields | A list of personal details fields this plugin requires to be filled for the lead passenger. If unset, no customer fields are forced during the booking process. | |
enfoorcedTravellerFields | A list of personal details fields this plugin requires to be filled for each traveller who is not lead passenger. If unset, no customer fields are forced during the booking process | |
extras | A list of extras available to book with this product |
Binary ticket data object differences
Binary ticket data type, if supported by the plugin, has slight differences in terms of how it should be served using different transport protocol.
gRPC supports bytes type which is an arbitrary sequence of bytes, and which perfectly fits the purpose of serving application/pdf content.
REST has no such native byte stream support. As a result of this, REST object attribute counterpart (BinaryTicket::ticketContent
) expects Base64-encoded byte stream instead.
Mapping process
Once the product information is returned to the Bókun platform, it will show a screen, similar to the one below:
The vendor (or Bókun support staff) would then go about mapping selected external products against local counterparts. Mapping specifics are not covered in this document as it is out of scope for plugin development. No API call is made for the mapping as Channel manager covers this without any additional involvement of the plugin.
Note: automatic price import as well as some other fields (such as start times) are not implemented in Bókun just yet, even though this information is provided by the plugin API. Make sure you go over product settings in Bókun platform to ensure all product properties are set correctly after mapping.