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
- Lines with
recoverablefalse are dropped entirely. -
Gross-up: when
gross_upis given andactual_occupancyis belowtarget_occupancy, every line markedvariableis multiplied bytarget ÷ actual. At or above the target there is no gross-up. -
The tenant's share of controllable and of uncontrollable lines is each
total × pro_rata_share × occupancy fraction, rounded to the cent. -
The cap applies to the controllable share only. The limit depends on
cap.method:compounding_from_baseisreference × (1 + rate)^years_elapsed,simple_from_baseisreference × (1 + rate × years_elapsed), andyear_over_yearisreference × (1 + rate), where the reference is the prior year's capped amount. The capped amount ismin(controllable share, limit). Uncontrollable lines are never capped. -
Admin fee:
admin_fee.ratetimes the tenant's share of lines withadmin_fee_applies, after gross-up. The fee on uncontrollable lines is never capped. On controllable lines,appliedsets whether the fee is computed on the share before the cap or on the capped amount.cappedsets whether the fee counts toward the cap limit or is added outside it. -
Structure:
nethas no deduction.base_yeardeductsbase_year_expenses × share × occupancy fraction.expense_stopdeductsstop_amount × share × occupancy fraction. The cap is applied before this deduction, and the result carries a warning saying so. -
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 flaggedcontrollable,recoverable,variableandadmin_fee_applies. -
gross_up: actual and target occupancy for grossing up variable lines. -
structure:net,base_yearwithbase_year_expenses, orexpense_stopwithstop_amount. -
cap:method,rate,reference_amountand, for the from-base methods,years_elapsed. -
admin_fee: feerate, and whether it isappliedbefore or after the cap andcapped. -
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 | Value |
|---|---|
recoverable_expenses | 700,000 |
grossed_up_expenses | 737,500 |
tenant_share_controllable | 38,750 |
tenant_share_uncontrollable | 35,000 |
cap_limit | 34,728.75 |
cap_reduction | 4,021.25 |
admin_fee | 0 |
occupancy_fraction | 1 |
structure_deduction | 0 |
tenant_charge | 69,728.75 |
estimates_paid | 60,000 |
balance_due | 9,728.75 |
Audit trail
Every intermediate value, in order, with the formula that produced it. Formula calc.cam_reconciliation@2.
| Step | Value | Formula |
|---|---|---|
| Recoverable expenses | $700,000.00 | excludes roof replacement |
| Gross-up factor (variable expenses) | 1.1875 | 95% 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.75 | min(tenant controllable, cap limit) |
| Tenant CAM charge | $69,728.75 | max(0, $34,728.75 + $35,000.00 − $0.00) |
| Balance due | $9,728.75 | $69,728.75 − $60,000.00 estimates paid |
| Rounding | each 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_reconciliationonhttps://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}}'