0saas

Job ticket 917123 · smb · expense desk · no subscription

Expensify scans receipts free — and prices the judgment at US$5 a member.

Submit is genuinely free: unlimited SmartScans, reports, categories. The paid step is exactly the judgment work — categorizing against company rules, flagging policy breaks, assembling the sheet an approver signs. That is rule-reading a free-tier model does on lines you paste. No card feed needed.

Expensify is a trademark of Expensify, Inc. This is an independent, unaffiliated comparison built on Expensify's own published pricing page, linked below and re-read every thirty days.

The expense desk — rendered in this browser

Source: noneRendered: 0Uploaded to 0saas: nothing

Sample data is illustrative, not a claim about Expensify. Every Expensify figure on this page comes from the linked pricing page, read 2026-09-28.

The prompt pack

Two prompts, each mapped one-to-one onto a Expensify feature you are currently rationed on. Run them from this page with a free key, or copy them into any free chat model — the text is identical either way, and it is printed in full at the bottom of this section so it survives this site.

Loading the pack from tools.json… If this fails, the full prompt text is still readable below.

One-time unlocks only, never a subscription. If a price ever appears here it was read from Stripe in that request, not typed by hand. An unlock is client-side gating, not secure payment verification: it is stored in this browser and cannot prove payment to anyone else.

What Expensify's own pricing page says

Read from expensify.com — pricing and plans on 2026-09-28. Fields we could not read are marked unconfirmed rather than filled in with a plausible number.

Where the free plan stops, and what this desk hands over — verified 2026-09-28
The jobExpensify Submit (free)The paid stepThis page + a free-tier model
Receipt scanningUnlimited SmartScans, US$0—You paste the lines; no OCR needed
Categorization'Requires a paid plan' per the FAQCollect, US$5/member/moGrouped, categorized rows per run
Policy rules & flagsCustom rules on ControlFrom US$9/active memberFlags against the rules you paste
Approvals & reimbursementApproval flows on Collect and upUS$5+/member/moOut of scope — a submission note, not a rail

What this replaces, and what it does not

A displacement claim you cannot substantiate is a lie with good typography. This is the whole scope, including the parts where Expensify wins.

Reports as files

A categorized, totaled sheet per pile, exported as CSV or Markdown — paste it into whatever approvals process you already run.

Your pile stays yours

Nothing is stored, synced or uploaded. No card feed, no SSO, no accounting connection.

Rules you wrote

The auditor enforces your pasted rules and quotes them; change the rules text and the flags change on the next run.

Not a spend platform

No reimbursement rails, no corporate cards, no ERP sync. Expensify (or your bank) still moves the money.

No receipt OCR

You paste the lines; the desk reads text, not photos. SmartScan remains genuinely free on Expensify's own Submit plan.

Not the approver

The auditor flags and cites; a human still approves, and should.

The prompts, in full, as text

Copy these into any model. They are the product; the page around them is convenience. Each block is the exact system prompt the interactive runner sends, plus the user-message template.

Prompt 01 — 1. Pile-to-report builder · expensify-report-builder v1.0.0 · best ally: Google Gemini API — Free usage tier · gemini-2.5-flash-lite

Replaces: The categorized-and-totaled report Collect prices at US$5 a member: raw pasted lines become a grouped, subtotaled expense sheet with a submission note.

Why this model: Grouping and totaling pasted lines is precise extraction with light judgment; a free Flash-lite at low temperature keeps amounts, dates and vendors intact while it categorizes. Fallback ally: Groq Cloud — free tier.

System prompt (1558 chars):

You sit at the expense desk: the reader pastes a raw pile of expense lines — dates, vendors, amounts, half-remembered contexts — and you return a report sheet: every line categorized, grouped, subtotaled, and a one-paragraph submission note an approver can read in fifteen seconds. You never alter an amount, and when a line is ambiguous you categorize it to the best reading and flag it in footnotes instead of guessing silently.

Return ONLY one JSON object. No markdown fences, no commentary, no preamble.

{
  "kicker": string (max 8 words),
  "headline": string (max 8 words),
  "subhead": string (max 20 words),
  "rows": [ { "label": string (the line item), "value": string (the finding, quote or number) } ],
  "stat": { "value": string (one count or price, digits), "label": string (max 12 words, what the number is) },
  "footnotes": [ string (one short footnote per assumption made) ]
}

Hard rules:
1. Return one row per expense line: label is 'DD Mon — Vendor', value is 'US$X.XX · category · one-clause context'.
2. Group rows by category in this order: Travel, Meals, Software, Supplies, Other.
3. The stat is the report total in US dollars, summed exactly from the pasted amounts — re-add before you finalize.
4. The subhead states the count of lines and the count of flagged lines.
5. Footnotes carry every flag: ambiguous vendor, missing date, amount near a policy limit — one clause each.
6. Never invent a line, a date or an amount; if the pile contains a total that disagrees with your sum, flag it in footnotes and keep your arithmetic.

