How to Use AI to Read Restaurant Invoices Without Losing Control of Costs

A repeatable photo-to-accounting workflow: capture, structured extraction, arithmetic and unit checks, a manager's approval, then posting. With a fictional invoice to practice on.

Ryan Speier

You can photograph a supplier invoice, ask an AI model to turn it into line-by-line data, and carry that draft through to your books. The part that protects your food cost is not the model. It is the set of checks that sit between the photo and the accounting entry: the arithmetic ties to a documented basis, every line has a unit you recognize, the quantities match what receiving actually accepted, the document is not a repeat or a credit in disguise, and a person approves before anything is posted or paid. This post lays out that workflow, with a fictional invoice to practice on, a copyable extraction schema and a short checklist for whoever holds the phone.

It is a workflow guide, not a product announcement and not a report of a test. The prompt and schema below are proposed, not benchmarked. The approach depends on the tool you choose supporting what it needs to: a photo or PDF as input and structured text as output, under business terms you have read. Check that before you start, and keep every approval and payment control you already have.

Who this is for and what you need

  • Owner: you want per-unit costs and price changes visible soon after delivery, without giving up the sign-off on what gets paid.
  • Manager or bookkeeper: you enter or import invoices and would rather check a draft than type from scratch.
  • Receiving staff: you take the photo and you record what actually arrived. Those two records decide whether the rest of the chain works.

Needed: a phone; an AI tool that accepts images and returns structured text, on an account whose data terms you have read (see the data section); a spreadsheet or your accounting system; your receiving log; and a one-page pack list of your items with their case and pack sizes. Expect to spend time on the pack list before the first invoice and on tuning the prompt to whatever your tool returns.

The workflow in five steps

  1. Capture. One clear photo per page, every page, plus any credit memo or delivery ticket photographed separately and labelled.
  2. Extract. Ask the model for a transcription into a fixed shape: what is printed, nothing calculated, unreadable fields left empty and flagged.
  3. Check. Recompute lines and totals against the invoice's own basis, confirm units and pack sizes against your pack list, match quantities to your receiving record, and look for repeats and credits.
  4. Review and approve. A manager compares the draft with the paper and the receiving record, resolves or holds every open question, and records the approval.
  5. Post. Enter or import the approved lines into accounting and inventory, with freight, fuel, deposits and tax captured as separate fields and allocated the way your accountant has set up. Payment follows your normal approval, never the extraction.

Step 1: capture the photo

A photo the model cannot read can produce a confident-looking draft with wrong numbers in it, so capture is the first control. Flat surface, whole page in frame, even light, no thumb over the totals, one photo per page. A blurred or shadowed line is a retake, not a guess. If the invoice says "Page 1 of 2", there is a page 2. Photograph credit memos and delivery tickets as their own documents and say what they are when you send them: a delivery ticket has quantities but usually no prices, and a credit memo may print its amount as a positive number under a "credit" heading.

Provider documentation is useful here for what to expect. One provider's guide to image inputs (OpenAI, Images and vision, read September 19, 2026) lists limitations of its vision models that map directly onto invoices: small text should be enlarged, rotated or upside-down text may be misread, images may be resized before analysis, counts may be approximate and descriptions may simply be wrong. Treat that as a checklist for your photos whatever tool you use, not as a statement about any tool's accuracy on your invoices.

Take the photo before the paper goes back on the truck or into a pile, and note the supplier and the printed document number, because that pair is the start of your duplicate check later.

Step 2: ask for a structured draft

Do not ask the model to "process this invoice". Ask it to transcribe what is printed into a fixed shape, to leave anything unreadable empty, and to add a flag whenever it is unsure. Calculation is your job in step 3, not the model's, because a model that helpfully "fixes" a total hides the very disagreement you need to see.

A proposed prompt, to adjust to your tool:

