Personal spending tracker that fetches bank transactions via the Enable Banking API (PSD2 AISP), stores them in MongoDB, and sends daily/monthly summaries to Telegram. Dashboards via Grafana.
Supports multiple banks — add a new bank by updating config and running the auth flow. No code changes needed.
graph LR
CJ[CronJob] -- triggers --> APP[App]
APP -- fetch transactions --> EB[Enable Banking API]
EB -. PSD2 .-> Banks[Bank 1, Bank 2, ...]
APP -- store --> DB[(MongoDB)]
APP -- send summaries --> TG[Telegram]
GF[Grafana] -- query --> DB
style EB fill:#1a73e8,color:#fff
style DB fill:#4db33d,color:#fff
style TG fill:#2aabee,color:#fff
style GF fill:#f46800,color:#fff
Grafana dashboard showing aggregated spending across multiple connected banks:
- Multi-bank, multi-account transaction fetching via Enable Banking (PSD2)
- Automatic deduplication (content-hash-based
_id) - Daily summary: yesterday's spending with individual line items
- Monthly summary: totals + top 5 counterparties
- Telegram notifications with optional Grafana dashboard links
- Smart fetch window: 7 days overlap (365 days on first run, auto-capped per bank)
- Weekly full lookback (Mondays) + manual
fetch --fulloption - Per-bank session management with 180-day validity
- TypeScript, Node 22, ESM, strict mode
- Enable Banking API (PSD2 AISP)
- MongoDB 7 (native driver)
- Telegraf (Telegram bot)
- Grafana + MongoDB datasource plugin (optional)
- Kubernetes (any distro), Helm, GitHub Actions, GHCR
- HashiCorp Vault + External Secrets Operator (optional — plain k8s Secrets work too)
| Variable | Description |
|---|---|
BANKS |
JSON array of bank configs (see below) |
MONGO_URI |
MongoDB connection string |
TELEGRAM_BOT_TOKEN |
Telegram bot token from @BotFather |
TELEGRAM_CHAT_ID |
Telegram chat ID for summaries |
| Variable | Default | Description |
|---|---|---|
GRAFANA_URL |
(none) | Full Grafana dashboard URL — if set, summary messages include a dashboard link |
MONGO_DB_NAME |
spending |
MongoDB database name |
[
{
"id": "swedbank-ee",
"name": "Swedbank",
"country": "EE",
"appId": "<your-app-id>",
"privateKey": "-----BEGIN RSA PRIVATE KEY-----\n...\n-----END RSA PRIVATE KEY-----",
"redirectUrl": "https://localhost:3000/callback"
}
]redirectUrl is optional (defaults to https://localhost:3000/callback). PEM keys use \n escape sequences inside JSON — JSON.parse() handles the conversion.
Two modes:
auth <bankId>— interactive CLI flow to link a bank account via BankID/Smart-ID (re-run every ~180 days)fetch— pull transactions from all banks, store in MongoDB, send Telegram summaries (designed for cron)fetch --full— same asfetchbut uses the maximum lookback window (365 days) instead of the last known transaction date. Runs automatically on Mondays.
See docs/setup-guide.md for kubectl commands to run these in-cluster.
npm install
npm run build
npm run lint
npm test
npm run test:coverage
npm run format:checkSee docs/setup-guide.md for full deployment instructions.
The GitHub Actions workflow builds and pushes a Docker image to GHCR, then deploys via helm upgrade. The Helm chart runs a CronJob that executes fetch on schedule. Works on any Kubernetes cluster.
The Helm chart supports two approaches:
Vault + ESO (default) — set externalSecret.enabled: true in values.yaml and configure the Vault path. ESO syncs secrets to a k8s Secret automatically.
Plain k8s Secret — set externalSecret.enabled: false and create the Secret manually:
kubectl -n <namespace> create secret generic <release>-secrets \
--from-literal=BANKS='[{"id":"...","name":"...","country":"...","appId":"...","privateKey":"..."}]' \
--from-literal=MONGO_URI='mongodb://...' \
--from-literal=TELEGRAM_BOT_TOKEN='...' \
--from-literal=TELEGRAM_CHAT_ID='...'The Secret name must match <release>-secrets (e.g. spending-secrets for release name spending).
- Register a new app in Enable Banking, get the app ID and PEM key
- Add the bank entry to the
bankssecret (Vault or env var) - Run
auth <bankId>to create the session - No code or Helm changes needed
Click to expand
src/
index.ts Entry point (auth / fetch mode)
config.ts Env var loading + validation
constants.ts Shared constants (timeouts, limits, defaults)
api/
jwt.ts RS256 JWT generation
client.ts Enable Banking API client
db/
mongo.ts MongoDB connection
collections.ts Typed collection accessors + indexes
models/
transaction.ts Transaction interface
session.ts Session interface
services/
auth.ts Interactive bank auth flow (CLI)
fetcher.ts Fetch, dedup, store transactions
summarizer.ts Daily/monthly aggregation pipelines
telegram.ts Telegram message formatting + sending
test/unit/ Unit tests (mirrors src/ structure)
charts/spending-tracker/ Helm chart (CronJob + ExternalSecret)
.github/workflows/ CI/CD pipeline (build+test → deploy)
docs/setup-guide.md Full deployment guide