Case Study · Finance & Accounting Automation

AI-Powered Journal Posting Automation Case Study

From bank statement to QuickBooks journal entry, without re-keying

How Decision Foundry automated journal posting for a multi-entity holding company

The result: with a rules engine backed by AI (Anthropic Claude), ~85% of transactions map to the GL automatically across 1,000+ bank transactions a month, so days of downloading and re-keying become a short review and approval cycle.

Contact Us

Or reach us directly at: sales@decisionfoundry.com

The customer

The customer is a US-based holding company with a portfolio of operating businesses across hospitality, vacation ownership, food & beverage (including a winery) and retail distribution. Each business is a separate legal entity with its own books, and each entity has its own QuickBooks Online company file. In total the finance function looks after six or more entities, with more expected as the group grows.

Finance & accounting is run by a lean in-house team (a controller, a few accountants and the entity approvers) working alongside an outsourced F&A partner that handles much of the day-to-day bookkeeping. The team is responsible for daily bank posting, payroll journals, card-processor and POS reconciliations, and the monthly close for every entity.

The group's banking is spread across several institutions (for example Chase, Bank of America and HSBC), and money comes in through many channels: card processors such as Clearent, AMEX settlements, POS systems such as Toast, wires, ACH and checks. Money goes out through payroll providers (Paychex, ADP), vendor payments, rent and utilities. In a typical month this adds up to well over a thousand bank transactions across all entities, and every one of them must end up correctly coded in QuickBooks.

At a glance

Industry
Diversified holding company: hospitality, vacation ownership, F&B, retail
Entities
6+ legal entities, each with its own QuickBooks Online file
Accounting system
QuickBooks Online
Monthly volume
1,000+ bank transactions across all entities
Team
Small in-house finance team plus an outsourced F&A partner

The problem

Before the project, journal posting was almost entirely manual and repeated for every entity, every month. A typical cycle looked like this:

  1. Download. An accountant logged into each bank portal and downloaded the statement for each account, in whatever format that bank provided: CSV from one bank, PDF from another, Excel or BAI2 from a third.

  2. Clean up. The file was opened in Excel and reshaped by hand, because no two banks use the same columns, date formats or sign conventions for debits and credits.

  3. Code. Each transaction was assigned a GL account. This relied on SOP documents, previous months' workbooks and the memory of the people who had done it before. For example, “CLEARENT DEPOSIT” goes to card sales income, “PAYCHEX” to payroll, but a wire with no clear reference needs someone to investigate.

  4. Chase unknowns. Transactions nobody recognised were sent to the client or entity manager over email. There was no central list of what was still open, how long it had been waiting or who was responsible.

  5. Re-key. Every coded line was typed into QuickBooks Online as a journal entry, one at a time, making sure the right company file was open and that debits matched credits.

  6. Evidence. Supporting documents were saved in shared folders, separate from the QuickBooks entries they supported.

The effects were felt across the finance function:

  • Slow close. Bank posting alone took several days of effort each month, pushing out the month-end close for every entity.
  • Errors. Manual keying led to wrong accounts, transposed amounts, occasional unbalanced entries and, worst of all, entries posted to the wrong entity's books.
  • Key-person risk. GL coding knowledge lived with a few individuals. When they were away or left, quality dropped and onboarding new staff took weeks.
  • Weak audit trail. It was hard to show auditors which statement line a QuickBooks entry came from, who coded it and who approved it.
  • Doesn't scale. Every new entity or bank account added the same amount of manual work again.

Challenges faced

Automating this process was not just a matter of reading a file and calling an API. The team had to solve several practical problems.

1. No standard input format

Every bank and payment platform exports data differently. CSV files differ in column names, date formats and whether withdrawals are negative numbers or in a separate column. PDFs are the hardest: some have clean tables, others are free text with wrapped descriptions and running balances. The solution needed to handle CSV, PDF, Excel, OFX/QFX and BAI2, recognise which bank produced the file, and turn everything into one consistent transaction format without manual setup for each upload.

2. Getting the entity right

With six or more QuickBooks company files, posting a statement to the wrong entity is a serious and time-consuming error to reverse. The system had to identify the entity automatically from the statement contents (account names, holder names, keywords) and make the chosen entity clearly visible before anything is posted.

3. Turning tribal knowledge into rules

