### Install task Source: https://github.com/juftin/lunchable/blob/main/docs/contributing.md Use this command to install the task runner. ```shell sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d ``` -------------------------------- ### Installing Lunchable Plugins Source: https://github.com/juftin/lunchable/blob/main/docs/plugins.md Instructions on how to install Lunchable with all its known plugins and their dependencies. ```APIDOC ## Installing Lunchable Plugins To install all the known plugins, and their dependencies, install lunchable with the `plugins` extra: ```shell pipx install "lunchable[plugins]" ``` ``` -------------------------------- ### Install lunchable CLI with plugins Source: https://github.com/juftin/lunchable/blob/main/README.md Recommended installation method for the CLI using pipx with the plugins extra. ```shell pipx install "lunchable[plugins]" ``` -------------------------------- ### Install project dependencies Source: https://github.com/juftin/lunchable/blob/main/docs/contributing.md Run this command to install project dependencies and list available tasks. ```shell task install ``` -------------------------------- ### MyCustomApp Example Source: https://github.com/juftin/lunchable/blob/main/docs/plugins.md An example of a custom Lunchable application demonstrating data loading and transaction updates. ```APIDOC ## MyCustomApp Example ### Description This example demonstrates how to create a custom Lunchable application that can load assets and transactions, and update existing transactions. ### Methods - `do_something_with_assets()`: Loads and processes asset data. - `do_something_with_transactions()`: Loads and processes transaction data, linking them to assets. - `update_transaction(transaction_id: int, payee: str)`: Updates a specific transaction with a new payee. ### Request Example (update_transaction) ```json { "transaction_id": 12345, "payee": "New Payee" } ``` ### Response Example (update_transaction) ```json { "status": "success", "message": "Transaction updated" } ``` ``` -------------------------------- ### Install uv Source: https://github.com/juftin/lunchable/blob/main/docs/contributing.md Use this command to install the uv package manager. ```shell curl -LsSf https://astral.sh/uv/install.sh | sh ``` -------------------------------- ### Install lunchable via pip Source: https://github.com/juftin/lunchable/blob/main/README.md Standard installation command for the lunchable library. ```shell pip install lunchable ``` -------------------------------- ### Install Lunchable CLI Source: https://context7.com/juftin/lunchable/llms.txt Instructions for installing the Lunchable command-line interface using pipx, with an option to include plugins. The access token must be set as an environment variable. ```bash # Install with pipx (recommended) pipx install lunchable # Or install with plugins pipx install "lunchable[plugins]" ``` -------------------------------- ### Initialize LunchMoney Client and Fetch Transactions Source: https://github.com/juftin/lunchable/blob/main/README.md Example showing how to authenticate with an access token and retrieve transaction data. ```python from typing import Any, Dict, List from lunchable import LunchMoney from lunchable.models import TransactionObject lunch = LunchMoney(access_token="xxxxxxxxxxx") transactions: List[TransactionObject] = lunch.get_transactions() first_transaction: TransactionObject = transactions[0] transaction_as_dict: Dict[str, Any] = first_transaction.model_dump() ``` -------------------------------- ### Building a Lunchable Plugin Source: https://github.com/juftin/lunchable/blob/main/docs/plugins.md Instructions and examples for creating a custom plugin for the Lunchable CLI. ```APIDOC ## Building a Plugin ### Description Plugins for Lunchable are built as separate Python packages and are detected via the `lunchable.cli` entrypoint. They utilize the `click` library for command-line interface creation. ### Setup To add a plugin, define an entrypoint in your package's configuration (e.g., `pyproject.toml` using hatch). ### Example Plugin Code ```python import click @click.group def plugin_name(): """ Plugin description """ pass @plugin_name.command def command(): """ Plugin description """ pass ``` ### `pyproject.toml` Entrypoint Configuration ```toml [project.entry-points."lunchable.cli"] your-package = "your_package.cli:plugin_name" ``` ### Usage Once installed, your plugin commands will be accessible via the `lunchable plugins` command. ```shell lunchable plugins plugin-name command ``` ``` -------------------------------- ### Commit message examples Source: https://github.com/juftin/lunchable/blob/main/docs/contributing.md Examples of commit messages following gitmoji and conventional commit standards. ```text ✨ New Feature Description ``` ```text 🐛 Bug Fix Description ``` ```text 💥 Breaking Change Description ``` ```text 📝 Documentation Update Description 👷 CI/CD Update Description 🧪 Testing Changes Description 🚚 Moving/Renaming Description ⬆️ Dependency Upgrade Description ``` -------------------------------- ### GET /api/crypto Source: https://github.com/juftin/lunchable/blob/main/docs/interacting.md Retrieves a list of crypto assets. ```APIDOC ## GET /api/crypto ### Description Get Crypto Assets ### Method GET ### Endpoint /api/crypto ### Parameters No parameters are specified in the provided text. ### Request Example (No request body or parameters specified) ### Response #### Success Response (200) - **crypto_assets** (array) - List of crypto assets. #### Response Example (No response example provided) ``` -------------------------------- ### GET /api/budgets Source: https://github.com/juftin/lunchable/blob/main/docs/interacting.md Retrieves a list of monthly budgets. ```APIDOC ## GET /api/budgets ### Description Get Monthly Budgets ### Method GET ### Endpoint /api/budgets ### Parameters No parameters are specified in the provided text. ### Request Example (No request body or parameters specified) ### Response #### Success Response (200) - **budgets** (array) - List of monthly budgets. #### Response Example (No response example provided) ``` -------------------------------- ### Custom App with Specific Data Loading Source: https://github.com/juftin/lunchable/blob/main/docs/plugins.md Example of a Lunchable app configured to load only specific data models. ```APIDOC ## CustomApp with Specific Data Loading ### Description This example shows how to configure a Lunchable application to load only a subset of data models (e.g., `PlaidAccountObject` and `AssetsObject`) when `refresh_data()` is called. ### Configuration Set the `lunchable_models` class variable to a list of desired `LunchableModel` types. ### Example Usage ```python from __future__ import annotations from typing import ClassVar from lunchable.models import AssetsObject, PlaidAccountObject, LunchableModel from lunchable.plugins import LunchableApp class CustomApp(LunchableApp): """ Custom Lunchable App This app syncs Plaid Accounts and Assets when its `refresh_data` method is called. """ lunchable_models: ClassVar[list[type[LunchableModel]]] = [ PlaidAccountObject, AssetsObject, ] def do_something_with_assets(self) -> None: """ Do something with the assets """ if not self.data.plaid_accounts: self.refresh_data() for plaid_account_id, plaid_account in self.data.plaid_accounts.items(): print(plaid_account_id, plaid_account) ``` ``` -------------------------------- ### GET /api/plaid-accounts Source: https://github.com/juftin/lunchable/blob/main/docs/interacting.md Retrieves a list of Plaid synced assets. ```APIDOC ## GET /api/plaid-accounts ### Description Get Plaid Synced Assets ### Method GET ### Endpoint /api/plaid-accounts ### Parameters No parameters are specified in the provided text. ### Request Example (No request body or parameters specified) ### Response #### Success Response (200) - **plaid_accounts** (array) - List of Plaid synced assets. #### Response Example (No response example provided) ``` -------------------------------- ### Get and Create Assets with Lunchable Source: https://context7.com/juftin/lunchable/llms.txt Retrieve all manually-managed assets and create new ones. This snippet also demonstrates how to update an asset's balance. ```python from datetime import datetime from lunchable import LunchMoney lunch = LunchMoney(access_token="your_access_token") # Get all manually-managed assets assets = lunch.get_assets() for asset in assets: print(f"{asset.name} ({asset.type_name})") print(f" Balance: {asset.currency} {asset.balance}") print(f" Institution: {asset.institution_name}") print(f" Last updated: {asset.balance_as_of}") # Create a new asset new_asset = lunch.insert_asset( type_name="cash", # cash, credit, investment, loan, vehicle, etc. name="Emergency Fund", display_name="Emergency Savings", balance=5000.00, currency="usd", institution_name="My Bank", balance_as_of=datetime.now() ) print(f"Created asset: {new_asset.name} (ID: {new_asset.id})") # Update an asset's balance updated_asset = lunch.update_asset( asset_id=new_asset.id, balance=5500.00, balance_as_of=datetime.now() ) print(f"Updated balance: {updated_asset.balance}") ``` -------------------------------- ### GET /api/assets Source: https://github.com/juftin/lunchable/blob/main/docs/interacting.md Retrieves a list of manually managed assets. ```APIDOC ## GET /api/assets ### Description Get Manually Managed Assets ### Method GET ### Endpoint /api/assets ### Parameters No parameters are specified in the provided text. ### Request Example (No request body or parameters specified) ### Response #### Success Response (200) - **assets** (array) - List of manually managed assets. #### Response Example (No response example provided) ``` -------------------------------- ### GET /api/tags Source: https://github.com/juftin/lunchable/blob/main/docs/interacting.md Retrieves a list of spending tags. ```APIDOC ## GET /api/tags ### Description Get Spending Tags ### Method GET ### Endpoint /api/tags ### Parameters No parameters are specified in the provided text. ### Request Example (No request body or parameters specified) ### Response #### Success Response (200) - **tags** (array) - List of spending tags. #### Response Example (No response example provided) ``` -------------------------------- ### Use Lunchable CLI for API Interaction Source: https://context7.com/juftin/lunchable/llms.txt Examples of using the Lunchable CLI to fetch transactions with filters, make raw HTTP requests, and enable debug output. Requires the LUNCHMONEY_ACCESS_TOKEN environment variable. ```bash # Set your access token export LUNCHMONEY_ACCESS_TOKEN="your_access_token_here" # Get transactions (outputs JSON) lunchable transactions get --start-date 2024-01-01 --end-date 2024-01-31 # Get transactions with filters lunchable transactions get --limit 10 --status cleared --category-id 12345 # Make raw HTTP requests to the API lunchable http v1/me lunchable http v1/categories lunchable http v1/assets # HTTP request with method lunchable http -X GET v1/transactions # Enable debug output lunchable --debug transactions get --limit 5 ``` -------------------------------- ### Get Tags with Lunchable Source: https://context7.com/juftin/lunchable/llms.txt Retrieve all tags associated with the user's account. This snippet initializes the LunchMoney client and fetches the tags. ```python from lunchable import LunchMoney lunch = LunchMoney(access_token="your_access_token") ``` -------------------------------- ### GET /api/user Source: https://github.com/juftin/lunchable/blob/main/docs/interacting.md Retrieves personal user details. ```APIDOC ## GET /api/user ### Description Get Personal User Details ### Method GET ### Endpoint /api/user ### Parameters No parameters are specified in the provided text. ### Request Example (No request body or parameters specified) ### Response #### Success Response (200) - **user_details** (object) - Personal user details. #### Response Example (No response example provided) ``` -------------------------------- ### Get User Information Source: https://context7.com/juftin/lunchable/llms.txt Fetches details about the authenticated user, including their ID, name, email, and account information. Requires a valid access token. ```python from lunchable import LunchMoney lunch = LunchMoney(access_token="your_access_token") user = lunch.get_user() print(f"User ID: {user.user_id}") print(f"Name: {user.user_name}") print(f"Email: {user.user_email}") print(f"Account ID: {user.account_id}") print(f"Budget Name: {user.budget_name}") print(f"API Key Label: {user.api_key_label}") ``` -------------------------------- ### GET /api/categories Source: https://github.com/juftin/lunchable/blob/main/docs/interacting.md Retrieves a list of spending categories. ```APIDOC ## GET /api/categories ### Description Get Spending categories ### Method GET ### Endpoint /api/categories ### Parameters No parameters are specified in the provided text. ### Request Example (No request body or parameters specified) ### Response #### Success Response (200) - **categories** (array) - List of spending categories. #### Response Example (No response example provided) ``` -------------------------------- ### GET /api/recurring-items Source: https://github.com/juftin/lunchable/blob/main/docs/interacting.md Retrieves a list of recurring items. ```APIDOC ## GET /api/recurring-items ### Description Get Recurring Items ### Method GET ### Endpoint /api/recurring-items ### Parameters No parameters are specified in the provided text. ### Request Example (No request body or parameters specified) ### Response #### Success Response (200) - **recurring_items** (array) - List of recurring items. #### Response Example (No response example provided) ``` -------------------------------- ### Get and Print Tags Source: https://context7.com/juftin/lunchable/llms.txt Retrieves all tags from Lunch Money and prints their details. Useful for managing and categorizing transactions. ```python tags = lunch.get_tags() for tag in tags: print(f"Tag: {tag.name} (ID: {tag.id})") if tag.description: print(f" Description: {tag.description}") print(f" Archived: {tag.archived}") ``` -------------------------------- ### Get All Categories (Flattened) Source: https://context7.com/juftin/lunchable/llms.txt Retrieve all spending categories as a flattened list. Each category object contains its ID, name, and income status. ```python # Get all categories (flattened list) categories = lunch.get_categories() for cat in categories: print(f"{cat.id}: {cat.name} (income={cat.is_income})") ``` -------------------------------- ### Get Recurring Items for a Month Source: https://context7.com/juftin/lunchable/llms.txt Fetches recurring expenses and income for a specific month. Supports filtering by date and displaying amounts as negative debits. ```python from datetime import date from lunchable import LunchMoney lunch = LunchMoney(access_token="your_access_token") # Get recurring items for current month recurring_items = lunch.get_recurring_items() # Get recurring items for a specific month recurring_items = lunch.get_recurring_items( start_date=date(2024, 2, 1), # Any date in the month debit_as_negative=True ) for item in recurring_items: print(f"\n{item.payee}") print(f" Amount: {item.currency} {item.amount}") print(f" Frequency: {item.granularity}") print(f" Billing date: {item.billing_date}") print(f" Is income: {item.is_income}") # Check occurrences within the month for occ_date, transactions in item.occurrences.items(): print(f" Occurrence on {occ_date}:") for txn in transactions: print(f" - {txn.payee}: ${txn.amount}") ``` -------------------------------- ### Get and Update Crypto Assets Source: https://context7.com/juftin/lunchable/llms.txt Retrieves cryptocurrency holdings from synced and manual accounts, and demonstrates updating a manually managed asset. Requires an access token. ```python from lunchable import LunchMoney lunch = LunchMoney(access_token="your_access_token") # Get all crypto assets crypto_assets = lunch.get_crypto() for crypto in crypto_assets: print(f"{crypto.name} ({crypto.currency})") print(f" Balance: {crypto.balance}") print(f" Source: {crypto.source}") # 'manual' or synced provider print(f" Institution: {crypto.institution_name}") print(f" Last updated: {crypto.balance_as_of}") ``` ```python # Update a manually-managed crypto asset updated_crypto = lunch.update_crypto( crypto_id=12345, balance=1.5, currency="btc", display_name="My Bitcoin" ) print(f"Updated: {updated_crypto.name} = {updated_crypto.balance} {updated_crypto.currency}") ``` -------------------------------- ### GET /api/transactions Source: https://github.com/juftin/lunchable/blob/main/docs/interacting.md Retrieves transactions using specified criteria. ```APIDOC ## GET /api/transactions ### Description Get Transactions Using Criteria ### Method GET ### Endpoint /api/transactions ### Parameters #### Query Parameters - **criteria** (object) - Optional - Criteria to filter transactions. ### Request Example (No request body or parameters specified) ### Response #### Success Response (200) - **transactions** (array) - List of transactions matching the criteria. #### Response Example (No response example provided) ``` -------------------------------- ### Get User Info Source: https://context7.com/juftin/lunchable/llms.txt Retrieve user information to verify the connection to the Lunch Money API. This includes the user's name, email, and budget name. ```python user = lunch.get_user() print(f"Connected as: {user.user_name} ({user.user_email})") print(f"Budget: {user.budget_name}") ``` -------------------------------- ### GET /api/category/{id} Source: https://github.com/juftin/lunchable/blob/main/docs/interacting.md Retrieves a single spending category by its ID. ```APIDOC ## GET /api/category/{id} ### Description Get single category ### Method GET ### Endpoint /api/category/{id} ### Parameters #### Path Parameters - **id** (string) - Required - The ID of the category to retrieve. ### Request Example (No request body or parameters specified) ### Response #### Success Response (200) - **category** (object) - Details of the single category. #### Response Example (No response example provided) ``` -------------------------------- ### GET /api/transaction/{id} Source: https://github.com/juftin/lunchable/blob/main/docs/interacting.md Retrieves a single transaction by its ID. ```APIDOC ## GET /api/transaction/{id} ### Description Get a Transaction by ID ### Method GET ### Endpoint /api/transaction/{id} ### Parameters #### Path Parameters - **id** (string) - Required - The ID of the transaction to retrieve. ### Request Example (No request body or parameters specified) ### Response #### Success Response (200) - **transaction** (object) - Details of the single transaction. #### Response Example (No response example provided) ``` -------------------------------- ### Get Single Category by ID Source: https://context7.com/juftin/lunchable/llms.txt Retrieve details for a specific category using its ID. Includes information such as name, description, and budget exclusion status. ```python # Get a single category by ID category = lunch.get_category(category_id=12345) print(f"Category: {category.name}") print(f"Description: {category.description}") print(f"Exclude from budget: {category.exclude_from_budget}") ``` -------------------------------- ### Get Transactions with Filters Source: https://context7.com/juftin/lunchable/llms.txt Retrieve transactions, optionally filtering by date range, category ID, or status. The `debit_as_negative` parameter can be used to represent expenses as negative amounts. Automatic pagination is handled unless limit/offset are specified. ```python from datetime import date from lunchable import LunchMoney from lunchable.models import TransactionObject lunch = LunchMoney(access_token="your_access_token") # Get all transactions for a date range (automatic pagination) transactions = lunch.get_transactions( start_date="2024-01-01", end_date="2024-01-31" ) print(f"Found {len(transactions)} transactions") # Filter by category transactions = lunch.get_transactions( start_date=date(2024, 1, 1), end_date=date(2024, 1, 31), category_id=12345 ) # Get transactions with expenses as negative amounts transactions = lunch.get_transactions( start_date="2024-01-01", end_date="2024-01-31", debit_as_negative=True ) # Filter by status (cleared, uncleared, recurring) transactions = lunch.get_transactions( start_date="2024-01-01", end_date="2024-01-31", status="cleared" ) ``` -------------------------------- ### Update Transaction using Get Update Object Source: https://context7.com/juftin/lunchable/llms.txt Obtain a TransactionUpdateObject from an existing TransactionObject, modify it, and then use it to update the transaction. This is useful for partial updates based on an existing record. ```python # Get an update object from an existing transaction update_obj = transaction.get_update_object() update_obj.payee = "New Payee" response = lunch.update_transaction( transaction_id=transaction.id, transaction=update_obj ) ``` -------------------------------- ### Get Categories (Nested Format) Source: https://context7.com/juftin/lunchable/llms.txt Retrieve categories organized in a nested structure, showing category groups and their sub-categories. Useful for understanding hierarchical category relationships. ```python # Get categories in nested format (with groups) categories = lunch.get_categories(format="nested") for cat in categories: if cat.is_group: print(f"Group: {cat.name}") if cat.children: for child in cat.children: print(f" - {child.name}") else: print(f"Category: {cat.name}") ``` -------------------------------- ### Get Transaction Group Source: https://context7.com/juftin/lunchable/llms.txt Retrieve a specific transaction group by its ID. The response includes group details and its associated child transactions. ```python # Get a transaction group group = lunch.get_transaction_group(transaction_id=group_id) print(f"Group: {group.payee}") print(f"Total: ${group.amount}") if group.children: for child in group.children: print(f" - {child.payee}: ${child.amount}") ``` -------------------------------- ### Get Single Transaction by ID Source: https://context7.com/juftin/lunchable/llms.txt Retrieve a specific transaction using its unique ID. Access properties like ID, date, payee, amount, category, notes, status, and tags. ```python from lunchable import LunchMoney lunch = LunchMoney(access_token="your_access_token") # Get a single transaction by ID transaction = lunch.get_transaction(transaction_id=123456) print(f"Transaction ID: {transaction.id}") print(f"Date: {transaction.date}") print(f"Payee: {transaction.payee}") print(f"Amount: ${transaction.amount}") print(f"Category: {transaction.category_name}") print(f"Notes: {transaction.notes}") print(f"Status: {transaction.status}") print(f"Tags: {[tag.name for tag in transaction.tags] if transaction.tags else []}") ``` -------------------------------- ### Initialize LunchMoney Client Source: https://github.com/juftin/lunchable/blob/main/docs/usage.md Create a client instance using an explicit access token. ```python from lunchable import LunchMoney lunch = LunchMoney(access_token="xxxxxxx") ``` -------------------------------- ### Display lunchable CLI help Source: https://github.com/juftin/lunchable/blob/main/docs/cli.md Executes the help command to list available options and subcommands for the lunchable CLI. ```bash lunchable --help ``` -------------------------------- ### Initialize LunchMoney Client Source: https://context7.com/juftin/lunchable/llms.txt Initialize the LunchMoney client with an explicit access token or by relying on the LUNCHMONEY_ACCESS_TOKEN environment variable. Verify the connection by fetching user information. ```python from lunchable import LunchMoney # Initialize with explicit access token lunch = LunchMoney(access_token="your_access_token_here") # Or let it read from LUNCHMONEY_ACCESS_TOKEN environment variable import os os.environ["LUNCHMONEY_ACCESS_TOKEN"] = "your_access_token_here" lunch = LunchMoney() # Verify connection by getting user info user = lunch.get_user() print(f"Connected as: {user.user_name} ({user.user_email})") print(f"Budget: {user.budget_name}") ``` -------------------------------- ### Initialize LunchMoney Client with Access Token Source: https://github.com/juftin/lunchable/blob/main/docs/interacting.md Instantiate the LunchMoney client with an explicit access token. The client defaults to using the LUNCHMONEY_ACCESS_TOKEN environment variable if no token is provided. ```python from lunchable import LunchMoney lunch = LunchMoney(access_token="xxxxxxxxxxx") ``` -------------------------------- ### Use Lunchable CLI Source: https://github.com/juftin/lunchable/blob/main/docs/usage.md Execute CLI commands to interact with transactions. ```shell lunchable transactions get --limit 5 ``` -------------------------------- ### Initialize and Use LunchableApp Source: https://context7.com/juftin/lunchable/llms.txt Demonstrates initializing the LunchableApp for building applications, refreshing data, and accessing loaded models like user, categories, and transactions. Supports selective data refresh. ```python from datetime import date from lunchable.plugins import LunchableApp from lunchable.models import ( TransactionObject, CategoriesObject, AssetsObject, PlaidAccountObject ) # Initialize the app app = LunchableApp(access_token="your_access_token") # Refresh all data (categories, assets, tags, etc. - excludes transactions) app.refresh_data() # Access the data print(f"User: {app.data.user.user_name}") print(f"Categories: {len(app.data.categories)}") print(f"Assets: {len(app.data.assets)}") print(f"Plaid Accounts: {len(app.data.plaid_accounts)}") print(f"Tags: {len(app.data.tags)}") # Refresh specific models only app.refresh_data(models=[CategoriesObject, AssetsObject]) # Refresh a single model type categories = app.refresh(CategoriesObject) # Refresh transactions separately (with filters) transactions = app.refresh_transactions( start_date="2024-01-01", end_date="2024-01-31" ) print(f"Loaded {len(transactions)} transactions") ``` -------------------------------- ### List all tasks Source: https://github.com/juftin/lunchable/blob/main/docs/contributing.md Display all available tasks defined in the Taskfile. ```bash task --list-all ``` -------------------------------- ### Execute lunchable CLI commands Source: https://github.com/juftin/lunchable/blob/main/README.md Commands for setting the access token and interacting with the API via the CLI. ```shell export LUNCHMONEY_ACCESS_TOKEN="xxxxxxxxxxx" lunchable transactions get --limit 5 lunchable http -X GET v1/assets ``` -------------------------------- ### Execute Plugin Commands Source: https://github.com/juftin/lunchable/blob/main/docs/plugins.md Run registered plugin commands using the lunchable CLI. ```shell lunchable plugins plugin-name command ``` -------------------------------- ### Define a CLI Plugin Source: https://github.com/juftin/lunchable/blob/main/docs/plugins.md Create a click-based command group and register it via project entry points. ```python import click @click.group def plugin_name(): """ Plugin description """ pass @plugin_name.command def command(): """ Plugin description """ pass ``` ```toml [project.entry-points."lunchable.cli"] your-package = "your_package.cli:plugin_name" ``` -------------------------------- ### Lunchable CLI Help Source: https://github.com/juftin/lunchable/blob/main/docs/cli.md Displays the main help message for the lunchable CLI, including available commands. ```APIDOC ## GET /help ### Description Displays the main help message for the lunchable CLI, including available commands. ### Method GET ### Endpoint /help ### Parameters #### Query Parameters - **help** (boolean) - Optional - Show this help message and exit. ### Request Example ```bash lunchable --help ``` ### Response #### Success Response (200) - **output** (string) - The help text output from the CLI. #### Response Example ``` usage: lunchable [-h] [--version] {init,build,test,deploy} ... CLI for managing lunchable projects. positional arguments: {init,build,test,deploy} init Initialize a new lunchable project. build Build the lunchable project. test Run tests for the lunchable project. deploy Deploy the lunchable project. options: -h, --help show this help message and exit --version show program's version number and exit ``` ``` -------------------------------- ### Use Lunchable CLI via Docker Source: https://github.com/juftin/lunchable/blob/main/docs/usage.md Run the CLI inside a Docker container. ```shell docker pull juftin/lunchable ``` ```shell docker run \ --env LUNCHMONEY_ACCESS_TOKEN=${LUNCHMONEY_ACCESS_TOKEN} \ juftin/lunchable:latest \ lunchable transactions get --limit 5 ``` -------------------------------- ### Activate virtual environment Source: https://github.com/juftin/lunchable/blob/main/docs/contributing.md Activate the virtual environment created by uv. ```shell source .venv/bin/activate ``` -------------------------------- ### Create Transaction with Tags Source: https://context7.com/juftin/lunchable/llms.txt Demonstrates creating a new transaction object using tag names or tag IDs. Ensure tags exist before using their IDs. ```python from lunchable import TransactionInsertObject from datetime import date new_transaction = TransactionInsertObject( date=date.today(), payee="Restaurant", amount=25.00, tags=["dining", "weekend"] # Tag names ) ``` ```python # Or use tag IDs: new_transaction = TransactionInsertObject( date=date.today(), payee="Restaurant", amount=25.00, tags=[1, 2, 3] # Tag IDs ) ``` -------------------------------- ### Manage Plaid Accounts with Lunchable Source: https://context7.com/juftin/lunchable/llms.txt Retrieve Plaid-synced accounts and trigger data fetches. Use the fetch trigger sparingly, as it is limited to once per minute. ```python from lunchable import LunchMoney lunch = LunchMoney(access_token="your_access_token") # Get all Plaid-synced accounts plaid_accounts = lunch.get_plaid_accounts() for account in plaid_accounts: print(f"{account.name} ({account.type}/{account.subtype})") print(f" Institution: {account.institution_name}") print(f" Balance: {account.currency} {account.balance}") print(f" Status: {account.status}") print(f" Last import: {account.last_import}") print(f" Mask: ****{account.mask}") # Trigger a fetch from Plaid (use sparingly - limit once per minute) success = lunch.trigger_fetch_from_plaid() print(f"Fetch triggered: {success}") # Fetch for a specific account and date range success = lunch.trigger_fetch_from_plaid( plaid_account_id=12345, start_date=date(2024, 1, 1), end_date=date(2024, 1, 31) ) ``` -------------------------------- ### Run task with arguments Source: https://github.com/juftin/lunchable/blob/main/docs/contributing.md Pass additional arguments to a task using the -- separator. ```bash task run -- python -m browsr --help ``` -------------------------------- ### POST /api/asset Source: https://github.com/juftin/lunchable/blob/main/docs/interacting.md Creates a single manually-managed asset. ```APIDOC ## POST /api/asset ### Description Create a single (manually-managed) asset ### Method POST ### Endpoint /api/asset ### Parameters #### Request Body - **asset_data** (object) - Required - Data for the new asset. ### Request Example { "asset_data": { "name": "Example Asset", "value": 1000 } } ### Response #### Success Response (200) - **asset** (object) - The newly created asset. #### Response Example { "asset": { "id": "asset_123", "name": "Example Asset", "value": 1000 } } ``` -------------------------------- ### Create a Custom Lunchable App Source: https://github.com/juftin/lunchable/blob/main/docs/plugins.md Define a class inheriting from LunchableApp to manage assets and transactions. Requires an access token for initialization. ```python from __future__ import annotations from typing import Any from lunchable.models import AssetsObject, TransactionUpdateObject from lunchable.plugins import LunchableApp class MyCustomApp(LunchableApp): """ My Custom App """ def do_something_with_assets(self) -> None: """ Do something with the assets """ if not self.data.assets: # If the data hasn't been loaded yet, load it # The following method loads all of the data besides Transactions # (Assets, Categories, Plaid Accounts, Tags, Crypto, User) self.refresh_data() for asset_id, asset in self.data.assets.items(): # Do something with the asset print(asset_id, asset) def do_something_with_transactions(self) -> None: """ Do something with the transactions """ if not self.data.transactions: # If the transactions haven't been loaded yet, load them self.refresh_transactions(start_date="2021-01-01", end_date="2021-01-31") # Refresh the latest assets latest_assets: dict[int, AssetsObject] = self.refresh(model=AssetsObject) for transaction_id, transaction in self.data.transactions.items(): if transaction.asset_id: asset = latest_assets[transaction.asset_id] print(transaction_id, transaction, asset) def update_transaction(self, transaction_id: int, payee: str) -> dict[str, Any]: """ You can do anything you want with the `self """ update_transaction = TransactionUpdateObject(payee=payee) response = self.lunch.update_transaction(transaction_id=transaction_id, transaction=update_transaction) return response if __name__ == "__main__": app = MyCustomApp(access_token="xxxxxxxx") app.do_something_with_assets() app.do_something_with_transactions() app.update_transaction(transaction_id=12345, payee="New Payee") ``` -------------------------------- ### Create and Update Categories with Lunchable Source: https://context7.com/juftin/lunchable/llms.txt Use this snippet to create new categories, category groups, and add categories to groups. It also covers updating and deleting existing categories, with a note that deletion may fail if dependencies exist. ```python from lunchable import LunchMoney lunch = LunchMoney(access_token="your_access_token") # Create a new category category_id = lunch.insert_category( name="Subscriptions", description="Monthly subscription services", is_income=False, exclude_from_budget=False, exclude_from_totals=False ) print(f"Created category with ID: {category_id}") # Create a category group with new categories group_id = lunch.insert_category_group( name="Entertainment", description="Entertainment expenses", new_categories=["Movies", "Games", "Concerts"] ) print(f"Created category group with ID: {group_id}") # Add existing categories to a group updated_group = lunch.insert_into_category_group( category_group_id=group_id, category_ids=[category_id], # Add existing category new_categories=["Streaming"] # Create and add new category ) # Update a category lunch.update_category( category_id=category_id, name="Software Subscriptions", description="Updated description", archived=False ) # Delete a category (will fail if has dependencies) try: lunch.remove_category(category_id=category_id) except Exception as e: print(f"Cannot delete: {e}") # Force delete (removes all associations) lunch.remove_category_force(category_id=category_id) ``` -------------------------------- ### Low Level Methods Source: https://github.com/juftin/lunchable/blob/main/docs/interacting.md Utility methods for making HTTP requests and processing responses. ```APIDOC ## Low Level Methods ### `request` Make an HTTP request. ### `arequest` Make an async HTTP request. ### `process_response` Process a Lunch Money response and raise any errors. ### `make_request` Make an HTTP request and `process` its response. ### `amake_request` Make an async HTTP request and `process` its response. ``` -------------------------------- ### Run a specific task Source: https://github.com/juftin/lunchable/blob/main/docs/contributing.md Execute a specific task by name. ```bash task test ``` -------------------------------- ### Manage Budgets with Lunchable Source: https://context7.com/juftin/lunchable/llms.txt Retrieve budget summaries for a specified date range and update budget amounts for categories. This snippet also shows how to remove budgets. ```python from datetime import date from lunchable import LunchMoney lunch = LunchMoney(access_token="your_access_token") # Get budgets for a date range budgets = lunch.get_budgets( start_date=date(2024, 1, 1), end_date=date(2024, 3, 31) ) for budget in budgets: print(f"\nCategory: {budget.category_name}") print(f" Is income: {budget.is_income}") print(f" Exclude from budget: {budget.exclude_from_budget}") # Access budget data by month for month_date, data in budget.data.items(): if data.budget_amount: print(f" {month_date}: Budget ${data.budget_amount}, " f"Spent ${data.spending_to_base} " f"({data.num_transactions} transactions)") # Set/update a budget for a category (start_date must be 1st of month) result = lunch.upsert_budget( start_date=date(2024, 2, 1), category_id=12345, amount=500.00, currency="usd" # Optional, defaults to primary currency ) # Remove a budget success = lunch.remove_budget( start_date=date(2024, 2, 1), category_id=12345 ) print(f"Budget removed: {success}") ``` -------------------------------- ### LunchableApp Class Source: https://github.com/juftin/lunchable/blob/main/docs/plugins.md Details on the LunchableApp class, which is used to build plugins and apps, including its main attributes and methods. ```APIDOC ## LunchableApp Class Lunchable provides a `LunchableApp` class that can be used to easily build plugins, apps, and more. Below are some of its main attributes and methods: ### Attributes and Methods | Attribute / Method | Description | Type | | ---------------------------------------------------- | -------------------------------------------------------------------------------- | ---------------------------------------------- | | **`lunch`** | The `LunchMoney` client | [LunchMoney](interacting.md#lunchmoney) | | **`data`** ¹ | The `LunchableData` object | [LunchableData](#lunchable.plugins.app.LunchableData) | | [refresh_data](#lunchable.plugins.LunchableApp.refresh_data) | Refresh all data (besides Transactions) | `method` | | [refresh_transactions](#lunchable.plugins.LunchableApp.refresh_transactions) | Refresh transactions, takes same parameters as `LunchMoney.get_transactions()` | `method` | | [refresh](#lunchable.plugins.LunchableApp.refresh) ² | Refresh the data for one particular model, takes **kwargs** | `method` | | [clear_transactions](#lunchable.plugins.LunchableApp.clear_transactions) ³ | Clear all transactions from the internal data | `method` | ### Notes ¹ This attribute contains all of the data that is loaded from LunchMoney. It has attributes for `assets`, `categories`, `plaid_accounts`, `tags`, `transactions`, `crypto` and `user`. These attributes (except for `user`) are `dict[int, LunchableModel]` objects, where the key is the ID of the object and the value is the object itself. ² This method refreshes all of the data for one particular model. For example, `refresh(AssetsObject)` will refresh the assets on the underling `data.assets` attribute and return a `dict[int, AssetsObject]` object. ³ This is the same as running `app.data.transactions.clear()` ``` -------------------------------- ### Configure Data Loading Models Source: https://github.com/juftin/lunchable/blob/main/docs/plugins.md Restrict data synchronization to specific models by defining the lunchable_models class attribute. ```python from __future__ import annotations from typing import ClassVar from lunchable.models import AssetsObject, PlaidAccountObject, LunchableModel from lunchable.plugins import LunchableApp class CustomApp(LunchableApp): """ Custom Lunchable App This app syncs Plaid Accounts and Assets when its `refresh_data` method is called. """ lunchable_models: ClassVar[list[type[LunchableModel]]] = [ PlaidAccountObject, AssetsObject, ] def do_something_with_assets(self) -> None: """ Do something with the assets """ if not self.data.plaid_accounts: self.refresh_data() for plaid_account_id, plaid_account in self.data.plaid_accounts.items(): print(plaid_account_id, plaid_account) ``` -------------------------------- ### Access Transactions as a List Source: https://context7.com/juftin/lunchable/llms.txt Iterate through all transactions in a list format. Ensure `app.data.transactions_list` is populated. ```python for transaction in app.data.transactions_list: print(f"{transaction.date}: {transaction.payee} - ${transaction.amount}") ``` -------------------------------- ### POST /api/trigger-plaid-sync Source: https://github.com/juftin/lunchable/blob/main/docs/interacting.md Triggers a Plaid synchronization. ```APIDOC ## POST /api/trigger-plaid-sync ### Description Trigger a Plaid Sync ### Method POST ### Endpoint /api/trigger-plaid-sync ### Parameters No parameters are specified in the provided text. ### Request Example (No request body or parameters specified) ### Response #### Success Response (200) - **message** (string) - Confirmation message indicating the sync has been triggered. #### Response Example { "message": "Plaid sync triggered successfully." } ``` -------------------------------- ### Insert New Transactions Source: https://context7.com/juftin/lunchable/llms.txt Create one or more new transactions using the `TransactionInsertObject`. Specify details like date, payee, amount, currency, category, notes, status, and tags. ```python from datetime import date from lunchable import LunchMoney, TransactionInsertObject lunch = LunchMoney(access_token="your_access_token") # Create a single transaction new_transaction = TransactionInsertObject( date=date(2024, 1, 15), payee="Coffee Shop", amount=5.50, currency="usd", category_id=12345, # Optional: assign to category notes="Morning coffee", status="cleared", tags=["coffee", "breakfast"] # Can use tag names or IDs ) # Insert and get the new transaction ID new_ids = lunch.insert_transactions(transactions=new_transaction) print(f"Created transaction with ID: {new_ids[0]}") ``` -------------------------------- ### Update Transaction by Fetching and Modifying Source: https://context7.com/juftin/lunchable/llms.txt Fetch an existing transaction, modify its properties directly on the TransactionObject, and then update it. This method allows for more granular control over the update process. ```python # Method 2: Fetch, modify, and update a TransactionObject transaction = lunch.get_transaction(transaction_id=123456) transaction.notes = "Modified notes" transaction.date = transaction.date + timedelta(days=1) response = lunch.update_transaction( transaction_id=transaction.id, transaction=transaction ) ``` -------------------------------- ### Create New Transaction Source: https://github.com/juftin/lunchable/blob/main/docs/usage.md Insert a new transaction using a TransactionInsertObject. ```python from lunchable import LunchMoney from lunchable.models import TransactionInsertObject lunch = LunchMoney(access_token="xxxxxxx") new_transaction = TransactionInsertObject( payee="Example Restaurant", amount=120.00, notes="Saturday Dinner" ) new_transaction_ids = lunch.insert_transactions(transactions=new_transaction) ``` -------------------------------- ### Access Combined Asset Map Source: https://context7.com/juftin/lunchable/llms.txt Iterate through a combined map of Plaid accounts and manual assets. Ensure `app.data.asset_map` is populated. ```python all_accounts = app.data.asset_map for account_id, account in all_accounts.items(): print(f"{account_id}: {account.name}") ``` -------------------------------- ### PUT /api/crypto/{id} Source: https://github.com/juftin/lunchable/blob/main/docs/interacting.md Updates a manual crypto asset. ```APIDOC ## PUT /api/crypto/{id} ### Description Update a Manual Crypto Asset ### Method PUT ### Endpoint /api/crypto/{id} ### Parameters #### Path Parameters - **id** (string) - Required - The ID of the crypto asset to update. #### Request Body - **update_data** (object) - Required - The fields to update for the crypto asset. ### Request Example { "id": "crypto_789", "update_data": { "quantity": 2.5 } } ### Response #### Success Response (200) - **crypto_asset** (object) - The updated crypto asset. #### Response Example { "crypto_asset": { "id": "crypto_789", "symbol": "BTC", "quantity": 2.5, "value": 50000 } } ``` -------------------------------- ### POST /api/category Source: https://github.com/juftin/lunchable/blob/main/docs/interacting.md Creates a new spending category. ```APIDOC ## POST /api/category ### Description Create a Spending Category ### Method POST ### Endpoint /api/category ### Parameters #### Request Body - **category_data** (object) - Required - Data for the new category. ### Request Example { "category_data": { "name": "Groceries", "group_id": "group_abc" } } ### Response #### Success Response (200) - **category** (object) - The newly created category. #### Response Example { "category": { "id": "cat_456", "name": "Groceries", "group_id": "group_abc" } } ``` -------------------------------- ### Split Transaction into Multiple Parts Source: https://context7.com/juftin/lunchable/llms.txt Split an existing transaction into multiple parts, each with its own category and amount. The sum of the split amounts must equal the original transaction amount. Requires a list of TransactionSplitObject. ```python # Define the split parts (amounts must sum to original transaction) splits = [ TransactionSplitObject( date=date(2024, 1, 15), amount=30.00, category_id=111, # Groceries notes="Food items" ), TransactionSplitObject( date=date(2024, 1, 15), amount=20.00, category_id=222, # Household notes="Cleaning supplies" ) ] # Split the transaction response = lunch.update_transaction( transaction_id=123456, split=splits ) print(f"Split response: {response}") ``` -------------------------------- ### Retrieve Transactions Source: https://github.com/juftin/lunchable/blob/main/docs/usage.md Fetch a list of transactions within a specified date range. ```python from typing import List from lunchable import LunchMoney from lunchable.models import TransactionObject lunch = LunchMoney(access_token="xxxxxxx") transactions: List[TransactionObject] = lunch.get_transactions( start_date="2020-01-01", end_date="2020-01-31" ) ``` -------------------------------- ### Create Transaction Group Source: https://context7.com/juftin/lunchable/llms.txt Create a transaction group by associating multiple existing transactions under a common payee, date, and optional category or tags. Returns the ID of the newly created group. ```python # Create a transaction group from existing transactions group_id = lunch.insert_transaction_group( date=date(2024, 1, 15), payee="Weekend Trip", transactions=[123456, 123457, 123458], # List of transaction IDs category_id=99999, # Optional category notes="Trip expenses", tags=[1, 2] # Optional tag IDs ) print(f"Created transaction group with ID: {group_id}") ``` -------------------------------- ### POST /api/transactions Source: https://github.com/juftin/lunchable/blob/main/docs/interacting.md Creates one or many Lunch Money transactions. ```APIDOC ## POST /api/transactions ### Description Create One or Many Lunch Money Transactions ### Method POST ### Endpoint /api/transactions ### Parameters #### Request Body - **transactions** (array) - Required - An array of transaction objects to create. ### Request Example { "transactions": [ { "amount": 100, "payee": "Online Store", "date": "2023-10-27" } ] } ### Response #### Success Response (200) - **created_transactions** (array) - Details of the transactions that were created. #### Response Example { "created_transactions": [ { "id": "tx_333", "amount": 100, "payee": "Online Store", "date": "2023-10-27" } ] } ``` -------------------------------- ### Insert Multiple Transactions Source: https://context7.com/juftin/lunchable/llms.txt Insert multiple transactions at once using a list of TransactionInsertObject. Supports applying rules, skipping duplicates, and checking for recurring expenses. ```python transactions_to_insert = [ TransactionInsertObject( date=date(2024, 1, 16), payee="Gas Station", amount=45.00, notes="Fill up" ), TransactionInsertObject( date=date(2024, 1, 16), payee="Lunch Restaurant", amount=15.75, category_id=67890 ) ] new_ids = lunch.insert_transactions( transactions=transactions_to_insert, apply_rules=True, # Apply account's existing rules skip_duplicates=True, # Dedupe by date, payee, amount check_for_recurring=True # Check for new recurring expenses ) print(f"Created {len(new_ids)} transactions: {new_ids}") ```