Metadata-Version: 2.4
Name: desjardins-py
Version: 0.1.1
Summary: Unofficial Desjardins AccèsD wrapper — track your balance, credit cards, transactions, and statements from Python
Project-URL: Homepage, https://github.com/MaximBacar/desjardins-py
Project-URL: Repository, https://github.com/MaximBacar/desjardins-py
Project-URL: Bug Tracker, https://github.com/MaximBacar/desjardins-py/issues
Project-URL: Changelog, https://github.com/MaximBacar/desjardins-py/releases
Author-email: Maxim Bacar <maximbacar@hotmail.ca>
License: Personal Use Only
Keywords: accesd,banking,desjardins,finance,scraper
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Office/Business :: Financial
Requires-Python: >=3.11
Requires-Dist: cloakbrowser>=0.3.32
Requires-Dist: openpyxl>=3.1
Requires-Dist: pandas>=2.2
Requires-Dist: pdfplumber>=0.11.10
Requires-Dist: playwright>=1.60.0
Requires-Dist: pydantic>=2.13.4
Requires-Dist: python-dotenv>=1.2.2
Requires-Dist: requests>=2.34.2
Requires-Dist: sqlmodel>=0.0.38
Provides-Extra: mysql
Requires-Dist: pymysql>=1.1; extra == 'mysql'
Provides-Extra: postgres
Requires-Dist: psycopg2-binary>=2.9; extra == 'postgres'
Description-Content-Type: text/markdown

# desjardins-py

[![PyPI](https://img.shields.io/pypi/v/desjardins-py)](https://pypi.org/project/desjardins-py/)

> **Disclaimer:** This project is not affiliated with, endorsed by, or in any way connected to Desjardins Group. It is an independent, unofficial tool that interacts with Desjardins' web interface through browser automation. Use at your own risk. Your credentials are never transmitted anywhere other than Desjardins' own servers.

> **Personal use only.** This project is intended solely for personal, non-commercial use. You may not redistribute, sublicense, or use it as part of a product or service.

Unofficial Desjardins AccèsD wrapper for Python. 
Track your balance, credit cards, transactions, and statements. Pipe the data anywhere you need it.

## Features

- Fetch accounts, credit cards, transactions, and statement metadata from AccèsD
- Returns typed Pydantic models — work with your data directly in Python
- Persist to SQLite, MySQL, or PostgreSQL with a single `save()` call
- Incremental fetching — only imports transactions newer than the last run
- Export to CSV or XLSX with `to_csv()` / `to_excel()`
- Persistent browser session — saves the session after the first OTP verification so subsequent runs are unattended

## How it works

1. Opens a headless Chromium browser to log into your AccèsD account and obtain a valid session token
2. Intercepts the accounts API response to collect `BankAccount` and `CreditCard` records
3. Calls the Desjardins REST API directly (reusing the session token) to fetch transactions and statement metadata for each account
4. Returns a typed `FetchResult` containing all fetched data. Use it directly in your code or persist it to a database

## Usage

Once fetched, your data is plain Python objects — use them however you like:

- **Budget automation** — categorize transactions and trigger alerts when spending thresholds are hit
- **Power BI / Tableau** — load into a database and connect a live report on top of it
- **Excel / Google Sheets** — export with `to_excel()` or `to_csv()` and refresh your spreadsheet on a schedule
- **Custom dashboards** — pipe into any Python data stack (pandas, Plotly, Streamlit, etc.)
- **Notifications** — send a daily summary to Slack, email, or a home automation system

## Installation

### With pip

```bash
pip install desjardins-py
playwright install chromium
```

### With uv

```bash
uv sync
uv run playwright install chromium
```

---

## Examples

### Basic fetch and inspect data

No database required. Credentials are passed directly.

```python
from desjardins_py import DesjardinsClient

client = DesjardinsClient(
    card_number="your_card_number",
    password="your_password",
)

result = client.fetch()

# result.accounts          → list[BankAccount]
# result.cards             → list[CreditCard]
# result.transactions      → list[Transaction]
# result.card_transactions → list[CardTransaction]
# result.statements        → list[Statement]

for account in result.accounts:
    print(account.name, account.amount, account.currency)

for tx in result.transactions:
    print(tx.effective_date, tx.description, tx.amount)
```

On the first run you will be prompted for an OTP verification code in the terminal. Subsequent runs reuse the saved session in `.session/`.

---

### Persist to SQLite

```python
from desjardins_py import DesjardinsClient

client = DesjardinsClient(
    card_number="your_card_number",
    password="your_password",
)
client.connect_db("sqlite:///accesd.db")

result = client.fetch()
result.save()  # inserts only transactions newer than the last fetch
```

---

### Persist to PostgreSQL

```bash
pip install desjardins-py[postgres]   # or: uv sync --extra postgres
```

```python
from desjardins_py import DesjardinsClient

client = DesjardinsClient(
    card_number="your_card_number",
    password="your_password",
)
client.connect_db("postgresql+psycopg2://user:password@localhost:5432/accesd")

result = client.fetch()
result.save()
```

> For MySQL: `pip install desjardins-py[mysql]` and use `mysql+pymysql://user:password@localhost:3306/accesd`.

---

### Export to XLSX

```python
from desjardins_py import DesjardinsClient

client = DesjardinsClient(
    card_number="your_card_number",
    password="your_password",
)

result = client.fetch()
result.to_excel("accesd.xlsx")   # one sheet per table
result.to_csv("./export")      # one CSV file per table
```

---

## OTP

When you log in for the first time (or after your saved session expires), Desjardins sends a one-time security code by SMS. By default, `desjardins-py` pauses and waits for you to type it in the terminal:

```
OTP code: ██████
```

Once entered, the session is saved to your `profile_dir` (default `./.session`) and subsequent runs are fully unattended.

### Automatic OTP with OTPCatcher

On macOS, you can have the library read the SMS code from the Messages app automatically by passing `catch_otp=True`:

```python
client = DesjardinsClient(
    card_number="your_card_number",
    password="your_password",
    catch_otp=True,
)
```

**Requirements:**

- **macOS only** — OTPCatcher reads from `~/Library/Messages/chat.db`, which only exists on macOS.
- **iMessage / SMS sync enabled** — your iPhone must be set up to forward SMS messages to your Mac via *Settings → Messages → Text Message Forwarding*.
- **Full Disk Access** — the process running the script (Terminal, iTerm2, your IDE, or the Python interpreter) must be granted Full Disk Access under *System Settings → Privacy & Security → Full Disk Access*. Without it, the database read will fail with a `PermissionError`.

OTPCatcher polls the Messages database for up to 10 attempts (10-second intervals) and looks for any SMS containing `"Votre code de sécurité AccèsD est"` received within the last 30 seconds.

---

## `DesjardinsClient` parameters

| Parameter | Type | Default | Description |
|---|---|---|---|
| `card_number` | `str` | — | Your AccèsD card number |
| `password` | `str` | — | Your AccèsD password |
| `verbose` | `bool` | `True` | Print INFO-level logs to stdout |
| `profile_dir` | `str` | `'./.session'` | Directory used to persist the browser session across runs |
| `catch_otp` | `bool` | `False` | Automatically read the OTP from the macOS Messages app (see [OTP](#otp)) |

---

## Database schema

| Table | Description |
|---|---|
| `bank_accounts` | Chequing / savings accounts |
| `credit_cards` | Credit cards and lines of credit |
| `transactions` | Bank account transaction history |
| `card_transactions` | Credit card transaction history |
| `statements` | Statement metadata (name, date, size) |

