My Journey Setting Up Plaid with Beancount - A Complete Walkthrough

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

  1. Wait for transactions: Plaid says 240 seconds, but I’ve found 15+ minutes works better for initial syncs
  2. Template syntax matters: The default Beancount template had some issues - metadata keys can’t start with underscores
  3. Mapping files are your friend: Build up your payee mappings gradually; the interactive mode helps
  4. 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!

Great walkthrough, Frederick! As someone who helps clients set up their accounting systems, I appreciate the detail here.

From a professional perspective, I want to highlight a few audit trail considerations for anyone using this for business accounting:

Documentation Best Practices:

  1. Keep raw Plaid data: The MongoDB storage is great for this - make sure you’re backing up that database. If you ever need to prove a transaction happened, having the original Plaid data is invaluable.

  2. Reconciliation logs: Your Sunday sync script is efficient, but consider adding logging:

#\!/bin/bash
LOG_FILE=~/ledger/sync_log.txt
echo "=== Sync started: $(date) ===" >> $LOG_FILE
for account in chase_checking chase_credit amex; do
    echo "Syncing $account..." >> $LOG_FILE
    plaid2text $account ~/ledger/imports/$account.beancount --quiet --since 7d 2>&1 | tee -a $LOG_FILE
done
echo "=== Sync completed: $(date) ===" >> $LOG_FILE
  1. Bank statement reconciliation: Even with automated imports, I strongly recommend monthly reconciliation against your official bank statements. Plaid is very accurate, but it’s not infallible - I’ve seen occasional missing transactions.

One question - how do you handle pending transactions? Plaid sometimes pulls transactions that later get adjusted or reversed. Do you have a workflow for that?

This is exactly what I’ve been looking for! I manage books for about 20 small businesses, and the CSV download dance is eating up way too much of my time.

Quick question - how do you handle multiple bank accounts across different clients? In my situation, I’d potentially have:

  • 5-10 different banks
  • Multiple checking/savings accounts per client
  • Various credit cards

Is plaid2text designed to handle that many accounts? I’m wondering about:

  1. Config organization: Does the config file get unwieldy with dozens of account sections?
  2. API limits: With 20+ clients, would I burn through those 200 free API calls in a day?
  3. Credential management: Is there a way to separate Plaid credentials by client, or does everything go through one developer account?

I’m also curious about your experience with smaller regional banks and credit unions. Most of my clients use local banks here in Austin - Chase and the big names are easy, but places like Frost Bank or University Federal Credit Union might be hit or miss with Plaid support.

Has anyone tried this approach for a bookkeeping practice rather than personal finance?

Great walkthrough! From a tax compliance perspective, I want to add some considerations about using automated bank imports.

Record-Keeping Requirements

The IRS generally requires you to keep records that support your income, deductions, and credits. When using Plaid:

  1. Source documentation: Plaid data alone may not satisfy IRS requirements. You still need the underlying receipts and invoices for business expenses.

  2. Audit trail: Alice’s point about keeping the raw Plaid data is crucial. In an audit, you may need to demonstrate where transaction data came from.

  3. Consistency: Once you start using automated imports, maintain them consistently. Gaps in your transaction history can raise questions.

Business Use Considerations

If you’re using this for business accounting:

  • Subscription costs may be deductible: If you upgrade to Plaid Production for business use, that’s typically a deductible business expense under ordinary and necessary business expenses
  • Mixed personal/business accounts: Be careful - automated imports make it easier to accidentally commingle personal and business transactions

Quarterly Estimated Taxes

One benefit I see for my clients: real-time transaction access makes it easier to calculate quarterly estimated taxes accurately. No more scrambling at quarter-end to catch up on transaction entry.

Has anyone set up automated income/expense tracking for quarterly tax estimates using Plaid data?