This system automatically detects and parses CSV files from multiple banks. Here's what's supported and how to add your own.
The following banks are already supported with intelligent format detection:
- Checking/Savings: Details, Posting Date, Description, Amount, Type, Balance, Check or Slip #
- Credit Cards: Transaction Date, Post Date, Description, Category, Type, Amount, Memo
- Amount Format: Negative for debits, positive for credits
- Format: Date, Description, Amount, Card Member, Extended Details, Category
- Amount Format: Positive for all (it's a credit card)
- Format: Date, Description, Amount, Running Bal.
- Amount Format: Negative for debits, positive for credits
- Format: Trans. Date, Post Date, Description, Amount, Category
- Amount Format: Positive for all
- Format: Transaction Date, Posted Date, Card No., Description, Debit, Credit
- Amount Format: Split columns (Debit/Credit)
- Format: Date, Amount, *, Check Number, Description
- Amount Format: Negative for debits
- Format: Status, Date, Description, Debit, Credit, Member Name
- Amount Format: Split columns (Debit/Credit)
- Intelligently detects common column patterns
- Works with most standard formats
- Used when no specific parser matches
If your bank isn't listed above, share a sanitized sample so I can build a custom parser.
Minimum: 3 rows from your CSV (header + 2 transactions)
Example:
Date,Description,Amount,Balance
01/15/2024,WHOLE FOODS #123,-125.50,1500.00
01/16/2024,NETFLIX,-15.99,1484.01You can replace:
- Merchant names: WHOLE FOODS #123 → MERCHANT_A
- Amounts: Use fake amounts
- Balances: Use fake balances
- Account numbers: Remove or replace
What I need to see:
- ✅ Column headers (exact names)
- ✅ Date format (MM/DD/YYYY, DD/MM/YYYY, etc.)
- ✅ Amount format (single column or debit/credit split)
- ✅ Negative sign placement (-, (), etc.)
- ✅ Any special columns (category, type, etc.)
Chase Checking:
Details,Posting Date,Description,Amount,Type,Balance,Check or Slip #
DEBIT,01/15/2024,GROCERY STORE,-45.67,ACH_DEBIT,1234.56,
CREDIT,01/16/2024,PAYROLL DEPOSIT,2000.00,ACH_CREDIT,3234.56,Amex:
Date,Description,Amount,Extended Details,Category
01/15/2024,RESTAURANT,-67.89,RESTAURANT NYC,Dining
01/16/2024,GAS STATION,-45.00,GAS STATION CA,Auto & TransportCapital One:
Transaction Date,Posted Date,Card No.,Description,Category,Debit,Credit
2024-01-15,2024-01-16,1234,GROCERY STORE,Groceries,125.50,
2024-01-17,2024-01-18,1234,PAYMENT RECEIVED,Payments,,500.00The system detects your bank's format by:
- Reading CSV headers - column names
- Checking first row - data patterns
- Matching to known banks - using unique column combinations
- Falling back to generic - if no match found
Chase detected by:
- Has columns: "Posting Date" + "Description" + "Balance"
- OR: "Transaction Date" + "Post Date" + "Amount"
Amex detected by:
- Has columns: "Date" + "Description" + "Amount"
- AND: "Card Member" OR "Extended Details"
Capital One detected by:
- Has columns: "Transaction Date" + "Posted Date" + "Debit" + "Credit"
If you want to build your own parser, use this template:
import { BaseBankParser } from './base-parser';
import { RawTransaction } from '../../types/transaction.types';
export class MyBankParser extends BaseBankParser {
name = 'My Bank';
detect(headers: string[], firstRow: any): boolean {
// Check for your bank's unique columns
return this.hasColumns(headers, ['unique_col_1', 'unique_col_2']);
}
parse(row: any): RawTransaction {
const date = this.findColumn(row, ['Date', 'Trans Date']) || '';
const description = this.findColumn(row, ['Description']) || '';
const amount = this.findColumn(row, ['Amount']) || '0';
return { date, description, amount };
}
}MM/DD/YYYY(US standard)DD/MM/YYYY(International)YYYY-MM-DD(ISO)MM/DD/YY(Short year)
Single Column:
Amount
-125.50 # Negative for debit
125.50 # Positive for creditSplit Columns:
Debit,Credit
125.50, # Debit transaction
,125.50 # Credit transactionParentheses for Negative:
Amount
(125.50) # Parsed as -125.50
125.50 # Parsed as 125.50Headers with Symbols:
*, Check Number, Description(Wells Fargo)- Handled automatically
Multi-line Descriptions:
- Some banks split description into multiple columns
- Parser combines them:
Description + Extended Details
Category/Type Columns:
- Preserved if present
- Used for initial categorization hints
-
Save a sample (3-5 transactions):
Date,Description,Amount 01/15/2024,Test Transaction,-50.00
-
Try importing:
pnpm cli import test.csv
-
Check detection:
Detected bank format: Chase ✓ Imported: 1 -
If "Generic" detected:
- Share your CSV format with me
- I'll build a custom parser
- You'll get better accuracy
- Parser selected - specific or generic
- Rows parsed - using bank's format
- Data validated - dates, amounts, descriptions
- Duplicates checked - prevents re-importing
- Categories applied - auto-categorization
- Transactions stored - ready for analysis
- Export full CSV - don't edit in Excel (loses formatting)
- Include headers - column names are crucial
- Keep format consistent - don't mix formats
- One bank per file - don't combine CSVs
- Share unknown formats - I'll add support
- Check for missing headers
- Ensure proper comma/quote escaping
- Try different delimiter option
- Your bank isn't recognized
- Share CSV format for custom parser
- Generic still works but less accurate
- Check date format in CSV
- Verify amount column has numbers
- Ensure required columns present
- You already imported this file
- Use
--forceto override (not recommended) - Check date range
Send me:
- Bank name
- 3 rows of CSV (header + 2 transactions)
- Sanitized data is fine
I'll build a custom parser in ~5 minutes and you'll get perfect import accuracy.
Current Parsers: Chase, Amex, BofA, Discover, Capital One, Wells Fargo, Citi, Generic
Add yours: Share CSV format → Custom parser built → Perfect imports