# Bank Fee Analysis: How to Stop Overpaying Your Banks

Source: https://gravam.com/blog/bank-fee-analysis
Author: Tan Gravam
Published: 2026-07-23
Updated: 2026-09-25
Reviewed: 2026-09-25
Summary: Bank fee analysis reconciles bank charges against agreed pricing. How camt.086, TWIST BSB and AFP service codes make fees comparable, field by field.

**Bank fee analysis is the practice of systematically reviewing what your banks charge — reconciling actual fees against agreed pricing, catching errors and overcharges, and benchmarking your costs.** It matters because bank charges are opaque, voluminous and _frequently wrong_: a large company can be billed for thousands of individual services a month, in inconsistent language, against pricing buried in contracts nobody's reopened in years. Left unchecked, the overcharges simply accumulate. Analyzed methodically, bank fees give back real money — and the data to manage your banking relationships from evidence instead of guesswork.

## Why bank fees are hard

The difficulty is structural, not accidental:

- **Opacity.** Charges are described in each bank's own terms, often cryptically.
- **Volume.** Thousands of line items across many [accounts](https://gravam.com/blog/bank-account-rationalization) and banks, every month.
- **Inconsistency.** The same service is named and coded differently by different banks.
- **Stale pricing.** The agreed rates live in contracts that may be years old and rarely consulted.

Put together, these make manual reconciliation practically impossible — which is precisely why errors survive. What can't be checked, isn't.

## The standards that make it possible

The key to tractable analysis is a _common language_ for charges, and there are three electronic formats that carry one, plus one code set that makes them comparable:

| Standard | What it is | Where you meet it |
| --- | --- | --- |
| **ANSI X12 822** (Account Analysis) | The US EDI transaction set for account analysis statements: service charges, balances, volumes, earnings credit | US banks, for decades; the US AFP Service Code is a mandatory field in it |
| **TWIST BSB** (Bank Services Billing) | The XML billing statement defined by the TWIST standards group, the design the ISO message was built from | Earlier global billing implementations |
| **camt.086** BankServicesBillingStatement | The ISO 20022 message; per AFP and trade coverage, the functional equivalent of TWIST BSB version 3.1, changed only to conform to ISO 20022 conventions | The format to ask for today, alongside your other [camt messages](https://gravam.com/blog/iso-20022-payments-pain-001-pain-002) |
| **AFP Service Codes** | The code set that maps each bank's own service names to a common identifier: six-character domestic (US) codes and eight-character global codes | Inside all three formats, and in bank RFP pricing grids |

The AFP codes go back to 1986, when they were created for the US 822 account analysis statement; the Global AFP Service Codes extended the idea for camt.086 and TWIST BSB files, and AFP has updated them in collaboration with the CGI-MP market-practice group that also shapes corporate [pain.001 implementations](https://gravam.com/blog/pain-001-structure-and-fields). The first two characters of a domestic code identify the service family.

> The common service code is what turns "every bank calls it something different" into "every charge maps to a comparable category." Without it you're comparing PDFs by hand; with it you can reconcile thousands of charges against agreed pricing automatically. Ask every bank for camt.086 with AFP codes populated, not just "electronic billing".

## Inside a camt.086: the fields that matter

ISO's message definition is explicit about what camt.086 is and isn't. It is a periodic, usually month-end, recounting of **every service-chargeable event** in the reporting cycle, with detailed tax and currency-translation information; account balances are strongly recommended but not required. It is **not designed to be an invoice**: it supplies the detail behind invoices or account debits, and becomes an invoice only by agreement between bank and customer. The structure is a report header and one or more billing statements, each for one account (or a parent account summarising children).

At statement level, per the camt.086.001.03 definition:

| Element | What it carries | Why fee analysis cares |
| --- | --- | --- |
| `StmtId`, `FrToDt`, `CreDtTm` | Statement identification and the billing period | The period key for matching to pricing and to the account's debits |
| `Sts` | `ORGN` original, `RPLC` replaces the original, `TEST` | A replacement must supersede, not add to, the original, or you double-count a month |
| `AcctChrtcs` / `CompstnMtd` | Account level and parent account; how charges are settled: `NOCP` not paid, `DBTD` debited, `INVD` invoiced, `DDBT` delayed debit | Tells you whether to reconcile against statement debits or against accounts-payable invoices |
| `RateData` | Non-tax per-annum rates and factors used in the statement | Earnings credit and similar rates, where the bank offsets fees against balances |
| `Bal` | Average balances held in the period | The input to balance-compensation checks |
| `Compstn` | Compensation values and service and tax totals | The statement's own totals, to foot your line-level recalculation against |
| `Svc` | One entry per service line | The analysis itself, below |
| `TaxRgn` | Tax by region, including the region's calculation method | VAT and similar taxes on bank charges, which finance may be able to recover |
| `BalAdjstmnt`, `SvcAdjstmnt` | Corrections to prior periods, incl. earnings adjustments, price and volume changes, original and new charge amounts | Retroactive corrections, which are both evidence of past errors and a way to confirm the bank fixed one |

Inside each `Svc` line:

| Element | Meaning |
| --- | --- |
| `BkSvc/Id` and `Desc` | The bank's own internal service code and description, different from the common code |
| `BkSvc/CmonCd` (`Issr`, `Id`) | The common code, with its issuer ("such as AFP", in ISO's words), so the service can be identified across banks |
| `BkSvc/BkTxCd` | Optionally, the ISO bank transaction code of the underlying transaction |
| `Vol` | The count of items charged |
| `Pric/UnitPric`, `Pric/Mtd` | Unit price, and how the charge was calculated (unit priced, flat, base, list, discount, minimum charge, tiers and others); if the method is absent, the charge is volume × unit price |
| `PmtMtd` | What happened to the charge: `BCMP` balance compensable, `FLAT` hard charge due, `PVCH` previously charged, `INVS` invoiced separately, `WVED` waived (original amount shown), `FREE` |
| `OrgnlChrgPric` | The original price, for example before a waiver |
| `BalReqrdAcctAmt` | For balance-compensable services, the average collected balance needed to offset the charge |
| `TaxDsgnt`, `TaxClctn` | Taxable status and the tax computed for the line |

## How the analysis uses them

> A camt.086 doesn't make the bank's bill right. It makes the bill recomputable, and a bill you can recompute is a bill you can dispute.

With those fields, most of the checks become arithmetic rather than detective work:

1. **Map every line to a common code.** Lines with only a bank-internal `Id` go to an exceptions list; the mapping from bank code to AFP code is the reference data your whole analysis depends on, so keep it versioned.
2. **Recompute every line.** Volume × unit price (or the stated method) against the charged amount catches calculation errors; unit price against your agreed price schedule for that common code catches off-contract pricing.
3. **Separate what is due from what is informational.** `PVCH` and `INVS` lines were charged elsewhere and must not be counted again; `WVED` lines show the value of waivers, which is worth tracking before a waiver quietly expires.
4. **Reconcile to money that moved.** Use the compensation method to tie totals to account debits (`DBTD`) or to supplier invoices (`INVD`), and apply `RPLC` statements as replacements.
5. **Check balance compensation where it applies.** For `BCMP` services, balances, rates and the balance required show whether the earnings credit covered the fees, a question that matters mostly in the US.
6. **Watch the adjustments.** A stream of `SvcAdjstmnt` entries on the same service is a process problem at the bank, and evidence for the renegotiation.

If you run SAP S/4HANA, bank fee import and monitoring is part of the full scope of [SAP Cash Management](https://gravam.com/blog/sap-cash-management-s4hana), which is where camt.086 data can land next to the bank accounts it belongs to.

## What the analysis finds

Done properly, fee analysis surfaces:

- **Billing errors.** Charges that are simply wrong — the bank's mistake, recoverable.
- **Off-contract pricing.** Being charged more than the rate you negotiated.
- **Redundant services.** Paying for things you no longer use or need.
- **Benchmarking gaps.** Costs out of line with the market or with your other banks.

## How to analyze fees

1. **Collect** the billing statements — electronically and in a standard format wherever possible.
2. **Normalize** the charges into comparable categories using standard service codes.
3. **Reconcile** actual charges against your _agreed_ pricing — which means having the agreed pricing captured and current in the first place.
4. **Investigate variances** — every gap is a billing error, an off-contract charge, or a service to question.
5. **Do it regularly**, not once — fees drift back, and small recurring overcharges compound.

## Where it connects

Fee analysis isn't isolated. Fewer accounts from [rationalization](https://gravam.com/blog/bank-account-rationalization) means fewer fees to begin with. And the fee data itself is powerful input to [**bank relationship management**](https://gravam.com/blog/bank-relationship-management) — deciding which banks get which business, and negotiating from evidence rather than impression. Combined with [cash visibility](https://gravam.com/blog/how-to-achieve-global-cash-visibility), it turns the banking relationship from a black box into something you actively manage.

## Why bank fee overcharges go unnoticed

- **Never checking.** Assuming the bank's charges are correct — they often aren't, and no one ever looks.
- **No standard format.** Trying to reconcile inconsistent PDFs by hand, so it never really happens.
- **No pricing baseline.** Having no captured record of what you agreed to pay, so there's nothing to reconcile _against_.
- **Ignoring small recurring charges.** Dismissing each as trivial while, monthly across every account, they add up to real money.
- **One-and-done.** Analyzing once, recovering some money, then letting it lapse until the charges drift back.

Get billing in a standard format, normalize with service codes, reconcile against agreed pricing, investigate every variance, and repeat it on a cycle — and bank fee analysis turns an opaque, quietly-overcharged cost into recovered money and negotiating leverage. It's unglamorous, entirely data-driven, and one of the more reliable ways treasury pays for itself.

***

_See also [bank account rationalization](https://gravam.com/blog/bank-account-rationalization) and [global cash visibility](https://gravam.com/blog/how-to-achieve-global-cash-visibility)._

## Primary sources

camt.086 elements and code values per ISO 20022 BankServicesBillingStatementV03 (camt.086.001.03, Bank Services Billing Maintenance 2018–2019); later message versions exist, so check the version and the AFP code edition your banks send. AFP Service Codes and ANSI X12 822 described at the level AFP publishes. Claims checked on 2026-09-25 through cross-checked excerpts of the listed sources.

- ISO 20022 — Message Definition Report Part 2, Bank Services Billing, Maintenance 2018–2019 (camt.086.001.03 BankServicesBillingStatementV03), approved by the Payments SEG 21 January 2019 — copy distributed in the moov-io/iso20022 repository — accessed 2026-09-25 — https://github.com/moov-io/iso20022/blob/v0.2.1/docs/specifications/bank_services_billing_3/ISO20022_MDRPart2_BankServicesBilling_2018_2019_v1.pdf
- AFP — AFP Service Codes (standard for balances and charges on account analysis statements since 1986; domestic and global code sets) — accessed 2026-09-25 — https://www.financialprofessionals.org/training-resources/resources/afp-service-codes
- AFP — Global AFP Service Codes Committee Review (codes for TWIST BSB and camt.086; update with CGI-MP) — accessed 2026-09-25 — https://www.financialprofessionals.org/training-resources/resources/articles/Details/global-afp-service-codes-committee-review
- AFP — The ISO BSB Electronic Billing Statement: Status, Acceptance, AFP Code Usage — accessed 2026-09-25 — https://www.financialprofessionals.org/docs/default-source/default-document-library/sp/81.pdf?sfvrsn=3c8d476b_2
- CTMfile — ISO 20022 camt.086 Message (BSB / Bank Services Billing) officially released — accessed 2026-09-25 — https://ctmfile.com/story/iso-20022-camt.086-message-bsb-bank-services-billing-officially-released
- Stedi — X12 822 Account Analysis transaction set — accessed 2026-09-25 — https://www.stedi.com/edi/x12/transaction-set/822

## Questions this article answers

**Q: What is bank fee analysis?**

Bank fee analysis is the practice of systematically reviewing what your banks charge you — reconciling the actual fees charged against the pricing you agreed, identifying billing errors and overcharges, spotting redundant or unexpected services, and benchmarking your costs. Because bank charges are opaque, high in volume and frequently wrong, analyzing them methodically recovers real money and gives you the data to negotiate and manage banking relationships.

**Q: Why are bank fees so hard to check?**

Bank fees are hard to check because they're opaque and voluminous: a large company can be charged for thousands of individual services across many accounts and banks each month, described in inconsistent, bank-specific language, with pricing spread across contracts that may be years old. Without a standard way to normalize and compare the charges, reconciling what you were actually billed against what you agreed to pay is nearly impossible to do by hand — which is exactly why overcharges persist unnoticed.

**Q: What is camt.086?**

camt.086 is the ISO 20022 BankServicesBillingStatement: a periodic, usually month-end, electronic statement from a bank listing every service-chargeable event on an account, with volumes, prices, how each charge was settled, taxes by region, average balances and corrections to earlier periods. It is the ISO counterpart of the TWIST Bank Services Billing format and usually carries AFP service codes so charges can be compared across banks. It supports invoices or account debits but is not itself an invoice unless bank and customer agree that it is.

**Q: How do you analyze bank fees?**

Collect the banks' billing statements (ideally in a standard electronic format such as camt.086, using standardized service codes like the AFP Service Codes), normalize the charges into comparable categories, reconcile the actual charges against your agreed pricing, and investigate every variance. This surfaces billing errors, off-contract pricing and redundant services. Doing it on a standard, automated basis — rather than eyeballing PDFs occasionally — is what turns it from a chore into recovered money and negotiating leverage.
