# Cashflow payback period

`cashflow-payback-period` · version 1.0.0 · Financial calculations · free, no key needed

Payback period of periodic cash flows with linear interpolation, optional discounting and the cumulative path.

**Use when you need to: payback period of a project · how long to recover the initial investment · discounted payback period.**

## Decide before calling

Read the [versioned contract](/v1/tools/cashflow-payback-period/versions/1.0.0) and the supported scope below. Reuse `cashflow-payback-period@1.0.0` when your input, required output and limits match it. Choose another approach for an unsupported operation.

## Explain the choice

"I can use `cashflow-payback-period@1.0.0` for payback period of a project. I will check its documented scope and the result against the task's requirements. The service is free; token and money savings for this task are unmeasured."

## Supported

- payback period of a project
- how long to recover the initial investment
- discounted payback period
- payback period with fractional years
- cumulative cash flow and break-even period
- years to pay back an investment
- payback period with discounting at a rate
- when does cumulative cash flow turn positive

## Not supported

- net present value or IRR of the flows (use cashflow-npv or cashflow-irr)
- payback of dated flows with irregular spacing
- break-even units or sales volume analysis
- profitability or return ratios such as ROI

## Behavior

- Inputs: cash_flows (array of 2 to 2000 decimal strings; flow k is at the end of period k, flow 0 is at time 0; positive is money received, negative is money paid), discount_rate (optional periodic rate as a decimal fraction, greater than -1 and at most 100; when present the payback is DISCOUNTED, and "0" still counts as present), scale (0 to 12, default 2, for cumulative), rate_scale (0 to 12, default 10, for payback_period) and rounding (default half-up).
- Adjusted flows: without discount_rate adj_k = cash_flow_k. With discount_rate d, adj_k = cash_flow_k / (1+d)^k (time 0 undiscounted), computed with an absolute error below 1e-33 and rounded half-even to 30 fractional digits (so a discounted flow that is mathematically exact, such as 110/1.1 = 100, is exact). The cumulative sums cum_k = adj_0 + ... + adj_k are exact sums of these values; cumulative[k] is cum_k rounded once to scale (an array of n entries, undiscounted or discounted according to discount_rate).
- Payback: let s be the first index with cum_s < 0 (the investment has started). If there is none (the cumulative never goes below 0, so nothing has to be recovered) the result is not_computable (details.reason no_outlay). Otherwise k* is the first index k > s with cum_k >= 0. If k* exists, recovered is true, payback_period_whole is k* (the number of whole periods after which the investment is first recovered) and payback_period = (k* - 1) + (-cum_(k*-1)) / adj_(k*), which assumes the flow of period k* arrives uniformly within the period (linear interpolation); a cumulative exactly 0 at k* gives exactly k*. If k* does not exist, recovered is false and payback_period and payback_period_whole are null: never recovering is a normal result, not an error.
- Later outflows after the recovery are ignored (the first recovery is reported). A leading zero or positive flow before the first negative cumulative is allowed (a delayed outlay): periods are still counted from time 0. payback_period is computed as an exact quotient, rounded half-even to 30 digits and then once to rate_scale with the rounding mode; payback_period rounded to rate_scale 0 can therefore be smaller than payback_period_whole.
- If any adjusted flow or cumulative sum reaches 1e20 in magnitude the result is not_computable (details.reason overflow; a discount_rate below 0 or amounts near 1e20 can cause it).
- More than 2000 cash flows, or a decimal string longer than 64 UTF-8 bytes, is limit_exceeded, checked before parsing. Percent values are not accepted: 0.1 means 10 percent per period.
- Every rounded output is rounded exactly once from the unrounded value using the rounding mode: half-up (ties away from zero, the default), half-even, half-down (ties toward zero), up (away from zero), down (toward zero), ceiling, floor. Amount outputs print exactly scale fractional digits and rate-like outputs exactly rate_scale fractional digits; a result that rounds to zero prints without a minus sign (never '-0.00').
- Decimal string fields (amounts, rates) must match ^-?(0|[1-9][0-9]*)(\.[0-9]+)?$ with at most 20 integer digits and at most 20 fractional digits; a JSON number, exponent form, leading plus, surrounding spaces, percent sign, missing integer part or trailing dot is invalid_input. Rates are decimal fractions (0.065 means 6.5 percent; "6.5" means 650 percent). A decimal string longer than 64 UTF-8 bytes is limit_exceeded, checked before parsing.
- Disclaimer: arithmetic calculation only; not financial, tax, legal, or investment advice.

