Seasonal Rule Overrides: Date Ranges, Months, and Defaults

Jun Zhou, Founder at AirROI
by Jun ZhouFounder at AirROI
Published: September 4, 2026
Updated: September 5, 2026

A seasonal rule override selects a different custom policy for certain stay dates. It replaces that rule's settings; it does not add another discount on top of the default settings.

Follow the scope that wins

Three possible policies. Exactly one selected scope.

On a calculation date of June 13, 2026, the stay date determines which complete last-minute settings are selected.

1 · Date range
June 15

June 13–15: flat +5%

$210
2 · Recurring month
June 20

June: flat −5% within 7 days

$190
3 · Default
July 1

20-day gradual −20%, 18 days out

$196
USD; $200 post-model starting price. A matching scope replaces settings rather than adding another adjustment.

Think of this as a settings selector, not a stack of discounts. Evaluate the stay date against explicit date ranges first, then recurring months, then the default. Stop at the first match.

A matching scope can legitimately produce zero

Suppose an explicit June 13–15 range selects a last-minute policy with a 7-day window. If you calculate on June 1, those dates are outside that window. The selected rule contributes zero; the engine does not fall back to June's monthly policy to find a nonzero result.

Replace the whole policy

For a lead-time rule, include start_days, adjustment_percent, and adjustment_type in every custom scope. Gap and adjacent scopes must include their own apply_on_weekends. For weekday settings, send all seven weekday values again.

Change you wantUse
Different policy every JuneRecurring june month override
Different policy for one event periodInclusive date_ranges entry
One exact nightly priceTop-level fixed price override, not a rule scope

Use non-overlapping date ranges within a rule. A June 13–15 range includes June 15, so a second range starting June 15 overlaps it.

Configure one rule with three scopes

The JSON below is an addition to this complete Calendar Prices request. Merge fields into one request; do not send a rule fragment by itself.

{
  "location": {
    "latitude": 25.7907,
    "longitude": -80.13
  },
  "currency": "USD",
  "base_price": 200
}

All worked prices use USD and assume a $200 price after model effects, with no other adjustments unless stated. They demonstrate arithmetic, not live forecasts.

{
  "pricing_rules": {
    "last_minute": {
      "mode": "custom",
      "settings": {"start_days": 20, "adjustment_percent": -20, "adjustment_type": "gradual"},
      "overrides": {
        "months": {
          "june": {
            "settings": {"start_days": 7, "adjustment_percent": -5, "adjustment_type": "flat"}
          }
        },
        "date_ranges": [{
          "start_date": "2026-06-13", "end_date": "2026-06-15",
          "settings": {"start_days": 14, "adjustment_percent": 5, "adjustment_type": "flat"}
        }]
      }
    }
  }
}

For a calculation on June 13, June 15 gets the date-range +5% (200 → 210); June 20 gets the June −5% (200 → 190). A date outside either scope uses the top-level settings.

Precedence is date range > recurring month > top-level settings. Month keys are lowercase English names and recur yearly; date ranges are absolute, inclusive, and cannot overlap within one rule. A matching scope replaces the complete settings, with no partial inheritance. The same shape works for all custom pricing and stay rules. Gap-day and adjacent-day scopes must also provide their own apply_on_weekends.

Select exactly one scope

Stay date, calculated June 13, 2026Selected policyStandalone USD result
June 15Explicit June 13–15 date range: flat +5%210
June 20Recurring June policy: flat −5% within 7 days190
July 1Default 20-day gradual −20% policy, 18 days out196

A month matches by the stay date, not the month when you submit the request. Recurring months repeat each year; an absolute date range does not.

Complete replacement, not a partial patch

If you override a last-minute rule, provide its start days, maximum percentage, and adjustment type together. For gap and adjacent-day overrides, also provide apply_on_weekends in the matching scope. Omitted pieces are not inherited from a broader scope.

A valid date-range scope still has its own eligibility rules. For example, if its last-minute window has not opened, it can yield no adjustment; the engine does not fall back to the month rule just because that would have applied.

Do not confuse two kinds of override

A rule override changes a custom rule's settings for a scope. A top-level price override directly applies a percentage to the running price or sets a fixed amount. Fixed prices have their own precedence and bypass owner price limits.

See price overrides and the World Cup example.