What it actually does

Every field is read, checked, and traced back to the original photo.

Not a scanner that hands you a total. A pipeline that decides whether that total is a legally valid GST claim, splits it correctly across tax categories, and posts it to a ledger that cannot go out of balance.

01 · Capture

The original is the legal record — kept forever

A quality gate on the device rejects a blurry or non-document frame before it ever uploads — the ATO only accepts a receipt copy that's a true and clear reproduction of the original. Once it's captured, the original bytes are never overwritten or recompressed; a separate normalised copy is derived for the model to read.

Tax invoice · captured 12 Jun 2026, 7:41am
Ironbark Trade Supplies
ABN 84 731 502 664
2 × Treated pine sleeper$34.00
1 × Impact driver bit set$28.95
1 × Safety glasses$12.50
Subtotal$75.00
GST$7.50
Total$82.50
Auto-accepted9/9 validators passed · G11 · 1B
02 · Extraction

Versioned, replayable — never a one-shot read

Claude Haiku 4.5 vision reads every field as {value, confidence, bbox}, and returns null with a reason rather than guessing. Anything uncertain escalates to Sonnet 5. Every run is kept — nothing is overwritten — so a better model in six months can re-run over your whole history without you lifting a finger.

Confidence, per field

A confident wrong ABN is worse than a missing one — it silently creates an unclaimable GST credit. The model is told to say so.

Escalation, automatic

~85% of scans resolve on the primary model. The remainder escalate to a stronger model, not to a person, unless validators still fail.

Nothing destroyed

Re-running extraction inserts a new run and moves the pointer. A posted transaction is never silently rewritten — it raises a review task instead.

03 · Validators

Nine deterministic checks — the biggest accuracy lever

Costs nothing to run and catches more than a bigger model would. Every extraction is checked against arithmetic and the ATO's own rules before anything is trusted, in code, not by asking the model to grade itself.

ABN format

Mod-89 checksum on every ABN read from the page.

ABN identity

Checked against the ABR register — legal name and GST registration status.

GST arithmetic

Exclusive amount + GST must equal the inclusive total, to the cent.

GST rate

An all-taxable invoice must show GST ≈ 1/11 of the inclusive price.

Line-item sum

Every line must add up to the invoice total before anything is trusted.

Cash rounding

AU 5c cash rounding tolerated to ±$0.02; the difference is recorded, not discarded.

Mixed-tax reconciliation

GST-free and taxable subtotals must each reconcile — not just the total.

Tax-invoice completeness

The seven ATO elements, checked — this is what sets is_tax_invoice.

Date sanity

Not in the future; not more than ten years past.

Any failure escalates to the stronger model. Still failing → flagged needs_review, with the specific check attached — never a silent guess.

04 · The ledger

Double-entry, and provably balanced

Every scan proposes a transaction with splits that must sum to exactly zero. A DEFERRABLE constraint trigger enforces it at commit, for posted transactions only — drafts can sit half-built and be edited freely. This is not a spreadsheet convention someone has to remember. Postgres refuses the commit.

$110 fuel on the card
Motor Vehicle — Fuel$100.00
GST Receivable$10.00
Credit Card$110.00
Sum$0.00
05 · BAS labels

Mapped the moment a line is posted

Each tax code carries its BAS labels — G11 and 1B for a non-capital purchase claiming a credit, G10 for capital purchases, G1 and 1A for a sale. Quarterly BAS becomes a query grouped by label, not a quarter spent re-reading a shoebox.

G11
Non-capital purchases
G10
Capital purchases
1B
GST on purchases (credit)
1A
GST on sales
06 · The unclaimable-GST report

Knows what it doesn't know — and says so before lodgement

A validator failure doesn't get silently dropped or silently claimed. It surfaces as a specific, fixable line: which receipt, which check, which fix — an ABN to chase, a re-issued invoice to request.

This quarter
$342.18

of GST credits you cannot claim. 12 receipts are missing a supplier ABN.

07 · Per-category GST subtotals

A grocery receipt, split correctly

Fresh food is GST-free; packaged snacks are taxable. Hubdoc records one header total. Snap Apps keeps a subtotal per tax category, on the same receipt, reconciled independently.

08 · The tax pack

Filled in before 1 July, not after

An occupation-aware deduction worksheet — car, travel, clothing and laundry, tools and equipment — built from a year of scans as they happen, not reconstructed from memory at tax time.

Electrician · FY2026
D1 — Car$2,140.00
D3 — Clothing & laundry$312.50
D5 — Tools & equipment$1,486.90
09 · Xero sync

Posts to the chart of accounts you already run

Snap Apps doesn't replace Xero — it feeds it a ledger that's already reconciled. Categories map to your existing accounts; BAS labels travel with each line; nothing here asks you to migrate.

See it move end to end