Metadata-Version: 2.4
Name: bankfetch
Version: 0.1.0
Summary: Download your own bank accounts transactions via the Enable Banking API
Project-URL: Repository, https://github.com/dpmungo/bankfetch
Author-email: Davide Mungo <dp.mungo@gmail.com>
License: PolyForm Noncommercial License 1.0.0
        
        <https://polyformproject.org/licenses/noncommercial/1.0.0>
        
        Acceptance
        
        In order to get any license under these terms, you must agree
        to them as both strict obligations and conditions to all
        your licenses.
        
        Copyright License
        
        The licensor grants you a copyright license for the
        software to do everything you might do with the software
        that would otherwise infringe the licensor's copyright
        in it for any permitted purpose. However, you may
        only distribute the software according to Distribution
        License and make changes or new works based on the
        software according to Changes and New Works License.
        
        Distribution License
        
        The licensor grants you an additional copyright license
        to distribute copies of the software. Your license to
        distribute covers distributing the software with changes
        and new works permitted by Changes and New Works License.
        
        Notices
        
        You must ensure that anyone who gets a copy of any part of
        the software from you also gets a copy of these terms or the
        URL for them above, as well as copies of any plain-text lines
        beginning with Required Notice: that the licensor provided
        with the software. For example:
        
        Required Notice: Copyright dp.mungo@gmail.com
        
        Changes and New Works License
        
        The licensor grants you an additional copyright license to
        make changes and new works based on the software for any
        permitted purpose.
        
        Patent License
        
        The licensor grants you a patent license for the software
        that covers patent claims the licensor can license, or will
        be able to license, that you would infringe by using the
        software.
        
        Noncommercial Purposes
        
        Any noncommercial purpose is a permitted purpose.
        
        Personal Uses
        
        Personal use for research, experiment, and testing for
        the benefit of public knowledge, personal study, private
        entertainment, hobby projects, amateur pursuits, or religious
        observance, without any anticipated commercial application,
        counts as use for a permitted purpose even if it is use
        of the software in the production of work you sell.
        
        Noncommercial Organizations
        
        Use by any charitable organization, educational institution,
        public research organization, public safety or health
        organization, environmental protection organization,
        or government institution counts as use for a permitted
        purpose regardless of the source of funding or obligations
        resulting from the funding.
        
        Fair Use
        
        You may have "fair use" rights for the software under the
        law. These terms do not limit them.
        
        No Other Rights
        
        These terms do not allow you to sublicense or transfer any of
        your licenses to anyone else, or prevent the licensor from
        granting licenses to anyone else. These terms do not imply
        any other licenses.
        
        Patent Defense
        
        If you make any written claim that the software infringes or
        contributes to infringement of any patent, your patent license
        for the software granted under these terms ends immediately. If
        your employer makes such a claim, your patent license ends
        immediately for work on behalf of your employer.
        
        Violations
        
        The first time you are notified in writing that you have
        violated any of these terms, or done anything with the software
        not covered by your licenses, your licenses can nonetheless
        remain in effect if you come into compliance within 32 days of
        receiving notice. Otherwise, all your licenses end immediately.
        
        No Liability
        
        As far as the law allows, the software comes as is, without
        any warranty or condition, and the licensor will not be liable
        to you for any damages arising out of these terms or the use
        or nature of the software, under any kind of legal claim.
        
        Definitions
        
        The licensor is the individual or entity offering these
        terms, and the software is the software the licensor makes
        available under these terms.
        
        You refers to the individual or entity agreeing to these
        terms.
        
        Your company is any legal entity, sole proprietorship,
        or other kind of organization that you work for, plus all
        organizations that have control over, are under the control of,
        or are under common control with that organization. Control
        means ownership of substantially all the assets of an entity,
        or the power to direct its management and legal affairs.
        
        Your licenses are all the licenses granted to you for the
        software under these terms.
        
        Use means anything you do with the software requiring one
        of your licenses.
        
        Trademark
        
        The licensor grants no trademark licenses under these terms.
License-File: LICENSE
Keywords: aisp,bank-transactions,banking,cli,csv,download,enable-banking,export,ledger,open-banking,personal-finance,psd2,transactions
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: End Users/Desktop
Classifier: License :: Other/Proprietary License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Office/Business :: Financial
Requires-Python: >=3.13
Requires-Dist: cryptography>=42.0
Requires-Dist: loguru>=0.7
Requires-Dist: pyjwt>=2.8
Requires-Dist: python-dotenv>=1.0
Requires-Dist: requests>=2.32
Requires-Dist: typer>=0.12
Description-Content-Type: text/markdown

# BankFetch, download your own bank account transactions via Enable Banking API

