BAI2 Bank Statement Format

If you have ever automated bank reconciliation or corporate cash management in the United States, you have likely met BAI2. Developed by the Bank Administration Institute, it is a compact, fixed-structure text format for reporting balances and transactions from a bank to its corporate customers. It is old, unglamorous, and still ubiquitous. This post explains how to read one.
What BAI2 is for
BAI2 answers a specific question a corporate treasurer asks every morning: what were my balances and what moved across my accounts yesterday? It is a reporting format, not a payment-initiation format. A bank generates a BAI2 file summarising opening and closing balances, available funds, and each transaction, and the customer's treasury or ERP system ingests it to reconcile and forecast cash.
The record hierarchy
A BAI2 file is a nested structure of records, each identified by a two-digit record type code in the first field. The hierarchy is: file, then one or more groups, then accounts within a group, then transactions within an account.
- 01 File Header: identifies the sender, receiver, creation date and time, and file control fields.
- 02 Group Header: opens a group, typically all accounts for one originating bank as of one date, with the reporting date and currency context.
- 03 Account Identifier: identifies a specific account and carries summary/status codes such as opening ledger balance, closing available balance, and totals.
- 16 Transaction Detail: a single transaction: its type code, amount, and reference or bank text.
- 88 Continuation: continues the preceding record when its data is too long for one line.
- 49 Account Trailer, 98 Group Trailer, 99 File Trailer: closing records that carry control totals and counts to validate that nothing was lost.
Every level opens with a header and closes with a trailer that carries a control total. Those trailers are your integrity check: if the totals do not tie out, the file is suspect.
Type codes: the heart of the format
The real meaning in BAI2 lives in its numeric type codes (sometimes called BAI codes). Each summary and transaction record carries a three-digit code that classifies what the amount represents. Some codes describe status/balance items on the 03 record, for example opening ledger balance, closing ledger balance, and closing available balance. Others describe transaction items on the 16 record, distinguishing, say, an incoming wire, an ACH credit, a lockbox deposit, a check paid, or a fee. A parser must map these codes to meaning; the number is authoritative, the accompanying text is not.
Reading a file in practice
To parse BAI2 reliably:
- Split on the record delimiter (records typically end with a slash) and read the leading type code of each record.
- Reassemble continuations: whenever an 88 record follows, append its content to the record it continues before interpreting fields.
- Track the hierarchy: maintain the current group, account and currency as you descend, so each 16 transaction is attributed correctly.
- Interpret amounts by type code, and note that BAI2 amounts are generally unsigned, with the type code (credit versus debit) determining direction.
- Validate against trailers: reconcile record counts and control totals in the 49, 98 and 99 records.
Where BAI2 fits today
BAI2 coexists with newer standards. Internationally, the ISO 20022 camt.053 (bank-to-customer statement) and camt.052 (intraday report) are the modern equivalents, offering richer, structured XML. Many banks provide both, and treasury systems often ingest BAI2 for domestic US reporting while moving to camt messages for cross-border and structured needs. Understanding BAI2 remains valuable precisely because so much existing tooling and so many bank feeds still emit it.
Common parsing gotchas
Real-world BAI2 files are less tidy than the specification suggests, and a few issues catch out first-time integrators. Bank text and reference data on 16 records can contain the field-delimiter character, so naive splitting on commas breaks; robust parsers respect quoting and known field counts. Amounts are usually expressed in the currency's minor units (for example cents), so a value must be scaled, not read as whole currency units. Type-code coverage varies between banks, meaning the same economic event can arrive under slightly different codes from different institutions, which is why a good implementation maintains a per-bank mapping rather than assuming one universal code set. Finally, always reconcile against the trailer control totals before trusting the parsed data; a silently truncated file is worse than an obviously broken one.
Key takeaways
- BAI2 is a fixed-structure format for bank-to-customer balance and transaction reporting, not payment initiation.
- Records nest as file (01), group (02), account (03), transaction (16), with 88 continuations and 49/98/99 trailers.
- Three-digit type codes classify balances and transactions and are the authoritative meaning, not the free text.
- Amounts are typically unsigned; the type code determines credit versus debit, and trailers carry control totals.
- ISO 20022 camt.053 and camt.052 are the modern structured equivalents, often provided alongside BAI2.