TL;DR
Bank of America’s CSV exports start with a 6–7 row metadata block — strip it before parsing. Their Description field mixes sender info with internal BofA codes (DES:, INDN:, CO ID:); regex out the noise before matching. Xero’s AmountDue is your source-of-truth for what’s still open.
What breaks when reconciling Bank of America with Xero
Three things that bite repeatedly:
The metadata header block. BofA’s CSV starts with several rows that aren’t transactions:
Description,,Summary Amt.
Beginning balance as of 04/01/2026,,52432.18
Total credits,,28940.00
Total debits,,-19873.45
Ending balance as of 04/30/2026,,61498.73
Date,Description,Amount,Running Bal.
04/01/2026,...
If your parser doesn’t skip these rows, you’ll get garbage cells. Look for the empty line followed by the Date,Description,... header — that’s the real data start.
The Description code soup. A typical BofA ACH credit shows up as:
DES:PAYMENT ID:1234567890 INDN:ACME CONSULTING CO ID:1234567890 CCD
DES: = transaction description, ID: = sender’s bank-assigned ID, INDN: = individual or company name (the actual payer), CO ID: = company ID, CCD = SEC code. You want the INDN: value for counterparty matching, but it’s buried mid-string.
Running Balance is end-of-business. BofA computes Running Bal. once at end of day, so two transactions posted the same day will both show the EOD balance regardless of intraday order. Useless for intra-day sequence reconstruction.
Export the Bank of America statement
- BofA Business → Accounts → pick the account → Download (top-right of activity list).
- File type: Microsoft Excel (
.csv). The Quicken / QuickBooks / Money options work too but are not standard CSV. - Date range: pick a calendar month. BofA caps at 18 months historical.
- File saves as
stmt.csv— yes, that’s the actual default filename, no date suffix. Rename immediately to avoid overwriting on the next export.
After stripping the metadata block, columns are: Date, Description, Amount, Running Bal.. Note the period in Bal.. Amount is signed: positive = credit, negative = debit.
Export the Xero invoice list
Same as the Wise + Xero guide: Business → Invoices → filter → Export → CSV.
Key columns for this combo: ContactName, InvoiceNumber, Reference, InvoiceDate, DueDate, Total, AmountDue, AmountPaid, Status, Currency.
AmountDue is what’s still open. AmountPaid is what Xero has already recorded against the invoice. If Status = PAID, AmountDue = 0. If Status = AUTHORISED and AmountPaid > 0, it’s a partial. Filter to AUTHORISED for “needs to be reconciled to bank” + PAID for “should already match a bank inflow”.
Match algorithm cheats for this combo
- Pre-process the BofA CSV. Drop rows where
Dateis empty or doesn’t parse asMM/DD/YYYY. The first 6–7 rows are metadata; skip until you hit the real header. - Extract
INDN:from description. RegexINDN:([^|]+?)(?=\s+CO ID:|\s+ID:|$). This gives you the payer name in uppercase. Lowercase + strip suffixes (INC,LLC,CORP) before fuzzy-matching. - Amount + date window. Match BofA
Amountagainst XeroTotalexactly. ACH typically settles within 1 business day; wires same-day. Use a ±2 business day window fromInvoiceDatetoDate(allowing prepayment) and a ±90 day window fromDueDate(catching late payments). - Reference field shortcut. If the BofA description contains a substring matching
INV-\d+,#\d+, or a 4–6 digit number, try it against XeroInvoiceNumberandReference(both fields — clients use either). - Status-based filtering. Drop Xero rows with
Statusin (DRAFT,VOIDED,DELETED) before matching. They’re not real receivables.
Real example
BofA inflow:
04/15/2026,"DES:RETAINER ID:0001234567 INDN:DELTA STUDIOS LLC CO ID:0001234567 CCD",7500.00,68932.50
Xero invoice line:
"Delta Studios","studios@delta.com",,"INV-2026-0421",,"04/01/2026","04/30/2026","7500.00","0.00","7500.00","PAID","USD"
Extract INDN: → "DELTA STUDIOS LLC". Normalize → "delta studios". Fuzzy-match against "Delta Studios" → 1.0 (after normalization). Amount exact match. Date within range. Status = PAID confirms Xero already recorded this — our match validates the bank-side cash event. Confidence: Exact (with Xero-side already-matched signal).
Edge cases this combo hits
Check deposits. BofA’s mobile/branch check deposits show in the description as "MOBILE CHECK DEPOSIT - REF #12345" or "BRANCH DEPOSIT - REF #12345". No payer name. Match on amount only and confirm visually in the result view. The check image is accessible via BofA’s web view but not in the CSV.
Zelle inbound. Zelle deposits show as "ZELLE PAYMENT FROM <NAME> ON <DATE> CONF# <ID>". The <NAME> is the Zelle account holder, usually a personal name even for business payers (“John Smith” for “Acme Inc” payments). Cross-reference Xero contacts by both company name and known contact person.
Wire transfers. Inbound wires show "WIRE TYPE:INTL IN DATE:042126 TIME:1432 ET TRN:..." or domestic equivalents. The originator name is buried deeper; sometimes it’s the next field after OBI: (Originator-to-Beneficiary Information). Manual extraction often required.
Fees and reversals. BofA charges occasional fees as separate same-day debit rows. If you reconcile by daily aggregate, fees will reduce your net inflow. Categorize them separately before matching against Xero.
Partial payments. If a customer wires partial payment (e.g., $5,000 against a $10,000 invoice), Xero will show Status = AUTHORISED, AmountPaid = 5000.00, AmountDue = 5000.00. Your BofA row shows $5,000. Match should mark the invoice as “Partially paid”, not “Paid”.
When this combo breaks our tool
If the BofA CSV has more than 90 days of transactions in one file, our matcher’s date-window optimization becomes less efficient. Performance is OK up to ~5,000 rows; past that, expect noticeable lag.
The INDN: extraction regex assumes English/Latin-character names. If you have international payers with non-Latin characters in their BofA registration, the regex may fail. We fall back to whole-description fuzzy match, which is less precise.
If you’ve enabled Xero’s bank feed for the BofA account, Xero may have auto-matched some inflows to invoices already. Our reconciliation will partially overlap; review the “Already matched” summary in Xero before comparing.
Faster way
Drop the BofA stmt CSV + Xero invoice export into the reconciler on the homepage — header skip, INDN: extraction, and ACH-prefix stripping all happen automatically. Run takes ~10 seconds for a typical month.
For the underlying AR concepts behind these invoices, the accounts receivable glossary entry covers the foundation.
If you handle a lot of overdue invoices coming out of these reconciliations, the how-to-recover-unpaid-invoices guide covers the chase scripts.