When a rental property is damaged by fire, flood, or a major system failure, two insurance questions must be answered quickly: what did the owner lose in rental income during the repair period, and was the rental income coverage set at the right level to begin with? Both questions require the same underlying data - a defensible estimate of market rent for the specific property at the time of loss. Getting this right matters because loss-of-rent claims on multifamily properties routinely run $15,000 to $80,000, and the market rent figure anchors the entire calculation.
This post covers both the claims-side workflow (loss-of-rent ACV calculation) and the underwriting-side workflow (coverage adequacy review), and shows exactly how to build both using the RentComp API alongside HUD Fair Market Rent data. For context on DSCR lending workflows that use similar data, see our post on DSCR loan underwriting with rental income APIs. For HUD FMR integration specifics, see HUD Fair Market Rent API integration.
The Two Insurance Use Cases
1. Loss-of-Rent Claims (Actual Cash Value of Lost Income)
Loss-of-rent coverage (also called "fair rental value" coverage) pays the property owner for rental income they cannot collect while the property is uninhabitable. The claim calculation is straightforward in theory: market rent per month times the number of months the property is uninhabitable. In practice, disputes arise when the adjuster and the claimant disagree on what "market rent" was at the time of loss.
The adjuster's default approach - pull up Zillow or Rentometer and eyeball a number - creates several problems. The data is stale (Zillow rental estimates often lag the market by 6-12 months). It is not address-specific (Zillow estimates for a ZIP code, not for a specific unit at a specific address with specific specs). And it produces no audit trail - the adjuster cannot explain exactly which comparable listings informed the number if the claim is disputed.
2. Coverage Adequacy Review at Renewal
At policy renewal, underwriters should verify that the declared rental income on the policy schedule matches current market rates. If a landlord declared $1,400/month when they wrote the policy three years ago and market rent has risen to $1,750/month, the policy is underinsured. In a total loss scenario, the insurer pays out on $1,400/month when the actual economic loss is $1,750/month - and the policyholder has a legitimate grievance.
For a carrier with 50,000 rental properties in their portfolio, manual verification is impossible. Automated batch processing using a rental comp API makes annual coverage adequacy reviews feasible at scale.
Why Current Methods Fail
The standard adjuster workflow is: open Zillow, type in the address, screenshot the "Zestimate" rent estimate, attach it to the claim file. This approach fails in four specific ways:
- Staleness: Zillow's rent estimates are model-based and update slowly. In a market that moved 8% in 12 months, the Zillow figure can be 6-10% stale on the date of loss.
- No comp table: The estimate is a black box. You cannot see which listings it is based on, so you cannot verify it is comparing like to like.
- No bedroom/bath/sqft precision: Zillow estimates for an address, not for a specific unit configuration. A duplex with a 2BR upstairs and a 1BR downstairs gets one estimate that fits neither unit.
- No confidence indicator: You have no idea whether the estimate is based on 20 nearby comps or 2 distantly comparable listings. There is no uncertainty range.
The Four-Data-Point Standard for Defensible Estimates
For a rental income estimate to hold up in a claim dispute or regulatory audit, it should document four data points:
- Median comparable rent - the market_stats.median from the comp query, reflecting current-listed comparable units
- Low comparable rent - the market_stats.p25 (25th percentile), representing the low end of the market for comparable units
- High comparable rent - the market_stats.p75 (75th percentile), the high end
- HUD Fair Market Rent - the FMR for the property's ZIP code and bedroom count, which serves as a regulatory floor anchored to federal methodology
Together, these four numbers tell the full story: here is where the market sits, here is the range, and here is the HUD floor that confirms the estimate is not outlier-driven. When a claim is disputed, this documentation answers every question a mediator or judge will ask.
Python Code: The Insurance Rental Income Report
import requests
import json
from datetime import datetime
RENTCOMP_API_KEY = "your_api_key"
RENTCOMP_BASE = "https://api.rentcompapi.com/v1"
def generate_insurance_rental_report(
address: str,
bedrooms: int,
bathrooms: float,
sqft: int,
loss_date: str,
repair_months: float,
policy_declared_rent: float
) -> dict:
"""
Generate a defensible rental income estimate for insurance purposes.
Returns a structured report with comp data, FMR, and claim calculations.
"""
report = {
"generated_at": datetime.utcnow().isoformat() + "Z",
"address": address,
"unit_specs": {
"bedrooms": bedrooms,
"bathrooms": bathrooms,
"sqft": sqft,
},
"loss_date": loss_date,
"repair_months": repair_months,
"policy_declared_rent": policy_declared_rent,
}
# Step 1: Pull rental comps
comp_resp = requests.post(
f"{RENTCOMP_BASE}/comps",
headers={"Authorization": f"Bearer {RENTCOMP_API_KEY}"},
json={
"address": address,
"bedrooms": bedrooms,
"bathrooms": bathrooms,
"sqft": sqft,
"radius_miles": 1.0,
"max_age_days": 90,
},
timeout=20
)
if not comp_resp.ok:
report["error"] = f"Comp API error: {comp_resp.status_code}"
return report
comp_data = comp_resp.json()
stats = comp_data.get("market_stats", {})
comps = comp_data.get("comps", [])
report["comp_data"] = {
"comp_count": comp_data.get("comp_count", 0),
"confidence_score": comp_data.get("confidence_score", 0),
"market_stats": stats,
"comp_table": [
{
"address": c.get("address"),
"bedrooms": c.get("bedrooms"),
"sqft": c.get("sqft"),
"monthly_rent": c.get("monthly_rent"),
"listed_date": c.get("listed_date"),
"distance_miles": round(c.get("distance_miles", 0), 2),
}
for c in comps[:10] # Include up to 10 comps in the report
],
}
# Step 2: Pull HUD Fair Market Rent
fmr_resp = requests.get(
f"{RENTCOMP_BASE}/fair-market-rent",
headers={"Authorization": f"Bearer {RENTCOMP_API_KEY}"},
params={"address": address, "bedrooms": bedrooms},
timeout=15
)
if fmr_resp.ok:
fmr_data = fmr_resp.json()
report["hud_fmr"] = {
"fmr_amount": fmr_data.get("fmr"),
"fiscal_year": fmr_data.get("fiscal_year"),
"metro_area": fmr_data.get("metro_area"),
"source": "HUD 40th Percentile Fair Market Rent",
}
fmr_amount = fmr_data.get("fmr", 0)
else:
report["hud_fmr"] = {"error": "FMR data unavailable"}
fmr_amount = 0
# Step 3: Calculate defensible market rent
market_median = stats.get("median", 0)
confidence = comp_data.get("confidence_score", 0)
# Use higher of market median or FMR (FMR is the floor)
defensible_market_rent = max(market_median, fmr_amount)
# Flag low-confidence results
if confidence < 60:
report["flag"] = "LOW_CONFIDENCE - human review required"
# Step 4: Calculate claim amounts
lost_rent_claim = defensible_market_rent * repair_months
policy_gap = defensible_market_rent - policy_declared_rent
policy_gap_pct = (policy_gap / policy_declared_rent * 100
if policy_declared_rent else 0)
report["rental_income_estimate"] = {
"defensible_market_rent": round(defensible_market_rent, 2),
"market_median_comp_rent": round(market_median, 2),
"hud_fmr": round(fmr_amount, 2),
"low_comp_rent": round(stats.get("p25", 0), 2),
"high_comp_rent": round(stats.get("p75", 0), 2),
"basis": "Market median" if market_median >= fmr_amount else "HUD FMR floor",
}
report["claim_calculation"] = {
"monthly_loss": round(defensible_market_rent, 2),
"repair_months": repair_months,
"total_loss_of_rent_claim": round(lost_rent_claim, 2),
}
report["coverage_adequacy"] = {
"policy_declared_rent": policy_declared_rent,
"current_market_rent": round(defensible_market_rent, 2),
"gap_dollars": round(policy_gap, 2),
"gap_pct": round(policy_gap_pct, 1),
"status": (
"ADEQUATE" if abs(policy_gap_pct) <= 10
else "UNDERINSURED" if policy_gap > 0
else "OVERINSURED"
),
}
return report
# Example: fire claim at a duplex in Nashville
report = generate_insurance_rental_report(
address="4521 Murphy Rd, Nashville, TN 37209",
bedrooms=2,
bathrooms=1.0,
sqft=950,
loss_date="2026-02-15",
repair_months=4.5,
policy_declared_rent=1350.00
)
print(json.dumps(report, indent=2))
Using Confidence Score in the Claims Workflow
The confidence score is a quality gate in a claims workflow, not a nice-to-have. The rule should be explicit:
- Confidence 75%+: Automated report is sufficient for claims under $25,000. Attach the report to the claim file and proceed.
- Confidence 60-74%: Report is usable but flag for senior adjuster review before finalizing. Consider expanding the radius or relaxing the sqft tolerance.
- Confidence below 60%: Do not rely on the automated estimate alone. Escalate to a licensed appraiser for a market rent opinion letter (MROL). Use the API report as a starting reference, not the final number.
Low-confidence results are concentrated in rural markets (thin listing density) and very niche unit types. A 5BR house in rural Wyoming may have zero comparable listings within 10 miles - in that case, HUD FMR is genuinely the most defensible number you have, and that is fine to say explicitly in the claim documentation.
Batch Processing for Portfolio Reviews
For carriers running annual coverage adequacy reviews, the batch approach is straightforward. Export the policy schedule (address, declared rent, beds/baths/sqft, policy number) and run it through a batch job that fires POST /comps and GET /fair-market-rent for each property. Flag any property where the declared rent differs from current market by more than 15% - those are the policies that need premium adjustment at renewal.
At typical API response times of 200-400ms per call and a 10-concurrent-request limit, a 10,000-property portfolio processes in roughly 20-40 minutes using Python's asyncio + aiohttp. That is a full portfolio review running overnight as a scheduled job.
Integration with Claims Management Systems
For carriers using Guidewire ClaimCenter or Duck Creek Claims, the rental income report integrates cleanly via REST webhook. The workflow:
- Claim created in ClaimCenter for a rental property
- ClaimCenter fires a webhook to your middleware service with claim ID, property address, and unit specs
- Middleware calls the RentComp API, generates the structured report
- Middleware posts the report back to ClaimCenter via the Guidewire REST API, attaching it to the claim as a document with structured data fields
- Adjuster opens the claim and sees the pre-populated market rent estimate with full comp table
This eliminates the manual Zillow step entirely. The adjuster still applies judgment - they can override the estimate if they have specific local knowledge - but they start from a documented, defensible baseline rather than a screenshot.
Regulatory Considerations by State
Documentation requirements for ACV calculations vary by state and are worth knowing before building automated workflows. California requires that market data used in claims calculations be current (within 90 days of loss) - the RentComp API's default 90-day listing window satisfies this. Texas DOI guidelines suggest that rental income estimates should be based on comparable properties within the same submarket, which aligns directly with the radius and similarity filtering the API applies. New York's Department of Financial Services requires that loss-of-rent disputes involving amounts over $50,000 include a licensed appraiser's opinion - the API report is useful documentation for the appraiser but does not replace their sign-off in these cases.
The safest practice is to include the full comp table (not just the median) and the HUD FMR reference in every claim file. This demonstrates methodology transparency and gives any reviewing party the ability to assess the quality of the underlying data.
Ready to Pull Rental Comps via API?
Join the waitlist and get 80% off founding member pricing - for life.
Join the Waitlist