GL coding decisions lived in people's heads and in old spreadsheets. They had to be captured as rules the finance team could own and change themselves, without asking a developer. Rules needed to support simple keyword matches, exact matches and regular expressions, with a priority order so that more specific rules win over general ones. Rules also differ by entity.

4. Keeping humans in control

Finance leadership was clear that automation must not mean losing control. Requirements included a maker-checker step (the person who prepares a batch is not the person who posts it), a hard rule that unknown transactions above a threshold (for example $500) are never auto-coded, and email alerts to the entity approver when such items appear.

5. Integrations and data sources

Statements arrive in more than one way: some are downloaded and uploaded, others are emailed by banks or colleagues to shared Outlook or Gmail inboxes. QuickBooks Online uses OAuth tokens that expire and must be refreshed securely, and each entity has its own QuickBooks connection. Some bank and payment portals have no API at all, which limits how far ingestion can be automated today.

6. Security, access and audit

Because the app handles bank data and posts to the general ledger, it had to meet corporate security expectations: single sign-on through the company identity provider, role-based access (admins, reviewers, approvers), encrypted storage of OAuth tokens and email credentials, and an audit log that cannot be edited.

The solution: AI-assisted journal posting

Decision Foundry designed and built Journal Posting, an AI-assisted web application that automates the whole journey from bank statement to posted journal entry, while keeping the finance team in charge of every decision that needs judgement. It follows a five-step Ingest → Process → Confirm → Execute → Learn flow.

  1. Ingest
  2. Process
  3. Confirm
  4. Execute
  5. Learn

Ingest: statements in, from anywhere

  • Drag-and-drop upload in the browser for CSV, PDF, Excel, OFX/QFX and BAI2 files.
  • Connected Outlook (Microsoft Graph) and Gmail inboxes are checked every few minutes.
  • Statement attachments are picked up and processed automatically, and the history of each inbox is visible in the app.
  • Duplicate detection prevents the same statement or transaction being imported twice.

Process: parse, normalise and map

  • Dedicated parsers for each format, with 90+ bank and payment-platform fingerprints, recognise the source automatically. For PDFs the parser extracts tables first and falls back to pattern matching on the text when there is no clean table.
  • Every parser outputs the same standard transaction record (date, description, amount, direction, reference), so everything downstream works the same regardless of source.
  • The entity is detected from keywords in the statement and linked to the right QuickBooks company file and bank GL account.
  • A priority-ordered rules engine assigns a GL account to each transaction using keyword, exact or regex rules, set up per entity. AI (Anthropic Claude) helps classify source documents where simple rules aren't enough.

Confirm: review, exceptions and approval

  • Reviewers see every transaction with its proposed GL account and which rule matched, and can change accounts inline.
  • Anything without a match goes to an Exception Queue with a days-open counter. Items above the alert threshold trigger an email to the entity's approver and are never coded automatically.
  • Batches move through a maker-checker approval step before anything reaches QuickBooks.

Execute: post to QuickBooks

  • Approved transactions are posted to QuickBooks Online through its API as balanced two-line journal entries. For a deposit, the bank account is debited and the mapped income account is credited; for a payment, the expense account is debited and the bank is credited.
  • The source statement is attached to the entry in QuickBooks, so the evidence travels with the transaction.
  • QuickBooks connections are managed per entity, with automatic token refresh.

Learn: get better every month

  • When a reviewer resolves an exception they can save the decision as a new rule. Other open exceptions that match are re-mapped straight away, and the same transaction maps automatically next month.
  • Over time the share of transactions needing manual attention keeps going down.

Security and administration

  • Single sign-on through AWS Cognito, with users created automatically on first login, plus role-based access for admins, reviewers and approvers.
  • OAuth tokens and email credentials are encrypted at rest.
  • Admin screens to manage entities, users, email sources, GL rules and QuickBooks connections without code changes.
  • An immutable audit log of every posting, exportable to CSV.

Tech stack

  • Python / FastAPI backend
  • Flutter web frontend
  • PostgreSQL
  • APScheduler for background jobs
  • Microsoft Graph and Gmail for email ingestion
  • QuickBooks Online REST API
  • Anthropic Claude
  • AWS Cognito SSO
  • Docker containers on AWS EC2 behind nginx

