CAM reconciliation calculator

CAM reconciliation calculator: tenant share of operating expenses with gross-up, controllable caps, admin fees, base year or expense stop, and balance due.

What it computes

A CAM reconciliation compares what a tenant owes for common area maintenance and other operating expenses in a year with the estimates it paid. The calculator takes the building's actual expense lines and the lease terms and returns the tenant's charge and the balance due. The lease terms covered are the pro rata share, exclusions, occupancy gross-up, a cap on controllable expenses, an administrative fee, and a net, base-year or expense-stop structure. A positive balance is owed by the tenant. A negative balance is a credit or refund owed by the landlord.

Method and conventions

  1. Lines with recoverable false are dropped entirely.
  2. Gross-up: when gross_up is given and actual_occupancy is below target_occupancy, every line marked variable is multiplied by target ÷ actual. At or above the target there is no gross-up.
  3. The tenant's share of controllable and of uncontrollable lines is each total × pro_rata_share × occupancy fraction, rounded to the cent.
  4. The cap applies to the controllable share only. The limit depends on cap.method: compounding_from_base is reference × (1 + rate)^years_elapsed, simple_from_base is reference × (1 + rate × years_elapsed), and year_over_year is reference × (1 + rate), where the reference is the prior year's capped amount. The capped amount is min(controllable share, limit). Uncontrollable lines are never capped.
  5. Admin fee: admin_fee.rate times the tenant's share of lines with admin_fee_applies, after gross-up. The fee on uncontrollable lines is never capped. On controllable lines, applied sets whether the fee is computed on the share before the cap or on the capped amount. capped sets whether the fee counts toward the cap limit or is added outside it.
  6. Structure: net has no deduction. base_year deducts base_year_expenses × share × occupancy fraction. expense_stop deducts stop_amount × share × occupancy fraction. The cap is applied before this deduction, and the result carries a warning saying so.
  7. Tenant charge = max(0, capped controllable + fees + uncontrollable − deduction). Balance due = tenant charge − estimates_paid.

Each tenant share, fee, cap limit and deduction is rounded to the cent, half away from zero, before it is combined. For a partial year, the occupancy fraction is occupied days ÷ period days, both ends inclusive. The period defaults to the calendar year of year, and setting period_start_date and period_end_date reconciles a lease year instead. The tenant's share, the cap limit and the base-year or stop deduction are all scaled by that fraction.

Lease language is where most disputes start. The terms "cumulative" and "non-cumulative" are used inconsistently, so FactLot names cap methods by what they compute and the input must pick one. Leases also differ on the gross-up target (often 95% or 100%), on whether a base year is grossed up (FactLot expects base_year_expenses already grossed up), on whether the cap or the base-year deduction comes first, and on which lines carry an admin fee. FactLot warns when a fee base includes taxes, insurance or utilities, and when a line named like a management or admin fee would itself carry a fee.

Inputs that matter

  • pro_rata_share: the tenant's share as a decimal, for example 12,000 ÷ 150,000 = 0.08.
  • expenses: building-level lines, each flagged controllable, recoverable, variable and admin_fee_applies.
  • gross_up: actual and target occupancy for grossing up variable lines.
  • structure: net, base_year with base_year_expenses, or expense_stop with stop_amount.
  • cap: method, rate, reference_amount and, for the from-base methods, years_elapsed.
  • admin_fee: fee rate, and whether it is applied before or after the cap and capped.
  • occupancy: move-in, move-out and period dates for a partial year.
  • estimates_paid: total estimated payments for the year, not a monthly amount.

Limits

  • It does not read the lease. Classifying lines as controllable, variable or excluded, and choosing the cap method, are the user's inputs.
  • One tenant and one pro rata share for every line. Separate pools with different shares or denominators are not modeled here.
  • A line flagged variable is grossed up in full. A line that is partly fixed has to be entered as two lines.
  • Capital items are either recoverable or excluded; this calculator does not amortize them.
  • Part years are prorated by days only, not by months. The cap reference is taken as a full-year amount.
  • The tenant charge cannot go below zero, so a base year or stop above current expenses gives a zero charge, not a negative one.
  • There are no cap floors, no minimum increases, no audit adjustments and no interest on late balances.

Worked example

Inputs from FactLot's shared test case "gross-up, exclusion, compounding_from_base cap", which the TypeScript and Python libraries must both reproduce:

{
  "year": 2026,
  "pro_rata_share": 0.1,
  "expenses": [
    {
      "category": "real estate taxes",
      "amount": 300000,
      "controllable": false
    },
    {
      "category": "insurance",
      "amount": 50000,
      "controllable": false
    },
    {
      "category": "janitorial",
      "amount": 200000,
      "variable": true
    },
    {
      "category": "repairs & maintenance",
      "amount": 150000
    },
    {
      "category": "roof replacement",
      "amount": 400000,
      "recoverable": false
    }
  ],
  "gross_up": {
    "actual_occupancy": 0.8,
    "target_occupancy": 0.95
  },
  "estimates_paid": 60000,
  "cap": {
    "method": "compounding_from_base",
    "rate": 0.05,
    "reference_amount": 30000,
    "years_elapsed": 3
  }
}

Result

Result values
ResultValue
recoverable_expenses700,000
grossed_up_expenses737,500
tenant_share_controllable38,750
tenant_share_uncontrollable35,000
cap_limit34,728.75
cap_reduction4,021.25
admin_fee0
occupancy_fraction1
structure_deduction0
tenant_charge69,728.75
estimates_paid60,000
balance_due9,728.75

Audit trail

Every intermediate value, in order, with the formula that produced it. Formula calc.cam_reconciliation@2.

Audit trail
StepValueFormula
Recoverable expenses$700,000.00excludes roof replacement
Gross-up factor (variable expenses)1.187595% target ÷ 80% actual
Recoverable expenses after gross-up$737,500.00
Tenant share of controllable$38,750.00$387,500.00 × 0.1
Tenant share of uncontrollable$35,000.00$350,000.00 × 0.1
Cap limit (compounding_from_base)$34,728.75$30,000.00 × (1 + 0.05)^3
Controllable after cap$34,728.75min(tenant controllable, cap limit)
Tenant CAM charge$69,728.75max(0, $34,728.75 + $35,000.00 − $0.00)
Balance due$9,728.75$69,728.75 − $60,000.00 estimates paid
Roundingeach tenant share, fee, cap limit, and deduction is rounded to the cent half away from zero before it is combined

Check it in Excel

The retail-cam-and-percentage-rent.xlsx workbook recomputes this calculator with live Excel formulas beside FactLot's numbers and a difference column. Its inputs are synthetic; the reconciliation guide explains each sheet.

Use it from an agent or your code

  • MCP: tool calc_cam_reconciliation on https://api.factlot.com/mcp (connect a client).
  • Python: factlot.run_tool("calc_cam_reconciliation", input) runs the same calculation offline (Python SDK).
  • Input schema: every field is described in tools.json.
curl -s https://api.factlot.com/v1/calc/cam_reconciliation \
  -H 'content-type: application/json' \
  -d '{"year":2026,"pro_rata_share":0.1,"expenses":[{"category":"real estate taxes","amount":300000,"controllable":false},{"category":"insurance","amount":50000,"controllable":false},{"category":"janitorial","amount":200000,"variable":true},{"category":"repairs & maintenance","amount":150000},{"category":"roof replacement","amount":400000,"recoverable":false}],"gross_up":{"actual_occupancy":0.8,"target_occupancy":0.95},"estimates_paid":60000,"cap":{"method":"compounding_from_base","rate":0.05,"reference_amount":30000,"years_elapsed":3}}'