Skip to content

4.5. RatePlans

If the action parameter is OTA_HotelRatePlanNotif:RatePlans the client sends information about rates and related rules.

4.5.1. Client request

The request parameter contains an OTA_HotelRatePlanNotifRQ document.

Each document contains one RatePlans element. For the attributes HotelCode and HotelName the rules are the same as for room availability notifications (section 4.1). Note that requests are limited to one hotel per message.

Nested inside RatePlans are RatePlan elements, one for each rate plan. The RatePlan element has the following mandatory attributes (but see the next section for exceptions):

  • RatePlanNotifType is either New, Overlay or Remove (see section "Synchronization" below).

  • CurrencyCode is the currency in which all amounts are expressed, it must be one of the ISO 4217 currency codes.

  • RatePlanCode is the rate plan ID.

The optional RatePlan attributes RatePlanType and RatePlanCategory are used to transmit special offers and are defined as follows: A special offer or package presented by the hotel must set RatePlanType to 12 (means "Promotional") and must not set the RatePlanCategory attribute. An offer or package campaigned by a third party (such as a consortium or a tourist organization) in which the hotel participates must set RatePlanType to 12 and also the RatePlanCategory attribute with a value defined by the third party.

The two optional attributes RatePlanID and RatePlanQualifier may be used by the client to identify a "master" rateplan and its alternative versions if the server supports them (see section about joining rate plans).

Each RatePlan element contains, in order:

  • Zero or more BookingRule elements: used to restrict the applicability of the rate plan to a given stay - zero means no restrictions.

  • Zero or more Rate elements: indicate the cost of stay.

  • Zero or more Supplement elements: to specify supplements such as final cleaning fees or similar extras.

  • One Offer element with one OfferRule element: it defines the cut-off age above which guests are considered adults, the allowed age range for children (or whether children are allowed at all), and optionally introduces more restrictions to the applicability of the rate plan.

  • Zero, one or two additional Offer elements: indicates potential discounts such as free nights or kids that go free.

  • Zero to five Description elements.

Here is the global structure of the document:

<?xml version="1.0" encoding="UTF-8"?> <OTA_HotelRatePlanNotifRQ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.opentravel.org/OTA/2003/05" xsi:schemaLocation="http://www.opentravel.org/OTA/2003/05 OTA_HotelRatePlanNotifRQ.xsd" Version="1.000"> <RatePlans HotelCode="123" HotelName="Frangart Inn"> <RatePlan RatePlanNotifType="New" CurrencyCode="EUR" RatePlanCode="Rate1-4-HB"> <BookingRules> <BookingRule Start="2014-03-03" End="2014-04-17"> …​ </BookingRule> </BookingRules> <Rates> <Rate> …​ </Rate> </Rates> <Supplements> <Supplement> …​ </Supplement> </Supplements> <Offers> <Offer> …​ </Offer> </Offers> <Description Name="title"> </Description> </RatePlan> </RatePlans> </OTA_HotelRatePlanNotifRQ>

samples/RatePlans/RatePlans-OTA_HotelRatePlanNotifRQ.xml - outer part

The elements BookingRule, Rate, Supplement and Offer are explained in the following sections.

Each Description element must have a Name attribute. Within a rate plan, the Name attribute values must be distinct. Allowed values are:

  • title

  • intro

  • description

  • gallery

  • codelist

For the optional Description elements with names title, intro or description, the following rules hold:

  • Each Description element contains one or more Text elements with the attribute TextFormat set to PlainText or HTML and the attribute Language set to a two-letter lowercase language abbreviation according to ISO 639-1. At most one Text element is allowed for each combination of Language and TextFormat.

  • The presence of a Text element with TextFormat set to HTML is intended as rich text alternative of a Text element with TextFormat set to PlainText of the same Language and makes the latter mandatory.

  • Please note that an AlpineBits® server is explicitly allowed to filter, shorten or even skip the HTML content, therefore the usage of Text elements with TextFormat set to HTML is not recommended but left as an option for implementers that absolutely need it.

Here is an example:

<Description Name="title"> <Text TextFormat="PlainText" Language="en">Wellness Offer</Text> <Text TextFormat="PlainText" Language="de">Wellness Angebot</Text> <Text TextFormat="PlainText" Language="it">Offerta Wellness</Text> </Description> <Description Name="intro"> <Text TextFormat="PlainText" Language="en">Lorem ipsum EN</Text> <Text TextFormat="PlainText" Language="de">Lorem ipsum DE</Text> <Text TextFormat="PlainText" Language="it">Lorem ipsum IT</Text> </Description> <Description Name="description"> <Text TextFormat="PlainText" Language="en">Lorem ipsum sit amet EN</Text> <Text TextFormat="PlainText" Language="de">Lorem ipsum sit amet DE</Text> <Text TextFormat="PlainText" Language="it">Lorem ipsum sit amet IT</Text> <Text TextFormat="HTML" Language="en">Lorem ipsum <br> sit amet EN</Text> <Text TextFormat="HTML" Language="de">Lorem ipsum <br> sit amet DE</Text> <Text TextFormat="HTML" Language="it">Lorem ipsum <br> sit amet IT</Text> </Description>

The optional Description element with name gallery is used to store a sequence of images. Each sequence describes one (independent) image and is made of:

  • One Image element containing the image URL.

  • Zero or more Text elements with attributes TextFormat (set to PlainText) and Language (at most one Text element per language) that describe the image above.

  • Zero or one Text elements with just the attribute TextFormat (set to PlainText) containing copyright information for the image above.

  • Zero or one URL elements containing a link to the attribution of image above.

Here is an example:

<Description Name="gallery"> <Image>http://www.example.com/my-beautiful-room.jpg</Image> <Text TextFormat="PlainText" Language="en">Description EN</Text> <Text TextFormat="PlainText" Language="it">Description IT</Text> <Text TextFormat="PlainText" Language="de">Description DE</Text> <Text TextFormat="PlainText">© 2012 Example Inc.</Text> <URL>http://www.example.com/attribution/</URL> <Image>http://www.example.com/my-even-more-beautiful-room.jpg</Image> <Text TextFormat="PlainText" Language="en">Description EN</Text> <Text TextFormat="PlainText" Language="it">Description IT</Text> <Text TextFormat="PlainText" Language="de">Description DE</Text> <Text TextFormat="PlainText">© 2012 Example Inc.</Text> <URL>http://www.example.com/attribution/</URL> </Description>