You are transcribing a photo of a restaurant supplier document.
Return only JSON that matches the schema below.
Copy values exactly as printed, including any minus sign, "CR" or "credit"
label. Do not calculate, round or correct anything.
If a value is unreadable, cut off or missing, use null and explain in "flags".
Never guess a pack size or a unit. If the document says it has more pages than
you were given, say so in "flags". If it is a credit memo, delivery ticket or
statement rather than an invoice, say so in "document.type".

And the schema to paste under it. Adjust field names to what your spreadsheet or import expects; keep the printed-sign, flags and confidence fields whatever else you change.

{
  "document": {
    "type": "invoice | credit_memo | delivery_ticket | statement | unknown",
    "supplier_name": "",
    "document_number": "",
    "document_date": "YYYY-MM-DD or null",
    "references_document_number": "for a credit memo, the invoice it credits, or null",
    "pages_stated": null,
    "pages_received": null,
    "delivered_to": ""
  },
  "lines": [
    {
      "line": 1,
      "item_code": "",
      "description": "",
      "quantity": null,
      "unit": "case | bag | jug | each | lb | unknown",
      "pack_size_text": "exactly as printed, for example 4/10 lb or 500 ct",
      "unit_price": null,
      "extended_price": null,
      "printed_sign_or_label": "as printed: minus sign, CR, credit, or none",
      "confidence": "high | medium | low",
      "notes": ""
    }
  ],
  "charges": [
    { "kind": "freight | fuel | deposit | tax | discount | other", "description": "", "amount": null, "printed_sign_or_label": "" }
  ],
  "totals": {
    "subtotal_printed": null,
    "total_printed": null,
    "total_printed_sign_or_label": "as printed next to the total: minus sign, CR, credit, or none",
    "totals_raw_text": "the totals block exactly as printed, one line per amount"
  },
  "flags": []
}

This schema was written for this post and has not been run against any named product. The prompt asks for this shape; it does not make the output match it. Validate every response against the schema before any check runs, and treat a response that does not parse, or that is missing fields, as a failed extraction to redo, not as data. Expect to tune the wording to whatever your tool returns, and keep a copy of every raw response next to the photo.

A worked example with a fictional invoice

Everything below is invented for teaching. Harborline Foods is a fictional teaching supplier, and the prices, tax rate and credit are not market figures for any date or region. Invoice HL-20481, dated September 9, 2026, delivered to a fictional bistro, marked "Page 1 of 1".

LineDescription as printedQtyUnitPackUnit priceExtended
1Tomatoes, Roma1case25 lb$28.50$28.50
2Onions, yellow2bag50 lb$22.00$44.00
3Chicken thighs, bnls sknls2case4/10 lb$96.00$192.00
4Oil, canola fryer3jug35#$41.25$123.75
5Container, deli 16 oz w/lid1case500 ct$58.90$58.90

Below the lines: subtotal $447.15; fuel surcharge $6.50; crate deposit, 2 at $6.00, $12.00; sales tax on non-food items $4.71; total $470.36. The receiving log for the same delivery records one case of Roma tomatoes refused at the door as damaged, everything else accepted as billed. The next day a credit memo CM-20481-A arrives showing "28.50 CR" against HL-20481.

What a good draft looks like

Five lines with quantities, units, the pack text copied verbatim, unit and extended prices, the charges, the two printed totals with whatever sign or label sits beside them, and flags such as "line 4 unit price partly covered, read as 41.25 with medium confidence" or "line 4 pack printed as 35#; meaning of # not confirmed". The model should not have converted 35# to 35 lb on its own. The credit memo, transcribed separately, should carry the printed "28.50 CR" in the total's sign-or-label field and the raw totals text, with the document type set to credit_memo, even when no line carries a label of its own; deciding that it posts as a negative is the reviewer's job, not the transcription's.

The unit math you do in step 3

