Plaid to Actual Budget integration
Find a file
Zepheris 661a993d1b Update README.md
Corrected for wrong readme.md file
2026-03-03 21:43:48 +00:00
_gitignore Initial commit 2026-03-03 14:28:21 -07:00
link_server.py Initial commit 2026-03-03 14:28:21 -07:00
Plaid_API.yml Initial commit 2026-03-03 14:28:21 -07:00
plaid_integration.py Initial commit 2026-03-03 14:28:21 -07:00
push_to_actual.py Initial commit 2026-03-03 14:28:21 -07:00
README.md Update README.md 2026-03-03 21:43:48 +00:00

Plaid → Actual Budget Sync

This project syncs bank account transactions from your real bank (using Plaid's API) into Actual Budget. It is designed to be safe to run repeatedly — it will never create duplicate transactions.


Table of Contents

  1. What This Project Does
  2. What Each File Does
  3. Prerequisites
  4. Setting Up a Python Environment
  5. Installing Required Packages
  6. Setting Up Your .env File
  7. Linking Your Bank Account (link_server.py)
  8. Verifying Your Connection (plaid_integration.py)
  9. Syncing Transactions to Actual Budget (push_to_actual.py)
  10. How to Re-run the Sync in the Future
  11. Troubleshooting

What This Project Does

This project is a set of Python scripts that:

  1. Connects to your bank via Plaid — a secure service used by many finance apps (like Venmo, Mint, etc.) to read your bank transactions.
  2. Fetches your transactions from Plaid's API.
  3. Pushes those transactions into your locally-running Actual Budget app.
  4. Prevents duplicates — you can run it every day and it will only add transactions that aren't already in Actual Budget.

Think of it as a bridge between your bank and your personal budgeting software.


What Each File Does

This is the first script you run — but only once (or when you need to re-link your bank). It starts a small temporary website on your server, listening on all network interfaces so you can access it from another device (like your laptop) on the same network. You open the page in your browser manually, and it walks you through Plaid's secure bank-linking process. When you successfully log into your bank through the Plaid popup, it saves a file called access_token.json to your project folder. This file is your long-lived permission slip to read your bank's transactions. Once the linking is complete, the server shuts itself down automatically.

⚠️ Keep access_token.json private! Anyone with this file can read your bank transactions. Do not commit it to Git. (Add it to your .gitignore file.)

plaid_integration.py

This is a helper and verification script. It contains the core functions for talking to Plaid's API (fetching accounts, fetching transactions, etc.). You can run it directly to verify that your Plaid connection is working and see a sample of your recent transactions printed in the terminal. The other scripts import functions from this file — it's the shared engine that powers everything.

push_to_actual.py

This is the main script you will run regularly. It:

  1. Loads your saved Plaid access token.
  2. Fetches your recent transactions from Plaid (up to 90 days back, but no earlier than January 1, 2026).
  3. Connects to your locally-running Actual Budget.
  4. Pushes those transactions into the correct accounts — safely skipping any that already exist.

On the very first run, it will generate an account_map.json file that you need to edit before running it again (see instructions below).

Plaid_API.yml

This is a reference file — a machine-readable description of Plaid's full API. You don't need to do anything with this file. It's there as documentation in case you want to understand what Plaid can do beyond what this project currently uses.


Prerequisites

Before you start, make sure you have the following:

  • Python 3.10 or newer installed on your computer.
    • Check by opening a terminal and typing: python3 --version
    • If not installed, download it from python.org
  • Actual Budget installed and running locally on your machine.
    • Download from actualbudget.org
    • It should be accessible in your browser at http://localhost:5006
  • A Plaid account (free for personal/development use — see next section for details)
  • Git (optional, but recommended for version control)

Setting Up a Python Environment

A virtual environment (venv) is a self-contained folder that holds all the Python packages for this project. This keeps things tidy and prevents conflicts with other Python projects on your computer. Think of it like a project-specific toolbox.

Step 1: Install the venv module (if needed)

On most systems, venv comes built into Python. But on some Linux/Ubuntu systems, you may need to install it separately:

# Only needed on some Linux systems:
sudo apt install python3-venv

On macOS and Windows, this step is usually not needed.

Step 2: Navigate to your project folder

Open a terminal (or Command Prompt on Windows) and navigate to the folder where you cloned this project:

cd /path/to/your/project

Step 3: Create the virtual environment

python3 -m venv .venv

This creates a folder called .venv inside your project directory. You only need to do this once.

Step 4: Activate the virtual environment

You need to activate the environment every time you open a new terminal to work on this project.

On macOS / Linux:

source .venv/bin/activate

On Windows:

.venv\Scripts\activate

When it's active, you'll see (venv) at the beginning of your terminal prompt. That means you're inside the virtual environment.

To deactivate it later (when you're done working), just type:

deactivate

Installing Required Packages

With your virtual environment activated, install all the required Python packages:

pip install requests python-dotenv actualpy

Here's what each package does:

Package Purpose
requests Sends HTTP requests to Plaid's API
python-dotenv Reads your .env file so secrets stay out of the code
actualpy Talks to your local Actual Budget app

Setting Up Your .env File

A .env file is a simple text file that holds your private configuration — like passwords and API keys. This file should never be committed to Git. (Make sure .env is listed in your .gitignore.)

Create a file named .env in the root of your project folder and fill it in with the following:

# ── Plaid Settings ───────────────────────────────
PLAID_CLIENT_ID=your_plaid_client_id_here
PLAID_SECRET=your_plaid_secret_here
PLAID_ENV=production

# ── Actual Budget Settings ───────────────────────
ACTUAL_URL=http://localhost:5006
ACTUAL_BUDGET_NAME=My Budget
ACTUAL_PASSWORD=your_actual_budget_password_here
ACTUAL_ENCRYPTION_PASSWORD=

Where to get your Plaid credentials

  1. Go to dashboard.plaid.com and create a free account.
  2. Once logged in, go to Team Settings → Keys.
  3. You'll see your Client ID and Secret. Copy those into your .env file.
  4. For PLAID_ENV, use:
    • sandbox — for testing with fake bank data (no real bank needed)
    • production — for use with your real bank account ← this is what you want for real use

⚠️ Important: To use production mode with a real bank, Plaid may require you to go through a short approval process on their website. For personal/developer use this is usually free and straightforward.

What each setting means

Setting Description
PLAID_CLIENT_ID Your unique Plaid app identifier
PLAID_SECRET Your Plaid API password (keep this secret!)
PLAID_ENV Which Plaid environment to use (sandbox or production)
ACTUAL_URL The web address of your running Actual Budget app
ACTUAL_BUDGET_NAME The exact name of your budget file as it appears in Actual Budget
ACTUAL_PASSWORD The password you use to log into Actual Budget
ACTUAL_ENCRYPTION_PASSWORD Only needed if you turned on end-to-end encryption in Actual Budget — leave blank otherwise

This step is only done once — or whenever you need to re-link your bank (e.g., if your bank credentials change).

Why is this necessary?

Plaid doesn't let you just hand it your username and password. Instead, it uses a secure flow where you log in through a Plaid-hosted popup in your browser. At the end of this flow, Plaid gives you a special token — an access token — that acts like a long-lived permission slip. This token lets the scripts fetch your transactions without ever storing your actual bank password. It's saved to access_token.json.

How to run it

Make sure your virtual environment is active, then run:

python link_server.py

You'll see output like:

=======================================================
  Plaid Link Server
=======================================================

[1/2] Creating link token...
      OK
[2/2] Starting server on port 8080
      Open http://<your-server-ip>:8080 in a browser to link your bank.

The server listens on all network interfaces (0.0.0.0), so it's accessible from any device on your network — this is intentional since the script is designed to run on a headless server (a machine with no monitor or browser).

From another device (like your laptop or phone) on the same network, open a browser and go to:

http://<your-server-ip>:8080

Replace <your-server-ip> with the local IP address of the machine running the script (e.g., http://192.168.1.50:8080). You can find your server's IP by running ip a or hostname -I on the server.

You'll see a simple page with a "Connect Bank Account" button. Click it and follow the steps to log into your bank through Plaid's secure popup.

Once you've successfully linked your bank:

  • The server will shut down automatically.
  • A file called access_token.json will be saved in your project folder.
  • You'll see a confirmation message in the terminal.

⚠️ Do not delete access_token.json! This is what all the other scripts use to access your bank data. If you delete it, you'll need to run link_server.py again.

⚠️ Do not commit access_token.json to Git. Add it to your .gitignore.


Verifying Your Connection (plaid_integration.py)

After linking, you can run this script to confirm everything is working:

python plaid_integration.py

It will print a list of your bank accounts and your most recent transactions. If you see your real data, you're good to go!


Syncing Transactions to Actual Budget (push_to_actual.py)

Make sure Actual Budget is open and running before you do this step.

First run — setting up the account map

Run the script:

python push_to_actual.py

On the very first run, the script doesn't know how to match your Plaid bank accounts to your Actual Budget accounts. So it will:

  1. Fetch your accounts from Plaid.
  2. Create a file called account_map.json.
  3. Stop and ask you to edit that file.

The account_map.json will look something like this:

{
  "abc123xyz": "Plaid Checking Account Name",
  "def456uvw": "Plaid Savings Account Name"
}

You need to edit the values (the part on the right of the colon) so they match the exact account names in your Actual Budget. For example:

{
  "abc123xyz": "Checking",
  "def456uvw": "Savings"
}

The names on the right must exactly match what you see in Actual Budget (including capitalization).

Second run and beyond — syncing transactions

Once account_map.json is set up, just run:

python push_to_actual.py

The script will:

  1. Load your Plaid access token.
  2. Fetch transactions from the last 90 days (or back to January 1, 2026, whichever is more recent).
  3. Connect to Actual Budget.
  4. Add any new transactions — skipping ones that already exist.
  5. Print a summary of how many transactions were added.

How to Re-run the Sync in the Future

When you come back to this project later, here's the quick checklist:

  1. Make sure Actual Budget is running (http://localhost:5006).
  2. Open a terminal and navigate to the project folder.
  3. Activate the virtual environment:
    # macOS/Linux:
    source .venv/bin/activate
    
    # Windows:
    .venv\Scripts\activate
    
  4. Run the sync:
    python push_to_actual.py
    

That's it! You do not need to re-run link_server.py unless your bank link has expired or you're setting up on a new computer.

If you're setting up on a new computer

You'll need to:

  1. Clone the repository.
  2. Create the .env file again with your credentials.
  3. Re-run link_server.py to re-link your bank (generates a new access_token.json).
  4. Re-create the virtual environment and install packages.
  5. Run push_to_actual.py as normal.

Running the Sync Automatically with Cron

Instead of manually running push_to_actual.py every day, you can schedule it to run automatically using cron — a built-in Linux task scheduler.

Why you must use the venv Python path

Cron runs in a bare-bones environment and doesn't know about your virtual environment. If you just write python push_to_actual.py in a cron job, it will use the system Python which doesn't have your installed packages, and the script will fail. The fix is to point cron directly at the Python executable inside your venv folder, which already has all the packages baked in.

Finding the correct Python path

First, find the full path to your project. If you cloned it to your home folder, it's likely something like /home/youruser/plaid-actual-sync. Confirm with:

pwd

Run this from inside your project folder. The venv Python will always be at:

/path/to/your/project/.venv/bin/python

For example, if your project is at /home/youruser/plaid-actual-sync, the Python path would be:

/home/youruser/plaid-actual-sync/.venv/bin/python

Setting up the cron job

Open your cron editor by running:

crontab -e

This opens a text editor. Add the following line at the bottom (adjust the path to match your actual project location):

0 6 * * * cd /home/youruser/plaid-actual-sync && /home/youruser/plaid-actual-sync/.venv/bin/python push_to_actual.py >> /home/youruser/plaid-actual-sync/sync.log 2>&1

Breaking down what this line does:

Part Meaning
0 6 * * * Run at 6:00 AM every day
cd /home/youruser/plaid-actual-sync Change into the project directory first (important — the script needs to find .env and access_token.json)
/home/.../.venv/bin/python push_to_actual.py Run the script using the venv Python
>> sync.log 2>&1 Append all output (and any errors) to a log file so you can review it later

Save and exit the editor. On most systems this is Ctrl+X, then Y, then Enter if using nano.

Changing the schedule

The first five values in the cron line control when it runs. Here are some common examples:

Cron schedule Meaning
0 6 * * * Every day at 6:00 AM
0 8 * * * Every day at 8:00 AM
0 6 * * 1 Every Monday at 6:00 AM
0 6,18 * * * Twice a day at 6:00 AM and 6:00 PM

Checking the log

After the cron job has run, you can check if it worked by viewing the log file:

cat /home/youruser/plaid-actual-sync/sync.log

If there are errors, the log will show the same output you'd see if you ran the script manually in the terminal.


Troubleshooting

"access_token.json not found" → You haven't run link_server.py yet, or you deleted the file. Run python link_server.py to re-link your bank.

"Plaid error: INVALID_API_KEYS" → Your PLAID_CLIENT_ID or PLAID_SECRET in .env is wrong. Double-check them on the Plaid dashboard.

"Connection refused" when connecting to Actual → Actual Budget isn't running. Open the Actual Budget app and make sure it's accessible at http://localhost:5006.

"Budget not found" error → The ACTUAL_BUDGET_NAME in your .env doesn't match the exact name of your budget in Actual. Check for typos or capitalization differences.

Transactions aren't showing up in Actual → Check that your account_map.json has the correct Actual Budget account names on the right side. The names must match exactly.

The virtual environment is missing after coming back to the project → The venv folder still exists, just re-activate it with source .venv/bin/activate (macOS/Linux) or .venv\Scripts\activate (Windows). If it was deleted, recreate it with python3 -m venv .venv and reinstall packages.


Files to Keep Private (add to .gitignore)

.env
access_token.json
.venv/
__pycache__/