AFFO
See the cash a property portfolio really generates: net income of 180,000 plus 95,000 of depreciation, minus 12,000 of sale gains, gives FFO of 263,000, and taking off 30,000 of maintenance capex leaves AFFO of 233,000. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
Worked example
- Net income
- 180,000
- Depreciation amortization
- 95,000
- Gains on sales
- 12,000
- Maintenance capex
- 30,000
- Affo
- 233,000
- Ffo
- 263,000
Adjusted funds from operations is the number REIT analysts actually trust, because net income was never designed for property businesses. Depreciation drags reported earnings down on assets that often appreciate, and one-off gains on sales inflate them.
Why net income is not enough for real estate
Under standard accounting rules, investment property is depreciated over its estimated useful life, which steadily reduces reported net income even when the building is holding or growing its market value. That makes earnings-per-share comparisons between REITs and ordinary companies misleading, and it is the reason the industry converged on funds from operations as the baseline metric.
The adjusted funds from operations calculator starts from net income and reverses the two distortions: it adds back depreciation and amortization, which is a non-cash charge, and it subtracts gains on sales of properties, because selling a building is a financing event, not an operating result you can count on next quarter. What remains is a cleaner view of the cash a portfolio actually generates from renting and operating its assets, period after period, without the noise of accounting conventions designed for factories rather than for income-producing real estate.
From FFO to AFFO: the maintenance capex step
FFO corrects net income, but it still flatters the business, because buildings wear out. Roofs, elevators, facades, HVAC systems and tenant improvements all require recurring spending just to keep the rent roll where it is, and that spending never appears in FFO. Adjusted funds from operations goes one step further and subtracts maintenance capital expenditures — the recurring, keep-the-lights-on portion of capex, as opposed to growth capex spent on acquisitions or developments.
The result, AFFO, is the closest widely used proxy for the distributable cash flow of a property portfolio, and it is the figure dividend coverage ratios and AFFO multiples are usually built on.
What you can do with it
Screen REITs on AFFO multiples
Feed quarterly figures from filings into a batch job and rank a universe of REITs by price-to-AFFO without maintaining the formula in every script.
Check dividend coverage
Compare AFFO per share against the declared dividend each quarter to flag payouts that recurring cash flow does not actually support.
Normalize earnings across a portfolio
Restate net income from property companies on an AFFO basis so quarters with asset sales stay comparable with quarters without them.
FAQ
What is the formula?
AFFO = net income + depreciation and amortization - gains on sales of properties - maintenance capital expenditures. The intermediate FFO is returned as well.
Can net income be negative?
Yes. A net loss is a valid input and simply produces a lower AFFO. The other three fields must be zero or positive.
Is any data stored?
No. The four numbers are processed in memory and discarded; only the computed result is returned.
Does it handle different currencies or per-share conversion?
No. All inputs must be in the same currency units, and dividing by share count is left to the caller. The arithmetic itself is currency-agnostic.
What is the difference between FFO and AFFO?
FFO adds depreciation back to net income and removes gains on property sales. AFFO goes one step further and subtracts maintenance capital spending, such as roofs, elevators or HVAC, which keeps the rent roll where it is.
Related tools
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, by email and from Telegram — and soon from our app too.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/fin/affo \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"net_income":180000,"depreciation_amortization":95000,"gains_on_sales":12000,"maintenance_capex":30000}'const res = await fetch("https://api.kit.forhosting.com/fin/affo", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"net_income": 180000,
"depreciation_amortization": 95000,
"gains_on_sales": 12000,
"maintenance_capex": 30000
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/fin/affo",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"net_income": 180000,
"depreciation_amortization": 95000,
"gains_on_sales": 12000,
"maintenance_capex": 30000
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/fin/affo", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"net_income":180000,"depreciation_amortization":95000,"gains_on_sales":12000,"maintenance_capex":30000}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"net_income":180000,"depreciation_amortization":95000,"gains_on_sales":12000,"maintenance_capex":30000}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/fin/affo", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"net_income": 180000,
"depreciation_amortization": 95000,
"gains_on_sales": 12000,
"maintenance_capex": 30000
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "fin.affo",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |
Technical notes
This API takes four figures — net income, depreciation and amortization, gains on sales, and maintenance capital expenditures — and returns the AFFO in a single deterministic call, together with the intermediate funds from operations (FFO), so you can drop it straight into a valuation model, a screening script or an earnings pipeline without rebuilding the formula by hand every quarter.
From FFO to AFFO: the maintenance capex step
This endpoint returns both numbers: the intermediate FFO and the final AFFO, each rounded to cents, so you can see exactly how much of the gap between the two is explained by recurring capital spending in the period you are analyzing.
Inputs, validation and how to integrate it
The call takes four required numeric fields: net_income, which may be negative when the period was a loss; depreciation_amortization, gains_on_sales and maintenance_capex, which must each be zero or positive and expressed in the same currency units. Any value that is missing, not a number, or not finite is rejected with an invalid_input error, and requests that fail validation are not billed. The computation is pure arithmetic with no network access and no stored state, so the same inputs always return the same outputs, which makes the endpoint safe to call inside batch screeners, scheduled earnings jobs or pre-trade checks. It runs on our global edge, and the identical code runs free in your browser on this page: paste four numbers to check a figure by hand, and only pay the $0.002 per request when you wire it into your own systems and automate the workflow.
Technical questions
What does it cost?
$0.002 per request. It is also free to run in your browser on this page.
What happens if an input is missing or not a number?
The request is rejected with an invalid_input error naming the offending field, and failed requests are not billed.