FreightAudit

Live demo

Pay the contract rate, not the invoice.

Every carrier charge checked against your rate card. AI reads the invoice; code does the math; a person approves.

97.4% overcharge recall on 98 synthetic test invoicesClaude first, measured November 2, 2026

Sample invoice 76644482

Bramblewood Express

Billing issues (1)
Linehaul billed
$6,145.14
Contract, rate card v2
$5,343.60
Held for review
$801.54

Linehaul above the rate card

Open

Rate card version 2 sets Linehaul at $5,343.60; billed $6,145.14.

+$801.54
Sample invoice from the demo set: Linehaul on Bramblewood Express #76644482, Wolfburgh, UT to Kassulkeburgh, AR. The carrier and places are synthetic. Open it in the sample
On 98 synthetic test invoicesClaude firstNovember 2, 2026Free models onlyOctober 27, 2026
Overcharge recall97.4%Met94.9%Met
Overcharge precision100%Met100%Met
Cost per invoice, paid-equivalent (digital / scanned)$0.0079 / $0.0105Met$0.0007 / $0.002Met

How it works: one invoice, start to finish

Three steps, each one recorded in the audit trail the reviewer sees.

  1. Upload

    The invoice arrives, and the model reads it into structured lines.

    • A PDF, PNG or JPG, or a batch of up to 500.
    • Each file is stored by its content, so a duplicate is never processed twice.
    • A text model reads digital PDFs; a vision model reads scans. A bad reading gets one repair, then a backup model.
  2. Check

    Each line is matched to its shipment and checked against the rate card.

    • Rules in code compare every line with the shipment's rate card.
    • They flag rate mismatches, charges not on the contract, and duplicates.
  3. Decide

    A reviewer approves or disputes each finding.

    • Invoices that match wait as Ready to approve; findings wait for a reviewer.
    • Nothing is approved without one.
    • A job that fails its retries goes to dead letters, to be replayed.

Until November 10, 2026, the live demo reads with Claude Sonnet first. See one sample invoice take each step.

Features, as the app shows them

Each card is a piece of the app, filled from the demo set's synthetic invoices.

Open the sample invoice
    1. Received, at 0.0 s
    2. Read3.3 s, at 0.0 s to 3.3 s
    3. Matched, at 3.4 s to 3.4 s
    4. HeldLinehaul above the rate card, +$801.54+$801.54, at 3.4 s

    Every step on the record

    Sample invoice 76644482, October 17, 2026, in seconds from receipt. Recorded before Claude first went live, so Gemini 3.5 Flash-Lite read it.

  • Invoice 53704390, 1 attempt
    Reconciliation failed
    1. Uploaded
    2. Reading
    3. Checking
    4. Checked

    shipment has no miles

    Failed jobs wait to be replayed

    A job that uses up its retries waits with its error, ready to replay once the cause is fixed.

  • Linehaul billed twiceTern & Tide Carriers #96079756, open+$5,522.06

    Findings that name the amount

    Each finding names its line and what it costs, before anyone pays.

  • $0.0105

    per scanned invoice, Claude first, measured November 2, 2026

    • $0.0079Digital
    • $0.0105Scanned
    Claude first
    • $0.0007Digital
    • $0.002Scanned
    Free models only

    Reading costs a fraction of a cent

    Per invoice at paid rates on 98 test invoices; the targets are $0.02 / $0.05.

  • packages/domain/src/reconcile.ts
      finding = { type: 'rate_mismatch', expectedCents: rate, evidence };}if (amountCents > finding.expectedCents) discrepancies.push({ ...finding, lineNumber, billedCents: amountCents });if (code !== null) billed.add(code);

    Rules in code, not in the model

    The model only reads the invoice; plain code checks each charge against the rate card.

    • Let the billed amount standApprove charge
    • Dispute the overchargeDispute

    A person decides each finding

    Each decision goes into the audit trail with its note, and an invoice is approved only once every finding is decided.

  • A redacted request headerSynthetic data only
    { "headers": { "x-api-key": [Redacted], "cookie": [Redacted] } }

    Keys stay out of the logs

    The demo holds only generated invoices from fictional carriers, and every service redacts keys and cookies from what it logs.

Evaluation results

98 synthetic invoices with known ground truth, read two ways. Claude first is Claude Sonnet 5.5 reading first, with the free models behind it (measured November 2, 2026). The free models alone are what CI checks on every change to extraction, and what reads once Claude's credits end (measured October 27, 2026).

MetricTargetClaude firstNovember 2, 2026Free models onlyOctober 27, 2026
Header field accuracy (digital)Target98%Claude first, November 2, 2026100%MetFree models only, October 27, 202699.4%Met
Header field accuracy (scanned)Target93%Claude first, November 2, 202693.4%MetFree models only, October 27, 202694.3%Met
Line-item F1 (scanned)Target0.88Claude first, November 2, 20260.968MetFree models only, October 27, 20260.95Met
Overcharge recallTarget90%Claude first, November 2, 202697.4%MetFree models only, October 27, 202694.9%Met
Overcharge precisionTarget95%Claude first, November 2, 2026100%MetFree models only, October 27, 2026100%Met
False flag rateTarget≤ 3%Claude first, November 2, 20260%MetFree models only, October 27, 20260%Met
Extraction latency p50 / p95 (3 pages or fewer)Target≤ 5 s / 12 sClaude first, November 2, 20262.9 s / 7.1 sMetFree models only, October 27, 20262.4 s / 10.7 sMet
Cost per invoice, paid-equivalent (digital / scanned)Target≤ $0.02 / $0.05Claude first, November 2, 2026$0.0079 / $0.0105MetFree models only, October 27, 2026$0.0007 / $0.002Met

On these runs Claude first is ahead on header field accuracy (digital), line-item F1 (scanned) and overcharge recall, and the free models alone on header field accuracy (scanned) and cost per invoice, paid-equivalent (digital / scanned).

Complete results with 95% confidence intervals are in the eval reports: Claude first and free models only.

Engineering, with its evidence

Each claim links to the file that proves it.

Exact money

Integer cents in pure functions, with no I/O. 5 property-based test suites run 1,000 cases each on a fixed seed.

No lost jobs

k6 sent 6,000 uploads an hour, 3x the design rate: 1,083 accepted, 0 lost, upload p95 86 ms (October 15, 2026). Failed jobs retry, then wait in a replayable dead-letter queue.

Contract-first APIs

OpenAPI and GraphQL schemas come before the code, with generated clients. Every pull request is checked for breaking REST changes against its base.

Continuous evaluation

20 of the 98 golden invoices run on every pull request that changes extraction, against quality floors; all 98 run weekly.

End-to-end tracing

OpenTelemetry follows each upload across the API, the queue and every model call, into a Grafana dashboard with alert rules.

Secrets stay out

gitleaks scans every commit, in CI and in the pre-commit hook. The browser never calls the API, and only synthetic data reaches model providers.

Built with TypeScript, Fastify, GraphQL Yoga, BullMQ, Redis, PostgreSQL, Drizzle, MinIO, Next.js, Playwright, OpenTelemetry, Grafana, k6, Gemini, Groq, Claude.

Check the next invoice against the contract.

Open the live demo and decide a finding yourself.

Open the demo