Case study
Accounting on autopilot for freelancers and sole proprietors in BiHThe bank statement engine behind Freelancing.ba
Freelancing.ba runs the whole accounting cycle for independent workers in Bosnia and Herzegovina. We built the piece that closes the loop: a bank statement goes in as a PDF, and expenses, invoice payments and tax obligations come out already reconciled.
- Client
- Freelancing.ba
- Industry
- Accounting software for freelancers
- Scope
- AI document engine and matching rules
- Stack
- Supabase, n8n, Claude Opus 5
- Guardrails
- The model reads, the rules decide
The challenge
The last mile of accounting is the bank statement
An independent worker in Bosnia and Herzegovina runs a full accounting cycle by hand every month, across three tax jurisdictions with different rates, forms and deadlines. Issue the invoices, chase the payments, record the expenses, keep the book of income, compute contributions and income tax, produce the government forms and the payment slips, file, pay. Freelancing.ba already automated most of that.
What was left was the reconciliation. Until the bank tells you what actually moved, nothing is settled: an invoice is only paid when the money lands, an expense is only real when it leaves the account, and a contribution payment only counts against the month it was owed for. That evidence arrives as a PDF, formatted differently by every bank, and it is the one place where automation is genuinely dangerous. Book a payment twice and the expenses are inflated. Attribute a contribution to the wrong month and the whole year's attribution collapses quietly, while the totals still add up.
What we did
The model reads the document, the rules decide what it means
We split the problem in two and kept the halves strictly apart. Claude Opus 5 reads the statement PDF directly as a document, with no OCR step, no text-extraction library and no template per bank, and returns a strict JSON schema: statement header, then one row per line with direction, amount, reference, counterparty and payment purpose copied verbatim. The prompt's standing instruction is that if something is not on the statement, the answer is null. Never guess. The same pipeline powers receipt scanning, where a photo or a PDF becomes a pre-filled expense with a suggested category.
Everything after that is deterministic. The model's answer is normalised, the totals are recomputed from the parsed lines rather than trusted, and every consequence is decided by explicit SQL with stated thresholds, running in a Postgres trigger so that an upload, a mailbox import and a manual insert all behave identically. An invoice settles only when the number appears verbatim, the amount matches to the last fening and exactly one candidate exists. A tax payment is bound to the obligation month printed on the statement, never to whichever obligation happens to carry the same amount. Anything less than certain is parked in a review queue for a person, which is what the team asked for: they see only the exceptions.
Deliverables
What we built
Six pieces that turn a bank PDF into reconciled books.
- 01
Statement intake, two ways
Upload a PDF, or connect a mailbox and let a whitelist of senders and labels pull statements in on a schedule. Both paths land in the same private, audited store.
- 02
Direct PDF extraction
Claude reads the statement itself and fills a strict schema, so a new bank needs no template, no parser and no configuration.
- 03
Receipt scanning
A photo or PDF of a receipt becomes a pre-filled expense with amount, date, tax and a suggested category, resolved against the user's own category list.
- 04
Booking in the database, not the app
One trigger books every line, so upload, inbox import and manual entry can never drift apart in behaviour.
- 05
Invoice settlement that learns
Payments settle invoices on an exact number and an exact amount. When a client never writes the number, one manual link teaches the engine that payer's name and account for next month.
- 06
Tax and contribution matching
Public-revenue payments are read for the revenue code and the period the bank prints, and joined to the exact obligation they pay, not to a matching amount.
The engine
What keeps an AI engine safe around money
Reading a PDF is the easy half. The hard half is deciding what to do with it, and knowing when to do nothing.
The model extracts, rules decide
No model output ever changes a financial record on its own. Every consequence is a deterministic rule with a threshold you can read.
Certainty or nothing
Every matcher returns exactly one answer or none at all. Two plausible candidates is not a tie to be broken, it is a question for a person.
Never guess, learn instead
There is no fuzzy name matching anywhere. The engine only gets better by recording what someone did by hand, and it forgets that the moment they undo it.
Never destroy, always park
A suspected double booking is flagged and queued with a "book it anyway" button. A false positive costs one click; a silent duplicate corrupts the books.
Results
What changed for the team
Freelancing.ba hasn't published figures from this work, and we don't invent them. What we can describe is what the engine now does on its own, and where it deliberately stops.
What changed
- A statement from any bank is read end to end, every line including fees and interest, with no template to write first.
- Expenses, invoice payments and tax obligations are reconciled from the statement without anyone retyping a row.
- Contribution payments land on the month they actually pay for, taken from the period the bank prints rather than from a matching amount.
- The same payment entered by hand and later imported from the bank is caught even months apart, and parked for review instead of booked twice.
- The team sees only the exceptions: everything certain is booked, everything else waits for a person.
- Live in production, with the matching rules the app is accountable for kept out of reach of the browser.
“We build accounting software for solo entrepreneurs, where every error costs a client. Agenthos automated document processing so our team only ever sees the exceptions.”
Reach us
How about a free audit?
Tell us a little about your business and where time gets lost. We'll come back with what's worth automating first.
What to expect
Confirmation email
01You'll receive an immediate confirmation with next steps.
Response within 24 hours
02A team member will reach out within one business day.
Discovery call
0330-minute conversation about your goals and challenges.
No obligation
04Exploratory conversations carry no commitment.