n8n + n8n: Expense Report Automation — Receipt Photo on Telegram → Google Sheets

Your finance team spends the last three days of every month chasing receipts. Employees dig through email, camera rolls, and glove compartments looking for a crumpled coffee receipt from two weeks ago

n8n + n8n: Expense Report Automation — Receipt Photo on Telegram → Google Sheets

Your finance team spends the last three days of every month chasing receipts. Employees dig through email, camera rolls, and glove compartments looking for a crumpled coffee receipt from two weeks ago. Someone manually types "$14.50 — Starbucks — 07/03 — Meals" into a spreadsheet, misreads a date, fat-fingers an amount, and the reconciliation doesn't match the credit card statement. Multiply that by every employee, every card, every month. This is pure operational drag — zero strategic value, high error rate, and it scales linearly with headcount.

This article shows you how to kill that workflow entirely with n8n, Telegram, and GPT-4o Vision. An employee snaps a photo of any receipt inside a Telegram chat. Within seconds, the amount, date, category, and merchant are extracted and appended to a Google Sheet — no app to install, no form to fill, no manual data entry. Here's exactly how to build it.

Why Receipt Capture Is the Wrong Problem to Solve Manually

Expense management tools like Expensify or Ramp exist, but they carry a cost per seat, force employees into yet another app, and often require admin overhead that doesn't justify itself for a 10–50 person company. For lean teams, the friction isn't the software budget — it's adoption. Employees won't open a dedicated app to log a $9 parking receipt. They will send a photo to a Telegram bot, because Telegram is already open on their phone.

The core insight: receipt data extraction used to require either human labor or brittle OCR that broke on crumpled thermal paper and non-standard layouts. GPT-4o Vision changes the economics. It reads a photographed receipt the way a person does — it understands that the largest number near the word "TOTAL" is the amount, that "07/03/26" is a date, and that a merchant named "Shell" means the category is Fuel/Transport. You stop maintaining regex rules and layout templates. You describe what you want in plain English and the model returns structured JSON.

The Solution Architecture

The whole system is one n8n workflow with roughly six nodes. The data flow is linear and easy to reason about:

Telegram Trigger → Get File → GPT-4o Vision (extract) → Parse JSON → Google Sheets Append → Telegram Reply.

An employee photographs a receipt and sends it to your company bot. The Telegram Trigger node fires on the incoming message, n8n downloads the image, sends it to OpenAI's vision model with an extraction prompt, parses the returned JSON, appends a row to the current month's sheet, and sends a confirmation message back — "✅ Logged: $14.50, Meals, Starbucks, Jul 3." The employee gets instant feedback that the expense was captured, which is exactly the reinforcement that drives adoption.

Step-by-Step Setup in n8n

Before you build, create a Telegram bot via @BotFather and copy the bot token. Create a Google Sheet with columns: Date, Amount, Category, Merchant, Employee, Raw Text. You'll also need an OpenAI API key with GPT-4o access.

1. Telegram Trigger node. Add the Telegram Trigger node and connect your bot credential (the BotFather token). Set Updates to message. This node emits an event every time someone messages the bot. The incoming photo arrives as an array under message.photo, where the last element is the highest resolution.

2. Telegram — Get File node. Add a Telegram node, resource File, operation Get File. Set the File ID to an expression pointing at the largest photo: {{ $json.message.photo[$json.message.photo.length - 1].file_id }}. This returns the actual image binary that you'll feed to the model. Make sure the node's output includes binary data (n8n handles this automatically for file downloads).

3. OpenAI Vision node. Add the OpenAI node (or the HTTP Request node if you want raw control), model gpt-4o. Use the "Analyze Image" operation, pass the binary from the previous node, and set the prompt to force structured output:

"You are a receipt parser. Extract these fields from the receipt image and return ONLY valid JSON, no markdown: {amount: number, currency: string, date: string in YYYY-MM-DD, merchant: string, category: one of [Meals, Travel, Fuel, Office, Software, Other]}. If a field is unreadable, use null."

