1
Call POST /markets/metrics/future/pacing to get the booking fill rate for each upcoming date. High fill rate means high demand — price up. Low fill rate means low demand — price down or reduce minimum nights to capture bookings.
High Demand
Normal
Low Demand
Python
import requests
response = requests.post(
"https://api.airroi.com/markets/metrics/future/pacing",
headers={
"X-API-KEY": "YOUR_API_KEY",
"Content-Type": "application/json",
},
json={
"market": {
"country": "us",
"region": "tennessee",
"locality": "nashville",
},
},
)
pacing = response.json()
print(f"{'Date':<12} {'Booked':>7} {'Avail':>7} {'Fill Rate':>10} {'Signal':<10}")
print("-" * 50)
for day in pacing[:14]: # Next 14 days
fill = day["fill_rate"]
signal = "HIGH" if fill > 0.7 else "LOW" if fill < 0.3 else "NORMAL"
print(
f"{day['date']:<12} "
f"{day['booked_count']:>6} "
f"{day['available_count']:>6} "
f"{fill:>9.0%} "
f"{signal:<10}"
)
# Identify high-demand dates for price increases
high_demand = [d for d in pacing if d["fill_rate"] > 0.7]
low_demand = [d for d in pacing if d["fill_rate"] < 0.3]
print(f"\nHigh-demand dates (fill > 70%): {len(high_demand)}")
print(f"Low-demand dates (fill < 30%): {len(low_demand)}")2
Call GET /listings/future/rates for 3-5 nearby competitor listings to understand their pricing and availability. Calculate the average competitor rate per date as a market benchmark.
Python
# Pull future rates for 3-5 nearby competitor listings
competitor_ids = ["48291037", "51038274", "49172836"]
competitor_rates = {}
for comp_id in competitor_ids:
response = requests.get(
"https://api.airroi.com/listings/future/rates",
headers={"X-API-KEY": "YOUR_API_KEY"},
params={"id": comp_id, "currency": "usd"},
)
data = response.json()
competitor_rates[comp_id] = data.get("rates", [])
# Calculate average competitor rate per date
from collections import defaultdict
date_rates = defaultdict(list)
for comp_id, rates in competitor_rates.items():
for rate_data in rates:
if rate_data["available"]:
date_rates[rate_data["date"]].append(rate_data["rate"])
print(f"{'Date':<12} {'Avg Comp Rate':>14} {'# Comps':>8}")
print("-" * 38)
for date in sorted(date_rates.keys())[:14]:
rates = date_rates[date]
avg = sum(rates) / len(rates)
print(f"{date:<12} ${avg:>12,.0f} {len(rates):>7}")3
Apply a demand multiplier to your base rate based on the fill rate for each date. The formula: demand_multiplier = 0.8 + (fill_rate * 0.6). This ranges from 0.8x at 0% fill to 1.4x at 100% fill.
Demand Multiplier Examples:
0% fill rate: 0.8 + (0.0 x 0.6) = 0.80x ($200 base = $160)
50% fill rate: 0.8 + (0.5 x 0.6) = 1.10x ($200 base = $220)
70% fill rate: 0.8 + (0.7 x 0.6) = 1.22x ($200 base = $244)
100% fill rate: 0.8 + (1.0 x 0.6) = 1.40x ($200 base = $280)
Python
# Calculate demand-adjusted rates
your_base_rate = 200 # Your current nightly rate
print(f"Base Rate: ${your_base_rate}")
print(f"\n{'Date':<12} {'Fill':>6} {'Multiplier':>11} {'Adj Rate':>9} {'Signal':<8}")
print("-" * 52)
pricing_recommendations = []
for day in pacing[:14]:
fill = day["fill_rate"]
# Demand multiplier: ranges from 0.8x (0% fill) to 1.4x (100% fill)
demand_multiplier = 0.8 + (fill * 0.6)
adjusted_rate = round(your_base_rate * demand_multiplier)
signal = "UP" if fill > 0.7 else "DOWN" if fill < 0.3 else "HOLD"
pricing_recommendations.append({
"date": day["date"],
"fill_rate": fill,
"multiplier": demand_multiplier,
"rate": adjusted_rate,
"signal": signal,
})
print(
f"{day['date']:<12} "
f"{fill:>5.0%} "
f"{demand_multiplier:>10.2f}x "
f"${adjusted_rate:>7} "
f"{signal:<8}"
)
# Summary
avg_adjusted = sum(r["rate"] for r in pricing_recommendations) / len(pricing_recommendations)
print(f"\nAverage adjusted rate: ${avg_adjusted:.0f}")
print(f"Rate range: ${min(r['rate'] for r in pricing_recommendations)} "
f"- ${max(r['rate'] for r in pricing_recommendations)}")4
Pull historical market data via POST /markets/metrics/all with 12 months of data. Calculate average occupancy per month. Months above the annual average get a seasonal boost: 1.0 + ((month_occ - annual_avg) / annual_avg * 0.5). The final rate combines demand and seasonal adjustments.
Python
# Pull historical market data for seasonal patterns
response = requests.post(
"https://api.airroi.com/markets/metrics/all",
headers={
"X-API-KEY": "YOUR_API_KEY",
"Content-Type": "application/json",
},
json={
"market": {
"country": "us",
"region": "tennessee",
"locality": "nashville",
},
"num_months": 12,
"currency": "usd",
},
)
monthly_data = response.json()
occupancies = [m["occupancy"]["avg"] for m in monthly_data]
annual_avg_occ = sum(occupancies) / len(occupancies)
print(f"Annual Average Occupancy: {annual_avg_occ:.0%}")
print(f"\n{'Month':<10} {'Occ':>6} {'vs Avg':>8} {'Seasonal Boost':>15}")
print("-" * 42)
seasonal_multipliers = {}
for m in monthly_data:
month_name = m["date"][:7] # YYYY-MM
month_occ = m["occupancy"]["avg"]
diff = (month_occ - annual_avg_occ) / annual_avg_occ
# Seasonal boost: amplify the deviation by 0.5x
seasonal_boost = 1.0 + (diff * 0.5)
seasonal_multipliers[month_name] = seasonal_boost
print(
f"{month_name:<10} "
f"{month_occ:>5.0%} "
f"{diff:>+7.0%} "
f"{seasonal_boost:>14.2f}x"
)
# Apply seasonal boost to demand-adjusted rate
print(f"\nFinal Pricing with Seasonal Adjustment:")
print(f"{'Date':<12} {'Demand Adj':>11} {'Season':>8} {'Final Rate':>11}")
print("-" * 46)
for rec in pricing_recommendations[:7]:
date_month = rec["date"][:7]
season = seasonal_multipliers.get(date_month, 1.0)
final_rate = round(rec["rate"] * season)
print(
f"{rec['date']:<12} "
f"${rec['rate']:>9} "
f"{season:>7.2f}x "
f"${final_rate:>9}"
)5
Use the market's average length of stay data from POST /markets/metrics/all to set smart minimum night requirements. For high-demand dates (fill rate > 70%), set higher minimums to capture premium longer stays. For low-demand dates, drop to 1-2 nights to attract last-minute bookings.
| Demand Level | Fill Rate | Min Nights | Strategy |
|---|---|---|---|
| High | > 70% | 3+ | Capture premium longer stays |
| Normal | 30-70% | 2-3 | Market average LOS |
| Low | < 30% | 1 | Accept any bookings |
Python
# Get market length-of-stay data for min-night rules
# The /markets/metrics/all response includes length_of_stay
market_los = {}
for m in monthly_data:
month = m["date"][:7]
market_los[month] = m.get("length_of_stay", {}).get("avg", 3.0)
avg_los = sum(market_los.values()) / len(market_los)
print(f"Market Average Length of Stay: {avg_los:.1f} nights")
print(f"\n{'Date':<12} {'Fill':>6} {'Min Nights':>11} {'Reason':<30}")
print("-" * 62)
min_night_rules = []
for rec in pricing_recommendations[:14]:
fill = rec["fill_rate"]
date_month = rec["date"][:7]
los = market_los.get(date_month, avg_los)
if fill > 0.7:
# High demand: set min nights = market avg or higher
min_nights = max(int(round(los)), 3)
reason = "High demand - capture longer stays"
elif fill < 0.3:
# Low demand: reduce min nights for last-minute bookings
min_nights = 1
reason = "Low demand - accept short stays"
else:
# Normal demand: use market average
min_nights = max(int(round(los)), 2)
reason = "Normal demand - market average"
min_night_rules.append({
"date": rec["date"],
"min_nights": min_nights,
"reason": reason,
})
print(
f"{rec['date']:<12} "
f"{fill:>5.0%} "
f"{min_nights:>10} "
f"{reason:<30}"
)6
Combine all steps into a single script that runs daily. It pulls pacing data, calculates demand-adjusted rates with seasonal multipliers, sets min-night rules, and outputs a CSV of date/rate/min_nights recommendations. Schedule it via cron or use a service like Zapier to trigger it automatically.
Cron Schedule Example:
0 6 * * * python optimize_pricing.py
Runs every day at 6 AM, generating fresh pricing for the next 30-90 days.
Python
import requests
import csv
from datetime import datetime
def generate_pricing_recommendations(api_key, market, base_rate):
"""
Daily pricing optimization workflow.
Run via cron: 0 6 * * * python optimize_pricing.py
"""
headers = {
"X-API-KEY": api_key,
"Content-Type": "application/json",
}
market_body = {"market": market}
# 1. Pull demand signals (future pacing)
pacing_resp = requests.post(
"https://api.airroi.com/markets/metrics/future/pacing",
headers=headers,
json=market_body,
)
pacing = pacing_resp.json()
# 2. Pull historical seasonality
hist_resp = requests.post(
"https://api.airroi.com/markets/metrics/all",
headers=headers,
json={**market_body, "num_months": 12, "currency": "usd"},
)
monthly = hist_resp.json()
# Calculate seasonal multipliers
occs = [m["occupancy"]["avg"] for m in monthly]
annual_avg = sum(occs) / len(occs)
seasonal = {}
for m in monthly:
month = m["date"][:7]
diff = (m["occupancy"]["avg"] - annual_avg) / annual_avg
seasonal[month] = 1.0 + (diff * 0.5)
# Calculate LOS data
los_data = {}
for m in monthly:
month = m["date"][:7]
los_data[month] = m.get("length_of_stay", {}).get("avg", 3.0)
avg_los = sum(los_data.values()) / len(los_data)
# 3. Generate recommendations
recommendations = []
for day in pacing:
fill = day["fill_rate"]
date_month = day["date"][:7]
# Demand multiplier
demand_mult = 0.8 + (fill * 0.6)
# Seasonal multiplier
season_mult = seasonal.get(date_month, 1.0)
# Final rate
final_rate = round(base_rate * demand_mult * season_mult)
# Min nights
los = los_data.get(date_month, avg_los)
if fill > 0.7:
min_nights = max(int(round(los)), 3)
elif fill < 0.3:
min_nights = 1
else:
min_nights = max(int(round(los)), 2)
recommendations.append({
"date": day["date"],
"fill_rate": f"{fill:.0%}",
"demand_mult": f"{demand_mult:.2f}",
"season_mult": f"{season_mult:.2f}",
"recommended_rate": final_rate,
"min_nights": min_nights,
})
# 4. Write to CSV
filename = f"pricing_{datetime.now().strftime('%Y%m%d')}.csv"
with open(filename, "w", newline="") as f:
writer = csv.DictWriter(f, fieldnames=recommendations[0].keys())
writer.writeheader()
writer.writerows(recommendations)
print(f"Wrote {len(recommendations)} recommendations to {filename}")
return recommendations
# Run the workflow
recs = generate_pricing_recommendations(
api_key="YOUR_API_KEY",
market={
"country": "us",
"region": "tennessee",
"locality": "nashville",
},
base_rate=200,
)
# Preview first 7 days
print(f"\n{'Date':<12} {'Rate':>6} {'Min Nights':>11}")
print("-" * 32)
for r in recs[:7]:
print(f"{r['date']:<12} ${r['recommended_rate']:>4} {r['min_nights']:>10}")Keep exploring the AirROI API with these related tutorials.
Daily updates are ideal for maximizing revenue. Market conditions, competitor rates, and booking pace change constantly. The automated workflow in this tutorial can be scheduled via cron to run every morning, generating fresh pricing recommendations based on the latest data. At minimum, update pricing weekly and before major events or holidays.
Fill rate is the percentage of available listings in a market that are booked for a specific date. A fill rate of 80% means 80% of STR properties are already booked. High fill rate (>70%) indicates strong demand where you can raise prices. Low fill rate (<30%) indicates weak demand where you may need to lower prices or reduce minimum nights to attract bookings.
No. Use competitor rates as a reference point, not a target. Your property may be worth more or less depending on location, amenities, reviews, and quality. The demand-adjusted pricing model in this tutorial uses market-wide demand signals (fill rate) to set pricing relative to your own base rate, which accounts for your property's unique value.
Start with your trailing twelve month ADR from actual bookings. If you are a new listing, use the P50 (median) ADR from the /calculator/estimate endpoint for a similar property at your location. Adjust up or down based on your amenities, reviews, and quality relative to comparables.
Yes. The automated workflow can be extended to loop through multiple properties, each with its own base rate. All properties in the same market share the same pacing data and seasonal multipliers, so you only need one pacing API call per market. Individual property adjustments come from the base rate parameter.
Minimum night requirements balance occupancy and revenue. During high-demand periods, longer minimums (3-5 nights) reduce turnover costs (cleaning, laundry) and capture premium guests willing to stay longer. During low-demand periods, dropping to 1-night minimums maximizes occupancy by capturing last-minute and short-stay bookings that would otherwise go to hotels.
Stay ahead of the curve
Join our newsletter for exclusive insights and updates. No spam ever.