Skip to main content
All recent work
5 Nov 2026By Revitt8 min read

What an AI Invoice Review Looks Like When a Person Still Approves

An inspectable synthetic example of AI-assisted supplier invoice exception review: tenant-scoped permissions, deterministic money validation and a person's bound decision before an internal draft is created.

Supplier invoice exceptions are a common place for AI to look useful. A model can read a PDF, compare it with a purchase order and suggest what to do, while a person keeps the decision. The interesting engineering is in what happens around that suggestion: who may see the invoice, which arithmetic decides the amount, whose approval counts and what the approved record is allowed to become.

This article walks through a small worked example we published with the site, as a script and a JSON fixture you can download and run. It is a synthetic demonstration: not a product and not a report of a live deployment. Every trading entity, supplier, invoice and principal in it is invented, the candidate proposals and the approvals are recorded fixture values standing in for model output and a person's decision, and no model is called when it runs. Read it as a structural example of a review boundary you could ask a supplier or an internal team to build.

The scenario

An operations group runs two trading entities. Each entity has its own supplier invoices and its own purchase orders, and accounts staff see only the invoices in their own queue. A supplier has invoiced a price above the agreed order price, which is the kind of exception that usually ends up in an inbox thread.

In the example, invoice EC-88121 charges £26.00 per unit for a part ordered at £24.00. The invoice totals £912.00, of which £20.00 is the difference across ten units. The arithmetic is ordinary: line totals, net, tax at 20%, gross and the variance against purchase order po-4471. A candidate proposal suggests approving the variance on the basis that the goods were received in full, and an accounts payable supervisor with a £1,000 approval limit records the decision.

The order of the checks

Each review follows the same order, and the order matters more than any individual step.

  1. Authorise the request. The grant is looked up under the tenant named in the request, so a principal's document list for one trading entity cannot be reused to reach the other entity's invoices. Only the request is used here, so the check cannot depend on anything read from the invoice.
  2. Read the invoice from that tenant's documents only. If the request was refused, this never happens: the refusal is recorded without the supplier's bank details, the delivery note or the candidate proposal appearing anywhere in the output. Documents are keyed by tenant as well as invoice number, so even a grant that wrongly listed another entity's invoice number comes back empty rather than returning the invoice.
  3. Validate the money. Line arithmetic, tax, the invoice total and the currency are recalculated in code. The proposal's amount is compared with the invoice total, so a proposal that states £886.00 against a £900.00 invoice fails regardless of how confident its wording sounds.
  4. Accept the person's recorded decision. A decision names an approving principal, the tenant it was recorded in, the document and the amount. The application checks that the principal holds approval authority in that tenant and that this invoice is in their own queue, that the decision was recorded in this tenant, that it names this invoice, that the recorded amount still equals the invoice total and that the total is inside the principal's approval limit. A decision for another invoice or another tenant, a stale amount, an approver the tenant never granted or whose queue does not include this invoice, and a clerk approving their own request all block the review.
  5. Write an internal draft. An approved invoice becomes a draft record inside the process that ran the review, naming the approving principal and approved amount, with an empty list of external writes. Nothing is sent to the supplier, no payment is raised and no purchase ledger is posted.

The authority check, the money checks and the decision binding are independent gates, and all three must pass before a draft exists. A click cannot override a failed amount check, correct arithmetic cannot approve anything on its own, and an approval recorded against a different figure has no effect on this one.

What the walkthrough demonstrates

CaseRequestOutcome
Price variance approvedClerk asks for inv-88121; a supervisor with a £1,000 limit approves £912.00Approved internal draft, £20.00 variance recorded against po-4471
Another entity's invoiceSupervisor from tenant-alpha asks for a tenant-beta invoiceRefused at the tenant, before any read
Invoice outside the queueClerk asks for an invoice assigned to another queueRefused at the document, before any read
Unknown approverDecision signed by a principal the tenant never grantedBlocked by the approval record
Clerk self-approvalThe clerk's own principal records the approvalBlocked: the clerk holds no approval authority
Decision from another entitytenant-alpha decision replays an approval recorded in tenant-betaBlocked: the decision belongs to another tenant
Approver outside their queueA team lead with approval authority approves an invoice not in their queueBlocked: the invoice is outside their approval scope
Decision for another invoiceSupervisor approves inv-88124, but the decision names inv-88121Blocked: the decision is bound to another document
Stale amountDecision records £0.01 against a £900.00 invoiceBlocked: the approved amount no longer matches
Wrong amount in the proposalProposal says £886.00 for a £900.00 invoice, with a correct approvalBlocked by arithmetic despite the approval
Valid proposal, refusedCorrect £900.00 proposal, reviewer rejects itRejected; no draft