Inside the AI-assisted app: from statement to posted entry

1. Home dashboard.

This is the first screen the team sees after signing in. The cards across the top show where every transaction stands for the selected entity and period: pending (just imported), mapped (GL account assigned by a rule), exceptions (needs a person), approved (ready to post) and posted (in QuickBooks), plus the total value posted. Below that, the recent statements list shows each file, which entity and bank it was matched to, whether it was uploaded or picked up from an email inbox, how many transactions it contained and what share was mapped automatically. A controller can see the state of bank posting across the group at a glance, and the “Check email now” button lets users trigger an inbox check without waiting for the next scheduled run.

2. Statement upload.

A user drags in a statement in any supported format (CSV, PDF, Excel, OFX/QFX or BAI2). The app identifies the bank from the file layout and the entity from keywords in the statement, here “Entity A Hospitality”, and fills in the matching QuickBooks bank account. Before anyone reviews a line, the extraction summary shows how many transactions were found, the statement period, total deposits and withdrawals (so they can be checked against the bank balance), how many were mapped automatically, how many went to the exception queue and how many duplicates were skipped. Statements that arrive in a connected Outlook or Gmail inbox go through exactly the same steps with no upload needed.

3. Transaction review.

Every extracted transaction is listed with its date, description, amount, the GL account the rules engine assigned and the type of rule that matched (keyword, exact or regex), so reviewers can see why an account was chosen. Status filters (Mapped, Exceptions, Approved and so on) make it easy to work through a statement, and accounts can be changed inline from the entity's chart of accounts. Reviewers select lines and approve them in bulk. A second user then posts the approved batch to QuickBooks Online (maker-checker), where each line becomes a balanced two-line journal entry, for example debit Operating Checking and credit Sales Income - Card for a card deposit.

4. Exception queue.

Transactions that no rule could map are held here and are never posted automatically. Each item shows how many days it has been open (colour-coded green, amber and red) so nothing is forgotten, and anything above the $500 threshold is flagged and triggers an email alert to the entity's approver. On the right, the reviewer picks the GL account, adds a note explaining the decision and can tick “Create rule for future transactions”. The new rule is applied straight away to other open exceptions that match, and the same kind of transaction will map automatically next month. This is how the system learns and the exception rate falls over time.

5. Audit log.

Every journal entry posted to QuickBooks is recorded here with the time it was posted, its QuickBooks transaction ID, the entity, the accounts debited and credited, the amount, who approved it, who posted it and the source statement it came from. Entries cannot be edited or deleted. The log can be filtered by date range and exported to CSV for auditors, and the source PDF is also attached to the entry inside QuickBooks. Controllers and external auditors can trace any number in the general ledger back to the exact bank statement line, and see who signed it off.

The results of AI-assisted journal posting

The new process replaces days of downloading, reformatting and re-keying with a short review and approval cycle: statement in (by upload or email), review, approve, post.

Far less manual work.

Most transactions are mapped automatically, so the team spends its time on the small set of exceptions that need judgement instead of typing entries into QuickBooks.

Gets better every month.

Each resolved exception can become a rule, so the share of auto-mapped transactions grows and month-end gets quicker over time.

Fewer errors.

Every entry is posted as a balanced two-line journal, and automatic entity detection prevents posting to the wrong company file. Keying mistakes are removed entirely.

Control is kept.

Unknown items above the threshold are never auto-coded, approvers are alerted by email, and maker-checker approval is built into the workflow.

Audit-ready.

Every QuickBooks entry links back to its source statement, approver and poster, and the source document is attached in QuickBooks. Preparing evidence for auditors takes minutes rather than days.

Less key-person risk.

GL coding knowledge now lives in rules that everyone can see and maintain, not in a few people's heads, which also makes onboarding new staff much faster.

Built to scale.

One platform serves every entity. A new entity or bank account is added through configuration in the admin screens, not new code.

What's next

The next phase removes the last manual step: an AI agent that logs into bank and payment portals on a schedule, downloads statements and hands them straight to the pipeline, with an alert to the finance team whenever a portal asks for a one-time passcode. Further plans include rolling out to the remaining entities and adding automation for related tasks such as payroll journals and card-processor reconciliations.

Get In Touch

Reach out to Decision Foundry today for AI automation of your business processes, saving time and money.