Overview
This API lets you specify possible discounts. Of the promotions specified, Google applies the eligible promotion or set of promotions that leads to the lowest price. If you are looking for an API which supports arbitrary rate adjustments that can either increase or decrease the price when conditions are satisfied, then consider our Rate Modifications API . Note that if both APIs are present, rate modifications are applied before promotions.
Requests
Syntax
The Promotions
message uses the following syntax:
<?xml
version="1.0"
encoding="UTF-8"?>
<Promotions
partner=
" partner_key
"
id=" message_ID
"
timestamp=" timestamp
">
<HotelPromotions
hotel_id=" HotelID
"
action="[overlay]">
<Promotion
id=" PromotionID
"
action="[delete]">
<BookingDates>
<DateRange
start="YYYY-MM-DD[THH:mm:ss]"
end="YYYY-MM-DD[THH:mm:ss]"
days_of_week= "MTWHFSU_or_subset"
/>
<DateRange
start="YYYY-MM-DD[THH:mm:ss]"
end="YYYY-MM-DD[THH:mm:ss]"
days_of_week= "MTWHFSU_or_subset"
/>
</BookingDates>
<BookingWindow
min=" integer_or_duration
"
max=" integer_or_duration
"/>
<Ceiling
amount_per_night=" float
"/>
<Floor
amount_per_night=" float
"/>
<CheckinDates>
<DateRange
start="[YYYY-]MM-DD"
end="[YYYY-]MM-DD"
days_of_week= "MTWHFSU_or_subset"
/>
</CheckinDates>
<CheckoutDates>
<DateRange
start="[YYYY-]MM-DD"
end="[YYYY-]MM-DD"
days_of_week= "MTWHFSU_or_subset"
/>
</CheckoutDates>
<!--
Specify
only
one
of
percentage,
percentage_of_base,
fixed_amount,
fixed_amount_per_night,
fixed_price,
or
fixed_price_per_night;
applied_nights
is
only
used
with
percentage,
fixed_amount_per_night,
and
fixed_price_per_night.
-->
<Discount
percentage=" float
"
percentage_of_base=" float
"
fixed_amount=" float
"
fixed_amount_per_night=" float
"
fixed_price=" float
"
fixed_price_per_night=" float
"
applied_nights=" integer_1_to_99
"
rank=" integer_1_to_99
">
<!--
FreeNights
may
not
be
used
in
conjunction
with
attributes
on
Discount
-->
<FreeNights
stay_nights=" integer
"
discount_nights=" integer
"
discount_percentage=" float
"
night_selection="[cheapest|last]"
repeats=" boolean
"/>
</Discount>
<!--
Exactly
one
of
Discount
or
BestDailyDiscount
must
be
specified.
Specify
only
one
of
percentage,
fixed_amount,
or
fixed_price.
-->
<BestDailyDiscount
percentage=" float
"
fixed_amount=" float
"
fixed_price=" float
"/>
<Devices>
<Device
type="[desktop|tablet|mobile]"/>
</Devices>
<InventoryCount
min=" integer
"
max=" integer
"/>
<LengthOfStay
min=" integer
"
max=" integer
"/>
<MembershipRateRule
id=" RateRuleID
"/>
<MinimumAmount
before_discount=" integer
"/>
<Occupancy
min=" integer
"
max=" integer
"/>
<RatePlans>
<RatePlan
id=" PackageID_1
"/>
<RatePlan
id=" PackageID_2
"/>
</RatePlans>
<RoomTypes>
<RoomType
id=" RoomID_1
"/>
<RoomType
id=" RoomID_2
"/>
</RoomTypes>
<Stacking
type="[any|base|none|second]"/>
<StayDates
application="[all|any|overlap]">
<DateRange
start="[YYYY-]MM-DD"
end="[YYYY-]MM-DD"
days_of_week= "MTWHFSU_or_subset"
/>
</StayDates>
<UserCountries
type="[include|exclude]">
<Country
code=" country_code
"/>
</UserCountries>
</Promotion>
</HotelPromotions>
</Promotions>
Elements and Attributes
The Promotions message has the following elements and attributes:
If you have a backend that provides feeds for
multiple accounts, this value needs to match the ID
attribute value specified in the <RequestorID>
element of your <OTA_HotelRateAmountNotifRQ>
and <OTA_HotelAvailNotifRQ>
messages for the same
account.
Promotions for a property. Each promotion applies to a single property.
Unless <Stacking>
is used,
the promotion with the biggest discount is applied to the booking when
multiple promotions are eligible.
<id>
in the <listing>
element
in the Hotel List Feed. The Hotel ID is also listed in Hotel Center
.If specified, the value must be "overlay"
. When the value is "overlay"
, all
stored promotions are deleted prior to storing the promotions specified
in the current message.
If not specified, then each promotion specified in the current message is either:
-
Added
(if none of the stored promotions has the sameid
) -
Updated
(if a stored promotion has the sameid
) -
Deleted
(if a stored promotion has the sameid
and the value of theaction
attribute for the promotion specified in the current message is"delete"
)
A single promotion for a property. Note that if action="overlay"
and a <Promotion>
is
not specified, all promotions for the property are deleted.
If you need to use more than 99 promotions, contact your Technical Account Manager (TAM).
If specified, the value must be delete
. If not
specified and a
promotion with the same id
isn't stored, then this
promotion is stored. Otherwise, if not specified and a promotion with
the same id
is stored, then the existing promotion is
updated.
If delete
is specified, the stored promotion with the
same id
is deleted.
When using delete
, don't include any child elements in <Promotion>
. Also, delete
is not
allowed in conjunction with <HotelPromotions
action="overlay"/>
.
The starting date or datetime (based on the property's time zone), inclusive, of the range.
- The date or datetime specified by
start
must be earlier than (or the same as) the date or datetime specified byend
. - If
start
isn't specified, the range is effectively unlimited in terms of a start time. - If
start
is populated as date "YYYY-MM-DD", it is interpreted as datetime "YYYY-MM-DDT00:00:00".
The ending date or datetime (based on the property's time zone), inclusive, of the range.
- The date or datetime specified by
end
must be later than (or the same as) the date or datetime specified bystart
. - If
end
isn't specified, the range is effectively unlimited in terms of an end time. - If
end
is provided as date "YYYY-MM-DD", it is interpreted as datetime "YYYY-MM-DDT23:59:59".
The days of the week that are allowed in the date range. If not specified, all days are allowed in the date range. Each character in the string specifies a day. For example, "MTWHF" specifies that weekdays are allowed in the date range.
Valid characters are:
-
M
for Monday -
T
for Tuesday -
W
for Wednesday -
H
for Thursday -
F
for Friday -
S
for Saturday -
U
for Sunday
Any character combination is valid.
0
, there is no minimum. Valid value types are:
- Integer:
The number of days before the check-in
date. For example, a value of
30
indicates the promotion only applies to bookings at least 30 days before the check-in date. - ISO 8601 Duration (days, hours, and minutes):
The number of
days (and optionally hours/minutes) before the check-in date. For
example, a value of
P30D
indicates the promotion only applies to bookings at least 30 days before the check-in date. A value ofP30DT6H
requires booking on or before 18:00 on the 30th day before arrival.
0
, there is no maximum. Valid value types are:
- Integer:
The number of days before the check-in
date. For example, a value of
30
indicates the promotion only applies to bookings at most 30 days before the check-in date. - ISO 8601 Duration (days, hours, and minutes):
The number of
days (and optionally hours/minutes) before the check-in date. For
example, a value of
P30D
indicates the promotion only applies to bookings at most 30 days before the check-in date. A value ofP30DT6H
requires booking on or after 18:00 on the 30th day before arrival.
Defines restrictions on the maximum value that a rate can be set to after promotions are applied.
Promotions must always specify a <Discount>
or a <BestDailyDiscount>
, so to create a promotion that
only applies a <Ceiling>
, one option is to set a <Discount>
with a percentage
of 0
.
If stacking is configured, then multiple promotions with <Ceiling>
could apply to a single stay. Each promotion
would apply its discount, immediately followed by its ceiling. The
following example demonstrates how each ceiling contributes to the next
promotion calculation in the stack.
Example:
Pricing a 1-night stay where AmountBeforeTax
is
100 and there is a stack of two promotions:
- Promotion with stacking type
base
, afixed_amount
of 25, and a ceilingamount_per_night
of 60 - Promotion with stacking type
second
,fixed_amount
of 25, and a ceilingamount_per_night
of 90
Here is the order of calculation:
- The
base
promotion is applied first and discounts theAmountBeforeTax
to 75, but then the ceiling lowers it to 60 . - The
second
promotion discounts theAmountBeforeTax
from 60 to 35. This is below the ceiling of 90 so the second ceiling is not applied. The final rate is 35 .
The fact that 60 is a stricter overall ceiling is irrelevant since it is valid only for its own promotion, and there can be no single ceiling that spans the entire promotion stack.
The maximum amount that a nightly rate can be set to after the discount is applied.
If a <Floor>
element is also specified, this
must be set to a value greater than or equal to the amount_per_night
attribute in <Floor>
.
amount_per_night
is applied to taxes and fees when they
are included in the nightly rate using AmountAfterTax
, but
not those specified using TaxFeeInfo.
Defines restrictions on the minimum value that a rate can be set to after promotions are applied.
Promotions must always specify a <Discount>
or a <BestDailyDiscount>
, so to create a promotion that
only applies a <Floor>
, one option is to set a <Discount>
with a percentage
of 0
.
<Floor>
logic still applies to <FreeNights>
discounts, even if the free night has a 100%
discount applied to it.
If stacking is configured, then multiple promotions with <Floor>
could apply to a single stay. Each promotion
would apply its discount, immediately followed by its floor. The
following example demonstrates how each floor contributes to the next
promotion calculation in the stack.
Example:
Pricing a 1-night stay where AmountBeforeTax
is
100 and there is a stack of two promotions:
- Promotion with stacking type
base
, afixed_amount
of 25, and a flooramount_per_night
of 90 - Promotion with stacking type
second
,fixed_amount
of 25, and a flooramount_per_night
of 60
Here is the order of calculation:
- The
base
promotion is applied first and discounts theAmountBeforeTax
to 75, but then the floor raises it up to 90 . - The
second
promotion discounts theAmountBeforeTax
from 90 to 65. This is above the floor of 60 so the second floor is not applied. The final rate is 65 .
The fact that 90 is a stricter overall floor is irrelevant since it is valid only for its own promotion, and there can be no single floor that spans the entire promotion stack.
The minimum amount that a nightly rate can be set to after the discount is applied.
If a <Ceiling>
element is also specified, this
must be set to a value less than or equal to the amount_per_night
attribute in <Ceiling>
.
amount_per_night
is applied to taxes and fees when they
are included in the nightly rate using AmountAfterTax
, but
not those specified using TaxFeeInfo.
A date range specifying when check-in must occur for the promotion to be applied. This element is not required if you're deleting one or more promotions.
The YearlessDate format is also supported.
- If one of
start
orend
is a yearless date, both must be populated as yearless dates. - Yearless date ranges must not wrap around the new year. Instead,
represent the range as two adjacent date ranges. For example,
{"12-29", "01-05"}
can be represented as{"12-29", "12-31"}
and{"01-01", "01-05"}
.
end
date. If start
isn't specified, the date
range is effectively unlimited in terms of a start date.start
date. If end
isn't specified, the date
range is effectively unlimited in terms of an end date.The days of the week that are allowed in the date range. If not specified, all days are allowed in the date range. Each character in the string specifies a day. For example, "MTWHF" specifies that weekdays are allowed in the date range.
Valid characters are:
-
M
for Monday -
T
for Tuesday -
W
for Wednesday -
H
for Thursday -
F
for Friday -
S
for Saturday -
U
for Sunday
Any character combination is valid.
A date range specifying when check-out must occur for the promotion to be applied. This element is not required if you're deleting one or more promotions.
The YearlessDate format is also supported.
- If one of
start
orend
is a yearless date, both must be populated as yearless dates. - Yearless date ranges must not wrap around the new year. Instead,
represent the range as two adjacent date ranges. For example,
{"12-29", "01-05"}
can be represented as{"12-29", "12-31"}
and{"01-01", "01-05"}
.
end
date. If start
isn't specified, the date
range is effectively unlimited in terms of a start date.start
date. If end
isn't specified, the date
range is effectively unlimited in terms of an end date.The days of the week that are allowed in the date range. If not specified, all days are allowed in the date range. Each character in the string specifies a day. For example, "MTWHF" specifies that weekdays are allowed in the date range.
Valid characters are:
-
M
for Monday -
T
for Tuesday -
W
for Wednesday -
H
for Thursday -
F
for Friday -
S
for Saturday -
U
for Sunday
Any character combination is valid.
desktop
, tablet
, or mobile
.Exactly one of Discount
or BestDailyDiscount
must be specified.
Specifies the discount to be applied for this promotion.
Exactly one of percentage
, percentage_of_base
, fixed_amount
, fixed_amount_per_night
, fixed_price
, or fixed_price_per_night
is required.
A decimal value from 0-100 which specifies the percentage discount.
It is applied to AmountAfterTax
(or AmountBeforeTax
if AmountAfterTax
isn't
specified).
Examples:
- If
AmountAfterTax
is 100 andpercentage
is 20, thenpromotion rate =
AmountAfterTax
* (1 - percentage discount)80.00 = 100 * (1 - 0.2)
- If
AmountBeforeTax
is 100,percentage
is 20 and TaxFeeInfo specifies a tax of 10, thenpromotion rate =
AmountBeforeTax
* (1 - percentage discount) + tax90.00 = 100 * (1 - 0.2) + 10
Exactly one of percentage
, percentage_of_base
, fixed_amount
, fixed_amount_per_night
, fixed_price
, or fixed_price_per_night
is required.
A decimal value from 0-100 which specifies the percentage of base
discount. Similar to percentage
, it is applied to AmountAfterTax
(or AmountBeforeTax
if AmountAfterTax
isn't specified).
Unlike percentage
, this discount is always calculated as
a percentage of base rates regardless of prior promotions that have
been applied in sequence.
Example:
- Suppose we have two promotions that are applied in sequence to a one night stay that is priced at 100. The first is a regular 10% percentage discount and the second is a 10% percentage of base discount. Then the discounted rate will be 80 since both promotions take 10 off. Note if the second promotion were also a regular percentage discount, then the discounted rate will be 81 since the second promotion discounts 10% of 90.
Exactly one of percentage
, percentage_of_base
, fixed_amount
, fixed_amount_per_night
, fixed_price
, or fixed_price_per_night
is required.
A fixed amount to be subtracted from the sum of the AmountAfterTax
nightly rates (or
sum of AmountBeforeTax
nightly rates if AmountAfterTax
isn't specified). It is assumed to be
in the same currency as nightly rates. If this is larger than the
sum of nightly rates, the resulting value is zero.
Examples:
- If we're pricing a 1-night stay where
AmountBeforeTax
is 90,AmountAfterTax
is 100, andfixed_amount
is 20, thenpromotion rate =
AmountAfterTax
- fixed discount80.00 = 100 - 20
- If we're pricing a 1-night stay where
AmountBeforeTax
is 100,fixed_amount
is 20, and TaxFeeInfo specifies a tax of 8%, thenpromotion rate = (
AmountBeforeTax
- fixed discount) * (1 + percentage tax)86.40 = (100 - 20) * 1.08
- If we're pricing a 1-night stay where
AmountBeforeTax
is 50,fixed_amount
is 60, and TaxFeeInfo specifies a tax of 10, thenpromotion rate = (
AmountBeforeTax
- fixed discount) * tax10.00 = 0 + 10
- If we're pricing a 3-night stay where the
AmountAfterTax
values are 100, 110, and 120; andfixed_amount
is 150, thenpromotion rate = sum(
AmountAfterTax
) - (fixed discount)180.00 = (100 + 110 + 120) - 150
Exactly one of percentage
, percentage_of_base
, fixed_amount
, fixed_amount_per_night
, fixed_price
, or fixed_price_per_night
is required.
A fixed discount applied to each of the AmountAfterTax
nightly rates (or the
cheapest N if applied_nights
is specified). If AmountAfterTax
isn't specified, it is applied to AmountBeforeTax
. It is assumed to be
in the same currency as nightly rates. If fixed_amount_per_night
is larger than a
nightly rate, that nightly rate is reduced to as zero—the
discount cannot cause a nightly rate to become negative.
Examples:
- If we're pricing a 3-night stay where the
AmountAfterTax
values are 100, 110, and 120; and thefixed_amount_per_night
is 10, thenpromotion rate = sum(
AmountBeforeTax
- fixed amount discount)300.00 = ((100 - 10) + (110 - 10) + (120 - 10))
- If we're pricing a 3-night stay where the
AmountAfterTax
values are 10, 50, and 100; and thefixed_amount_per_night
is 20, thenpromotion rate = sum(
AmountAfterTax
- fixed amount discount)110.00 = (0 + (50 - 20) + (100 - 20))
Exactly one of percentage
, percentage_of_base
, fixed_amount
, fixed_amount_per_night
, fixed_price
, or fixed_price_per_night
is required.
If AmountAfterTax
nightly rates are specified, then this
sets the price for the stay, including taxes and fees, to the
specified value. If AmountBeforeTax
is specified, then
whether or not AmountAfterTax
is specified, this sets the
pre-tax price for the stay to the specified value. It is assumed to be
in the same currency as nightly rates.
If AmountAfterTax
is intended to reflect a
percentage tax, then setting a fixed price for AmountBeforeTax
can result in inaccurate taxes and fees.
In general, it is strongly recommended to use TaxFeeInfo
to specify a property's taxes and fees.
Examples:
- If we're pricing a 1-night stay where
AmountBeforeTax
is 90,AmountAfterTax
is 100, andfixed_price
is 80, then the promotion rate is 80. - If we're pricing a 1-night stay where
AmountBeforeTax
is 100,fixed_amount
is 80, and TaxFeeInfo specifies a tax of 8%, thenpromotion rate = fixed price * (1 + percentage tax)
86.40 = 80 * 1.08
- If we're pricing a 3-night stay where the
AmountAfterTax
values are 100, 110, and 120; andfixed_amount
is 300, thenpromotion rate = 300
Exactly one of percentage
, percentage_of_base
, fixed_amount
, fixed_amount_per_night
, fixed_price
, or fixed_price_per_night
is required.
If AmountAfterTax
nightly rates are specified, then this
sets the price for each night of stay, including taxes and fees, to the
specified value. If AmountBeforeTax
is specified, then
whether or not AmountAfterTax
is specified, this sets the
pre-tax price for each night of stay to the specified value. It is
assumed to be in the same currency as nightly rates.
If AmountAfterTax
is intended to reflect a
percentage tax, then setting a fixed price for AmountBeforeTax
can result in inaccurate taxes and fees.
In general, it is strongly recommended to use TaxFeeInfo
to specify a property's taxes and fees.
If applied_nights
is specified, then the new price is
applied to the cheapest N nights.
Examples:
- If we're pricing a 2-night stay where
AmountBeforeTax
values are 90, 90;AmountAfterTax
values are 100, 100; andfixed_price
is 80, then the promotion rate is 80 + 80 = 160. - If we're pricing a 2-night stay where
AmountBeforeTax
is 100, 100;fixed_amount
is 80, and TaxFeeInfo specifies a tax of 8%, then the promotion rate is (80 + 80) * 1.08 = 172.8. - If we're pricing a 3-night stay where the
AmountAfterTax
values are 100, 110, and 120; andfixed_amount
is 110, then the promotion rate is 110 * 3 = 330.
This should only be used with percentage
or fixed_amount_per_night
.
The number of nights to which the discount is applied, starting with the least expensive. Must be an integer from 1 to 99. If not specified, discount is applied to all nights.
Discount
element
are not allowed if this element is used.Number of required nights for the discount to be applied. Each discount is applied to a separate segment of stay nights.
For example, for a 10-night stay where stay_nights
is
4 (and repeats
is true), then there are two stay night
segments: the 1st through 4th nights and the 5th through 8th nights; the
9th and 10th nights are not part of a stay night segment.
50
, then each selected night is 50% off.cheapest
or last
. If last
, then the nights at the end of the segment of stay
nights are discounted. If cheapest
, then the cheapest
nights within the segment of stay nights are discounted.Whether the discount may be applied to multiple stay night
segments. If false
, then only the segment of stay nights at
the beginning of the itinerary is discounted. If true
, then
any segment of stay nights is discounted.
For example, if stay_nights
is 4 and the itinerary is 10
nights, then, if repeats
is true
, then 2
segments are discounted (nights 1-4 and nights 5-8); but, if repeats
is false
, then only 1 segment is
discounted (nights 1-4).
Exactly one of Discount
or BestDailyDiscount
must be specified.
Specifies a
daily discount which may be applied to a night of stay. This is in
contrast with Discount
, which applies discounts to entire
stays.
Each property may have a single group of promotions that are considered "best daily." This means that for each night of stay, the single "best daily" promotion that is eligible and yields the deepest discount for that night is selected and may be applied.
Stacking
may be specified with BestDailyDiscount
. It must be set to either base
or none
. The "best daily" discounts
yielding the deepest discount for each night are combined and treated as
a single stay discount (i.e. Discount
) while respecting
the configured stacking type. This combined discount is compared
against, and can be stacked with, other eligible <Discount>
promotions to find the one or combination that provides the deepest
discount. Either the combination of BestDailyDiscount
or a
single Discount
, whichever yields the lower price, is
selected and applied for the base
stacking type.
StayDates
can be specified with this type of discount,
but the application
must be set to overlap
Exactly one of percentage
, fixed_amount
, or fixed_price
is required.
A decimal value from 0-100 which specifies the percentage discount.
It is applied to AmountAfterTax
(or AmountBeforeTax
if AmountAfterTax
isn't
specified).
Examples:
- If
AmountAfterTax
for a night of stay is 100 andpercentage
is 20, thenpromotion rate =
AmountAfterTax
* (1 - percentage discount)80.00 = 100 * (1 - 0.2)
- If
AmountBeforeTax
for an ight of stay is 100,percentage
is 20 and TaxFeeInfo specifies a tax of 10, thenpromotion rate =
AmountBeforeTax
* (1 - percentage discount) + tax90.00 = 100 * (1 - 0.2) + 10
Exactly one of percentage
, fixed_amount
, or fixed_price
is required.
A fixed amount to be subtracted from a single AmountAfterTax
nightly rate (or AmountBeforeTax
nightly rate if AmountAfterTax
isn't specified). It is assumed to be
in the same currency as nightly rates. If this is larger than the
sum of nightly rates, the resulting value is zero.
Examples:
- If
AmountBeforeTax
for a single night is 90,AmountAfterTax
is 100, andfixed_amount
is 20, thenpromotion rate =
AmountAfterTax
- fixed discount80.00 = 100 - 20
- If
AmountBeforeTax
for a single night is 100,fixed_amount
is 20, and TaxFeeInfo specifies a tax of 8%, thenpromotion rate = (
AmountBeforeTax
- fixed discount) * (1 + percentage tax)86.40 = (100 - 20) * 1.08
Exactly one of percentage
, fixed_amount
, or fixed_price
is required.
If AmountAfterTax
nightly rates are specified, then this
sets the price for the night of stay, including taxes and fees, to the
specified value. If AmountBeforeTax
is specified, then
whether or not AmountAfterTax
is specified, this sets the
pre-tax price for the stay to the specified value. It is assumed to be
in the same currency as nightly rates.
Examples:
- If
AmountBeforeTax
for a single night is 90,AmountAfterTax
is 100, andfixed_price
is 80, then the promotion rate is 80. - If
AmountBeforeTax
for a single night is 100,fixed_amount
is 80, and TaxFeeInfo specifies a tax of 8%, thenpromotion rate = fixed price * (1 + percentage tax)
86.40 = 80 * 1.08
fixed_amount
discount. Note that the number of available
rooms is specified with either OTA_HotelInvCountNotifRQ
( InvCount
)
or OTA_HotelAvailNotifRQ
( BookingLimit
).Container for a membership rate rule that triggers a specific UI treatment for the associated discount.
This element should not
be specified unless <Discount>
is also specified.
ID of the rate rule associated with a membership program.
AmountBeforeTax
or AmountAfterTax
) that must
be exceeded for the promotion to be applied.<RatePlans>
isn't specified, the promotion
applies to all rate plans.<PackageData>
in a Transaction (Property Data)
message, and in the RatePlanCode
attribute in <StatusApplicationControl>
in both <OTA_HotelRateAmountNotifRQ>
and <OTA_HotelAvailNotifRQ>
messages.
The maximum number of characters allowed is 50.<RoomType>
specified. If <RoomTypes>
isn't specified, the
promotion applies to all rooms.<RoomData>
element in a Transaction (Property Data)
message and is
referenced using its <RoomID>
value. (Its <RoomID>
value is also referenced by the InvTypeCode
attribute in OTA_HotelRateAmountNotifRQ
messages.)<RoomID>
in a Transaction (Property Data) message.
The maximum number of characters allowed is 50.base
.Multiple promotions can be applied to a single rate depending on this setting:
-
any
: Can be combined with any other promotion (exceptnone
), but the order in which the promotions should be applied is not guaranteed. -
base
: The best eligiblebase
promotion is selected and applied first, before other promotions. This was previously namedbase_only
. -
second
: The best eligiblesecond
promotion is selected and applied after abase
promotion (if applicable) and beforeany
promotions. -
none
: Can not be combined with other promotions.
Of the allowed combinations, the set of promotions which yields the largest discount are applied to the rate.
Describes how the promotion should be applied.
Valid values are:
-
all
: Applies the promotion to each night in the itinerary if alldates in the itinerary overlap with the stay dates. -
any
: Applies the promotion to all nights in the itinerary if any date in the itinerary overlaps with a date in the stay dates range. -
overlap
: Applies the promotion only to those nights in the itinerary that overlap with a date in the stay dates range.
This attribute must always be specified.
- If
<Discount>
specifiespercentage
andapplication
is set toall
orany
, the discount is applied as a percentage of the full stay. - If
<Discount>
specifiespercentage
andapplication
is set tooverlap
, the discount is applied as a percentage of nightly rates for overlapping nights. -
<Discount>
specifyingfixed_amount
andapplication
set tooverlap
is an invalid combination. -
<FreeNights>
supports allapplication
values. Note that foroverlap
, only overlapping nights of stay are considered for the discount requirements.
A date range specifying dates when the promotion is to be applied.
The YearlessDate format is also supported.
- If one of
start
orend
is a yearless date, both must be populated as yearless dates. - Yearless date ranges must not wrap around the new year. Instead,
represent the range as two adjacent date ranges. For example,
{"12-29", "01-05"}
can be represented as{"12-29", "12-31"}
and{"01-01", "01-05"}
.
If you want to set StayDates
range to
allow the promotion on specific days of the week, you should set the start
date as the current date with no end
so
that the promotion doesn't expire.
end
date. If start
isn't specified, the date
range is effectively unlimited in terms of a start date. You should specify start
value if the end
value isn't provided.
start
date. If end
isn't specified, the date
range is effectively unlimited from the start
date onwards. You should specify end
value if the start
value isn't provided.
The days of the week that are allowed in the date range. If not specified, all days are allowed in the date range. Each character in the string specifies a day. For example, "MTWHF" specifies that weekdays are allowed in the date range.
Valid characters are:
-
M
for Monday -
T
for Tuesday -
W
for Wednesday -
H
for Thursday -
F
for Friday -
S
for Saturday -
U
for Sunday
Any character combination is valid.
Valid values are include
and exclude
.
If the UserCountries type
is set as include
, the promotion applies to users from the
listed countries.
If the UserCountries type
is exclude
,
the promotion applies to users from outside the listed
countries.
If the UserCountries type
is unset, it is treated as include
and the promotion is applied to users from
the listed countries.
DE
or FR
. Note that, for some
countries, the CLDR country code isn't the same as the 2-letter ISO
country code. Also, CLDR region codes are not supported.Examples
There is a limit of 500 promotions per property. Refer to "Delete one promotion" example to remove promotions from a property.
Basic message
The following example shows a basic Promotions
message:
<?xml
version="1.0"
encoding="UTF-8"?>
<Promotions
partner="account_xyz"
id="123_abc"
timestamp="2020-05-18T16:20:00-04:00">
<HotelPromotions
hotel_id="Property_1">
<Promotion
id="1">
<BookingDates>
<DateRange
start="2020-07-01"
end="2020-07-31"
days_of_week="MTWHF"/>
<DateRange
start="2020-09-01"
end="2020-09-30"/>
</BookingDates>
<BookingWindow
min="7"
max="330"/>
<CheckinDates>
<DateRange
start="2020-10-01"
end="2020-10-31"
days_of_week="FSU"/>
</CheckinDates>
<CheckoutDates>
<DateRange
start="2020-10-08"
end="2020-11-07"
days_of_week="FSU"/>
</CheckoutDates>
<Devices>
<Device
type="mobile"/>
<Device
type="tablet"/>
</Devices>
<Discount
percentage="20"
applied_nights="2"/>
<LengthOfStay
min="2"
max="14"/>
<RatePlans>
<RatePlan
id="234"/>
<RatePlan
id="567"/>
</RatePlans>
<RoomTypes>
<RoomType
id="123"/>
<RoomType
id="456"/>
</RoomTypes>
<Stacking
type="base"/>
<UserCountries>
<Country
code="US"/>
<Country
code="GB"/>
</UserCountries>
</Promotion>
</HotelPromotions>
</Promotions>
Inventory condition
The following example shows how to create a discount if there is excess inventory close to the arrival date:
<?xml
version="1.0"
encoding="UTF-8"?>
<Promotions
partner="account_xyz"
id="123_abc"
timestamp="2020-05-18T16:20:00-04:00">
<HotelPromotions
hotel_id="Property_1">
<Promotion
id="1">
<BookingWindow
max="7"/>
<Discount
percentage="10"/>
<InventoryCount
min="3"/>
</Promotion>
</HotelPromotions>
</Promotions>
Delete one promotion
The following example shows how to delete one promotion for a property:
<?xml
version="1.0"
encoding="UTF-8"?>
<Promotions
partner="account_xyz"
id="123_abc"
timestamp="2020-05-18T16:20:00-04:00">
<HotelPromotions
hotel_id="Property_1">
<Promotion
id="1"
action="delete"/>
</HotelPromotions>
</Promotions>
Delete all promotions
The following example shows how to delete all promotions for a property:
<?xml
version="1.0"
encoding="UTF-8"?>
<Promotions
partner="account_xyz"
id="123_abc"
timestamp="2020-05-18T16:20:00-04:00">
<HotelPromotions
hotel_id="Property_1"
action="overlay"/>
</Promotions>
Overlay all promotions
The following example shows how to overlay <HotelPromotions>
for a property
with one or more new promotions. When action="overlay"
, all stored
promotions are deleted prior to storing the promotions specified in the
current message:
<?xml
version="1.0"
encoding="UTF-8"?>
<Promotions
partner="account_xyz"
id="123_abc"
timestamp="2020-05-18T16:20:00-04:00">
<HotelPromotions
hotel_id="Property_1"
action="overlay">
<Promotion
id="1">
<BookingDates>
<DateRange
start="2020-09-01"
end="2020-09-30"/>
</BookingDates>
<Discount
percentage="10"/>
<RoomTypes>
<RoomType
id="123"/>
<RoomType
id="456"/>
</RoomTypes>
<RatePlans>
<RatePlan
id="234"/>
<RatePlan
id="567"/>
</RatePlans>
<Stacking
type="base"/>
</Promotion>
</HotelPromotions>
</Promotions>
3 Different Stacking Types
The following example shows a case where three different promotions would be
applied ( base
, second
, any
). Note that the none
promotion wouldn't be
applied since the other promotions provide a better discount. If the original
price was $100, the discounted price would be $72.90.
<?xml
version="1.0"
encoding="UTF-8"?>
<Promotions
partner="account_xyz"
id="123_abc"
timestamp="2020-05-18T16:20:00-04:00">
<HotelPromotions
hotel_id="Property_1">
<Promotion
id="1">
<Discount
percentage="10"/>
<Stacking
type="base"/>
</Promotion>
<Promotion
id="2">
<Discount
percentage="10"/>
<Stacking
type="second"/>
</Promotion>
<Promotion
id="3">
<Discount
percentage="10"/>
<Stacking
type="any"/>
</Promotion>
<Promotion
id="4">
<Discount
percentage="25"/>
<Stacking
type="none"/>
</Promotion>
</HotelPromotions>
</Promotions>
None Stacking Type
The following example shows a case where the none
promotion is used because
the combination of other promotions provides a smaller discount. If the
original price was $100, the discounted price would be $75.
<?xml
version="1.0"
encoding="UTF-8"?>
<Promotions
partner="account_xyz"
id="123_abc"
timestamp="2020-05-18T16:20:00-04:00">
<HotelPromotions
hotel_id="Property_1">
<Promotion
id="1">
<Discount
percentage="10"/>
<Stacking
type="base"/>
</Promotion>
<Promotion
id="2">
<Discount
percentage="10"/>
<Stacking
type="any"/>
</Promotion>
<Promotion
id="3">
<Discount
percentage="25"/>
<Stacking
type="none"/>
</Promotion>
</HotelPromotions>
</Promotions>
Booking Window Duration Bounds
The following example shows a case where the BookingWindow
element is used with its start and end bounds defined as an ISO 8601 Duration
type. This booking window restriction requires booking on or before 18:00
the day prior to arrival, and on or after 12:00 on the 2nd day before
arrival.
<?xml
version="1.0"
encoding="UTF-8"?>
<Promotions
partner="account_xyz"
id="123_abc"
timestamp="2020-05-18T16:20:00-04:00">
<HotelPromotions
hotel_id="Property_1">
<Promotion
id="1">
<BookingWindow
min="P1DT6H"
max="P2DT12H"/>
<Discount
percentage="20"/>
</Promotion>
</HotelPromotions>
</Promotions>
Booking Dates DateTime Bounds
The following example shows a case where the BookingDates
element is used with start
and end
attributes as DateTime
types. This booking date restriction requires booking to occur
between 06:30 on 2020-07-01 and 18:45 on 2020-07-02.
<?xml
version="1.0"
encoding="UTF-8"?>
<Promotions
partner="account_xyz"
id="123_abc"
timestamp="2020-05-18T16:20:00-04:00">
<HotelPromotions
hotel_id="Property_1">
<Promotion
id="1">
<BookingDates>
<DateRange
start="2020-07-01T06:30:00"
end="2020-07-02T18:45:00"/>
</BookingDates>
<Discount
percentage="20"/>
</Promotion>
</HotelPromotions>
</Promotions>
Yearless date ranges
The following example shows a case where the CheckInDates
element contains DateRanges
that have start
and end
fields without years. In this example, the promotion applies
to check-in dates between 12/29 and 1/2, regardless of the year. Yearless
date ranges that cross the new-year boundary are invalid, so the DateRange
is expressed as two adjacent date ranges.
<?xml
version="1.0"
encoding="UTF-8"?>
<Promotions
partner="account_xyz"
id="123_abc"
timestamp="2020-05-18T16:20:00-04:00">
<HotelPromotions
hotel_id="Property_1">
<Promotion
id="1">
<CheckInDates>
<DateRange
start="12-29"
end="12-31"/>
<DateRange
start="01-01"
end="01-02"/>
</CheckInDates>
<Discount
percentage="20"/>
</Promotion>
</HotelPromotions>
</Promotions>
FreeNights discount
The following example discounts two nights 50% for each four nights stayed for the specified range of booking dates. For a ten night itinerary, a total of four nights would be discounted 50%.
<?xml
version="1.0"
encoding="UTF-8"?>
<Promotions
partner="account_xyz"
id="123_abc"
timestamp="2020-05-18T16:20:00-04:00">
<HotelPromotions
hotel_id="Property_1">
<Promotion
id="1">
<BookingDates>
<DateRange
start="2022-01-01"
end="2022-05-31"/>
</BookingDates>
<Discount>
<FreeNights
stay_nights="4"
discount_nights="2"
discount_percentage="50"
night_selection="cheapest"
repeats="true"/>
</Discount>
</Promotion>
</HotelPromotions>
</Promotions>
The next example discounts one night 50% for each three nights stayed for the specified ranges of stay dates. Only the overlapping nights of stay count towards qualifying for the discount. For the following itinerary with check-in on 2022-01-01 and check-out on 2022-01-07, the qualified nights of stay and discounts are applied as follows.
- 2022-01-01 (stay)
- 2022-01-02 (stay)
- 2022-01-03
- 2022-01-04 (discounted)
- 2022-01-05 (stay)
- 2022-01-06 (stay)
<?xml
version="1.0"
encoding="UTF-8"?>
<Promotions
partner="account_xyz"
id="123_abc"
timestamp="2020-05-18T16:20:00-04:00">
<HotelPromotions
hotel_id="Property_1">
<Promotion
id="1">
<StayDates
application="overlap">
<DateRange
start="2022-01-01"
end="2022-01-02"/>
<DateRange
start="2022-01-04"
end="2022-01-06"/>
</StayDates>
<Discount>
<FreeNights
stay_nights="3"
discount_nights="1"
discount_percentage="50"
night_selection="last"
repeats="true"/>
</Discount>
</Promotion>
</HotelPromotions>
</Promotions>
Ranked Selection
The following example offers two discounts, one for 20% off and another for 15% off. During evaluation, only the 15% discount is applied because it has a lower rank.
<?xml
version="1.0"
encoding="UTF-8"?>
<Promotions
partner="account_xyz"
id="123_abc"
timestamp="2020-05-18T16:20:00-04:00">
<HotelPromotions
hotel_id="Property_1">
<Promotion
id="1">
<Discount
percentage="15"
rank="25"/>
</Promotion>
<Promotion
id="2">
<Discount
percentage="20"
rank="50"/>
</Promotion>
</HotelPromotions>
</Promotions>
BestDailyDiscount
The following example discounts a two night stay by applying BestDailyDiscount
stacked with a Discount
.
<?xml
version="1.0"
encoding="UTF-8"?>
<Promotions
partner="account_xyz"
id="123_abc"
timestamp="2020-05-18T16:20:00-04:00">
<HotelPromotions
hotel_id="HotelID"
action="overlay">
<Promotion
id="general">
<BestDailyDiscount
fixed_amount="20"/>
</Promotion>
<Promotion
id="may">
<BestDailyDiscount
fixed_amount="50"/>
<StayDates
application="overlap">
<DateRange
start="2023-05-01"
end="2023-05-31"/>
</StayDates>
</Promotion>
<Promotion
id="fiesta">
<Discount
fixed_amount_per_night="5"/>
<Stacking
type="any"/>
</Promotion>
</HotelPromotions>
</Promotions>
Consider a two night stay from April 30, 2023 to May 2, 2023 For calculation, the combination of best daily discounts that yields the deepest discount is found first.
For the first night, the "general" promotion is the only eligible amount with a fixed discount of 20.
For the second night, the "may" promotion offers a deeper discount than the "general" discount. So, when "may" is selected the fixed discount amount is 50.
Then for the stay, the "fiesta" promotion discounts to 5 per night, or
10 total. It can be stacked with the combination of best daily discounts
because "fiesta" has stacking type set to any
. If it were set
to base
, then only the combination of best daily discounts or
the "fiesta" discount is applied. See description of Stacking
for more information.
`Overall, the price of the stay receives a 20 + 50 + 10 = 80 fixed amount discount.
Responses
Syntax
The PromotionsResponse
message uses the following syntax:
<?xml
version="1.0"
encoding="UTF-8"?>
<PromotionsResponse
timestamp=" timestamp
"
id=" message_ID
"
partner=" partner_key
">
<!--
Either
Success
or
Issues
are
populated.
-->
<Success/>
<Issues>
<Issue
code=" issue_code
"
status=" issue_type
">
issue_description
</Issue>
</Issues>
</PromotionsResponse>
Elements and Attributes
The PromotionsResponse
message has the following elements and attributes:
Element / @Attribute | Occurrences | Type | Description |
---|---|---|---|
PromotionsResponse
|
1 | Complex element | The root element indicating the success or issues for a received Promotions request message. |
PromotionsResponse / @timestamp
|
1 | DateTime | The creation date and time of this message. |
PromotionsResponse / @id
|
1 | string | The unique identifier from the associated Promotions message. |
PromotionsResponse / @partner
|
1 | string | The partner account for this message. |
PromotionsResponse / Success
|
0..1 | Success | Indicates that the Promotions message was processed successfully
without warnings, errors, or failures. Either |
PromotionsResponse / Issues
|
0..1 | Issues | A container for one or more issues encountered while processing the
Promotions message. Either |
PromotionsResponse / Issues / Issue
|
1..n | Issue | The description of a warning, error, or failure encountered while processing the Promotions message. Details on these issues can be found in Feed Status Error Messages . |
PromotionsResponse / Issues / Issue / @code
|
1 | integer | The identifier for the issue. |
PromotionsResponse / Issues / Issue / @status
|
1 | enum | The type of issue encountered. Valid values are |
Examples
Success
The following is a response to a successfully processed Promotions message.
<?xml
version="1.0"
encoding="UTF-8"?>
<PromotionsResponse
timestamp="2020-05-18T16:20:00-04:00"
id="12345678"
partner="partner_key">
<Success/>
</PromotionsResponse>
Issues
The following is a response to a Promotions message not processed due to errors.
<?xml
version="1.0"
encoding="UTF-8"?>
<PromotionsResponse
timestamp="2020-05-18T16:20:00-04:00"
id="12345678"
partner="partner_key">
<Issues>
<Issue
code="1001"
status="error">Example</Issue>
</Issues>
</PromotionsResponse>