Choosing a receipt extraction API: six questions that separate tax-aware from just-OCR

Choosing a receipt extraction API: six questions that separate tax-aware from just-OCR

Here’s the honest version of the pitch first: if all you need is vendor, date, and total off a receipt, you should probably build it yourself. A single vision-model call — GPT-4o-mini, Gemini Flash — with a “return JSON” prompt gets you most of the way there in an afternoon, for a fraction of a cent per image. We’d rather tell you that than sell you a service you don’t need.

The reason a dedicated tool earns its place is the part that quietly isn’t fine — the production invoices where the tax treatment has to hold up at audit, where a silent schema break kills your pipeline, and where “confidently wrong” costs you at audit time. So here are six questions worth asking of anything you evaluate, ours included.

1. Is tax treatment applied per line item, or is it just OCR?

“Find the total” is an optical problem. Deciding whether the GST on a $180 client dinner is claimable is a rules problem — and the receipt looks identical to an in-flight meal on a business trip that’s treated differently. A generic model will confidently guess from keywords like “meal” or “bar.” Ask: does the tool assign a tax_code per line (a taxable / gst-free / entertainment-ITC-denied-style value) with a rationale naming the actual rule? If it just extracts text and totals, you’ve moved the hard part into your own business logic. The tradeoff: rules tagging adds inference complexity, and for a stream where every line is plainly taxable, raw extraction is enough.

2. Does it validate the ABN checksum, or just transcribe what it sees?

Every Australian Business Number carries a modulus-89 checksum baked into its digits. A smudged 3 read as an 8 becomes a mathematically invalid ABN — but only if something actually runs the check (we added a fixture specifically to catch that). Ask: does the API validate the checksum and flag invalids (without silently “fixing” them)? A raw model call hands back whatever it read, and will often fabricate a plausible digit to make the sequence look complete rather than surface that the image is unreadable there. The tradeoff is negligible latency; if your documents don’t carry ABNs, you can skip it entirely.

3. Does it transcribe verbatim, or auto-correct to “plausible”?

This is the silent data-rot risk. A model told to “extract the vendor” might turn McDonalds #402 into McDonald's Restaurant Group because it knows the entity better than the receipt does. Ask: are vendor strings and line items verbatim copies of the source? If the tool “helpfully” normalizes, you lose the audit trail linking the digital record back to the paper — the thing an auditor actually wants. The tradeoff: verbatim output is messier, and if you’re only indexing receipts for search, light normalization may save you downstream cleaning.

4. Is the schema stable and versioned, or does it drift with model upgrades?

The afternoon prototype works until you bump the model version and the JSON shape shifts — a field goes missing, an enum gains a value, a nested object flattens. Ask: is there a typed contract with semantic versioning? If every model update makes your parser a moving target, the “cheap” API is expensive in maintenance. The tradeoff: stable contracts require discipline, and while you’re still changing fields daily in a prototype, raw JSON is more flexible.

5. Is the confidence calibrated — and will it return an honest null?

A number between 0 and 1 next to a wrong-but-confident answer is worse than no number at all. What you want is a low score, or an explicit null, when the input genuinely doesn’t determine a field — a thermal print with a torn-off header has no date to read. Ask: feed it a deliberately degraded receipt and watch what it does. If it fabricates a date to satisfy the schema, the confidence value is meaningless. The tradeoff: honest nulls lower raw recall, and for low-stakes personal expense tracking, forcing a best-guess is fine.

6. Can it explain why a claim is treated the way it is?

The ATO doesn’t care that your JSON says a line is non-claimable; a human eventually has to know why. Entertainment expenses, for instance, have their input tax credit denied by default under AU GST rules — and nothing printed on the receipt tells you that. Ask: does each tax decision carry a one-line rationale referencing the actual rule? Without it, someone on your finance side re-justifies every flagged line by hand, which defeats the automation. The tradeoff is output size and token cost; if your receipt stream never touches meals or entertainment, that reasoning is dead weight.

