Read-only financial data platform powered by the Comdirect REST API β CSV export, Finance API, and normalization pipeline.
Try the live mock demo
Static browser demo with fake data. No backend, no Comdirect credentials, no real banking data.
A personal project, not a finished product. I run it daily on my own bank data and iterate from real usage β features land when I miss them, not on a public roadmap. It works well enough that I trust it with my own finances; whether that bar is high enough for you is your call. No guarantees, no support.
Companion repo: k-fin-ui β React frontend for this backend.
Connects to the Comdirect REST API (read-only), normalizes your financial data into a local Postgres database, and serves it via a Finance API. Also supports CSV/JSON export for AI agents and dashboards.
- Comdirect connector β OAuth2 + pushTAN authentication, strictly read-only
- CSV/JSON export β Accounts, transactions, depot positions, depot transactions, financial overview
- Finance API β REST API for normalized financial data (transactions, categorization, aggregates)
- Normalization pipeline β Ingests raw Comdirect data into a canonical schema in Postgres
- Gmail mail evidence β Read-only Gmail import for sanitized invoice/order evidence and transaction matching
- AI categorization β LLM agents (pydantic-ai + Claude) categorize transactions, detect anomalies, generate monthly summaries
- MCP server β Exposes the Finance API as MCP tools for agent use; read-only by default, with a tiny opt-in write allowlist for trusted local sessions
- Self-hostable β
docker compose upfor a single laptop or a Helm chart for K3s/K8s; two-microservice split keeps bank credentials off the public-facing API
The project is split into two microservices with strict secret separation:
| Service | Port | Role | Bank Secrets |
|---|---|---|---|
| comdirect-api | 8000 | Public-facing read-only API | No |
| comdirect-worker | 8001 | Internal export/sync worker | Yes |
A Kubernetes NetworkPolicy ensures only comdirect-api can reach comdirect-worker. Both services share a PVC for exported data.
| Module | Description |
|---|---|
src/external/ |
Upstream provider clients β Comdirect (auth, accounts, transactions, depot) and yfinance (price history) |
src/api/ |
FastAPI app, routers, JWT auth (src/api/auth/) |
src/normalization/ |
Ingest + canonicalize pipeline for Postgres |
src/agents/ |
LLM agents β categorization, anomaly detection, monthly analysis, orchestrator |
src/mcp_server/ |
MCP server exposing the Finance API as agent tools; read-only unless write tools are explicitly enabled |
src/exporter/ |
Finance agent mapper + model-based JSON export |
src/scheduler/ |
Sync job orchestration (comdirect-worker) |
src/core/ |
Config (pydantic-settings), logging, SQLAlchemy DB models |
alembic/ |
DB migrations |
scripts/ |
Export, report, migration, and debug CLIs |
| Component | Technology |
|---|---|
| Language | Python 3.13 |
| Package manager | uv |
| HTTP client | httpx (async) |
| API | FastAPI + uvicorn |
| Config | pydantic-settings, .env |
| Containers | Docker, Helm, Tilt |
| Releases | semantic-release |
- Python 3.13+ and uv
- Postgres 16+ (local instance or Docker)
- Comdirect API credentials (Client ID, Client Secret, account number, PIN) β register at https://developer.comdirect.de/
- A pushTAN-capable device for authentication
- Docker (optional, for container setup)
- An Anthropic API key if you want the AI categorization features
git clone https://github.com/max5800/k-fin.git
cd k-fin
# Python deps
uv sync
# Config β fill in your Comdirect creds, API_TOKEN, DATABASE_URL,
# OWN_IBANS, ANTHROPIC_API_KEY (see .env.example for the full list)
cp .env.example .env
$EDITOR .env
# Database β apply schema migrations (uses DATABASE_URL from .env)
uv run alembic upgrade headuv run python scripts/export_csv.py --output-dir exportsThis triggers the Comdirect OAuth flow (including pushTAN confirmation) and writes CSV files to exports/.
uv run uvicorn main:app --reloadThe API serves the exported CSVs at http://localhost:8000.
After upgrading past v1.33.0 (refund-aware accounting), run this once
to list historical positive-amount rows in the erstattungen bucket so
you can decide which are real income (SteuerrΓΌckzahlung, Cashback) and
which are misclassified refunds of a prior expense (Krankenkasse,
Splitwise, Retouren). The script is read-only.
# Local
uv run python scripts/refund_backfill_report.py
uv run python scripts/refund_backfill_report.py --json
# In-cluster (worker pod has the venv + DATABASE_URL ready)
kubectl exec deploy/k-fin-worker -- \
/app/.venv/bin/python scripts/refund_backfill_report.pyMost rows are auto-decided by apply_refund_heuristic on API startup
and via POST /api/v1/aggregates/refund-audit/auto-apply. Use the
script when you want a printable list before doing manual PATCHes via
/api/v1/transactions/{id}.
Three supported paths, ordered by setup effort:
The fastest way to run the full stack β api, worker, UI, and Postgres β on a laptop or a single VM. No K8s, no Helm, no operators.
cp .env.compose.example .env
$EDITOR .env # fill in COMDIRECT_*, rotate the change_me_* values
docker compose pull && docker compose up -d
open http://localhost:3000The compose file pulls prebuilt images from
ghcr.io/max5800/k-fin-{api,worker,ui} by default. Worker port 8001 is
intentionally not published β only the api can reach it on the
compose-internal network, mirroring the chart's NetworkPolicy. See the
top of docker-compose.yml for the full layout.
pushTAN required. Every sync needs interactive Comdirect pushTAN approval on your phone β there is no fully-headless mode. This is a deliberate security boundary, not a missing feature.
If you already run a cluster, install via the Helm chart in chart/
or directly from the published OCI chart:
helm upgrade --install k-fin oci://ghcr.io/max5800/helm-charts/k-fin \
--version 1.28.2 -n k-fin --create-namespace -f my-values.yamlThe chart deploys api, worker, UI, a CloudNativePG Cluster for Postgres,
a NetworkPolicy isolating the worker, and a pre-install,pre-upgrade
migration job. K3s with Traefik + CloudNativePG is the maintainer's
tested reference platform; plain K8s works with ingress.className
overrides.
The full guide β prerequisites, BYO-Secret path, ExternalSecrets path,
backups, upgrades β is in docs/kubernetes-deployment.md.
The maintainer iterates against a remote K3s cluster with Tilt, Rancher
Desktop, and ExternalSecrets pulling from Vault. You do not need this
path to install or run k-fin β it's specific to the maintainer's
homelab. If you want to contribute, see docs/local-development.md
for the full setup.
| Endpoint | Description |
|---|---|
GET /exports?token=... |
List all available CSV files |
GET /exports/latest?token=... |
Latest file per export category |
GET /exports/{filename}?token=... |
Download a specific CSV |
Set API_TOKEN in your .env to require authentication.
- Manual pushTAN is a feature, not a bug: Because Comdirect does not offer scoped read-only API tokens, requiring a manual pushTAN confirmation for every sync is a deliberate security boundary. It ensures no automated system can quietly access your bank data or initiate sessions without your physical device approval.
- Your credentials never leave your machine. All data flows from Comdirect into your local Postgres DB via the normalization pipeline.
- Read-only API. The Comdirect connector implements only
GEToperations. Write operations (transfers, orders) are not and will not be supported. - Never commit your
.envfile. It contains banking credentials.
This is a personal project shared as-is under the Apache 2.0 license (see LICENSE).
- No warranty. Use at your own risk. Read the full warranty disclaimer in
LICENSE. - Banking data is sensitive. You are responsible for securing your own deployment β credentials, network exposure, database access, backups, and the host running k-fin. Don't put this on the public internet without auth and TLS.
- Not affiliated with Comdirect. k-fin is an independent open-source project. It uses the public Comdirect REST API with end-user credentials. The Comdirect API specification (
docs/comdirect_REST_API_Dokumentation.*) is not included in this repository β fetch it directly from https://developer.comdirect.de/ for local reference. - No support guarantee. Issues and PRs are welcome but answered as time allows.
For security-relevant findings, see SECURITY.md.
I do not write the code in this project. Claude (via OpenClaw) writes it; I direct the architecture, security model, and product decisions, and review every change before it ships. Treat this as a human-curated AI-built codebase rather than a hand-written one β the design choices and the trust boundary are mine, the implementation is the model's.
Apache License 2.0 β see LICENSE.
