An Open Finance study with Pluggy
Wallet
An end-to-end personal project built to study Open Finance APIs: a bank account connected through Pluggy brings in transactions and investment positions without typing, and the backend takes on the work of reconciling the statement, classifying and summarizing.
- Role
- Backend and frontend
- Period
- 2025
- Status
- Open source

What the system does
- Bank account connection over Open Finance, with consent handled inside the aggregator's widget.
- Expenses and income from the connected account, alongside manual entries, in the same listing.
- Statement reconciliation: credit card purchases, bill payments and transfers between the holder's own accounts handled before anything counts as spending.
- Investment positions by type and subtype, with the issuing institution and the twelve-month rate.
- A monthly summary and spreadsheet export, by month, by category and by year.
Architecture
- A NestJS API with TypeORM over PostgreSQL, with a global prefix and Swagger documentation.
- Seven modules in the backend, with the bank connection split into three controllers, connect token, bank item and transactions, plus the investment submodule.
- Bank consent inside the aggregator's widget: the server exchanges client credentials for an API key and returns the connect token, and bank credentials are typed into the widget, never into the application.
- Authentication by a Firebase token verified on the server, in a route guard. The same guard provisions the user on the first authenticated request, with no signup route.
- A uniform response contract: an interceptor wraps every successful response and a global filter handles exceptions. On the way in, a ValidationPipe with a whitelist that refuses unknown fields.
- Spending comes in through two paths and goes out through one: the listing merges connected-account transactions and manual entries into the same response, each tagged with its origin, and the monthly summary adds both.
- Investments as their own domain: a position entity with twenty-eight subtypes and six types in enums, the institution as a separate entity, and an assembler that translates the aggregator's vocabulary at the response boundary.
- The schema versioned across five migrations, with no automatic synchronization.
- Structured logging with Pino, a health-check route and three spreadsheet exports with exceljs.
- The web app in Next.js with Recharts charts, consuming the API directly with the Firebase token in the header.
Implementation details
- Card reconciliation subtracts the bill payment and ten excluded categories, so a purchase is not counted twice.
- Synchronization is on demand: there is no schedule and no webhook, the bank item is refreshed when the client asks.
- Investment deduplication uses the asset's ISIN as its key.
Technologies
- TypeScript
- The language of both repositories.
- NestJS
- The API framework, with a guard, an interceptor and a global filter.
- TypeORM
- Entities and the five versioned migrations.
- PostgreSQL
- The database for expenses, income, positions and institutions.
- Pluggy
- The Open Finance aggregator: connect token, transactions and investments.
- Firebase
- Identity, with the token verified on the server.
- Pino
- Structured logging for the API.
- exceljs
- The three spreadsheet exports.
- Swagger
- API documentation.
- Next.js
- The web application, with the investment and expense screens.
- Recharts
- Charts for spending by month and by category.
- Docker
- A multi-stage API image, running as a non-root user.
Want to talk about architecture, technical decisions and shipping to production?