The optional Description element with name codelist is used to exchange "theme" information about the rate plan that is not meant to be read by humans.

Such a Description element contains nothing but one or more ListItem elements with no attributes, each containing a code (the quoted part) from the following list:

  • "ALPINEBITS:1001" meaning Bicycle touring

  • "ALPINEBITS:1002" meaning Car-free Holiday

  • "ALPINEBITS:1003" meaning Cars & Motorcycle

  • "ALPINEBITS:1004" meaning Christmas Markets

  • "ALPINEBITS:1005" meaning Culture

  • "ALPINEBITS:1006" meaning Ecologic Holiday

  • "ALPINEBITS:1007" meaning Events

  • "ALPINEBITS:1008" meaning Family

  • "ALPINEBITS:1009" meaning Food

  • "ALPINEBITS:1010" meaning Golf

  • "ALPINEBITS:1011" meaning Hiking

  • "ALPINEBITS:1012" meaning Horseback Riding

  • "ALPINEBITS:1013" meaning Luxury Holiday

  • "ALPINEBITS:1014" meaning Mountain Bike

  • "ALPINEBITS:1015" meaning Other Summer Activities

  • "ALPINEBITS:1016" meaning Other Winter Activities

  • "ALPINEBITS:1017" meaning Pets-friendly Holiday

  • "ALPINEBITS:1018" meaning Road Bike

  • "ALPINEBITS:1019" meaning Romantic Holiday

  • "ALPINEBITS:1020" meaning Ski & Snowboard

  • "ALPINEBITS:1021" meaning Spa & Health

  • "ALPINEBITS:1022" meaning Wine

  • "ALPINEBITS:1023" meaning eBike

The "ALPINEBITS" and "OTA" namespaces are reserved, but partners are free to define custom namespaces. A server can safely ignore codes it doesn’t recognize and must not return a warning or error if it encounters one.

Here is an example:

<Description Name="codelist"> <ListItem>ALPINEBITS:1001</ListItem> <ListItem>ALPINEBITS:1006</ListItem> </Description>

Booking rules

BookingRule elements can be linked to room categories (see section 4.4) via their Code attribute. If the Code attribute is given, also the CodeContext attribute must be set and its value must be ROOMTYPE (OTA lacks a InvTypeCode attribute in this context). A BookingRule without a Code attribute applies to all room categories.

A BookingRule element must have attributes Start and End (both must be valid dates in the form YYYY-MM-DD) and satisfy the condition StartEnd. Unless otherwise specified, Start and End must be considered inclusive.

Within the same rate plan, BookingRule elements must not overlap (concerning their Start and End attributes) if they belong to the same class. Classes are:

  • BookingRule elements with no Code attribute.

  • BookingRule elements with the same value for the Code attribute.

The server must consider overlaps as an error.

BookingRule elements are used to define a number of restriction criteria:

  • The minimum or maximum length of stay (LOS) using the LengthOfStay element.

  • The arrival day of week (arrival DOW) using the ArrivalDaysOfWeek element.

  • The departure day of week (departure DOW) using the DepartureDaysOfWeek element.

  • A master restriction status (values Open/ Close) using the RestrictionStatus element.

Any missing criteria is to be interpreted as unrestricted.

LengthOfStay elements indicate a minimum length of stay (by setting the attribute MinMaxMessageType to SetMinLOS or SetForwardMinStay) or a maximum length to stay (by setting the attribute MinMaxMessageType to SetMaxLOS or SetForwardMaxStay). Each value of MinMaxMessageType must not appear more than once in the same LengthsOfStay container element. It is the responsibility of the client to check that - if the attribute MinMaxMessageType sets a value for SetMinLOS, it must be ≤ than SetMaxLOS, similarly SetForwardMinStay must be ≤ SetForwardMaxStay.

When matching a BookingRule, a server must consider the following rules:

  • The criteria of the booking rule (if any) that applies to the arrival day (Start ≤ arrival day ≤ End): SetMinLOS, SetMaxLOS, arrival DOW, master status Open.

  • The criteria of the booking rule (if any) that applies to the departure day (Start ≤ departure day ≤ End): departure DOW.

  • The criteria of the booking rule (if any) that applies and need to be checked for each day of the stay (excluding the departure day): the day must not be denied by a master status Close rule. The whole length of the stay must be consistent with SetForwardMinStay and SetForwardMaxStay attributes.

A stay must be allowed by all applicable booking rules. In particular, there might be a BookingRule element with a Code attribute and a BookingRule element without a Code attribute, both applicable to a given stay. In such a case, both rules must allow the stay.

Three booking rule examples are shown here.

In example A, length of stay (LOS) restrictions are given. The Time attribute must be an integer > 0 and the TimeUnit must be Day. This rule would restrict any stay having 2016-03-03 ≤ arrival day ≤ 2016-04-17 to a duration between 5 and 7 nights.

<BookingRule Start="2016-03-03" End="2016-04-17"> <LengthsOfStay> <LengthOfStay Time="5" TimeUnit="Day" MinMaxMessageType="SetMinLOS"/> <LengthOfStay Time="7" TimeUnit="Day" MinMaxMessageType="SetMaxLOS"/> </LengthsOfStay> </BookingRule>

Booking rule (example A)

In example B, arrival day of week (arrival DOW) and departure day of week (departure DOW) restrictions are given. At most one ArrivalDayOfWeek element and at most one DepartureDayOfWeek element must be given. The DOW attributes that are 0 or false indicate restricted DOWs. A missing DOW attribute or a value of 1 or true indicate there is no restriction. This example would restrict any stay requesting a "double" room (note the Code attribute) to arrive and depart on a Thursday or Saturday.