CLI tool that fetches bank account transactions via [Enable Banking](https://enablebanking.com) and exports them to CSV. Enable Banking acts as the licensed AISP intermediary, so you don't need an eIDAS certificate or TPP registration of your own.

Built primarily for accessing transactions in my Banca Mediolanum account, but you implement your own parser to support other banks in a hopefully straightforward way.

## Requirements

- Python 3.14+
- [uv](https://docs.astral.sh/uv/)
- An Enable Banking account with a registered app and a linked bank account

## Setup

1. Register at [enablebanking.com/cp/applications](https://enablebanking.com/cp/applications) and create a **Production (Restricted)** app (free for personal use on your own accounts).
2. During app creation, set the redirect URL to `https://localhost/auth_redirect`. This must match exactly what the tool uses for the OAuth callback.
3. Download the generated `.pem` private key.
4. In the Control Panel, activate the app by linking your bank account ("Activate" button next to the app).
5. Copy `.env.example` to `.env` and fill in the values:

```
EB_APP_ID=<your-app-uuid>
EB_PRIVATE_KEY_PATH=<path-to-key.pem>
EB_REDIRECT_URL=https://localhost/auth_redirect   # default, must match Control Panel
EB_SESSION_FILE=.session.json                     # default
EB_ACCESS_DAYS=30                                 # how many days ahead the bank access grant is valid
```

Both `.env` and the `.pem` file must be owner-readable only (`chmod 600`). The tool refuses to start if they are world-readable.

6. Install dependencies:

```bash
just install
```

## Usage

A [Justfile](Justfile) is included with shortcuts for all common tasks. Run `just` or `just --list` to see everything available.

**Authenticate:**

```bash
just auth
```

This opens a browser to the bank's login page. After completing authentication, the browser redirects to `https://localhost/auth_redirect` (which will not load — that's expected). Copy the full URL from the address bar and paste it into the terminal. The session is saved to `.session.json` and reused on subsequent calls. Re-authentication is triggered automatically when the session expires.

**Fetch transactions to CSV:**

```bash
just fetch --from 2024-01-01
just fetch --from 2024-01-01 --output my-transactions.csv
just fetch --from 2024-01-01 --to 2024-12-31 --account IT60X0542811101000000123456
just fetch --help
```

### Options for `fetch`

| Option | Default | Description |
|---|---|---|
| `--from YYYY-MM-DD` | none | Start date (inclusive) |
| `--to YYYY-MM-DD` | none | End date (inclusive) |
| `--output FILE` | `transactions.csv` | Output path |
| `--account IBAN\|UID` | first available | Target account |
| `--parser NAME` | `generic` | Transaction parser to use |

## CSV format

```
Date, Type, Description, Notes, Amount
```

- `Date` - booking date, falls back to value date
- `Type` - movement category
- `Description` - merchant, counterparty, or reference text
- `Notes` - free-text note left by the user in the banking app (parser-dependent)
- `Amount` - signed amount (negative = debit)

## Parsers

Parsers translate raw Enable Banking transaction objects into the CSV columns above. Selected with `--parser NAME`.

| Name | Description |
|---|---|
| `generic` | Default. Works with any bank. Uses `bank_transaction_code`, creditor/debtor name, and the first remittance segment. |
| `mediolanum` | Banca Mediolanum. Parses the bank's `remittance_information` segments in detail to extract movement category, merchant/counterparty, and user notes. |

### Adding a parser

Create a module under `src/bankfetch/parsers/`, subclass `BaseParser`, and decorate the class with `@register("your-name")`. It will be auto-discovered at import time — no manual wiring needed.

```python
from . import BaseParser, ParsedTransaction, register

@register("mybank")
class MyBankParser(BaseParser):
    def parse(self, txn: dict) -> ParsedTransaction:
        ...
```

## Repository layout

```
src/bankfetch/
├── config.py          Config dataclass; loads .env; enforces file permissions
├── auth.py            RS256 JWT signing; OAuth2 redirect flow; SessionStore
├── client.py          EnableBankingClient: account details + paginated transactions
├── export.py          to_csv(): runs a parser over transactions and writes CSV
├── cli.py             Typer CLI — `auth` and `fetch` subcommands
└── parsers/
    ├── __init__.py    BaseParser ABC; @register decorator; auto-discovery
    ├── generic.py     GenericParser — works with any bank
    └── mediolanum.py  MediolanumParser — Banca Mediolanum remittance parsing

tests/
├── conftest.py        Shared fixtures (RSA key generation, sample transactions)
├── test_auth.py       JWT generation, redirect URL validation, session flow
├── test_client.py     Account and transaction fetch, pagination
└── test_export.py     GenericParser, _variazione, to_csv()
```

## Development

```bash
just install  # install dependencies including dev and pre-commit hooks
just test     # run all tests
```

Linting, formatting, and type-checking run automatically via pre-commit on every commit.