Personal finance code that fetches European bank transactions via Enable Banking.
It also includes a Firefly III Docker setup and integration for importing transactions into Firefly III, using Enable Banking.
.pem file downloaded when registering the Enable Banking app, placed in the project root..pem file and store it in the root directory of the repo..pem file name..pem file and store it in the root directory of the repo..pem file name.| Platform | Command |
|---|---|
| Windows | winget install FiloSottile.mkcert |
| Linux | sudo apt install mkcert libnss3-tools |
| macOS | brew install mkcert |
And then:
mkcert -install
Run this from the firefly/certs/ directory:
mkcert localhost importer.localhost firefly.localhost
This produces localhost+2.pem (certificate) and localhost+2-key.pem (private key).
The easiest way to use persfin is the interactive CLI. It lists all Norwegian banks, lets you pick one, opens the bank login in your browser, and then prints your balances and recent transactions and stores to csv file.
.env.example in the root directory to .env..env file, and set the Enable Banking application ID
and .pem-file to the one you downloaded from Enable Banking.uv run persfin-cli
Sample session:
Fetching available banks for country 'NO'…
Found 23 bank(s):
1. BRAbank
2. DNB Bank
3. Eika Alliansen
…
23. Sbanken
Select a bank [1–23]: 23
→ You selected: Sbanken (NO)
Opening browser for bank login…
https://auth.enablebanking.com/…
Waiting for you to complete the bank login in your browser…
✅ Login successful!
════════════════════════════════════════════════════════════
Session ID : xxxxxxxx-…
Accounts : 2
════════════════════════════════════════════════════════════
── Account: <uid1> ──
closingBooked 12345.67 NOK
…
uv run uvicorn persfin.main:app --reload
# or
uv run persfin
The server starts at http://localhost:8000.
Interactive API docs are available at http://localhost:8000/docs.
curl http://localhost:8000/banks?country=NO
curl -s -X POST http://localhost:8000/connect \
-H "Content-Type: application/json" \
-d '{"aspsp_name": "Sbanken", "aspsp_country": "NO"}' | python -m json.tool
The response contains a url – open it in your browser.
The bank sandbox login credentials are typically customera / 12345678.
After you log in, the bank redirects to http://localhost:8000/callback?code=….
The app exchanges the code for a session automatically and shows the connected accounts.
curl http://localhost:8000/accounts
curl http://localhost:8000/accounts/<account_uid>/balances
# Last 90 days (default)
curl https://localhost:8000/accounts/<account_uid>/transactions
# From a specific date
curl "https://localhost:8000/accounts/<account_uid>/transactions?date_from=2024-01-01"
# Next page (pagination)
curl "https://localhost:8000/accounts/<account_uid>/transactions?continuation_key=<key>"
src/persfin/
├── __init__.py # package entry point
├── cli.py # interactive CLI (bank picker + transaction printer)
├── config.py # settings (pydantic-settings + .env)
├── enablebanking.py # Enable Banking API client (httpx + JWT)
├── models.py # Pydantic response models
└── main.py # FastAPI application
# Lint
uv run ruff check src/
# Type-check
uv run mypy src/
# Tests
uv run pytest
Requirement: A working docker installation.
Go to the firefly directory and copy all .example files to the same
filename, without the .example extension.
Edit the following variables in the files:
.db.env: Change the MYSQL_PASSWORD to your own password.
.env: Change the DB_PASSWORD to the same as the MYSQL_PASSWORD.
.importer.env: Set FIREFLY_III_ACCESS_TOKEN to the personal access token
generated by following
this description.
Start the containers, in the firefly directory:
docker compose -f docker-compose.yml up -d --pull=always
Open the Firefly III web interface at https://firefly.localhost/
Open the Data Importer web interface at https://importer.localhost/
Showing logs:
docker compose -f docker-compose.yml logs -f
Shutting down the containers:
docker compose -f docker-compose.yml down