The honest tradeoff

Per-line tax tagging, checksum validation, schema guarantees, and calibrated nulls aren’t free — they add a verification layer and a little latency over a bare model call, and they cost more than a fraction-of-a-cent inference. For a small volume of simple expenses you check by hand, that overhead isn’t worth it: build it yourself.

For a growing feed where the tax treatment has to stand up at audit, where a stable typed contract across model upgrades matters to code you’d rather not babysit, and where “confidently wrong” is the expensive failure mode, these features are the whole point. That’s the bar we hold our own Receipt Extraction API to — per-line AU tax treatment with a rule rationale, verbatim fidelity with ABN checksum validation, honest nulls, and a schema that won’t drift on you. It’s new, and we’d rather you test it against these six questions than take our word for it.

Run your hardest receipts through whatever you’re considering — including us — and see which ones admit what they don’t know.

GST/ABN handling reflects publicly documented Australian tax law and is provided as software output, not tax advice.

Related Posts

A wrong ABN and a smudged one look the same to OCR. We made sure ours doesn't guess.

A wrong ABN and a smudged one look the same to OCR. We made sure ours doesn't guess.

Every Australian Business Number carries a checksum — a modulus-89 formula baked into the digits themselves, so a wrong ABN is usually mathematically detectable, not just "looks a bit off." Which…

read more
Build vs. buy: should your bookkeeping tool parse receipts with a raw LLM call?

Build vs. buy: should your bookkeeping tool parse receipts with a raw LLM call?

Here's the honest version of the pitch first: if all you need is vendor, date, and total off a receipt, you should probably build it yourself. A single vision-model call — GPT-4o-mini, Gemini Flash…

read more
Choosing a product categorization API: five questions that separate grounded from guessing

Choosing a product categorization API: five questions that separate grounded from guessing

If you're mapping a product feed to the Google Product Taxonomy, you have more options than you did a year ago — a raw LLM call, a handful of categorization APIs, a feed tool with categorization…

read more
The GST rule your receipt scanner doesn't know exists

The GST rule your receipt scanner doesn't know exists

A restaurant receipt and a client dinner look identical to an OCR tool. Under Australian GST rules, they aren't: entertainment expenses have their input tax credit (ITC) denied by default — GST was…

read more
How to integrate the catalog attribute normalizer MCP server

How to integrate the catalog attribute normalizer MCP server

This guide covers the mechanical integration steps for the catalog-attribute-normalizer MCP server: client configuration, authentication, and tool usage, so you can normalize product catalogs against…

read more
How to integrate the ACJ Labs receipt extraction MCP server

How to integrate the ACJ Labs receipt extraction MCP server

This guide covers the mechanical integration steps for the ACJ Labs receipt extraction MCP server: client configuration, authentication, schema definitions, and error handling, so you can consume the…

read more
x402 Bazaar Listing Monitor: catch a vanished listing before your revenue does

x402 Bazaar Listing Monitor: catch a vanished listing before your revenue does

If you sell over x402, your buyers find you through Coinbase CDP's Bazaar discovery catalog. It's the directory that lets an agent or a buyer's client discover your payTo address and the resources…

read more
How accurate is "just ask the model to categorize it"? We measured — 1–2 of 12 checks.

How accurate is "just ask the model to categorize it"? We measured — 1–2 of 12 checks.

If you're mapping a product catalog into Google's Product Taxonomy, the obvious first move is to hand the title and description to a capable model and ask for the category. It reads well in a demo.…

read more
AI product classifiers hand you category IDs that don't exist. Here's how we stopped ours.

AI product classifiers hand you category IDs that don't exist. Here's how we stopped ours.

Ask a capable AI model to classify a product into Google's Product Taxonomy and it will do something unsettling: return an ID that looks completely valid — right format, plausible category name — and…

read more