Per-unit cost comes from the extended price and the pack size, never from a rounded unit cost typed back in.

  • Tomatoes: $28.50 for one 25 lb case is $1.14 per lb.
  • Onions: $44.00 for 100 lb (two 50 lb bags) is $0.44 per lb.
  • Chicken thighs: "4/10 lb" is four 10 lb bags per case, so two cases are 80 lb and $192.00 divided by 80 is $2.40 per lb. Read the pack as "2 each" and your recipe cost for chicken is wrong by a factor of forty.
  • Oil: "35#" is a pack notation to confirm against the supplier's own item listing or your pack list, not to assume. If it is 35 lb, $41.25 divided by 35 is $1.1786 per lb. If your inventory counts oil in jugs, keep the jug price and the confirmed pounds per jug in the pack list instead of converting on every invoice.
  • Containers: 500 per case, so $58.90 divided by 500 is $0.1178 each. Round that to $0.12 and re-extend it and you get $60.00, not $58.90. Store the printed extended price as the transcribed figure and the per-each cost as a derived number with four decimals.

Case versus each, and the pack list

A line where the invoice unit is a case and the inventory unit is an each, a pound or a portion is where recipe costs go quietly wrong. Maintain one pack list per supplier: item code, description, invoice unit, units per pack, your inventory unit, and the date you confirmed it. The check in step 3 is then "does this line's pack text match the pack list?" When it does not, the line goes to a person, and the pack list is updated after the person decides, so the same question is not asked next week.

Step 3: the checks

Some of these are formulas a spreadsheet or an import rule can run. Others need a person with the paper, the photo and the receiving log in front of them. The table says which.

CheckRuleWho or whatIf it fails
Complete documentPages received equals pages stated; supplier, document number, date and document type present; photo legiblePersonStop. Capture the missing page or field before checking totals.
Line arithmeticQuantity times unit price equals extended price on the invoice's own basis: catch weights, discounts, tax-included pricing and the supplier's rounding all change what "equals" meansFormula, with the basis documented per supplierExplain the difference; do not adjust either figure. A mismatch may be a legitimate basis you have not recorded yet, or a misread.
Subtotal and totalSum of extended prices equals the printed subtotal; subtotal plus every charge equals the printed total. In the example: 447.15 + 6.50 + 12.00 + 4.71 = 470.36FormulaA line or charge was missed, doubled or misread, or the invoice itself is wrong. Either way it is held, not fixed.
Units and packsEvery line has a unit and its pack text matches the pack listFormula flags; person decidesRoute to a person; update the pack list after the decision.
Received quantitiesBilled quantities match the receiving log, including refusals and returnsPerson, with the receiving recordInventory takes what was accepted, not what was billed. Hold the difference for the supplier credit.
Repeat or reissued documentSupplier plus document number, date and document type compared against your retained payables history, all of it; where the number is unclear, compare dates, totals and the images tooFormula on the identifiers; person on the near-matchesHold for reconciliation. A reissued invoice is not posted twice and not ignored.
CreditsA credit memo is transcribed with its printed sign or label and linked to the invoice it credits; the accounting sign is decided at reviewPersonPost it as its own document. Never net it into an invoice line; the supplier statement has to reconcile.
ChargesFreight, fuel, deposits, tax and discounts are captured as separate fieldsFormula captures; accountant's rules allocateAllocation (expense, landed inventory cost, refundable deposit, tax) follows what your accountant has set up, not a rule of thumb.
Price changeUnit cost for the same item code compared with the last approved invoice; a change over your own threshold is flaggedFormula flags; person confirmsConfirm the price or call the supplier before approval.
Unresolved uncertaintyNo open flag, no low-confidence field, and every field checked against the source even when the model marked it highPersonAnything unresolved is held. Confidence labels describe the model's guess, not the document.

On the fictional invoice the arithmetic ties, so the questions that reach a manager are the ones a formula cannot settle: what 35# means for this supplier, whether the chicken pack is four 10 lb bags, that receiving accepted one fewer case of tomatoes than was billed, and whether CM-20481-A has already been applied.

Step 4: review and approve

