After reading @finance_fred’s excellent introduction to plaid2text, I wanted to share some more advanced configuration tips. In my role as a financial controller, I’ve set up plaid2text to handle transaction imports from multiple bank accounts across our company, and there are some gotchas worth knowing about.
Multiple Account Configuration
The basic config file structure works fine for a few accounts, but when you’re managing 5+ accounts, organization becomes important.
Organizing Your Config
Here’s how I structure my config for a company with multiple bank accounts and credit cards:
[DEFAULT]
encoding = utf-8
currency = USD
mongo_db = plaid2text
mongo_db_uri = mongodb://localhost:27017
output_format = beancount
default_expense = Expenses:Uncategorized
[PLAID]
client_id = your_client_id
secret = your_secret
# ==== OPERATING ACCOUNTS ====
[main_checking]
posting_account = Assets:Bank:MainChecking
mapping_file = ~/.config/plaid2text/main_checking/mapping
template_file = ~/.config/plaid2text/main_checking/template
journal_file = ~/accounting/imports/main_checking.beancount
[payroll_account]
posting_account = Assets:Bank:Payroll
mapping_file = ~/.config/plaid2text/payroll/mapping
template_file = ~/.config/plaid2text/payroll/template
journal_file = ~/accounting/imports/payroll.beancount
# ==== CREDIT CARDS ====
[amex_corporate]
posting_account = Liabilities:CreditCard:AmexCorporate
mapping_file = ~/.config/plaid2text/amex_corp/mapping
template_file = ~/.config/plaid2text/amex_corp/template
journal_file = ~/accounting/imports/amex_corp.beancount
[visa_purchasing]
posting_account = Liabilities:CreditCard:Visa
mapping_file = ~/.config/plaid2text/visa/mapping
template_file = ~/.config/plaid2text/visa/template
journal_file = ~/accounting/imports/visa.beancount
Per-Account Template Files
Here’s a template that works well for business accounts. Save this as your template file:
{date} * "{payee}"
plaid_id: "{plaid_id}"
plaid_category: "{category}"
{account} {amount} {currency}
{posting_account}
Key points:
- Always include
plaid_idas metadata - it helps with deduplication plaid_categoryis useful for reviewing AI categorization suggestions- Make sure metadata values are quoted strings (learned this the hard way)
Mapping File Best Practices
Your mapping file handles payee-to-account mappings. Structure it by expense category:
# === PAYROLL ===
ADP PAYROLL.*|Expenses:Payroll:Processing
GUSTO.*|Expenses:Payroll:Processing
# === UTILITIES ===
APS ELECTRIC.*|Expenses:Utilities:Electric
SOUTHWEST GAS.*|Expenses:Utilities:Gas
COX COMMUNICATIONS.*|Expenses:Utilities:Internet
# === OFFICE SUPPLIES ===
STAPLES.*|Expenses:Office:Supplies
OFFICE DEPOT.*|Expenses:Office:Supplies
AMAZON.*OFFICE.*|Expenses:Office:Supplies
# === PROFESSIONAL SERVICES ===
QUICKBOOKS.*|Expenses:Software:Accounting
ZOOM.*|Expenses:Software:Communications
Common Gotchas
1. Template Metadata Syntax
This will fail:
_plaid_id: {plaid_id}
This works:
plaid_id: "{plaid_id}"
Beancount metadata keys can’t start with underscore, and values should be quoted strings.
2. Duplicate Transaction Detection
plaid2text stores transactions in MongoDB to avoid duplicates, but this only works per-account. If you’re pulling the same transaction from multiple linked accounts (like a transfer between accounts), you’ll get it twice.
My workaround: use a post-processing script that identifies transfers by amount/date matching:
# Simple transfer detection
def find_transfers(transactions):
potential_transfers = []
for t1 in transactions:
for t2 in transactions:
if (t1.account \!= t2.account and
abs(t1.amount) == abs(t2.amount) and
t1.date == t2.date):
potential_transfers.append((t1, t2))
return potential_transfers
3. OAuth Token Expiration
Plaid access tokens don’t expire by default, but some banks require periodic re-authentication. Chase, in my experience, needs re-linking every 90 days or so. Set up calendar reminders for accounts that need this.
4. Rate Limiting
If you’re syncing many accounts at once, add delays between API calls:
#\!/bin/bash
for account in main_checking payroll amex_corporate visa_purchasing; do
plaid2text $account ~/accounting/imports/$account.beancount --since 7d
sleep 5 # Be nice to the API
done
Questions for the Community
- Has anyone found a better approach to transfer detection?
- How do you handle account nicknames vs. official names in Plaid?
- Any tips for managing configs across multiple machines (version control?)?
Happy to share more details if anyone’s working on similar setups!