The refusals and blocks are the cases worth copying into your own acceptance discussion. A demonstration that shows only a successful approval says nothing about tenant boundaries, about who may approve, or about what a mistaken amount does to the rest of the process. The self-test goes one step further and gives the supervisor a grant that wrongly lists the other entity's invoice number: the review still comes back refused, because the invoice is looked up in the requesting tenant's documents, and no supplier detail from the other entity reaches the record.

Run it yourself

The example is two files, published beside each other on this site: ai-invoice-review.mjs and ai-invoice-review.json. Download both into one folder and run the script next to the fixture:

node ai-invoice-review.mjs             # print the eleven reviews
node ai-invoice-review.mjs --self-test # check the invariants

The script reads ai-invoice-review.json from its own folder, so a downloaded pair works anywhere Node 24 is installed. In this repository the same file runs from public/examples/; it has no dependencies and no credentials.

The self-test checks that refused requests never load a document, that a misconfigured grant still cannot return another entity's invoice, that protected supplier fields appear in no review record, that an unknown, unauthorised, out-of-scope, cross-tenant, wrong-document or stale-amount decision blocks the review, that the wrong proposal amount is stopped by the money checks, that only the valid approval produces a draft and that the draft carries the approving principal and no external writes.

If you want to see what fails, change the proposal amount in the wrong-amount case to £900.00: it becomes an approved draft, which is the correct behaviour for a proposal that matches the invoice. Change the stale-amount decision to £900.00, the unknown approver's principal to ap-supervisor-alpha, or the cross-tenant decision's tenant to tenant-alpha, and those blocks disappear as well. Each edit should change the printed outcome, and the self-test should then fail on its own expectations, which is how you know it is checking behaviour rather than matching its wording.

What the example does not prove

Keep these limits in view when you use it in a proposal, a design review or a conversation with an auditor.

  • No model was called. The proposals are fixtures, so the example says nothing about extraction accuracy, latency or cost on your invoices.
  • No results are measured. There is no claim about time saved, error rates or return on investment, and a synthetic walkthrough cannot produce one.
  • It is not a production application. There is no database, no authentication server, no review screen and no audit log: the decisions are fixed values in the fixture, and the draft exists only inside the process that printed it.
  • The draft is the last step. Posting to an accounts package, paying a supplier and sending remittance advice are all outside the boundary shown, and each needs its own approval and testing.

Those limits are the reason the example is small. It shows the shape of the control you need, and leaves the parts that depend on your systems, suppliers and staff to a scoped build.

Where the approval boundary belongs in your workflow

Most of the value in this pattern comes from decisions made before anyone writes code.

  • Permissions from your existing directory. Reviewers, queues and tenants should come from the system that already grants access, so a supplier invoice does not need a parallel permission list to drift out of date, and so one entity's grant cannot be stretched over another's documents.
  • Money rules live in code rather than in the prompt. Totals, tolerances, tax treatment and the maximum amount a supervisor may approve are deterministic rules with their own tests.
  • A decision attached to the amount. Record who approved which figure, when, and on what evidence. If the invoice is later re-read or re-extracted, the previous approval does not silently carry over to a different total, and an approval recorded for one invoice cannot release another.
  • Exceptions with an owner. Every blocked or refused case needs somewhere visible to go, with a person responsible for clearing it.
  • Draft-only writes until agreed otherwise. Start with records that a person can inspect and post. Extend the boundary deliberately, with the posting action behind its own permission and test.

The same boundary applies to sales credits, expense claims, purchase requisitions and customer refunds. The document changes; the sequence of authority, arithmetic, decision and internal draft does not.

Where this fits in Revitt's work

Our Global HRIS case study describes software that compares payroll runs and uses AI to classify differences without sending employees' personal details to a model. It is a published example of AI inside a controlled business process, and it explains the parts around the model that made it usable.

AI consultancy in Sheffield is where we assess a workflow like invoice review: data and access, where a model helps, what the application must enforce and how staff adopt it. Admin automation is the delivery side, for the repetitive checks and hand-offs you decide to take off a team's desk.

If you are still choosing the first workflow, AI proof of concept to production sets out the acceptance checks worth agreeing before anyone depends on the result.

If your accounts team has a queue of supplier exceptions and you want to agree what a safe first version looks like, talk it through with Max. An assessment or a defined engineering engagement has a scope and a price; we do not start from an AI platform decision.