Set temperature to 0 so extraction is deterministic, and enable JSON response mode if available. Determinism matters here — you want the same receipt to always parse identically.

4. Parse / Set node. The model returns a JSON string. Add a Code node or an Edit Fields (Set) node to parse it: {{ JSON.parse($json.message.content) }}. Wrap this in a try/catch inside a Code node so a malformed response doesn't crash the run — if parsing fails, route the raw text to a "needs review" column instead of dropping it.

5. Google Sheets — Append node. Add the Google Sheets node, operation Append Row. Connect your Google credential, select the spreadsheet, and map each column to the parsed fields. For the sheet name, use an expression that targets the current month — e.g. {{ $now.format('yyyy-MM') }} — so July receipts land in the "2026-07" tab automatically. Add the Telegram username via {{ $('Telegram Trigger').item.json.message.from.username }} so you know who submitted each expense.

6. Telegram — Send Message node. Close the loop with a confirmation reply. Set the chat ID to {{ $('Telegram Trigger').item.json.message.chat.id }} and the text to something like ✅ Logged: {{ $json.amount }} {{ $json.currency }} — {{ $json.category }} @ {{ $json.merchant }} ({{ $json.date }}). This single message is what makes the system feel instant and trustworthy to employees.

Activate the workflow. Total build time is well under an hour, and the whole thing runs on your existing n8n instance with no per-seat cost.

The Payoff: What This Actually Buys You

The obvious win is eliminated data entry — but the second-order effects are bigger. Because capture happens at the moment of the transaction, receipts stop getting lost. There's no month-end scramble because the spreadsheet is already complete and current. Reconciliation becomes a diff against the card statement rather than a reconstruction from memory.

Adoption climbs because the interface is a chat app employees already use, and the confirmation reply gives them certainty their expense is filed. Data quality improves because GPT-4o reads amounts and dates more reliably than a tired human transcribing at 11pm. And because everything lands in a structured Google Sheet, you get downstream analytics for free — pivot by category, by employee, by month, or pipe it into your accounting system with another n8n branch. For a 30-person team, this quietly reclaims several hours of finance labor every single month and removes an entire category of manual error.

Common Pitfalls and How to Avoid Them

Grabbing the wrong photo resolution. Telegram sends multiple sizes in the photo array. Always take the last element for the highest resolution — low-res thumbnails cause the vision model to misread small print like the total.

Trusting the JSON blindly. Vision models occasionally wrap output in markdown fences or add a stray sentence. Strip code fences and wrap your parse in a try/catch. Route failures to a "review" tab rather than letting them silently vanish — a dropped receipt is worse than a flagged one.

Ambiguous dates. A receipt showing "03/07" is July 3rd in most of the world and March 7th in the US. Instruct the model in your prompt to assume your team's locale, and normalize everything to YYYY-MM-DD before it hits the sheet. Consistency here saves you from broken sorting and reporting later.

No spend controls or duplicate detection. Someone will eventually photograph the same receipt twice. Add a lightweight dedupe step — hash the amount+date+merchant and check the sheet before appending — or run a weekly n8n job that flags duplicates. Similarly, consider an IF node that pings a manager channel when an amount exceeds a threshold.

Multi-currency and tips. If your team travels, capture the currency field explicitly (already in the prompt above) and don't assume dollars. For restaurant receipts, decide whether you want the pre-tip subtotal or the final total, and state it in the prompt so the model is consistent.

Handle these five cases and you have a production-grade expense pipeline that runs itself. The build is simple; the discipline is in the edge cases. Get the extraction prompt tight, guard the parsing, and let n8n do the rest.

Expense Report Automation — Receipt Photo on Telegram → Google Sheets
PRONTO PARA USAR

Ja construimos isso pra voce

Nao comece do zero. O Expense Report Automation — Receipt Photo on Telegram → Google Sheets e um workflow n8n pronto para instalar — conecta suas ferramentas em minutos, sem codigo.

Instalar por $29.0 →