<BookingRule Start="2016-01-01" End="2017-12-31" Code="double" CodeContext="ROOMTYPE"> <DOW_Restrictions> <ArrivalDaysOfWeek Mon="0" Tue="0" Weds="0" Thur="1" Fri="0" Sat="1" Sun="0"/> <DepartureDaysOfWeek Mon="0" Tue="0" Weds="0" Thur="1" Fri="0" Sat="1" Sun="0"/> </DOW_Restrictions> </BookingRule>

Booking rule (example B)

Alternatively, example B could also be written as:

<BookingRule Start="2016-01-01" End="2017-12-31" Code="double" CodeContext="ROOMTYPE"> <DOW_Restrictions> <ArrivalDaysOfWeek Mon="0" Tue="0" Weds="0" Fri="0" Sun="0"/> <DepartureDaysOfWeek Mon="0" Tue="0" Weds="0" Fri="0" Sun="0"/> </DOW_Restrictions> </BookingRule>

Booking rule (example B - alternative)

The following example (C) forbids any stay in the suite in August (departure on the 1st of August is possible).

<BookingRule Start="2016-08-01" End="2016-08-31" Code="suite" CodeContext="ROOMTYPE"> <RestrictionStatus Restriction="Master" Status="Close"/> </BookingRule>

Booking rule (example C)

Both attributes, Restriction and Status are mandatory. The value Close is necessary for the restriction to occur. An Open value would be equivalent to no restriction.

Another specific CodeContext for BookingRule is ALPINEBITSEXTRA-PETS which denotes a special BookingRule that restricts the applicability of the rate plan to the presence of pets in the group. It applies to the whole rate plan and to every category specified in it. Code must have the fixed value ANY (to express that it refers to any kind of animal). It must not overlap with other ALPINEBITSEXTRA-PETS BookingRule elements and must only contain a RestrictionStatus element with Restriction set to Master and a Status attribute set either to Close to disallow pets for the given time period or Open to allow them (which is equivalent to no restriction).

<BookingRule Start="2021-09-09" End="2021-11-30" CodeContext="ALPINEBITSEXTRA-PETS" Code="ANY"> <RestrictionStatus Restriction="Master" Status="Open" /> </BookingRule>

Pets' Booking rule

Check the Supplements' section later in this chapter for further details about pricing of pets.

Rates

AlpineBits® classifies Rate elements into two kinds: static Rate elements and date dependant Rate elements.

Static rates.

Static Rate elements are used to avoid sending the same information repeatedly for each rate of the same rate plan. They:

  • Contain static information that is valid for the whole Rateplan and is not date dependant.

  • Can only be transmitted in messages with RatePlanNotifType set to New.

  • Can only be used at position 1 in a list of Rate elements.

Here is an example of such a static rate:

<Rate RateTimeUnit="Day" UnitMultiplier="1"> <BaseByGuestAmts> <BaseByGuestAmt Type="7"/> </BaseByGuestAmts> <MealsIncluded MealPlanIndicator="true" MealPlanCodes="12"/> </Rate>

samples/RatePlans/RatePlans-OTA_HotelRatePlanNotifRQ.xml - static rate

By default, all rates are per night. It is, however, possible to specify rates per an arbitrary amount of nights. This is done by adding both of the optional attributes RateTimeUnit (Day is the only allowed value) and UnitMultiplier (number of nights) to the static Rate element. This will implicitly set the time unit for all the rates in the rate plan.

The mandatory BaseByGuestAmt element with the only and mandatory Type attribute determines if the amounts given in the rates of the containing rate plan are to be considered per person (Type 7) or per room (Type 25).

Finally, a static rate also sets the board type for the rate plan. This is done with the mandatory MealsIncluded element. The mandatory MealPlanIndicator attribute must be true and the mandatory MealPlanCodes attribute assumes one of the following values (a subset of the full OTA list):

  • 1 - All inclusive

  • 3 - Bed and breakfast

  • 10 - Full board

  • 12 - Half board

  • 14 - Room only

Note that AlpineBits® does not use the single Breakfast/Lunch/Dinner booleans.

Date dependant rates.

The date dependant rates (just "called" rates from here on) must have an InvTypeCode attribute that links them to room categories (see section 4.4).

A Rate element must have attributes Start and End (both must be valid dates in the form YYYY-MM-DD) and satisfy the condition StartEnd.

A stay matches the Start and End attributes if the the arrival day is ≥ Start and the departure day ≤ End + 1. When the server computes the total cost of the stay it must find a matching rate for each night of the stay. Otherwise it cannot compute the total cost, and the stay is not possible.

Within the same rate plan, two Rate elements must not overlap (concerning their Start and End attributes) if they have the same InvTypeCode attribute.

The server must consider overlaps as an error.

Rate elements specify costs after taxes; all amounts must be expressed in the currency specified by the RatePlan CurrencyCode attribute and must follow its currency convention of decimal digit amount after the decimal sign. Rate sub-elements are: BaseByGuestAmt and AdditionalGuestAmount.

Here is an example of such a rate (the prices are considered "per person" because of the static rate described above):

<Rate InvTypeCode="double" Start="2014-03-03" End="2014-03-08"> <BaseByGuestAmts> <BaseByGuestAmt NumberOfGuests="1" AgeQualifyingCode="10" AmountAfterTax="106"/> <BaseByGuestAmt NumberOfGuests="2" AgeQualifyingCode="10" AmountAfterTax="96"/> </BaseByGuestAmts> <AdditionalGuestAmounts> <AdditionalGuestAmount AgeQualifyingCode="10" Amount="76.8"/> <AdditionalGuestAmount AgeQualifyingCode="8" MaxAge="3" Amount="0" /> <AdditionalGuestAmount AgeQualifyingCode="8" MinAge="3" MaxAge="6" Amount="38.4"/> <AdditionalGuestAmount AgeQualifyingCode="8" MinAge="6" MaxAge="10" Amount="48" /> <AdditionalGuestAmount AgeQualifyingCode="8" MinAge="10" MaxAge="16" Amount="67.2"/> </AdditionalGuestAmounts> </Rate>

samples/RatePlans/RatePlans-OTA_HotelRatePlanNotifRQ.xml - rate

