Skip to main content
Expense tools, bookkeeping and procurement all start with a photo of a receipt. A vision model with a strict JSON schema reads it, but the check that matters is arithmetic: do the lines add up to the subtotal, and the subtotal plus tax to the total? This pipeline runs the cheap model first, only escalates to the large one when the numbers disagree, and posts each result to your endpoint signed, keyed by the image’s hash so a retry never books it twice. Three receipts cost six hundredths of a cent.

Build it in your project

Paste this line into your agent (Claude Code, Codex, Cursor, OpenCode, Cline). It sets up your key, then builds the pipeline in your project:

The code

One file per language. Both read RUNCRATE_API_KEY from the environment; nothing secret is in the code.

What the proof run cost

The Python file on three receipt photos made for the test (rotated and slightly blurred), with known totals. Measured on 2026-10-23 against api.runcrate.ai; costs are what the account was billed, read from each response’s X-LLM-Cost header or usage.cost. All three totals, vendors, dates and currencies were exact, in both languages (TypeScript: $0.000629, 17 s). Every receipt added up, so the escalation to the 235B model did not run.

Scale it

  • Thousands a day: each receipt is independent; run a thread pool, or a job group over a folder on a volume.
  • PDF invoices: render each page to an image first (pdftoppm -r 150), then send the pages in one message.
  • Cap the spend with a key limit; a broken loop stops at your number.

Gotchas found in the proof run

  • inclusionAI/Ling-3.0-flash-VL is cheaper but ignored response_format and answered in prose; Qwen3-VL honoured the strict schema every time.
  • Ask for line totals “as printed”: otherwise the model sometimes multiplies quantity by unit price itself and disagrees with the receipt.
  • Sign the exact bytes you send (separators=(",", ":") in Python) or the receiver’s HMAC will not match.