Backend FastAPI service that helps match and update BLIK transactions in Firefly III using bank CSV exports. Upload a statement, preview parsed rows, review matches, and bulk-apply tags/notes in Firefly.
Internal tool, actively developed. No persistent database; in-memory match cache is reset on restart. Docker images are published to GHCR from main.
- CSV ingest and preview for Polish bank statement formats.
- Match pipeline against Firefly III transactions with configurable filters.
- Bulk apply notes/description updates and a "done" tag.
- JWT auth with a simple user list from
.env. - Docker-first deployment with optional Nginx proxy.
- FastAPI app (
src/main.py) with routers:auth: JWT token issuance from/api/auth/token.system: health/version endpoints under/api/system/*.blik_files: CSV upload -> preview -> match -> apply flow.
- CSV ingest: files stored temporarily in
/tmp, parsed byBankCSVReader. - Matching:
TransactionProcessor.matchqueries Firefly, filters byBLIK_DESCRIPTION_FILTER, excludesTAG_BLIK_DONE, and computes candidates. - Apply: writes updates in Firefly and tags transactions. Match results are cached in-process (
MEM_MATCHES) and cleared on restart. - Middleware: CORS (via
ALLOWED_ORIGINS), logging toblik_sync.logand stdout.
- Backend: Python 3.12, FastAPI, Starlette, Pydantic v2, PyJWT,
fireflyiii-enricher-core - Runtime: uvicorn, python-dotenv
- Tooling:
uv, pytest, black, ruff, isort, mypy, commitizen - Infra: Docker, docker-compose, GitHub Actions
- Python >= 3.12
uv(https://github.com/astral-sh/uv) orpip/venv- Firefly III API access + personal access token
- Docker (optional, for production/runtime)
# 1) Install deps
uv sync
# 2) Configure
cp .env.example .env
# 3) Run API
uv run uvicorn src.main:app --reload --host 0.0.0.0 --port 8000
# 4) Health check
curl http://localhost:8000/api/system/healthAuth:
# x-www-form-urlencoded token request
curl -X POST http://localhost:8000/api/auth/token \
-d 'username=user1&password=secret' \
| jq -r .access_token
# use in requests: Authorization: Bearer <token>Start with .env.example and fill in:
FIREFLY_URL: Firefly III API base URL.FIREFLY_TOKEN: Firefly personal access token.USERS: comma-separateduser:passlist.SECRET_KEY/ALGORITHM/ACCESS_TOKEN_EXPIRE_MINUTES: JWT settings (must be consistent for issuing and validating tokens).ALLOWED_ORIGINS:*, CSV (a,b,c), or JSON list for CORS.DEMO_MODE: feature flag (currently unused).BLIK_DESCRIPTION_FILTER: description fragment used to filter Firefly transactions.TAG_BLIK_DONE: tag applied afterapply.
Note: avoid spaces around = in .env for predictable parsing.
POST /api/blik_fileswith CSV file (filein form-data) -> returnsid.GET /api/blik_files/{id}-> preview parsed rows.GET /api/blik_files/{id}/matches-> match results and stats.POST /api/blik_files/{id}/matcheswith{ "tx_indexes": [<id_csv>, ...] }for rows that have exactly one match.
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| POST | /api/auth/token |
Issue JWT access token | No |
| GET | /api/system/health |
Health check | No |
| GET | /api/system/version |
Version info | No |
| POST | /api/blik_files |
Upload CSV file | Yes |
| GET | /api/blik_files/{id} |
Preview parsed CSV rows | Yes |
| GET | /api/blik_files/{id}/matches |
Compute and list match candidates | Yes |
| POST | /api/blik_files/{id}/matches |
Apply matches for selected rows | Yes |
Build/run locally:
docker build -t ff-iii-toolkit-api:local .
docker run --env-file .env -p 8000:8000 ff-iii-toolkit-api:localCompose (backend + proxy to Firefly on host):
cd infra
docker compose up -dEdit infra/nginx-firefly.conf if your Firefly instance listens on a different host/port.
.github/workflows/build.yml: builds and publishes images to GHCR onmainandv*tags.- Tests are not enforced in the pipeline; run locally before release.
src/main.py- FastAPI app and router/middleware wiring.src/api/routers/-auth,blik_files,system.src/api/models/- Pydantic request/response models.src/services/- CSV parser, auth utils, transaction processor.src/utils/- logger and helpers.infra/-docker-compose.yml,nginx-firefly.conf.Dockerfile- multi-stage build usinguv.makefile- shortcuts (make dev,make test).tests/- tests forSimplifiedRecord.pretty_print.
- 500 on
/statistics/matches/apply: missingFIREFLY_URLorFIREFLY_TOKEN. - 401 after login:
SECRET_KEY/ALGORITHMmismatch between token issuance and validation environment. - No matches: verify
BLIK_DESCRIPTION_FILTERand ensure transactions are not already tagged withTAG_BLIK_DONE. - "No match data found" during apply: in-memory cache cleared on restart; call
/matchesagain. - CORS blocked: set
ALLOWED_ORIGINSto correct CSV/JSON or*. - Missing CSV preview: files live in
/tmp/<id>.csv; cleanup or restart removes them.
- Logs: stdout and
blik_sync.login the working directory. - Tests:
uv run pytestormake test. - Lint/format:
uv run ruff check,uv run black .,uv run mypy.
See LICENSE.