Token ROI model
Token ROI model.
Enter one workflow. See its cost per accepted output, payback, and the two breakevens that decide whether it survives a price change or a quality dip. Nothing leaves this page.
Presets are illustrative starting points, not any vendor's list price. Replace them with your contracted rates.
file://. Serve the folder over HTTP (python -m http.server) or use netesis.com/calculator.html. The formulas are listed below, so you can still run it by hand.
Results · Invoice triage
At 12,000 tasks/month and an 80% acceptance rate, Invoice triage saves $14,346/month net and pays back the build in 2.3 months. It stops paying for itself below a 64% acceptance rate.
Token spend · per month
- Input tokens
- 82.8M
- Output tokens
- 8.28M
- Input cost
- $414
- Output cost
- $207
- Token cost
- $621
Per task
- Token cost per task
- $0.052
- Effective cost per taskTokens plus review and rework, over every task.
- $3.74
- Cost per accepted outputThe same cost over the 9,600 outputs you keep.
- $4.67
Baseline
- Human cost per task
- $5.42
- Human baseline / month
- $65,000
Savings · per month
- AI operating costTokens $621 plus review and rework $44,200.
- $44,821
- Gross savings
- $20,179
- Program costRecurring cost plus the build spread over the amortization window.
- $5,833
- Net savings
- $14,346
Breakevens
- PaybackBuild of $40,000 repaid by $17,679/month of cash flow after recurring costs.
- 2.3 months
- Breakeven acceptanceBelow this acceptance rate the workflow loses money.
- 64% Floor
- Breakeven token priceBoth prices would have to rise ×24.1, to $120.50 in and $602.52 out per million tokens, before the margin disappears.
- ×24.1
| Scenario | Net / month | vs base |
|---|---|---|
| Base | $14,346 | — |
| Volume ×0.5 | $4,256 | −$10,089 |
| Volume ×2 | $34,525 | +$20,179 |
| Acceptance −15 pts | $696 | −$13,650 |
| Token price ×2 | $13,725 | −$621 |
| Review time ×2 | −$6,454 | −$20,800 |
The browser refused clipboard access. Select this text and copy it.
Formulas
Nothing hidden.
Every number above comes from the lines below, in this order. Copy them into a spreadsheet and you will get the same answers.
How this is calculated All of it
- Sanitize the inputs first
every number = Number(field); not finite → 0 (amort → 1) negative → 0 acceptance clamped to 0…100 amort = max(1, round(amort)) name trimmed, at most 80 characters currency one of USD, EUR, GBP, CAD, AUD, else USDNothing downstream has to defend itself against a blank box, a minus sign, or the word “abc”. A quantity that cannot be defined — a cost per task with no tasks — is reported as an em dash, never as a number.
- Monthly token volume and token cost
inTokM = tasks × inTok × retry outTokM = tasks × outTok × retry inputCost = inTokM / 1e6 × priceIn outputCost = outTokM / 1e6 × priceOut tokenCost = inputCost + outputCostThe retry multiplier applies to both directions, because a regenerated call re-sends the whole prompt as well as writing a new answer. Prices are per million tokens, so the volume is divided by a million before it is priced.
- Quality reality: what review and rework cost
a = acceptance / 100 accepted = tasks × a rejected = tasks × (1 − a) reviewCost = accepted × reviewMin / 60 × hourly reworkCost = rejected × reworkMin / 60 × hourly laborCost = reviewCost + reworkCostEvery accepted output still costs review minutes; every rejected one costs rework minutes. This is the term that decides most workflows, and it is the one pilot decks leave out.
- Operating cost, and the three unit costs
aiCost = tokenCost + laborCost tokenCostPerTask = tasks > 0 ? tokenCost / tasks : — effectiveCostPerTask = tasks > 0 ? aiCost / tasks : — costPerAccepted = accepted > 0 ? aiCost / accepted : —Cost per accepted output is the honest unit: you cannot ship the rejects, so they are overhead on the ones you keep.
- The human baseline
humanPerTask = humanMin / 60 × hourly humanMonthly = tasks × humanPerTaskThe same hourly cost prices the baseline and the review labour, so a change in the loaded rate moves both sides of the comparison together.
- Gross savings, program cost, net savings, cash flow
grossSavings = humanMonthly − aiCost buildMonthly = build / amort programMonthly = recurring + buildMonthly netSavings = grossSavings − programMonthly cashflow = grossSavings − recurringNet savings amortize the build; cash flow does not, because the build is already paid. Cash flow is what actually repays it.
- Payback period
build ≤ 0 → no build cost to recover cashflow ≤ 0 → does not pay back otherwise → months = build / cashflowPrinted in months, never as an infinity symbol. A workflow can show a payback figure and still lose money on net: that happens when
build / cashflowis longer than the amortization window, and the verdict says so in words.- Breakeven acceptance rate
netSavings(a) = K − L × (reworkMin + a × (reviewMin − reworkMin)) K = humanMonthly − tokenCost − programMonthly L = tasks × hourly / 60 slope = L × (reviewMin − reworkMin) slope = 0 → net ≥ 0 ? pays at any rate : never pays aStar = (K / L − reworkMin) / (reviewMin − reworkMin) reviewMin < reworkMin (normal) → aStar is a FLOOR aStar ≤ 0 → pays at any rate | aStar ≥ 1 → never pays reviewMin > reworkMin (inverted) → aStar is a CEILING aStar ≥ 1 → pays at any rate | aStar ≤ 0 → never paysNet savings are linear in the acceptance rate, so there is exactly one root. When review is cheaper than rework — the normal case — more acceptance means more savings and the root is a floor to stay above. When review costs more than rework, the line runs the other way and the root is a ceiling; that is a sign the two time inputs deserve a second look.
- Breakeven token price
netSavings(m) = netSavings − (m − 1) × tokenCost = 0 m = 1 + netSavings / tokenCost tokenCost ≤ 0 → price cannot matter; nothing is spent on tokens m > 1 → prices would have to RISE to m × today's 0 < m ≤ 1 → already losing; prices would have to FALL to m × today's m ≤ 0 → free tokens would still not make it pay impliedPriceIn = priceIn × m, impliedPriceOut = priceOut × mThe multiplier moves both prices together. On most workflows it lands far above any plausible price change, which is the point: the quality lever dominates the price lever.
- The six sensitivity scenarios
Each row re-runs the whole model on one modified copy of the inputs and reports net savings per month, plus the change against the base row.
Base inputs as entered Volume ×0.5 tasks × 0.5 Volume ×2 tasks × 2 Acceptance −15 pts acceptance − 15, floored at 0 Token price ×2 priceIn × 2 and priceOut × 2 Review time ×2 reviewMin × 2- How the numbers are printed
money |v| < 1 → 3 decimals; < 100 → 2; otherwise 0 negatives take a true minus sign, never parentheses anything that rounds to zero prints as a plain zero percent 0 decimals · months 1 decimal · multiplier ×24.1 tokens three significant figures with a unit: 82.8M missing an em dash — never NaN, Infinity, undefined or nullFormatting is
Intl.NumberFormatin the en-US locale with the currency you selected. The currency is a display choice: nothing is converted.
Latency, and what a slower workflow costs the people waiting on it. Provider reliability — outages, rate limits, and the fallback path you build for them. Prompt-caching and batch discounts, unless you fold them into the prices above. The cost of the review tool itself, and of the reviewers' context switching. Opportunity cost: what the same engineering month would have earned elsewhere.
It also assumes the acceptance rate you type is measured, not estimated. If it is a guess, the breakeven acceptance rate is the number to read first — it tells you how wrong the guess is allowed to be.
Want these numbers from your real data?
This page runs on what you typed. An engagement runs on your logs, your review tool, and a baseline we measure — and the verdict is written down, including when it says stop.