User message template:

Build the report sheet from this pile. Expense lines: {{pile}} Your categories and any context (one line): {{policy}}

Variables:

  • {{pile}} — The raw expense lines (max 2500 chars) sample data shipped with the tool
  • {{policy}} — Categories, or any context the desk should know (max 400 chars) sample data shipped with the tool

Output schema (the answer must match this exactly):

{ "type": "object", "required": [ "rows" ], "properties": { "kicker": { "type": "string" }, "headline": { "type": "string" }, "subhead": { "type": "string" }, "rows": { "type": "array", "minItems": 1, "maxItems": 40 }, "stat": { "type": "object" }, "footnotes": { "type": "array" } } }

Decoding: temperature 0.2 · max 2000 output tokens · responseMimeType application/json · budget ~450 in / ~900 out for a week's pile · cost per run: 1 request against Gemini's free daily messages; the relay floor needs no key at all.

Prompt 02 — 2. Policy auditor · expensify-policy-auditor v1.0.0 · best ally: Google Gemini API — Free usage tier · openai/gpt-oss-120b

Replaces: The rules layer that Control sells from US$9 a member: every line checked against the rules you paste, each flag carrying its reason.

Why this model: Auditing lines against written rules is deterministic rule-reading with quotes; a free instruct model at low temperature cites each line, names the rule broken, and never inflates a flag. Fallback ally: OpenRouter — :free model variants.

System prompt (1428 chars):

You are the desk's policy auditor. Read the pasted expense lines against the pasted rules and file an audit sheet: one row per line that breaks or strains a rule, each row quoting the line, naming the rule, and proposing the smallest fix. Lines that pass never appear — silence is a finding, and the sheet's stat counts what passed.

Return ONLY one JSON object. No markdown fences, no commentary, no preamble.

{
  "kicker": string (max 8 words),
  "headline": string (max 8 words),
  "subhead": string (max 20 words),
  "rows": [ { "label": string (the line item), "value": string (the finding, quote or number) } ],
  "stat": { "value": string (one count or price, digits), "label": string (max 12 words, what the number is) },
  "footnotes": [ string (one short footnote per assumption made) ]
}

Hard rules:
1. Return one row per flagged line: label quotes the line's vendor and amount, value names the rule broken and the fix in one sentence.
2. Order rows by amount, largest first.
3. The stat is the count of lines that passed, and the label says so plainly ('of N lines, X passed').
4. Name the rule by its own words from the pasted rules; if two rules conflict, flag the conflict instead of picking silently.
5. A flag needs a fix smaller than the violation: an attendee name, a client code, a re-categorization — never a lecture.
6. If every line passes, the sheet says exactly that in one row and the stat states it.

User message template:

Audit these lines against these rules. Expense lines: {{lines}} The rules: {{ruleset}}

Variables:

  • {{lines}} — The expense lines to audit (max 2000 chars) sample data shipped with the tool
  • {{ruleset}} — The rules to check against (max 800 chars) sample data shipped with the tool

Output schema (the answer must match this exactly):

{ "type": "object", "required": [ "rows" ], "properties": { "kicker": { "type": "string" }, "headline": { "type": "string" }, "subhead": { "type": "string" }, "rows": { "type": "array", "minItems": 1, "maxItems": 40 }, "stat": { "type": "object" }, "footnotes": { "type": "array" } } }

Decoding: temperature 0.2 · max 1600 output tokens · responseMimeType application/json · budget ~400 in / ~700 out for a week's lines · cost per run: 1 request against Groq's free daily pool; the relay floor needs no key at all.

Questions worth asking before you cancel

Expensify's scanning is free — what exactly is being replaced?

The layer above the scan: categorization against company rules, policy flags, and the totaled report with its submission note. Their own FAQ says expense categorization requires a paid plan; that is the US$5/member step this desk displaces, read 2026-09-28.

Can it get a total wrong?

It can, which is why the sheet's stat is re-added from your pasted amounts and any disagreement is flagged in footnotes. Check the stamp against the pile once; you'll see the discipline immediately.

What about photos of receipts?

Out of scope — the desk reads pasted text. Expensify's free Submit plan handles OCR honestly and well; use it for capture and this desk for judgment.

Where do my expense lines go?

Nowhere. No account, no storage, no analytics beyond the site beacon. Paste, render, download, clear the tab.

Does it work without an API key?

Yes. Copy the printed prompt into any free chat model, paste the JSON answer into the relay box, and the sheet renders exactly the same way.

Nothing is loaded from X or LinkedIn until you click, and no share is counted, logged or reported back to us — the buttons are plain links to each network's own share page.

Next on the ledger