The BaseByGuestAmt elements (at least one must be present) have the following attributes:

  • NumberOfGuests (mandatory) is an integer value > 0,

  • AmountAfterTax (mandatory) is a positive non zero decimal value (zero is not allowed) which must follow the currency convention of decimal digit amount after the decimal sign for the specified currency,

  • AgeQualifyingCode (mandatory) is set to 10 ("adult").

For a given Rate, all BaseByGuestAmt elements must have distinct NumberOfGuests values.

One or more BaseByGuestAmt elements are needed to cover all possible guest occupancies compatible with the room category occupancy limits. In particular, one BaseByGuestAmt element with attributes NumberOfGuests equal to the standard occupancy must be present. Additional BaseByGuestAmt elements with values between the minimum and the standard occupancy may be present. See the section "Computing the cost of a stay" below for details.

The AdditionalGuestAmount elements (zero or more can be present) are used to transmit the prices for guests that are in a room beyond the minimum number of guests that ought to pay the full rate (see below for the definition). Specific prices for children may also be sent with these elements. They have the following attributes:

  • AgeQualifyingCode (mandatory) is set to 8 ("child) or 10 ("adult").

  • MinAge and MaxAge are both integer values > 0 (a value of 0 is forbidden by OTA, even for MinAge); when both are given together, the inequation MaxAge > MinAge must hold.

  • Amount (mandatory) is a positive decimal value (zero is allowed) which must follow the currency convention of decimal digit amount after the decimal sign for the specified currency.

AdditionalGuestAmount elements must also comply with these rules that help resolve ambiguities when computed the total cost of a stay:

  1. If AdditionalGuestAmount are defined at all, at most one AdditionalGuestAmount element with a AgeQualifyingCode set to 10 ("adult") may be present.

  2. AdditionalGuestAmount elements having AgeQualifyingCode set to 8 ("child") must have at least one of the attributes MinAge or MaxAge. Contrary, those with AgeQualifyingCode set to 10 ("adult") must have neither.

  3. The attributes MinAge and MaxAge are used to identify age brackets. An age matches the bracket if and only if the following two conditions hold:

    • MinAge is not given or MinAge ≤ age

    • MaxAge is not given or MaxAge > age

All the Rate elements in a Rateplan must be consistent with the "brackets" defined in the first OfferRule element, it is a client responsibility to ensure this.

A server must return a warning outcome or error outcome if this is not the case.

Supplements

Supplements are supported through Supplement elements.

Each Supplement element has the following mandatory attributes:

  • InvType is set to EXTRA.

  • InvCode can be set freely (1 - 16 characters according to OTA) and is used as a key to identify a supplement.

The InvType value ALPINEBITSEXTRA is not currently used, but is reserved for a future shared list of common InvCode values. The InvType value ALPINEBITSEXTRA-PETS is used for transmitting pets’ supplements. See end of section for further details.

Supplements, analogously to Rates are split into static and date dependant Supplement elements.

The static supplements contain the information used to identify and describe the supplement to guests. For each distinct InvCode that is specified, there must be exactly one static Supplement element and there may be several date depending Supplement elements.

The following attributes and sub-elements are used in static supplements:

  • The mandatory attribute AddToBasicRateIndicator must be set to true (to indicate the supplement amount must be added to the amount coming from the rate).

  • The mandatory attribute MandatoryIndicator (a boolean value) indicates that the customer must book the supplement (true) or can choose to book the supplement (false).

  • The mandatory attribute ChargeTypeCode must have one of the following values:

    • 1 - Daily

    • 18 - Per room per stay

    • 19 - Per room per night

    • 20 - Per person per stay

    • 21 - Per person per night

    • 24 - Item (per stay, see below).

    Note that when ChargeTypeCode is 1 or 24, if MandatoryIndicator is true, their amount should be considered as "1 per day" and "1 per stay" respectively; otherwise, for an optional Supplement, the total cost of stay should be computed by asking the user for the number of items.

  • An optional PrerequisiteInventory sub-element with the mandatory InvType attribute set to ALPINEBITSDOW can be used to make supplements available only on certain days of the week. The mandatory InvCode attribute can be used to identify those days of the week: it is a string made of seven binary digits. Each position in the string refers to a day of the week, starting with Monday. A 1 at a given position means that the supplement is available on the corresponding day, a 0 means it’s not. A value of 1100000 for instance, would indicate a supplement available only on Monday and Tuesday.

  • Zero to five Description elements - the format of the descriptions follow what has been explained for rate plan level descriptions (with the same name values).

All the Supplement attributes mentioned are mandatory.

No other attributes or sub-elements are allowed for static data supplements (in particular attributes Start and End are not allowed).

The following attributes and sub-elements define the price of the supplement for specific periods of time. They are thus used in date depending supplements:

  • The attribute Amount indicates the cost of the supplement after taxes; amounts must be expressed in the currency specified by the RatePlan CurrencyCode attribute and must follow its currency convention of decimal digit amount after the decimal sign; a value of 0 indicates the supplement is free of charge. If the attribute is missing, the Supplement is not available.

  • The attributes Start and End (with the usual meaning) define the period where the Amount surcharge is applied.

  • An optional PrerequisiteInventory sub-element with the mandatory InvType attribute set to ROOMTYPE can be used to make supplements available only for certain room categories or price them differently for different room categories. The mandatory InvCode attribute can be used to identify the room category the supplement applies to.

The attributes Start and End are mandatory for supplements that contain date depending data, the attribute Amount and the sub element PrerequisiteInventory are optional. No further Element or Attribute is allowed.

Multiple date depending Supplement elements referring to the same InvCode and PrerequisiteInventory might be used to specify different prices for different date ranges. Overlaps are not allowed: it is the responsibility of the client to check that different amounts are never set for the same date and the same Supplement; a server must return an error if it detects such an inconsistency in the data.

When defining supplements, static and date dependant data must be transmitted in separate Supplement elements.

Here is a complete example of a supplement:

<Supplements> <Supplement InvType="EXTRA" InvCode="0x539" AddToBasicRateIndicator="true" MandatoryIndicator="true" ChargeTypeCode="18"> <Description Name="title"> <Text TextFormat="PlainText" Language="de">Endreinigung</Text> <Text TextFormat="PlainText" Language="it">Pulizia finale</Text> </Description> <Description Name="intro"> <Text TextFormat="PlainText" Language="de"> Die Endreinigung lorem ipsum dolor sit amet. </Text> <Text TextFormat="PlainText" Language="it"> La pulizia finale lorem ipsum dolor sit amet. </Text> </Description> </Supplement> <Supplement InvType="EXTRA" InvCode="0x539" Amount="20" Start="2014-10-01" End="2014-10-11"> </Supplement> </Supplements>

samples/RatePlans/RatePlans-OTA_HotelRatePlanNotifRQ.xml - supplement

Static data may only be transmitted in messages with RatePlanNotifType set to New. Moreover, all the static data must be defined within a single Supplement element.

Date dependant data may be also transmitted in messages with RatePlanNotifType set to Overlay.

See the section "Synchronization" below for more details.

Supplements contribute to the total cost of a stay. The general rule is that this contribution must always be added to the amount calculated from the applied rates on a day by day basis. The departure day supplements must not be applied, as the guest is leaving.

In case of ChargeTypeCode with value 18, 20 and 24 (see above, all supplements that are per stay) the cost of a supplement may vary in the period of the stay. In this case, the total cost of the supplement must be calculated using the following algorithm (assuming a 3-night stay with a cost of € 80 for the first two days and € 85 for last two (including the departure day)):

  • Calculate the number of days where the supplement applies (the supplement must not be applied to the departure day, hence the result is 3).

  • Sum the applicable price for each day (80 + 80 + 85 = 245 €).

  • Divide the result for the number of days obtained at step 1 and round the result at the second decimal place (245 / 3 = 81.67 €).

Note that the rate plan is available also in dates for which a Supplement declared as mandatory is not specified. Of course in these dates the supplement will not be available to guests. Similarly when a supplement is not applicable to a potential stay due to an unmatched PrerequisiteInventory, the rate plan - without the supplement - is still available.

A specific kind of supplements can be sent with InvType value ALPINEBITSEXTRA-PETS in order to transmit supplements regarding pets’ pricing (called “Pets’ Supplements” in the following paragraphs). These special supplements, if present, follow the same rules just mentioned for the regular Supplement elements with the addition that they should be defined only for Open time periods of BookingRule elements with CodeContext value ALPINEBITSEXTRA-PETS (called “Pets’ BookingRules” in the following paragraphs).

A best practice is to dedicate a separate RatePlan for managing categories that host pets: in fact if a “Pets’ BookingRule” defines a period for which pets are allowed, every category without an associated “Pets’ Supplement” will not charge any extra for the pets since no Supplement can be added to the total cost, as stated above in the Supplements definition.

Defining at least one of “Pets’ BookingRules” or “Pets’ Supplements” implies that the information about pets’ acceptance and prices is managed. If both are undefined it means the information is unknown.

<Supplements> …​ <Supplement InvType="ALPINEBITSEXTRA-PETS" InvCode="…​supplementID…​" AddToBasicRateIndicator="true" MandatoryIndicator="false" ChargeTypeCode="14"> <Description Name="title"> <Text TextFormat="PlainText" Language="it">Supplemento animali al seguito</Text> <Text TextFormat="PlainText" Language="de">…​</Text> </Description> </Supplement> <Supplement InvType="ALPINEBITSEXTRA-PETS" InvCode="…​supplementID…​" Amount="15" Start="2021-09-09" End="2021-11-15"> </Supplement> <Supplement InvType="ALPINEBITSEXTRA-PETS" InvCode="…​supplementID…​" Amount="20" Start="2021-11-16" End="2021-11-30"> <PrerequisiteInventory InvType="ROOMTYPE" InvCode="DOUBLE" /> </Supplement> …​ </Supplements>

Pets' Supplements - supplement

Offers

Offers are considered static data and can only be transmitted in messages with RatePlanNotifType set to New.

The mandatory first Offer element must contain one OfferRule element, no Discount element and no Guest element.

The first OfferRule element contains:

  • Zero or one LengthOfStay elements with MinMaxMessageType set to SetMinLOS.

  • Zero or one LengthOfStay elements with MinMaxMessageType set to SetMaxLOS.

  • Zero or one ArrivalDaysOfWeek elements.

  • Zero or one DepartureDaysOfWeek elements.

The use of these elements inside an OfferRule is analogous to their use inside a BookingRule as explained above.

The first OfferRule element further contains:

  • One Occupancy element with the AgeQualifying attribute set to 10 ("adult") and an optional MinAge attribute (integer value > 0)

  • Zero or one Occupancy element with the AgeQualifying code set to 8 ("child") and optional attributes MinAge and MaxAge (integer value > 0)

Rules regarding these Occupancy elements:

  • If the only Occupancy element present is the one with AgeQualifying attribute 10 ("adult") and no MinAge attribute, all guests are to be considered "adults"; if the MinAge attribute is present, MinAge must be ≤ 18 – all guests ≥ MinAge are considered "adults" and all guests < MinAge are considered "children".

  • If and only if the MinAge attribute is specified for the "adult" guests, then in order to allow the presence of children, the Occupancy element with AgeQualifying attribute 8 ("child") must be present. If that element has a MinAge and/or a MaxAge attribute, the age of "children" is restricted to the interval MinAge ≤ age < MaxAge.

  • Any of the Occupancy elements may contain also the attributes MinOccupancy with integer values between 0 and 99 and MaxOccupancy with integer values between 1 and 99 having the purpose to restrict the total number of adults or children allowed in a stay with this rate plan.

The first OfferRule element might also have any of the following arguments with values that are durations given in days encoded in ISO 8601 (thus always in the form PxD where x is the integer number of days):

  • MinAdvancedBookingOffset - the rate plan is only bookable before the given number of days before the arrival date.

  • MaxAdvancedBookingOffset - the rate plan is only bookable if booked after the given number of days before the arrival date.

The first OfferRule element contains all the static booking rules of the rate plan. All the restrictions that are defined in this element must be fulfilled by a stay in order to make the rate plan bookable.

Here is a quite minimal first OfferRule element without any restrictions: guests are considered adults if they are of age 16 or older and children (of any age) are allowed:

<Offer> <OfferRules> <OfferRule> <Occupancy AgeQualifyingCode="10" MinAge="16"/> <Occupancy AgeQualifyingCode="8"/> </OfferRule> </OfferRules> </Offer>

samples/RatePlans/RatePlans-OTA_HotelRatePlanNotifRQ.xml - offer

The first offer element is followed by zero, one or two additional Offer elements describing discounts.

AlpineBits® only supports offers having a Discount element with the Percent attribute set to 100. There are two use cases:

  • free nights offers, such as "7+1" formulas and the like.

  • family offers, such as "first kid goes free".

Rate plans may only contain at most one of each kind. Note that discounts (if given at all) do not necessarily need to apply to a stay in order to make the rate plan bookable.

A free nights offer has a Discount element with the following attributes:

  • Percent (mandatory) - value is always 100.

  • NightsRequired (mandatory) - how many nights at least must be booked for the discount to apply.

  • NightsDiscounted (mandatory) - how many nights are discounted.

  • DiscountPattern (optional) - the pattern is required to be in the form (nights required - nights discounted) times the 0 followed by (nights discounted) times the 1. No other pattern is allowed.

If the DiscountPattern is present, the discount pattern can be applied repeatedly from the beginning of the stay. If, for instance, NightsRequired is 7 and the stay is 14 nights, the pattern applies exactly twice, thus two times the NightsDiscounted nights are free (corresponding to the nights having a 1 in the pattern).

If the DiscountPattern is absent, the discount is not repeatable and the free nights are simply the last NightsDiscounted nights of the stay.

Free night offers apply to every amount referring to the discounted night (rates as well as per-day or per-night supplements, including mandatory ones).

Free night offers may be only used in conjunction with rates that have a UnitMultiplier of 1.

A family offer has a Discount element with just the Percent attribute set to 100 followed by at most one Guest element defining who goes free. Guest attributes (all mandatory) are:

  • AgeQualifyingCode is set to 8.

  • MaxAge is an integer value > 0: the discount only applies to guests having age < MaxAge.

  • MinCount is an integer value ≥ 0: it identifies the minimum number of guests having age < MaxAge that are required for the offer to be applicable.

  • FirstQualifyingPosition - always set to 1.

  • LastQualifyingPosition - number of persons the discount applies to.

Family offers apply to every amount referring to the discounted guest (rates as well as per-person supplements, including mandatory ones).

In case the number of age-matching guests exceeds the number of discounted guests, AlpineBits® requires to discount the guests starting from the youngest.

Following are a few complete examples of the Offers element.

Example A (early booking offer): must be booked at least 30 days in advance, guests ≥ 16 are considered adults, guest < 10 are not allowed.

<Offers> <Offer> <OfferRules> <OfferRule MinAdvancedBookingOffset="P30D"> <Occupancy AgeQualifyingCode="10" MinAge="16" /> <Occupancy AgeQualifyingCode="8" MinAge="10" MaxAge="16" /> </OfferRule> </OfferRules> </Offer> </Offers>

Offers - example A

Example B (last minute offer): cannot be booked more than 7 days in advance, guests ≥ 16 are considered adults, children of any age allowed.

<Offers> <Offer> <OfferRules> <OfferRule MaxAdvancedBookingOffset="P7D"> <Occupancy AgeQualifyingCode="10" MinAge="16" /> <Occupancy AgeQualifyingCode="8" /> </OfferRule> </OfferRules> </Offer> </Offers>

Offers - example B

Example C (four nights for the price of three): only applicable to a stay of exactly 4 nights with arrival on Sunday and departure on Thursday, last night is free, guests ≥ 16 are considered adults, children of any age allowed.

<Offers> <Offer> <OfferRules> <OfferRule> <LengthsOfStay> <LengthOfStay Time="4" TimeUnit="Day" MinMaxMessageType="SetMinLOS" /> <LengthOfStay Time="4" TimeUnit="Day" MinMaxMessageType="SetMaxLOS" /> </LengthsOfStay> <DOW_Restrictions> <ArrivalDaysOfWeek Sun="1" Mon="0" Tue="0" Weds="0" Thur="0" Fri="0" Sat="0" /> <DepartureDaysOfWeek Sun="0" Mon="0" Tue="0" Weds="0" Thur="1" Fri="0" Sat="0" /> </DOW_Restrictions> <Occupancy AgeQualifyingCode="10" MinAge="16" /> <Occupancy AgeQualifyingCode="8" /> </OfferRule> </OfferRules> </Offer> <Offer> <Discount Percent="100" NightsRequired="4" NightsDiscounted="1" /> </Offer> </Offers>

Offers - example C

Example D (another free nights example): the last night is free if the stay is ≥ 4 nights. Since there is no DiscountPattern, you still get just one (the last) night free, even if the stay is ≥ 8 nights. Guests ≥ 16 are considered adults, children of any age allowed. Note the rate plan is still bookable for stays of less than 4 nights (but then there’s no discount).

<Offers> <Offer> <OfferRules> <OfferRule> <Occupancy AgeQualifyingCode="10" MinAge="16" /> <Occupancy AgeQualifyingCode="8" /> </OfferRule> </OfferRules> </Offer> <Offer> <Discount Percent="100" NightsRequired="4" NightsDiscounted="1" /> </Offer> </Offers>

Offers - example D

Example E (one child goes free): if there are at least two children < 5, one of them (the younger one) goes free. Guests ≥ 16 are considered adults, children of any age allowed. Note the rate plan is still bookable if the family offer isn’t applicable.

<Offers> <Offer> <OfferRules> <OfferRule> <Occupancy AgeQualifyingCode="10" MinAge="16" /> <Occupancy AgeQualifyingCode="8" /> </OfferRule> </OfferRules> </Offer> <Offer> <Discount Percent="100" /> <Guests> <Guest AgeQualifyingCode="8" MaxAge="5" MinCount="2" FirstQualifyingPosition="1" LastQualifyingPosition="1" /> </Guests> </Offer> </Offers>

Offers - example E

Example F has the same family discount as example E, but here there is also a restriction, stating the rate plan is only bookable if there are at least two children < 5.

<Offers> <Offer> <OfferRules> <OfferRule> <Occupancy AgeQualifyingCode="10" MinAge="16" /> <Occupancy AgeQualifyingCode="8" MaxAge="5" MinOccupancy="2"/> </OfferRule> </OfferRules> </Offer> <Offer> <Discount Percent="100" /> <Guests> <Guest AgeQualifyingCode="8" MaxAge="5" MinCount="2" FirstQualifyingPosition="1" LastQualifyingPosition="1" /> </Guests> </Offer> </Offers>

Offers - example F

Example G combines some restriction with a family offer and a free nights offer! N nights are free according to the pattern, if the stay is at least N times 4 nights. Additionally one child < 5 goes free. The stay must be > 4 nights due to LOS restriction, but the rate plan is bookable also without the presence of a child < 5 (the family offer just doesn’t apply).

<Offers> <Offer> <OfferRules> <OfferRule> <LengthsOfStay> <LengthOfStay Time="4" TimeUnit="Day" MinMaxMessageType="SetMinLOS" /> </LengthsOfStay> <Occupancy AgeQualifyingCode="10" MinAge="16" /> <Occupancy AgeQualifyingCode="8" /> </OfferRule> </OfferRules> </Offer> <Offer> <Discount Percent="100" NightsRequired="4" NightsDiscounted="1" DiscountPattern="0001" /> </Offer> <Offer> <Discount Percent="100" /> <Guests> <Guest AgeQualifyingCode="8" MaxAge="5" MinCount="1" FirstQualifyingPosition="1" LastQualifyingPosition="1" /> </Guests> </Offer> </Offers>

Offers - example G

Joining rate plans

The use case of having alternative prices for alternative meal plans is fairly common. To this end, AlpineBits® provides the functionality of joining rate plans. In this case, the two optional attributes RatePlanID and RatePlanQualifier may be used by the client to identify a "master" rateplan and its alternative versions. They can only be sent if the server supports the OTA_HotelRatePlanNotif_accept_RatePlanJoin capability. All these rate plans share the same RatePlanID: exactly one rate plan (the "master") for each RatePlanID value must have the RatePlanQualifier set to true, every other rate plan (the alternative versions) that shares the same RatePlanID must have the RatePlanQualifier set to false.

When the server joins rate plans, it must use these components from the "master" rate plan:

  • Descriptive content

  • Static information about rates (except the element MealsIncluded)

  • Offers

  • Static information about supplements

and must take these components from the alternative versions:

  • Booking rules

  • Date dependent information about rates

  • Date dependent information about supplements.

4.5.2. Computing the cost of a stay

The information contained in a rate plan message (together with information about the stay and the inventory) can be used to compute the total cost of a given stay, provided the stay is possible at all.

The computation is somewhat complex due to the large number of rules involved. The rationale is that the algorithm should be as unambiguous and as top-down as possible. It is never necessary to perform permutations or recursion to find an "optimized solution". Elements with Start and End attributes, for example, must not overlap. The same is true for age brackets, as we’ve seen. The application of children rebates is very carefully designed to give a unique result and the same holds for offers, etc.

The required steps to perform such a computation are outlined in this section. Also see the section "Implementation tips and best practice" below for a link to a reference implementation.

The following information is needed about the stay:

  • The number of adult guests: n ≥ 0.

  • The ages (in years) of all guest that are considered children (the cut-off age above which guests are considered adults is defined in the first OfferRule element): an array of integers c.

  • The requested room category (i.e. InvTypeCode / Code): code.

  • The arrival date arr and the departure date dep where dep > arr.

The total number of guests (n + the length of the array c) must be > 0.

The following information is needed about the requested room category from inventory (see section 4.4):

  • The value of MinOccupancy min > 0,

  • The value of StandardOccupancy stdmin,

  • The value of MaxOccupancy maxstd,

  • (Optional) the value of MaxChildOccupancy mco, such that 0 ≤ mcomax.

From these values the minimum number of guests that ought to pay the full rate (minfull) can be computed:

  • If MaxChildOccupancy is not given, minfull = std,

  • Otherwise, minfull = minimum(max - mco std).

Then, to verify that a stay is allowed and to compute its total cost, the following steps need to be performed.

Step 1 (total occupancy check)

Verify that min ≤ total number of guests (n + the length of the array c) ≤ max. Unless this inequation holds, the stay in the selected room category is not possible and no cost can be computed.

Step 1b (offer rule check)

Verify that arr, n and c are consistent with the first OfferRule element explained in the Offers section. It is not allowed to promote children to "adults" (that is remove elements from c and increment n) to force a match.

Step 2 (transformation)

While n < minfull and the length of c is > 0, keep removing the greatest element from the array c and incrementing n by 1. In simple words: transform kids to adults as long as there are any left in an attempt to reach the minimum number of guests that pay the full rate.

Step 3 (family offers)

If there are any matching family offers, apply them. When a family offer is applied, the corresponding elements from the array c are removed. The number of removed elements is referred to as numfree below.

A rate plan can be booked for a given a stay, even if it contains family offers that do not match the stay (of course the discount is not applied in that case).

Step 4a (restrictions check)

Verify that no BookingRule elements impose restrictions that forbid the stay. The restrictions to consider have been detailed earlier in this section (see the section "booking rules"): the minimum/maximum length of stay (LOS), the arrival/departure day of week (DOW), the master restriction status.

Step 4b (compute cost)

Loop over the dates of the period of stay, finding the rate with matching Start and End values. Thanks to the fact that rates must not overlap, there is no ambiguity there.

It might be necessary, and it is explicitly allowed

  • To "stitch" rates together to cover longer stays, accumulating the amount due and/or.

  • To "split" rates having a UnitMultiplier > 1, dividing the amount due by the fraction of nights used.

A stay is only possible if every night of the stay can be covered by a rate.

The detailed implementation for this particular loop-over-and-match-rate step will likely depend on the data model used. However, for each rate, the following sub-steps are to be performed to pick the correct amount from the BaseByGuestAmt and AdditionalGuestAmount elements:

  • Each child (e.g. each element of the array c) is matched to the corresponding AdditionalGuestAmount element with AgeQualifyingCode set to 8 ("child"). At this point the fact that a match can be made for each child is guaranteed by the rules related to the first OfferRule element and by the check in step 1b.

  • Out of the n guests, up to and including std, each pay an amount given by the one BaseByGuestAmt element having:

    • A NumberOfGuests value of minimum(n + length of c + numfree, std) if the Type value is 7 ("per person") or

    • A NumberOfGuests value of minimum(n, std) if the Type is 25 ("per room")

    If the correct BaseByGuestAmt element is not available, the stay as a whole is not possible (the rate plan is incomplete and cannot be applied).

  • The remaining guests among the n - if any - each pay an amount given by the AdditionalGuestAmount elements with AgeQualifyingCode set to 10 ("adult").

    If the correct AdditionalGuestAmount element is not available, the stay as a whole is not possible (the rate plan is incomplete and cannot be applied).

At this point, unless a free nights offer applies to the date and rate just considered (note that free nights offers are compatible only with rates having a UnitMultiplier of 1), sum the contribution to the total cost.

Next, consider the supplements (mandatory and optional ones). Again, the exact implementation of the supplement matching algorithm will depend very much on the data model used. Note in any case, that free nights offers also apply to supplements, so the contribution to the cost from supplements that are per day is affected too.

Here is a flowchart of the whole process:

flowchart

4.5.3. Synchronization

Clients and servers often wish to exchange only delta information about rates in order to keep the total amount of data to be processed in check.

AlpineBits® uses the RatePlanNotifType attribute in each RatePlan element to define exactly how deltas have to be interpreted. In order to transmit new rate plans or to replace them RatePlanNotifType = New must be used. To transmit changes (deltas) a RatePlanNotifType value of Overlay must be used.

Note, however, that:

  • RatePlanNotifType = New

    At least one Description element must be present in the rate plan.The server adds the rate plan as a whole. If a rate plan with the same RatePlanCode already exists, it is replaced. In case of supplements, all static data must be sent within this message. Static rates must be sent within this message too. Offers are always considered static and hence must also be send within this message. The attributes RatePlanID and RatePlanQualifier - if supported by the server - might only be sent within this message.

  • RatePlanNotifType = Overlay

    The server updates the rate plan (identified by RatePlanCode) using the received data. At most one RatePlan element for each RatePlanCode is allowed within a single message. Elements that are not transmitted are not touched, elements that are transmitted are completely replaced (including all subelements). Since empty elements replace existing elements, sending empty elements can be a means to delete them (see clarification below). In case of supplements or rates, only date depending data may be sent within this message. Empty date depending rate elements are meant for deletion. Date depending supplements might be set as not available. Offers cannot be changed with an Overlay message. In order to update offers, the whole RatePlan has to be sent again (using New ). If the server has no rate plan with the given RatePlanCode, it may ignore the client request but must return a warning if it does.

  • RatePlanNotifType = Remove

    The rate plan must be empty (no child elements). The server deletes the rate plan (identified by RatePlanCode). If the server has no rate plan with the given RatePlanCode, it may ignore the client request but must return a warning in this case.

Generally sending a rate plan, BookingRule and Rate elements are always updated as a whole, single sub-elements (such as only the LengthOfStay restrictions) cannot be updated individually. Sending empty BookingRule or empty Rate elements will delete them including all sub-elements.

That being said, there is the special case of rate plan messages that contain a UniqueID element with attribute Instance set to CompleteSet.

In this case a client indicates it wishes to initiate sending the complete list of its rate plans. The server must then consider all rate plans it has on record that are not contained in the current message as expired. (hint: delete them). In that case, the RatePlan element will not have any RatePlanNotifType and no child elements must be present (the RatePlanCode must of course be present).

Also regarding the CompleteSet case, if the client wishes to reset all rate plans for a given hotel it can send a single empty RatePlan element (sending no RatePlan element at all would violate OTA validation).

Regarding these synchronization mechanisms, a server must support everything except RatePlanNotifType = Overlay. A server must set the corresponding capability if it does.

In order to limit the amount of transferred data and processing time, the following rules and recommendations must be taken into account:

  • RatePlanNotifType = New

    Complete RatePlans must be transmitted one at a time.

  • RatePlanNotifType = Overlay

    Updates to more than one RatePlan may be bundled into a single request. However, care should be taken to keep the data size within reasonable limits. In case of doubt, the updates should be transmitted for one RatePlan at a time.

4.5.4. Server response

The server will send a response indicating the outcome of the request. The response is a OTA_HotelRatePlanNotifRS document. Any of the four possible AlpineBits® server response outcomes (success, advisory, warning or error) are allowed.

See Appendix A for details.

4.5.5. Implementation tips and best practice

A server, before declaring support for the capability OTA_HotelRatePlanNotif_accept_RatePlan_mixed_BookingRule must ensure that an update to a generic booking rule has no impact on existing specific rules.

About Supplements:

AlpineBits® supplements allow for the following use cases:

  • Exchange of included, mandatory or optional supplements

  • Exchange of multi-language descriptions of supplements with title and short text ("intro")

  • Exchange of date depending prices

  • Examples: cleaning fees, parking, New Year’s Eve dinner

  • Exchange of images

  • Categorization of supplements

AlpineBits® supplements don’t currently allow for the following use cases (these will be addressed in a future release of AlpineBits®, therefore it’s possible that substantial modifications will be made):

  • Supplements available

Other things to note about supplements:

  • AlpineBits® does not allow the child element RoomCompanions

  • A rate plan must describe any local taxes and fees in its description (as opposed to giving them as a supplement). The rationale behind this is that a portal does not have enough information to decide whether these local taxes and fees apply to a given booking request or not

Reference Implementation:

A reference implementation for the computation of the cost of a stay is available at https://development.alpinebits.org/#/rtapp. This implementation can be used manually (by using the website) or automatically (by sending data to a web service). The implementation can also be run from the command line, source code is available.

Please let the AlpineBits Alliance know if you find a discrepancy between this document and the reference implementation.

If there is a discrepancy the following rules can be used to solve it:

  • If the document is clear, the document prevails.

  • If the document is ambiguous, the reference implementation prevails.