Restate past budgets and contract values at current prices

A report that compares past budgets or contract values with current ones has to restate them to one month's prices. Choose the base month, name the price index and label the result. Narwhal returns the consumer price index for any month and the latest published one, so each amount is multiplied by the latest index and divided by the index of its own month.

Three choices every restated report has to make

A report that sets a lease signed years ago beside this year's budget compares different money. Finance planning and contract owners fix that by restating every amount to the prices of one month, and three choices decide whether the result can be defended. The base month is the month all amounts are restated to. The index is the price series used to move between months. The label is the sentence that tells a reader both. The API supplies the index values, and the report states the choices.

The observations endpoint returns a country's headline consumer price index by month. This request reads the index for March 2012, the month of an office lease.

curl, the index for the month a lease was priced
curl -s -H "Authorization: Bearer $NARWHAL_API_KEY" \
  "https://api.narwhalapi.com/v1/economics/USA/cpi/observations?start=2012-03&end=2012-03"
Response
{
  "country": "USA",
  "as_of": "2026-10-14T00:00:00Z",
  "index_base": "1982-84=100",
  "observations": [
    {
      "period": "2012-03",
      "value": "229.392"
    }
  ],
  "next_cursor": null
}

start and end take YYYY-MM. value is a decimal string, and index_base names the base period of the index series, which has no effect on a ratio between two of its months.

Use the latest published month as the base month

The CPI endpoint without a period returns the newest published index. Use its month as the base month for the whole report, so every line is restated to the same prices.

curl, the latest index
curl -s -H "Authorization: Bearer $NARWHAL_API_KEY" \
  "https://api.narwhalapi.com/v1/economics/USA/cpi"
Response
{
  "country": "USA",
  "period": "2026-09",
  "value": "336.940",
  "index_base": "1982-84=100",
  "released_on": "2026-10-14"
}

period is the base month, value is the index and released_on is the date it was published. A restated amount is expressed in the prices of that month and not in the prices of the day the report is run. Say so in the report.

Restate a list of contracts and budgets in one pass

  1. List each amount with the month it was priced Use the month the price applied, which for a contract is usually its signing or indexation month, not the year it was reported.
  2. Read the series once One observations request covers the whole range of months. The script asks for 2012-01 to 2024-12 with limit set to 1000 and builds a dictionary by period.
  3. Multiply and divide with Decimal Each amount is multiplied by the base-month index and divided by the index of its own month. Round to cents once, at the end.
  4. Print the label with the table The first line of the output names the base month, the country and the index base, so the table cannot be read without it.
    Python, a restated amounts table
    import json
    import os
    import urllib.request
    from decimal import Decimal, ROUND_HALF_UP
    
    def get(path):
        req = urllib.request.Request(
            "https://api.narwhalapi.com" + path,
            headers={"Authorization": "Bearer " + os.environ["NARWHAL_API_KEY"]},
        )
        with urllib.request.urlopen(req, timeout=30) as r:
            return json.load(r)
    
    latest = get("/v1/economics/USA/cpi")
    base_month, cpi_base = latest["period"], Decimal(latest["value"])
    series = get("/v1/economics/USA/cpi/observations?start=2012-01&end=2024-12&limit=1000")
    cpi = {o["period"]: Decimal(o["value"]) for o in series["observations"]}
    
    lines = [
        ("Office lease", "2012-03", "480000"),
        ("Software contract", "2018-06", "120000"),
        ("Equipment purchase", "2022-01", "75000"),
    ]
    print(f"All amounts in {base_month} prices, US CPI {cpi_base}, base {latest['index_base']}")
    for name, month, amount in lines:
        restated = (Decimal(amount) * cpi_base / cpi[month]).quantize(Decimal("0.01"), ROUND_HALF_UP)
        print(f"{name:20} {month}  {Decimal(amount):>10,}  index {cpi[month]}  restated {restated:>12,}")

The lease of 480,000 from March 2012 becomes 705,042.90 in September 2026 prices. Dividing the base index by the lease month index gives 1.469, so prices in this series rose by 46.9 percent over that span. The software contract rose by 33.7 percent and the equipment purchase by 19.8 percent.

Output of the script
All amounts in 2026-09 prices, US CPI 336.940, base 1982-84=100
Office lease         2012-03     480,000  index 229.392  restated   705,042.90
Software contract    2018-06     120,000  index 251.989  restated   160,454.62
Equipment purchase   2022-01      75,000  index 281.148  restated    89,883.26

How to label the restated column

ItemWording in the report
Base monthIn September 2026 prices, the latest month published when the report was run
IndexUS consumer price index, headline, base 1982-84=100
Source monthShow the month each original amount was priced, in the column beside the restated one
RoundingRound once to cents at the end and state it

Keep the original and the restated amount side by side. A reviewer can then check any row with one multiplication.

An annual budget has no single price month. Pick one month of that year, such as the month the budget was approved, apply it to every line of that budget and state the month in the label. The average of that year's twelve monthly observations is the alternative, and the report should name whichever it uses.

Which price index should a contract use?

Use the index the contract names. The API returns the headline consumer price index of a country. If a lease or supply contract is indexed to a core, regional or sector index, the restated figure will differ from the contractual one, so confirm the index before the report goes out.

Can one report restate amounts from several countries?

Restate within one country at a time, because each series has its own base and an index value from one country says nothing about another country's prices. To show the results in one currency, convert the restated amounts with an exchange rate for a date you name as a separate step.

What if the month I need has not been published yet?

A request for a period without a published value returns a 404 problem response with the code series_not_found. For the United States, asking for October 2026 does so at the time of writing. Use the period from the CPI endpoint as the base month and say so in the label.

Published .

Next steps