# Snap Receipt: receipts, costed to the job

> Snap Receipt reads every line of a supply-counter receipt, files it under the right supplier and costs it to the right job. Built for tradespeople. Where the AI is used, and where it isn't.

Source: https://ahmedprime.dev/projects/snap-receipt

# Snap Receipt

- Status

  Live

- Platforms

  iPhone · Android

- Since

  February 2026

- Stack

  Flutter · TypeScript · Hono · PostgreSQL · BullMQ · MCP

- Last shipped

  2026-10-01

- Links

  - [snap-receipt.app](https://snap-receipt.app)
  - [App Store](https://apps.apple.com/us/app/snap-receipt-expense-tracker/id6764552545)
  - [Google Play](https://play.google.com/store/apps/details?id=com.appsvanta.expense_tracker)

What did that job actually cost?

Most tradespeople find out at tax time. From a shoebox.

Photograph a supply-counter receipt. Snap Receipt reads every line item, files it under the right supplier and costs it to the right job. You know what a job has cost so far, in money and in materials, and you can show the client where the money went.

![A Home Depot receipt read by Snap Receipt on Android: PTFE tape, saw blades and nitrile gloves, each line with its quantity and unit price, filed under Materials, $51.07 in all, and a job one tap away.](/_astro/snap-receipt-line-items.CRWRbV8q_Z18f6H3.jpg)

- [snap-receipt.app](https://snap-receipt.app)
- [App Store](https://apps.apple.com/us/app/snap-receipt-expense-tracker/id6764552545)
- [Google Play](https://play.google.com/store/apps/details?id=com.appsvanta.expense_tracker)

## Who it's for

Plumbers, electricians, HVAC techs, handymen, mobile mechanics, builders and fitters. Solo operators and crews of up to five.

Not household budgets. Not invoicing, payroll or bank reconciliation.

## Built for consumers, kept by tradespeople

Snap Receipt launched as a consumer spending app, with budgets, shopping lists and subscription detection. In June 2026 the usage data told a different story: the people who stayed were self-employed trade contractors, using it as a receipt shoebox for their jobs.

So I rebuilt the product around jobs, suppliers and clients, and shipped it on 2 August. The consumer features weren't hidden behind a setting. They were deleted, and their endpoints answer 410 so old app versions get a clean answer. Tax figures became a by-product instead of the point.

## What it does

- **Line-item scanning.** Merchant, date, taxes, tips, fees, total, payment method, and every line with quantity and unit price. A 60-line supply-house invoice gives you 60 items.
- **Bad scans get flagged.** Unreadable receipts are flagged, likely duplicates are caught, and photos that aren't receipts are rejected.
- **Jobs, clients and budgets.** Live job cost by category and supplier, with budget alerts.
- **One supplier, however it's spelled.** Five spellings of the same supply house add up to one real total.
- **Price history.** What you paid for that fitting last month, and where it was cheaper.
- **Reports** for clients and accountants: job cost, client expenses, supplier spend, quarterly figures. PDF and CSV.
- **Ask.** A question in plain English, answered from your own records.
- **Your AI assistant, connected** (on Pro). Claude, ChatGPT, Codex and Grok can read your records through a secure connector, plus a plugin with five ready-made skills: job cost, supplier prices, quarter-end figures, client report, receipt clean-up.

* ![Snap Receipt's dashboard on Android for July 2026: $10,968.35 across 47 receipts, Materials the top category, two active jobs, the receipts still to cost to a job, and the plan's scans used so far.](/_astro/snap-receipt-dashboard.BA43EN7b_ZNa8WD.jpg)

  Dashboard
* ![Further down Snap Receipt's dashboard on Android: July's spending climbing through the month, and the total split by category, Materials and subcontractor labour first.](/_astro/snap-receipt-categories.Djjje33y_ZtW76G.jpg)

  Expenses by category
* ![A job in Snap Receipt on Android: Flooring for the Johnson Residence, $3,050 spent of a $5,000 budget, where the money went, and buttons for the full report and the client expense report.](/_astro/snap-receipt-job.Bo58BSAx_1PILJ3.jpg)

  Job

## Where should AI be trusted with money?

Only where you can check its work.

**Extraction.** One structured call per receipt, against a strict schema. The prompt's first rule: *a wrong value is worse than an empty one.* The model never infers a missing amount and never "fixes" the arithmetic, so some receipts come back with a field for you to fill. An empty field gets noticed. A wrong one gets filed. Every receipt records which model read it, so the model can be swapped without losing the audit trail.

**Ask.** The model is a query planner, not an oracle. It turns your question into a typed query. The server runs it, computes the figures and writes the answer. The model never sees your job, client or supplier names, and never produces a number.

*Diagram: How Ask works in Snap Receipt: the model sees only the question and turns it into a typed query; the server runs the query against your records and computes every figure, so the model never sees a name or a number.*

### The connector (MCP)

- Read-only by construction. Its 25 tools come from an explicit list, and the only one that changes anything is `switch_account`, which changes whose records you're reading, not the records. A test enforces it.
- Sign-in through its own OAuth server: PKCE, single-use codes, the app's own email sign-in, and refresh tokens that rotate, where a replayed token revokes the chain.
- A coverage tool tells the assistant which questions the data can't answer, like revenue or mileage, so it declines instead of guessing.
- Receipt photos never leave the app.

A permission check can be wrong. A tool that doesn't exist can't be called.

## Decisions

### Why is manual entry never limited?

Because a tool that stops you recording the work is a tool you stop opening. AI scans cost money, so each plan includes a number of them. Typing a receipt in by hand is unlimited on every plan.

### How do you match suppliers without wrecking someone's data?

A deterministic key plus a similarity score. Above one threshold it links automatically, above a lower one it suggests a merge, and a merge never destroys anything. A human's decision always outranks the matcher.

### How do you stop a new category shipping unreachable?

The category list in the AI prompt is generated from the same table the tax report uses. One source, so they can't drift.

### What happens to old app versions when an endpoint goes away?

Retired endpoints answer with a clean "gone", so old versions degrade politely instead of crashing.

### Technology choices

| Layer           | Choice                                                   | Why                                                                                                |
| --------------- | -------------------------------------------------------- | -------------------------------------------------------------------------------------------------- |
| Mobile          | Flutter, Riverpod 3, GoRouter, Dio                       | One codebase for iPhone and Android, on the same architecture as my other Flutter apps             |
| Subscriptions   | RevenueCat                                               | Store billing on both platforms through one entitlement model                                      |
| Backend         | Node.js and Hono, use-case architecture                  | Every request runs through a use-case with its own context. Easy to test, easy to expose to agents |
| Database        | PostgreSQL with Drizzle ORM                              | Typed schema, migrations as code, line items as first-class rows                                   |
| Background work | Redis and BullMQ                                         | Summaries, alerts and heavy jobs stay off the request path                                         |
| AI              | Vercel AI SDK through OpenRouter, Zod schemas            | The model is configuration. It moved from Gemini to an OpenAI model in September without a rewrite |
| Agent access    | MCP over streamable HTTP, its own OAuth server with PKCE | A standard door for Claude, ChatGPT and Codex                                                      |
| Reports         | Puppeteer                                                | Pixel-accurate PDFs from HTML templates                                                            |
| Monitoring      | Sentry                                                   | Errors from the phone and the server in one place                                                  |

## The numbers

- **934 commits since 11 February 2026.** One author.
- **About 62,000 lines of Dart and 66,000 lines of TypeScript,** tests included.
- **Version 26.10.1** on both stores, 1 October 2026.

## What this project says about how I work

- I changed the audience when the usage data said to, and deleted what the new audience didn't need.
- The model plans the query. The server computes every number the user acts on.

**Still have questions?** [Ask the agent about this page](/ask?about=snap-receipt)

- [How does Snap Receipt keep the AI away from the numbers?](/ask?about=snap-receipt\&q=How+does+Snap+Receipt+keep+the+AI+away+from+the+numbers%3F)
- [Why did it pivot to tradespeople?](/ask?about=snap-receipt\&q=Why+did+it+pivot+to+tradespeople%3F)
- [What can its MCP connector do?](/ask?about=snap-receipt\&q=What+can+its+MCP+connector+do%3F)

Or [write to Ahmed](/contact)
