Finance ledger agent: deterministic receipt normalization into Firefly III
Automated personal financial transaction normalization from read-only Gmail ingestion into self-hosted Firefly III using deterministic HTML and regex parsers.
Private personal finance tooling. Architecture and verification logic shown; zero amounts or merchant names disclosed.
- Ingestion
- Read-Only Gmail API (OAuth 2.0 PKCE)
- Parsing Architecture
- Rule-based parsers for each receipt format
- Target Ledger
- Self-Hosted Firefly III (REST API)
- Idempotency
- Order ID duplicate check · Automatic refund netting
Problem
Manual expense tracking across multiple payment apps and email receipts is tedious and prone to double-counting. Receipts arrive with varying HTML layouts, complex tax splits, adjustments, and delayed refund notifications.
What I Built
- Read-only import: A Python job runs every six hours, reads my Gmail with read-only access, and picks out receipt emails.
- Rule-based parsers: One parser per receipt format pulls out the amount, date and order number, so no AI model guesses at the numbers.
- No duplicates: Each entry is tagged with its order number, and if the same email is read again the existing entry is found and skipped. Refunds are matched to the original order number and netted off.
- Firefly III Integration: Staged transactions are posted to a self-hosted Firefly III instance via its authenticated REST API.
Outcome
Receipts reach the ledger without me entering them by hand, and re-reading an email does not create a second entry.
Stack
Python · Firefly III API · Gmail API · SQLite · scheduled jobs