As someone obsessed with tracking every penny toward early retirement, I’ve spent the last few months experimenting with different ways to automate my bank transaction imports into Beancount. After trying several approaches, I wanted to share my experience setting up plaid2text - it’s been a game-changer for my FIRE tracking workflow.
Why Plaid + Beancount?
Before Plaid, I was manually downloading CSV files from my bank every week. It worked, but it was tedious and I’d sometimes forget for a few weeks, leading to a backlog of transactions to categorize. With Plaid integration, transactions flow automatically into my Beancount files.
Getting Started
Step 1: Create a Plaid Developer Account
First, you need to sign up at plaid.com/docs. The free tier (Limited Production) gives you 200 API calls to test with real data, which is enough to evaluate whether this approach works for you.
Important: The sandbox environment lets you test unlimited with fake data first. I recommend playing with the sandbox for a week before connecting real accounts.
Step 2: Install plaid2text
The plaid2text project is a Python tool that bridges Plaid and Beancount. Install it via pip:
pip install plaid2text
You’ll also need MongoDB running locally to store transaction history:
# On macOS with Homebrew
brew install mongodb-community
brew services start mongodb-community
Step 3: Configure Your Accounts
Create your config file at ~/.config/plaid2text/config:
[DEFAULT]
posting_account = Assets:Bank:Checking
default_expense = Expenses:Unknown
encoding = utf-8
currency = USD
mongo_db = plaid2text
mongo_db_uri = mongodb://localhost:27017
output_format = beancount
[PLAID]
client_id = YOUR_PLAID_CLIENT_ID
secret = YOUR_PLAID_SECRET
[chase_checking]
posting_account = Assets:Bank:Chase:Checking
mapping_file = ~/.config/plaid2text/chase_checking/mapping_bc
template_file = ~/.config/plaid2text/chase_checking/template_bc
Step 4: Link Your Bank Account
Run the link command to authenticate with your bank:
plaid2text --link chase_checking
This opens a browser window where you log into your bank. Plaid handles all the OAuth complexity.
Step 5: Pull Transactions
After linking, wait about 15 minutes for Plaid to gather historical transactions, then:
plaid2text chase_checking /path/to/output.beancount --quiet --output-format beancount
What I Learned
- Wait for transactions: Plaid says 240 seconds, but I’ve found 15+ minutes works better for initial syncs
- Template syntax matters: The default Beancount template had some issues - metadata keys can’t start with underscores
- Mapping files are your friend: Build up your payee mappings gradually; the interactive mode helps
- MongoDB persistence: Transactions are stored locally, so you can re-run exports without re-downloading
My Current Workflow
Every Sunday morning, I run a simple script that pulls the week’s transactions from all my linked accounts:
#!/bin/bash
for account in chase_checking chase_credit amex; do
plaid2text $account ~/ledger/imports/$account.beancount --quiet --since 7d
done
Then I review the imports in Fava and adjust categories as needed.
Cost Considerations
The free tier works well for testing, but be aware:
- 200 API calls total in Limited Production
- Each transaction sync uses multiple calls
- For ongoing use, you may need Production access (requires application)
Has anyone else set up Plaid with their Beancount workflow? I’d love to hear about different approaches and any tips for improving my setup!