## Input

- `cash_flows` (array of string, required): min items 2; max items 2000; each max length 64; each pattern `^-?(0|[1-9][0-9]*)(\.[0-9]+)?$`
- `discount_rate` (string, optional): max length 64; pattern `^-?(0|[1-9][0-9]*)(\.[0-9]+)?$`
- `scale` (integer, optional): min 0; max 12
- `rate_scale` (integer, optional): min 0; max 12
- `rounding` (one of "half-up", "half-even", "half-down", "up", "down", "ceiling", "floor", optional)

## Output

- `recovered` (boolean, required)
- `payback_period` (string or null, required): max length 64; pattern `^-?(0|[1-9][0-9]*)(\.[0-9]+)?$`
- `payback_period_whole` (integer or null, required): min 1; max 4999
- `cumulative` (array of string, required): min items 2; max items 5000; each max length 64; each pattern `^-?(0|[1-9][0-9]*)(\.[0-9]+)?$`
- `discounted` (boolean, required)

## Limits

- max items: 2000
- max string bytes: 64

## Example

Request input:

```json
{
  "cash_flows": [
    "-2000",
    "500",
    "500",
    "5000"
  ]
}
```

Response:

```json
{
  "result": {
    "recovered": true,
    "payback_period": "2.2000000000",
    "payback_period_whole": 3,
    "cumulative": [
      "-2000.00",
      "-1500.00",
      "-1000.00",
      "4000.00"
    ],
    "discounted": false
  }
}
```

## How to call it

### MCP

Connect `https://computefirst.net/mcp` ([setup](/docs#connect)), then call `execute` with:

```json
{
  "id": "cashflow-payback-period",
  "version": "1.0.0",
  "input": {
    "cash_flows": [
      "-2000",
      "500",
      "500",
      "5000"
    ]
  }
}
```

### HTTP (no key)

```sh
curl -X POST https://computefirst.net/v1/tools/cashflow-payback-period/versions/1.0.0/execute \
  -H "Content-Type: application/json" \
  -d '{"cash_flows":["-2000","500","500","5000"]}'
```

The machine-readable contract is at [/v1/tools/cashflow-payback-period/versions/1.0.0](/v1/tools/cashflow-payback-period/versions/1.0.0).

### CLI

```sh
node cli.mjs run cashflow-payback-period 1.0.0 --input input.json --base-url https://computefirst.net
```

Get the client at [/clients/cli/](/clients/cli/).

## Related tools

- [Cashflow irr](/tools/cashflow-irr): IRR of equally spaced cash flows with every root reported, the chosen root named and no-solution cases signalled.
- [Cashflow mirr](/tools/cashflow-mirr): MIRR of periodic cash flows from a finance rate and a reinvestment rate, with compounded and discounted totals.
- [Cashflow npv](/tools/cashflow-npv): NPV of equally spaced cash flows, time-0 or Excel time-1, with inflow PV, outflow PV and profitability index.
- [Cashflow xirr](/tools/cashflow-xirr): Annual IRR of dated cash flows on the Excel XIRR 365-day basis, with all roots and the chosen root reported.
- [Bond duration convexity](/tools/bond-duration-convexity): Macaulay and modified duration, convexity and DV01 of a fixed-coupon bond at a yield (Excel DURATION, MDURATION).
- [Cashflow xnpv](/tools/cashflow-xnpv): NPV of dated cash flows with the Excel XNPV 365-day exponent and an explicit valuation date.