The manager opens the photo, the draft and the receiving record side by side, reads the flags first, then runs down every line. Corrections go into the draft, not into the accounting entry, so the raw response, the corrected draft and the approval are three separate records. Approval means a named person, a date and the document number. A price change that was accepted is a decision, and the pack list or price list is updated so next week's check compares against the approved figure.

When the draft and the paper disagree, the paper is the evidence and the model's wording is not. When the paper and the receiving log disagree, that is a supplier conversation, and the difference stays open until the credit arrives. If the supplier's own invoice is wrong, the printed figures are still what you transcribe; what you approve is what you owe.

Step 5: post to accounting and inventory

Post the approved lines the way you post any invoice. Goods go to the purchase or inventory accounts you already use. Freight, fuel, deposits and tax were captured as separate fields so that your accountant's allocation can be applied consistently: some operators expense freight, others roll it into landed inventory cost; a deposit that the supplier confirms is refundable is not a purchase expense, and one that is not refundable is treated however your accountant has decided. The credit memo posts as its own document against the same supplier, with the sign decided at review.

Inventory receives the quantities from the verified receiving record, in your inventory unit via the pack list: in the example, zero cases of tomatoes, not one, and the credit memo does not reduce stock a second time. The pack list is the most valuable file in this whole process.

Payment is a separate step with its own approval. Extraction never authorizes a payment, and neither does a draft that "looks right".

Checklists for the people doing the work

Whoever takes the photo

  • Flat, whole page, good light, no shadows or fingers, one photo per page, every page.
  • Credit memos and delivery tickets photographed separately and labelled as such.
  • Photograph before signing away the paper or before it leaves the receiving area.
  • Note the supplier and the printed document number, and record what was refused or short on the receiving log.
  • If a page is torn, wet or missing, say so in the note; do not retake from memory.

Whoever reviews

  • Flags first. Then every line against the paper, then totals against the invoice's documented basis.
  • Pack text against the pack list; any mismatch is a decision, and the list is updated afterwards.
  • Billed quantities against the receiving log; differences held for credit.
  • Repeat check on supplier, document number, date and type against all retained records; near-matches held.
  • Credits, freight, fuel, deposits, tax and discounts captured separately; allocation per the accountant's rules.
  • Record who approved and when. Only then post. Payment stays on its own approval.

Starting small

Run the workflow on a handful of invoices with every check and approval in place, and count what the draft got wrong and why. That tells you where to tighten the capture instructions or the prompt. It does not tell you which controls to drop: the approval and payment controls stay as they are, because the cost of one wrong posting is not measured by a small pilot.

Data you are uploading

An invoice carries your supplier account number, your negotiated prices and sometimes remittance or bank details. Before the first upload, read your provider's terms for business use on data retention and whether inputs are used for training, and prefer an account type where those terms are documented in writing. Do not upload supplier statements with bank details, and never upload anything with customer or employee data alongside an invoice. Keep your own copy of every photo and response; the provider's history is not your records system.

What this post does not do

  • It does not provide a tool. The schema and checks are yours to run in whatever you already use, if that tool supports the inputs and outputs described.
  • It does not claim any model reads invoices at any accuracy. Nothing here was measured; count your own errors on your own invoices.
  • It is not accounting or tax advice. Account coding, tax treatment, freight allocation and deposit handling follow what your accountant has set up.

Sources and scope

Prepared September 16 and source-checked September 19, 2026 as an evergreen workflow guide. Harborline Foods, the item prices, the tax rate, the receiving log and the credit memo are fictional and were created for this post; they are not benchmarks. The prompt and schema are original and untested against any named product. The one provider document cited, OpenAI's Images and vision guide (read September 19, 2026), is used only for its stated limitations of image inputs, not for any accuracy, pricing or data-retention claim. The checks are ordinary invoice-to-ledger and receiving reconciliation, written out so the parts a formula can test are separated from the parts a person must decide.

More on technology

Next steps

All technology posts · Free restaurant calculators · Opening planner