The indexation clock: the increase your contract already allows, and nobody sent the letter
Every recurring contract with its index, its anniversary and its notice period in one list, so the annual rise arrives as a signed letter on time instead of as a regret two years later
- Contracts that actually contain an indexation clause - if yours do not, this is a contract-drafting job first and an automation second
- The base index value and its base year from each contract, because the ratio is meaningless unless numerator and denominator sit on the same base
- Which index each clause names, exactly: Belgian rent uses the ordinary health index, wage indexation uses the smoothed four-month average, and they are different numbers with nearly the same name
- The notice period the contract or your local rules require, and how far back indexation may be claimed - in Belgium that is three months from the written request
- Three contracts you indexed by hand last year, to backtest the engine against the figure you actually charged
- Someone with the authority to sign the letter, because this sets a paying customer's price for a year
Version history
One row per recurring contract, the official index each one points at, and a draft letter on your desk before the notice deadline. The rise your own contract already allows, worked out and evidenced, instead of noticed two years late.
The architecture
the same flow as text
▼
[ Docling + local model — read the clause ONCE ]
│ which index, which base month, cap/floor, notice days
│ you confirm every field before it counts
▼
[ Grist — the contract register ]
│ customer, start date, base price, base index + its base year
│ the clause's own formula, as a formula
▼
[ n8n — monthly, on the 27th ]
├─ fetch this month's index (Eurostat / Statbel / ONS / BLS)
├─ which anniversaries fall inside their notice window?
├─ apply the clause, including cap, floor and rounding
└─ draft letter + the two index figures used
Nothing leaves the building. You sign it, or you don't.
The design decision worth defending is the split between the register and the engine. The clause is data, read once and confirmed by a human. The index is a feed that changes monthly and will change shape again. Keeping those apart means the day Eurostat renames a dataset you edit one node, not fifty rows.
The problem
A maintenance contract at €4,000 a month with a plain cost-of-living clause, skipped for one year at 2.5%, is €1,200 you will not invoice. That is the small part. The expensive part is that next year's rise is calculated on the base you failed to raise, so the gap never closes. Skip it three years running on a €120,000 book of recurring work and you are carrying roughly €9,000 of permanently lost margin, on a clause both parties already signed.
Nobody skips this out of generosity. They skip it because the arithmetic is annoying in a specific way. The formula is a ratio of two index figures from two named months, and both figures have to be on the same base year. The figure you need is published about four weeks after the month it describes, so the calculation genuinely cannot be done on the anniversary itself. And the deadline is real: for Belgian leases the indexation is retroactive for a maximum of three months from your written request, so a letter sent in November for a June anniversary collects three months and loses the other two. Late is not "catch up later". Late is gone.
Then 2026 quietly broke every script anyone had already written. In January the harmonised index moved to a new classification and a new base year, and the Eurostat dataset most tutorials point at was discontinued rather than updated. It still answers. It just answers with last year's number, forever.
Tool choices — and why
prc_hicp_minr, not the widely-cited prc_hicp_manr, which Eurostat's own page now marks discontinued. Belgium's health index comes from Statbel and is published around the 26th of the following month. The UK's ONS developer API is open with no registration, and is explicitly still in beta with breaking changes possible, so pin your parsing and check it yearly. The US BLS API is public domain: version 1 needs no key and gives you 25 queries a day, version 2 needs a free registration key and gives 500. At one call a month, version 1 is enough.Setup outline
1. Pull your recurring contracts into one folder. Not the quotes, not the one-off jobs. The ones that renew.
2. Build the register in Grist, one row per contract: customer, start date, anniversary month, current price, base price, base index value, base year of that index, index name, cap, floor, rounding rule, notice days, and the date you last indexed it.
3. Read the clauses. Docling converts the PDF, the local model proposes the fields, and you approve each one. Budget an hour for twenty contracts and expect to correct roughly one field in five.
4. Wire one n8n workflow per index source. Fetch, cache the monthly figure into the register, and log the dataset code you called so a silent swap is visible in the log.
5. Write the clause as a formula in Grist: new price = base price × (index of the month before the anniversary) ÷ (base index), then apply cap, floor and the rounding the contract actually specifies. Both index figures must be on the same base year.
6. Schedule the engine monthly, after the publication date of your slowest index. Filter for anniversaries falling inside the notice window plus a safety margin — 60 days out is a sane default.
7. Generate the letter with the two index figures and their months printed in it. A customer who can check your arithmetic argues about it far less.
8. Backtest before you trust it. Take three contracts you indexed by hand last year and confirm the engine reproduces the number you actually charged. If it does not, the clause is not what you think it is.
Pitfalls — the real ones
prc_hicp_manr; it is frozen at December 2025 and its replacement is prc_hicp_minr. Anything written against the old code still returns HTTP 200 and a plausible figure. This is the failure that costs you the most, because nothing looks broken.Verified repos
Grist — Apache-2.0, 11.6k stars, v1.7.17 released 29/07/2026
n8n — Sustainable Use License (free self-hosted internal use), 202.8k stars, active (checked 31/08/2026)
Docling — MIT, 65.7k stars, LF AI & Data Foundation project, active (checked 31/08/2026)
Ollama — MIT, 179.4k stars, v0.33.2 released 27/08/2026
Baserow — open-core, non-premium features under MIT, 5.7k stars, v2.3.3 (checked 31/08/2026) — alternative register if you already run one
Index sources, all free and official: Eurostat prc_hicp_minr (no key) · Statbel consumer price and health index · ONS developer API (open, beta) · BLS Public Data API (public domain; v1 keyless, 25 queries/day).
Get the next blueprint as it publishes — free, practical, verified tooling only.
Subscribe · Want it audited or extended for your business? DM @RXed_EU
What this costs to run
Priced as Extract fields from a document — one OCR'd page; output is a JSON record of 8-20 fields. the model reads the indexation clause out of the signed PDF once per contract, because clauses are prose written by six different lawyers; every field it proposes is confirmed by a human before it can drive a price, and the monthly arithmetic afterwards is division. Adjust the volume to yours; the bill is a range because the assumptions are ranges.
| Model | $/day | $/month | Reasoning |
|---|
Cheapest eight shown — straight per-token
arithmetic on list prices: no caching, no batch discount, thinking tokens bill as output.
All models + every assumption in the full explorer →
Capability & cost data: Artificial Analysis