Inspiration

Every group dinner ends the same way. One person pays the full bill, screenshots it into the group chat, and then spends the next week sending awkward follow-up messages. Everyone else either forgets, misremembers what they ordered, or disputes the tip split. The tools that exist today help with the maths but not the transfer — you still have to manually chase each person and hope they actually send the money.

We wanted to close that loop entirely. A receipt goes in, money comes out, and no one has to think about it again.

What it does

bunqShare turns a receipt photo into a settled bill in under 90 seconds.

The host photographs the restaurant receipt. GPT-4o vision extracts every line item, quantity, and price into structured JSON within a few seconds. A side panel shows the host's most frequent bunq contacts — no typing names or IBANs — and tapping Send Links generates a unique invite URL for each person and delivers it by email and bunq inbox notification.

Each friend opens their link in a browser — no app download, no account required. They tap the items they ordered. Tapping the same item again enters sharing mode, where they can mark it as split equally among however many people also claimed it. A running total at the bottom updates live. When they tap Confirm & Pay, a bunq payment executes directly from their account to the host's IBAN for the exact calculated amount.

The host watches a live tracking screen that flips each person's status from Pending to Paid as payments come through, with a per-person breakdown of what they covered. When everyone has paid or skipped, a summary screen shows the total collected against the receipt total.

How we built it

The stack splits cleanly into two services.

Python FastAPI backend — all bunq interactions go through a dedicated service using the official bunq Python SDK. It authenticates with bunq, ranks the host's top contacts by transaction frequency, executes payment transfers from invitees to the host's IBAN, and exposes a seeding endpoint that generates realistic demo data: five friend profiles, twelve months of transaction history, and an automatic daily limit bump for the sandbox.

Next.js frontend — the central orchestrator. It serves the UI, runs Sharp image normalisation server-side before calling GPT-4o vision, manages in-memory split sessions keyed by UUID, generates unique invite URLs per invitee, dispatches email invitations, and proxies payment requests to the FastAPI backend. All AI and payment logic stays server-side; the client only handles item-selection state while the invitee is choosing.

The session store is intentionally in-memory — no database, no Redis. For a 24-hour hackathon demo this is the right call: zero infrastructure, instant setup, and sessions expire naturally after 24 hours anyway.

Challenges we ran into

Receipt parsing accuracy. Real receipts are not clean documents. Thermal paper fades, items run together, specials are handwritten, and prices appear in whatever position fits on the roll. Getting GPT-4o to reliably associate the right price with the right item — across languages, layouts, and lighting conditions — required careful prompt engineering and a validation step where the server recomputes totals independently and flags mismatches rather than silently accepting wrong data. Sharp preprocessing for sharpening and contrast normalisation made a significant difference on dark or blurry photos.

Shared item logic. Two people claiming the same item independently creates a consistency problem: each thinks they owe the full price. The correct amount is the line total divided by however many people ultimately claimed it, but that count is not known until everyone has submitted. The solution is to compute the final share server-side at pay time using the confirmed claim count, not client-side at selection time. This meant the invitee UI had to clearly communicate that the displayed total is an estimate until confirmed.

bunq sandbox setup. Getting the Python SDK authenticated, the session persisted correctly across restarts, and the daily payment limit high enough to handle a realistic demo took longer than expected. The seeder script now handles the limit bump automatically on first run.

Accomplishments that we're proud of

The full end-to-end flow works: photo in, payments out, tracking screen updates live. That is not a given in a 24-hour build — every integration point (vision API, bunq SDK, email dispatch, session state, real-time polling) had to work together without a single one failing mid-demo.

The invitee experience requires no bunq account and no app install. A link in an email is enough. That decision kept the demo accessible to anyone in the room without setup friction.

The seeder script producing twelve months of realistic transaction history in about 90 seconds means the dashboard and inbox screens look credible immediately, not like empty states.

What we learned

GPT-4o vision is genuinely good at structured extraction from unstructured documents — better than we expected on non-English receipts and unconventional formats. The key is giving it an explicit JSON schema to fill rather than asking it to describe what it sees. Null for unreadable fields, no guessing, and the model respects that constraint reliably.

The bunq Python SDK abstracts the sandbox/production difference almost entirely. Swapping environments is one line. That made it straightforward to build confidently against the sandbox knowing the production path is the same code.

Keeping session state in-memory forced clean thinking about data flow. With no database to fall back on, every piece of state had to live in the right place — client for ephemeral selection, server for anything shared across participants.

What's next for bunqShare

bunq OAuth for invitees. The current flow executes payments using a pre-authorised token. The natural next step is a proper bunq OAuth redirect for each invitee so they authorise the exact transfer amount before it goes through — more transparent, more secure, and the right UX for a production app.

bunq payment request API. Rather than pulling money directly, the host could issue a bunq payment request to each invitee. This keeps the invitee fully in control of approving the charge inside their own bunq app and removes the need for invitees to interact with bunqShare at all beyond selecting their items.

Receipt camera UX. The current upload flow works on mobile but a native camera capture with live edge detection and auto-crop would make the host experience significantly faster and more polished.

Built With

Share this project:

Updates