Someone says our numbers are wrong.
That sentence used to mean: open a ticket, export two CSVs, argue in email, and hope the spreadsheet still matches when the credit note finally posts.
Finno treats it as a first-class workflow. Billing disputes are the machinery that finds where the difference is, accounts for every unit of it, and settles it symmetrically — for consumers and providers alike.
What a dispute is
A dispute names:
- who raises it (consumer or provider),
- what they dispute — an invoice, a settlement payment, or a bare period,
- our figure at intake, snapshotted and never recomputed,
- their figure, if they gave one.
Our side is frozen when the dispute opens. A case raised in August and answered in November must be judged against the numbers that were live when it was raised — not against a total that has since moved for unrelated reasons.
Consumers dispute invoices and periods. Providers dispute settlements and periods. Cross-party subjects are refused; ownership checks do not leak whether another party’s document exists.
Age and span windows keep the feature a reconciliation job, not a three-year commercial archaeology dig.
Claim files, not vibes
The counterparty uploads their own record set as CSV. Column names are matched by alias, so their export often works unedited. The best shape is the annotated round-trip: download our itemization, write what you believe next to what we billed, upload it back.
Hard caps protect the platform: file size, row count, files per dispute, and a cooldown between uploads. Fractional units are refused rather than quietly rounded. Persian and Arabic-Indic digits are accepted — because real counterparties send them.
Matching that does not trust clocks
A background worker matches their rows against ours down a ranked ladder: idempotency key, session id, request id, content and units signatures, amount signature, and only then time proximity.
Time is never a key. It is the last resort, and a match made on it is marked fuzzy in the evidence. Two calls a second apart with the same price are not the same call because they happened at the same time.
Every micro lands somewhere
Reconciliation produces an additive decomposition: every micro of the difference lands in exactly one bucket, and the buckets sum to the total difference. Whatever is left is an explicit unexplained residual — not a silent plug.
A diagnosis catalogue then names recognisable patterns against that decomposition. Diagnosis explains buckets; it never redefines them. If diagnosis and decomposition disagree, the decomposition wins.
The evidence bundle is stored with the dispute. A case answered in August still shows, in November, the figures it was answered with.
Resolution that moves real money
Closing a dispute can write up to two money legs in one transaction — a consumer balance adjustment and a provider adjustment — both pending, so the existing maker/checker on those tables is what actually releases funds.
Rules that keep the books honest:
- An adjusting outcome must carry at least one leg; a non-adjusting outcome must carry none.
- A dispute with an unexplained residual cannot be closed unless the operator explicitly accepts that residual — recorded with their name.
- A dispute whose claim file has not been reconciled yet is refused; an absent bundle is not a zero residual.
Standing detectors watch for invoice totals that drift from their immutable ranges, and for aged provider claw-backs that have become uncollectible.
What this unlocks
- Counterparties raise and evidence their own cases in the panel
- Ops get a ranked, audited explanation instead of a gut feel
- Settlement flows through the same adjustment rails as day-to-day credits
- Finance can refuse to “just close it” when micros remain unexplained
What to ask your team
When a customer says the invoice is wrong, do you reconcile every micro — or negotiate a round number and hope the residual never resurfaces?
See revenue assurance on the features page or talk to us about a technical evaluation.