Bank Fee Analysis¶
Metadata¶
- Customer: ON
- Status: Active
- Domain(s): Categorization, Pulse
- Started: 2026-03-05
- Source: Notion
Problem Statement¶
Corporate treasury teams at multi-entity, multi-currency companies pay significant bank fees across dozens of banking relationships — transaction fees, account maintenance, SWIFT charges, FX commissions, collection fees, financing costs (RCF, guarantees), and more.
These fees are:
- Opaque. Fee line items on bank statements are cryptic, inconsistent across banks, and sometimes in local languages. A single bank may use different description formats across countries.
- Unverified. Most treasury teams never reconcile what they were charged against what they agreed to pay. Banks are notorious for mis-charging: applying expired rate cards, billing for services not used, putting accounts in wrong volume tiers, or charging fees not in the agreement.
- Unoptimized. Payment routing decisions (which bank, which account, domestic vs cross-border) are often made based on historical setup rather than current pricing.
- Scattered. Fee data lives in bank statements (free-text descriptions), pricing agreements (PDFs), and BSB/camt.086 files (machine-readable, but rarely requested). No single system reconciles all three layers.
Why Existing Tools Fall Short¶
Kyriba Bank Fee Analyzer ingests BSB (Bank Service Billing) files and compares them against rate cards. Limitations:
- Requires BSB files from banks (many companies don't request them)
- Limited to the banks and fee codes in its database
- No cross-referencing with actual payment flows (can't do routing analysis)
- No AI-based description parsing for non-BSB data
- Static rule engine, not adaptive to new fee patterns
Spreadsheets are the reality for most treasury teams. Someone pulls bank statements, eyeballs the fee lines, and maybe compares against the pricing PDF once a year. This doesn't scale past 10-20 accounts.
The Opportunity¶
A company like ON (31 entities, 124 accounts, 16 banks, 21 countries) generates ~12,000 bank fee transactions per year. The data already flows into Palm. An AI-based analyzer can:
- Parse fee descriptions in any language across any bank format
- Sub-classify fees by type without manual mapping
- Reconcile across all three layers (agreed, charged, should-have-been)
- Cross-reference fees against payment flows for routing optimization
- Flag anomalies and trends automatically
Estimated savings potential: 5-15% of total bank fee spend, plus the elimination of hours of manual analysis per month.
Solution / Approach¶
The Three-Layer Reconciliation Model¶
The core of any bank fee analysis is reconciling three views of reality:
LAYER 1: WHAT WE AGREED TO PAY
Source: Pricing agreement PDFs per bank
Content: Fee codes, rates, thresholds, tiers
Format: Semi-structured (tables in PDFs)
Update: Renegotiated every 1-3 years
| GAP A: "Unauthorized fees"
v
LAYER 2: WHAT THE BANK CHARGED
Source: Bank statements (Palm fact_transactions)
OR BSB/camt.086 files (structured)
Content: Actual fee debits with descriptions
Format: Free-text descriptions (inconsistent)
Update: Daily / monthly
| GAP B: "Miscalculations"
v
LAYER 3: WHAT WE SHOULD HAVE BEEN CHARGED
Source: Actual account activity * pricing rates
Content: Calculated fees based on real volumes
Requires: Layer 1 rates + transaction/balance data
Update: Computed on demand
Gap A (Layer 1 vs 2): The bank charged a fee that doesn't appear in the pricing agreement. Common causes: default fee schedules applied instead of negotiated rates, fees for services auto-enabled without request, post-negotiation rate card not applied to all accounts.
Gap B (Layer 2 vs 3): The bank charged the right type of fee but the wrong amount. Common causes: volume tier not updated after growth, balance-based ECR not applied correctly, FX conversion at wrong rate, per-item charges applied to a bundled service, quarterly fees charged monthly.
Gap A + B combined is the total overcharge. In practice, 3-10% of bank fees are incorrect in the bank's favor (source: Redbridge, TIS, industry surveys).
Phase 0: Data Foundation (Week 1)¶
Goal: Clean and reliable fee data in Palm.
| Step | Action | Owner | Tool |
|---|---|---|---|
| 0.1 | Verify bank fee category exists for the customer in Palm | Palm team | palm-chat |
| 0.2 | Audit fee categorization quality: flag miscategorized transactions | AI + Palm team | palm-chat queries |
| 0.3 | Consolidate duplicate bank name labels (e.g., "DEUT" vs "Deutsche Bank") | Palm team | Palm admin |
| 0.4 | Request BSB/camt.086 files from top 3 banks (by fee volume) | Customer treasury | Bank portals |
| 0.5 | Request pricing agreement PDFs from top 3 banks | Customer treasury | Internal files |
Deliverable: Clean fee dataset with known data quality issues documented.
Phase 1: Fee Visibility (Weeks 2-3)¶
Goal: Sub-classify every fee transaction by type. Produce the first analytical view the treasury team has never had.
| Step | Action | Detail |
|---|---|---|
| 1.1 | Build per-bank description parsers | Regex rules for structured banks. LLM fallback for ambiguous descriptions. |
| 1.2 | Define fee type taxonomy | Account management, transaction fees, FX commissions, collection/DD charges, platform/eBanking fees, tax on bank services, financing costs. |
| 1.3 | Classify all fee transactions | Apply parsers to historical data. Target: <20% "Other/Unclassified". |
| 1.4 | Build fee dashboard | Spend by: bank, entity, country, fee type, month. Year-over-year trends. |
| 1.5 | Flag anomalies | Unusual spikes, new fee types, dormant account charges. |
Deliverable: Fee spend dashboard with sub-classified fee types. Layer coverage: Layer 2 (what was charged) — fully visible and classified.
Phase 2: Pricing Agreement Ingestion (Weeks 3-5)¶
Goal: Digitize pricing agreements into structured, queryable data. Enable Layer 1.
| Step | Action | Detail |
|---|---|---|
| 2.1 | Collect pricing PDFs | Per bank relationship. Include: fee schedules, service agreements, amendments, side letters. |
| 2.2 | Parse PDFs with LLM | Extract: fee code, description, rate type, amount, currency, volume thresholds, effective date, expiry date. |
| 2.3 | Normalize to common schema | Map bank-specific fee codes to the taxonomy from Phase 1. |
| 2.4 | Store structured pricing | One record per fee type per bank per effective period. |
| 2.5 | Validate: match pricing line items to actual fee categories | Every fee type in Layer 2 should have a matching pricing entry. Unmatched = Gap A candidates. |
Deliverable: Structured pricing database linked to fee categories. Layer coverage: Layer 1 (what was agreed) — digitized and queryable.
Phase 3: Reconciliation Engine (Weeks 5-8)¶
Goal: Compare what was charged against what should have been charged.
| Step | Action | Detail |
|---|---|---|
| 3.1 | Calculate expected fees | For each bank/account/period: actual volumes × agreed rates = "should have been charged" |
| 3.2 | Compare: charged vs expected | Per fee type, per bank, per account, per month. Flag deviations >5% or >EUR 100. |
| 3.3 | Classify deviations | Unauthorized fee, rate mismatch, volume tier error, balance credit error, duplicate charge, expired rate. |
| 3.4 | Generate discrepancy report | Per bank: total overcharge, by fee type, with evidence. |
| 3.5 | Prioritize claims | Rank by: amount, recoverability, bank relationship importance. |
Deliverable: Bank-by-bank discrepancy report with estimated recoverable overcharges.
Phase 4: Routing Optimization (Weeks 6-10)¶
Goal: Identify structural savings using Palm's full payment flow data.
| Step | Action | Detail |
|---|---|---|
| 4.1 | Map cross-border vs local routing | Per entity: which payments go through cross-border banks vs local banks? |
| 4.2 | Identify underutilized local banks | Entities with a local bank that route most payments cross-border. Quantify fee premium. |
| 4.3 | Identify missing local banks | Entities with no local bank where opening one could reduce fees. Estimate break-even. |
| 4.4 | Benchmark bank-to-bank | Compare fee-to-flow ratios across banks. |
| 4.5 | Consolidation candidates | Identify dormant/low-activity accounts (<25 txns/year) with maintenance fees. |
| 4.6 | FX spread analysis | Compare executed rates against mid-market benchmarks. |
Deliverable: Routing optimization report with per-entity recommendations and estimated savings.
Phase 5: Ongoing Monitoring (Continuous)¶
Goal: Prevent fee creep and catch new overcharges as they happen.
| Step | Action | Detail |
|---|---|---|
| 5.1 | Monthly fee reconciliation | Automated comparison of monthly fees against pricing. Alert on deviations. |
| 5.2 | New fee detection | Flag any fee type or fee code that hasn't appeared before. |
| 5.3 | Volume tier monitoring | Track transaction volumes against pricing tier thresholds. |
| 5.4 | Pricing expiry tracking | Alert when a pricing agreement is approaching expiry. |
| 5.5 | Quarterly fee report | Automated report: spend trends, savings realized, open claims, upcoming renewals. |
Data Sources and Requirements¶
| Data Source | What It Provides | Format | Who Provides |
|---|---|---|---|
| Palm fact_transactions | Actual fee debits with descriptions, bank/entity/country metadata | BigQuery via palm-chat | Already in Palm |
| Palm fact_transactions (all categories) | Full payment flows for routing analysis | BigQuery via palm-chat | Already in Palm |
| Palm fact_account_balances | Daily balances for ECR / balance-based fee calculation | BigQuery via palm-chat | Already in Palm |
| Pricing agreement PDFs | Contractual fee rates per bank | Customer treasury team | |
| BSB / camt.086 files | Machine-readable fee breakdowns per bank | XML / structured | Requested from banks |
| TWIST files | Standardized bank fee statements | Industry format | Requested from banks |
Expected Outcomes¶
| Metric | Typical Range | Source |
|---|---|---|
| Fee overcharges recovered | 3-10% of total fee spend | Industry benchmarks (Redbridge, TIS) |
| Routing optimization savings | 5-20% of cross-border fees | Domestic vs cross-border fee differential |
| Dormant account savings | EUR 500-2,000 per account closed | Standard European bank maintenance fees |
| Time saved vs manual analysis | 20-40 hours/quarter | Treasury team estimate |
| Time to first actionable insight | 1-2 weeks (Phase 0-1) | Based on Palm data availability |
Measured Outcomes¶
| Metric | Before | After | Date Measured |
|---|---|---|---|
| Fee visibility | No sub-classification | Keyword-based classification across 11 banks | 2026-03-05 |
| Savings identified | Unknown | ~CHF 300-500K equivalent (see results) | 2026-03-05 |
| Accounts analyzed | — | 124 accounts, 16 banks, 21 countries | 2026-03-05 |
| Fee transactions analyzed | — | ~11,850 (2025) | 2026-03-05 |
| CapEx categorization precision | 95.3% | 100% | 2026-02 |
| CapEx targeted vendor recall | 8.9% | 44% | 2026-02 |
| CapEx avg. confidence | 90% | 96% | 2026-02 |
CapEx categorization improvements from FC Validation deck — AI categorization improvement case study showing Palm's re-categorization engine correctly splitting CapEx from Payables for targeted vendors (e.g., On AG Cyan Tec Systems).
Findings & Results¶
See Bank Fee Analysis Results for the full Pulse analysis output including fee spend by bank, sub-classification, monthly trends, data quality issues, and CFO-level recommendations.
Risk and Caveats¶
- Fee categorization quality is the foundation. If Palm's categorization model tags non-fees as fees (or vice versa), the entire analysis is skewed. Phase 0 data cleanup is non-negotiable.
- Pricing agreements may be outdated. Banks sometimes apply updated rate cards without formally amending the agreement.
- Cash pooling complicates routing analysis. A centralized treasury structure may exist for liquidity management reasons, not cost reasons.
- FX spread costs are invisible in statement data. Banks make more on FX spreads than on visible transaction fees.
- Bank relationship dynamics matter. The cheapest bank on fees may not be the right bank for credit facilities, guarantees, or strategic partnerships.