Downloads
Download the n8n workflow (JSON)
whatsapp-expense-tracker-n8n-claude.json · n8n workflow · 22 steps · starts with Bill photo on WhatsApp · uses WhatsApp, Google Drive, Anthropic, Google Sheets, Slack, Summarize, Gmail · 38 KB
Import into n8n: Create Workflow, then the menu, then Import from File.
How to import it into n8n
- In n8n, create a new workflow.
- Open the ⋯ menu at the top right and choose Import from File, then pick the downloaded .json. (Or open the file, copy everything and paste it on the canvas.)
- Open each node with a warning and connect your own account: the file carries no passwords or keys.
- Run it once with Test workflow, check the result, then switch it to Active.
What it does
Anyone on your team sends a bill photo to your business WhatsApp number. n8n accepts photos only from the team numbers you list, skips repeats and downloads the image. The photo is saved to your Bills folder in Drive, and Claude reads the vendor, GSTIN, bill number, date, taxable amount, GST, total, payment mode and a category. A Code node checks the numbers by rule (GSTIN format, believable date, taxable plus GST equals total) and builds a duplicate key. Duplicates get an 'already logged' reply. Bills of Rs 10,000 or more, blurry photos and anything that failed a check go to Slack for your approval; the rest are logged straight away. The sender gets a WhatsApp confirmation. On the 1st of every month, last month is totalled by category and saved as a draft email to your CA.
Who it is for
Founders, small teams and freelancers who pay for things on the go (fuel, travel, client lunches, software) and currently keep bills in a WhatsApp chat or a shoebox until the CA asks.
What you need
- An n8n account (n8n Cloud or self-hosted, reachable from the internet)
- A WhatsApp Business Cloud API number and a permanent access token
- An Anthropic API key for Claude (vision is included)
- Google Drive (a Bills folder) and a Google Sheet
- Slack with an #expenses channel
- Gmail for the monthly draft to your CA
How the workflow runs, node by node
The slides show the same steps. Open the workflow in n8n and you will see a sticky note over each one.
Step 1 · Snap the bill on WhatsApp
Anyone on your team sends a bill photo to your business WhatsApp number, with a note if they like. n8n accepts photos only from team numbers you list, skips repeats, and downloads the image.
- Bill photo on WhatsApp: Fires for every message to your WhatsApp Business number.
- Only from my team: Accepts photos only from the team numbers you list (with 91). Customers' photos and text messages never reach this flow.
- Skip repeats: Remembers every WhatsApp message id, so a re-delivered webhook never logs the same photo twice.
- Get media URL: Asks WhatsApp's Cloud API for the photo's temporary download link.
- Download bill image: Downloads the photo as a file (binary 'data'). The link expires in minutes, so this runs straight away.
Step 2 · Claude reads the bill
The photo is saved to your Bills folder in Drive. Claude reads vendor, date, bill number, GSTIN, taxable amount, GST, total and payment mode, and picks a category. n8n then checks the date, the GSTIN format and the GST maths.
- Save bill to Drive: Saves every photo to your Bills folder in Drive, named by date, time and the sender's last 4 digits. Runs before Claude, side by side.
- Read bill with Claude: Looks at the photo and returns vendor, GSTIN, bill number, date, taxable amount, GST, total, payment mode, a category from your list and a confidence score.
- Claude: Claude (claude-sonnet-5-5) at temperature 0, so answers stay consistent from run to run.
- Bill schema: Forces fixed fields (vendor, vendor_gstin, invoice_no, bill_date, taxable, gst_amount, total, payment_mode, category, confidence).
- Check the numbers: Checks Claude's numbers by rule: GSTIN format, a believable date, taxable plus GST equals total, GST not over 30%. Builds a duplicate key from vendor, bill number and total.
Step 3 · The same bill never counts twice
Each bill gets a key made from vendor, bill number and total. If that key is already in your expense sheet, the sender gets an 'already logged' reply instead of a double entry.
- Already logged?: Looks for the same bill key in your Expenses tab. Always output data is on, so new bills continue with an empty row.
- New bill?: True when the bill is not in the sheet yet. A bill already logged (the same photo sent twice, or by two people) goes to the reply.
Step 4 · Big or unclear bills come to you
Bills of ₹10,000 or more, blurry photos, or anything that failed a check go to Slack with the photo link. Tap Log it to add it. Everything else is logged straight away.
- Big or unclear?: True for bills of Rs 10,000 or more, low-confidence reads, or any failed check. These need your approval; the rest are logged straight away.
- Approve expense: Posts the bill with the photo link, the numbers and any failed check to #expenses, and waits up to 20 hours (inside WhatsApp's 24 hour reply window).
- Approved?: True only when you tapped Log it.
Step 5 · Logged, confirmed, summed up for your CA
The expense goes into your sheet with the Drive photo link, and the sender gets a WhatsApp confirmation. On the 1st of every month, n8n totals last month by category and saves a draft email to your CA.
- Log expense: Writes the expense to your Expenses tab, keyed on Bill key, with month, GST, category, who paid and the Drive photo link.
- Confirm on WhatsApp: Replies to the sender: logged with the numbers, not logged (you declined), or already logged (duplicate). Its error output goes to the alert.
- Alert owner: Tells you in Slack if the WhatsApp confirmation failed. The sheet row is already saved.
- 1st of every month: Runs at 9 AM on the 1st of every month for the month-end summary.
- Read last month: Reads every expense row for last month.
- Totals by category: Adds up last month's totals and GST per category, with the number of bills.
- Draft email to CA: Saves a draft email to your CA with totals per category, total GST and links to the sheet and photos. You read it and send it. Runs once.
Setup
- In n8n, create a new workflow, open the menu and choose Import from File, then pick the JSON file.
- Connect WhatsApp on Bill photo on WhatsApp and Confirm on WhatsApp. Put your permanent access token in place of
YOUR_WHATSAPP_ACCESS_TOKENin Get media URL and Download bill image. - In Only from my team, replace the example numbers with your team's WhatsApp numbers, written as 91 followed by 10 digits.
- Create a Bills folder in Drive and put its id in Save bill to Drive and in the CA email.
- Create an Anthropic credential on Claude.
- Make a Google Sheet with an
Expensestab (Bill key, Logged at, Month, Bill date, Vendor, Vendor GSTIN, Bill no, Category, Taxable, GST, Total, Payment, Paid by, Note, Photo, Status). Paste its URL in the three sheet nodes. - Connect Slack on Approve expense and Alert owner, and Gmail on Draft email to CA (replace
YOUR_CA_EMAIL,YOUR_BUSINESS,YOUR_NAME). - Activate the workflow, send a bill photo from a team phone, and check the Drive file, the sheet row and the WhatsApp reply.
How to customise it
- Change the Rs 10,000 approval limit in Big or unclear?.
- Change the category list in Check the numbers and in the Claude prompt to match your CA's ledger heads.
- Accept PDF invoices too: add a branch for WhatsApp documents with Extract from File, and read the text instead of the image.
- Forward Swiggy, Uber and software invoices from email with a Gmail trigger into the same flow.
- Add a 'Project' or 'Client' column and ask the team to write it in the note, for client-wise billing.
Guardrails
Big or unclear bills are logged only after you approve. The CA email is a draft you send yourself.
- Only photos from team numbers you list are processed.
- Claude reads at temperature 0 and is told never to guess a GSTIN. A Code node checks the maths by rule.
- Bills of Rs 10,000 or more, unclear photos and failed checks are logged only after your approval.
- Duplicates (same vendor, bill number and total) are never logged twice.
- The CA email is saved as a draft. Nothing financial is sent outside your team automatically.
Troubleshooting
- Photos never arrive. The Meta app webhook must be subscribed to
messages, and the sender's number must be in the list in Only from my team with 91 and no plus sign. - Download bill image fails with 401. The media download needs the same access token as the API call. Use a permanent system user token, not the 24 hour test token.
- Claude reads 0 for the total. The photo is blurry or cut off. Ask for a straight, well-lit photo of the whole bill; it goes to Slack meanwhile.
- The same bill is logged twice. Two photos of one bill can read slightly differently (for example a missed bill number). Check the Bill key column and delete the extra row.
- The monthly draft is empty. The Month column must be filled as YYYY-MM, which Log expense does. Rows added by hand need it too.
Want the members-only resources too?
A free account unlocks them all, including the ones shared in DMs.

