Nothing gets paid
until it’s plumb.

Accounts payable for a real estate group that runs construction, private lending, materials importing and freight across half a dozen LLCs. Invoices arrive by email. Bills land in QuickBooks. The one that is wrong gets caught before the check prints.

Working prototype — 31 screens, real interactions, no sign-in.

plumb.raritanholdings.com/invoice/INV-8391
$9.40industry average cost to process one invoice by hand. Best in class is $2.78.
7 daysaverage time from an invoice arriving to being approved. Best in class is 3.1.
32.6%of invoices go straight through without a person touching them. Best in class is 49.2%.
<50%of available early-payment discounts get captured on a manual process.

Eight stages, and a person only appears in two of them

This is the actual sequence, in order. Six AI prompts do the reading and the coding; the approvers do the deciding. Everything is logged, and nothing posts to your books without a human having seen it.

01

Intake

Email, scan, or vendor portal. Sender resolves to a vendor, or lands in an unmatched queue that teaches itself.

DKIM check
02

Extract

Header fields and line items with per-field confidence and bounding boxes.

invoice_ocr_extract
03

Match

Vendor by EIN, then the subcontract or PO, then the delivery ticket. Two-way and three-way.

EIN · commitment
04

Code

Job, phase, cost code, cost type, then the GL account. Split across LLCs where it needs to be.

project_infer · gl_code
05

Check

Duplicates, over-billing, expired insurance, missing waivers. Anything failing blocks the pay button.

duplicate_detect
06

Route

Four tiers by amount, entity, method and vendor age. Wires and new vendors always reach the principal.

routing_recommend
07

Approve

Each approver gets a two-line brief on why the invoice looks normal — or does not.

human
08

Post & pay

Bill into QuickBooks Online or an IIF file for Desktop. Check run, waivers out, Positive Pay file built.

QBO · IIF · ACH

Every module is live in the prototype

Click any of these and you land in the real screen with real data behind it. Nothing below is a picture.

Structural steel frame rising under two tower cranes on an urban site

Built for a business that pours concrete, not one that ships software

CSI cost codes with cost types. Retainage held at 10% into its own account. Conditional waivers out with the check and unconditional back before the next draw. Certificates that expire per policy line, not per certificate. A prompt-pay clock that knows New Jersey gives you ten days to pass a payment down to your sub.

The six prompts, with what they actually return

Confidence thresholds are set per field type rather than globally, because a long description naturally scores lower than a six-character invoice number. Each prompt also carries named blockers that stop straight-through processing no matter how confident the model is.

The integrations, described the way your developer would describe them

DocuSign eSignature

  • JWT Grant with an RSA keypair and an impersonated user — signature impersonation. No refresh token; the hour-long access token is re-minted from a fresh assertion.
  • Envelopes from templates with templateRoles, and record IDs carried as hidden envelope custom fields so the webhook is a lookup rather than a guess.
  • Connect webhooks verified against X-DocuSign-Signature-1 — base64 HMAC-SHA256 over the raw body, accepting any of up to 100 keys during rotation.
  • Recipient AutoResponded gets its own state, because a bounced address is a different problem from a declined signature.

QuickBooks Online

  • One app, one realm per LLC, tokens stored per realm.
  • The refresh token rotates roughly every 24 hours — refreshing with a stale one revokes the whole authorization and forces a browser reconnect. That countdown is on the health screen.
  • Bill lines map AccountRef to the GL, CustomerRef to the job, ClassRef to the cost code and DepartmentRef to the location.
  • Errors get distinct states: 6240, 6140, 5010, 3200, 429.

QuickBooks Desktop

  • Tab-delimited IIF with !TRNS / !SPL / !ENDTRNS.
  • The TRNS line carries the A/P credit and is negative; the SPL expense lines are positive, so every block nets to zero.
  • A preflight validator checks that every vendor, account, Customer:Job and class already exists before the file downloads.
  • ASCII only — a UTF-8 BOM breaks the import outright.

Bank & Positive Pay

  • Issue file in comma-delimited or fixed-position layout, with configurable amount format and date format.
  • Payee normalization preview, because "&" versus "and" is the top cause of a false Payee Match exception.
  • Exception decisioning with the bank's own reason codes and a live countdown to cutoff.
  • ACH debit filtering off a standing approved list.

Where it runs

A small always-on webhook receiver in the cloud, and the heavy work on a mini-PC in your own office where the QuickBooks Desktop files already live.

What it saves, on your numbers

Move the sliders. The maths uses the published Ardent and APQC benchmarks, and assumes you land mid-pack rather than best-in-class.

420
14
$42
0.3%
$11,800
Recovered in the first year
$0
Hours given back0
Labour saved$0
Duplicate payments avoided$0
Early-pay discounts captured$0
Cost per invoice, after$0
Cycle time, after0 days

Assumes 78% of handling time removed on the straight-through share, duplicates cut by four fifths, and half of available 2/10 discounts captured. Conservative on all three.

The controls a CFO asks about

Segregation of duties

Whoever creates a vendor can never approve its first invoice. Whoever enters an invoice can never release its payment. The vendor master change log is its own report, because it is the first thing an auditor asks for.

Bank-change callback

Any change to a vendor's banking freezes payment until someone calls the number already on file — never one supplied in the request — logs who they reached, and a second person signs off.

Compliance gate

An expired certificate or a below-minimum limit blocks payment mechanically. Not a warning someone can click past.

Immutable audit trail

Every field change, every approval, every model decision, with the confidence and the cost. Exportable as an evidence packet per invoice.

What this prototype is, honestly

Real in here
  • Every screen, every interaction, every filter and sort
  • The full data model — entities, projects, vendors, 91 cost codes, 69 invoices, commitments, waivers, envelopes
  • The workflow logic: routing tiers, compliance gating, duplicate scoring, retainage
  • File formats: the IIF structure, the Positive Pay layouts, the QuickBooks field mapping
  • Statutory detail: N.J.S.A. 2A:44A-38 on waivers, the Prompt Payment Act clocks, NJ retainage
Not real yet
  • No backend. No Python running, no database, no API calls to anyone
  • Vendors, projects and people are invented — no real company data is in here
  • Documents are drawn, not scanned. The OCR is scripted, not live
  • Nothing sends an email, signs an envelope, or moves a dollar
  • Insurance minimums and approval ceilings are sensible defaults, not yours

The whole thing is one folder of HTML. Open index.html and it runs — no install, no server, no npm. All the data lives in a single data.js file, so swapping in your real vendors and jobs is a find-and-replace, not a rebuild.

Start where the work is

Open the review screen and try to approve an invoice you should not. The system will stop you, and it will tell you exactly why.

Open the review screen Pick a different seat