A few weeks ago I was having dinner with 5 friends. The check came — crumpled thermal paper, foreign language, nobody has cash.
Usually what happens:
- One person stares at the calculator app looking depressed.
- Someone says "let's just split equally", even though two people only had tea and one ordered a $30 steak.
- Someone suggests Splitwise. But two people don't have it, one forgot their password, the App Store wants an update, and nobody wants to spend 10 minutes setting up an account at midnight just to pay for noodles.
I was looking at that receipt thinking: phone cameras and vision models are crazy good now. Why are we still manually typing numbers into spreadsheets?
So over the last few weeks I ended up building a Telegram bot to do this for us.
How it works
The goal was zero friction — nobody wants to download another 150MB native app for a 20-second task:
- You snap a photo of the receipt in Telegram.
- The vision LLM parses items, prices, tax, and tip into JSON (translating foreign dish names on the fly).
- The bot drops a Telegram Mini App link into your group chat. Everyone opens it inside Telegram and taps what they ordered. No signups, no passwords.
- The backend calculates who owes what and collapses all debts into minimum payments.
The restaurant math is surprisingly messy
I thought OCR would be the hardest part, but vision models handled crumpled receipts surprisingly well. The real headaches were edge cases in bill math:
- Proportional tips: If Bob gets a $5 beer and Alice orders a $50 bottle of wine, splitting a 15% service charge 50/50 is unfair. Tax and tips have to scale proportionally to each person's actual consumption. If you didn't drink, you don't pay tip on alcohol.
-
The missing cent: When you split 100 by 3, you get 33.3333. Round to 2 decimals and you lose a cent. In the end I just rounded with
ROUND_HALF_UPand dumped the leftover penny on whoever had the biggest bill. Nobody notices, but the ledger stays at exact zero. - Debt simplification: If 6 people owe each other random amounts, having everyone send 10 tiny Revolut/Venmo payments is awful. The backend computes net balances (who is in the red vs green) and matches the biggest debtor with the biggest creditor.
Before: 6 people sending 10 chaotic payments to each other
After: Boris sends $20 to Anna, Charlie sends $15 to Anna. Done.
For $N$ people, it mathematically guarantees at most $N - 1$ transfers total.
Things that broke
- Thermal paper + camera flash: If you take a receipt photo with flash on glossy thermal paper, it turns into a white mirror and numbers vanish. I had to add a quick inline editor so you can fix prices with a tap if the photo is blurry.
-
Telegram iOS Webview: Pure pain. The bottom action button kept disappearing behind the keyboard, and the viewport has this weird inertia bounce. Took a ton of
100dvhCSS hacks and viewport meta tweaks to make it feel like a real app. - The reversed sign bug: In my first settlement test, I flipped the repayment sign in the formula. Every time someone made a payment, their debt doubled instead of clearing. Glad I caught that before testing on friends.
Anyway, it's live and free to mess with:
- Web: botsplit.com
- Telegram: @spbill_bot
Curious how you guys split bills when traveling with friends? And if anyone builds Telegram Mini Apps — how do you handle the iOS keyboard viewport resizing?

Top comments (0)