Skip to main content

Python SDK for the FinWise API

Project description

FinWise Python SDK

A simple, well-documented Python client for the FinWise API.

Installation

pip install finwise-python

For development:

pip install finwise-python[dev]

Quick Start

from finwise import FinWise

# Initialize the client
client = FinWise(api_key="your-api-key")

# Or use the FINWISE_API_KEY environment variable
client = FinWise()

# List all accounts
accounts = client.accounts.list()
for account in accounts.data:
    print(f"{account.name}: {account.currency} {account.balance}")

Features

  • Simple, intuitive API design
  • Full type hints for IDE support
  • Comprehensive error handling
  • Automatic retries with exponential backoff
  • Pagination support
  • Context manager support

Usage

Accounts

from finwise import FinWise

client = FinWise(api_key="your-api-key")

# Create an account
account = client.accounts.create(
    name="Savings Account",
    type="savings",  # checking, savings, credit, investment, loan, other
    currency="USD",
    description="Emergency fund",
    initial_balance=10000.00,
)
print(f"Created: {account.id}")

# Get a specific account
account = client.accounts.retrieve("acc_123")
print(f"{account.name}: {account.balance}")

# Update an account
account = client.accounts.update(
    "acc_123",
    name="Renamed Account",
    description="Updated description",
)

# List accounts with pagination
accounts = client.accounts.list(page_number=1, page_size=50)
print(f"Total accounts: {accounts.total_count}")

for account in accounts.data:
    print(f"  - {account.name}")

if accounts.has_next:
    next_page = client.accounts.list(page_number=2, page_size=50)

# Archive an account
archived = client.accounts.archive("acc_123")
print(f"Archived at: {archived.archived_at}")

Transactions

from decimal import Decimal
from datetime import date
from finwise import FinWise

client = FinWise(api_key="your-api-key")

# Create a transaction
transaction = client.transactions.create(
    account_id="acc_123",
    amount=Decimal("-50.00"),  # Negative for expenses
    transaction_date=date.today(),
    description="Grocery shopping",
    category_id="cat_groceries",
    type="expense",  # income, expense, transfer
)

# List transactions with filters
transactions = client.transactions.list(
    account_id="acc_123",
    start_date=date(2024, 1, 1),
    end_date=date(2024, 1, 31),
    type="expense",
)

for txn in transactions.data:
    print(f"{txn.transaction_date}: {txn.description} ({txn.amount})")

# Get aggregated summary
summary = client.transactions.aggregated(
    start_date=date(2024, 1, 1),
    end_date=date(2024, 1, 31),
)
print(f"Income: {summary.total_income}")
print(f"Expenses: {summary.total_expenses}")
print(f"Net: {summary.net_amount}")

# Archive a transaction
client.transactions.archive("txn_123")

Account Balances

from decimal import Decimal
from datetime import date
from finwise import FinWise

client = FinWise(api_key="your-api-key")

# Create a balance record (point-in-time snapshot)
balance = client.account_balances.create(
    account_id="acc_123",
    balance=Decimal("5000.00"),
    balance_date=date(2024, 1, 15),
)

# List balance records
balances = client.account_balances.list(account_id="acc_123")

# Get aggregated balance across all accounts
summary = client.account_balances.aggregated()
print(f"Total: {summary.currency} {summary.total_balance}")
print(f"Across {summary.account_count} accounts")

Transaction Categories

from finwise import FinWise

client = FinWise(api_key="your-api-key")

# Create a category
category = client.transaction_categories.create(
    name="Groceries",
    color="#4CAF50",
    icon="shopping_cart",
)

# Create a subcategory
subcategory = client.transaction_categories.create(
    name="Organic Food",
    color="#8BC34A",
    parent_id=category.id,
)

# List categories
categories = client.transaction_categories.list()
for cat in categories.data:
    prefix = "  " if cat.is_subcategory else ""
    print(f"{prefix}{cat.name}")

# Delete a category
client.transaction_categories.delete("cat_123")

Error Handling

The SDK provides a comprehensive exception hierarchy:

from finwise import (
    FinWise,
    FinWiseError,          # Base exception
    FinWiseAPIError,       # API returned an error
    AuthenticationError,   # Invalid/missing API key (401)
    PermissionDeniedError, # Permission denied (403)
    NotFoundError,         # Resource not found (404)
    ValidationError,       # Invalid request data (400, 422)
    ConflictError,         # Conflict error (409)
    RateLimitError,        # Rate limit exceeded (429)
    ServerError,           # Server error (5xx)
    FinWiseConnectionError,# Connection failed
    FinWiseTimeoutError,   # Request timed out
)

client = FinWise(api_key="your-api-key")

try:
    account = client.accounts.retrieve("invalid_id")
except NotFoundError as e:
    print(f"Not found: {e.message}")
    print(f"Request ID: {e.request_id}")  # For debugging
except AuthenticationError as e:
    print(f"Auth failed: {e.message}")
except RateLimitError as e:
    print(f"Rate limited. Retry after: {e.retry_after}s")
except FinWiseAPIError as e:
    print(f"API error {e.status_code}: {e.message}")
except FinWiseConnectionError as e:
    print(f"Connection failed: {e.message}")
except FinWiseError as e:
    print(f"Error: {e.message}")

Configuration

from finwise import FinWise

client = FinWise(
    api_key="your-api-key",
    base_url="https://api.finwiseapp.io",  # Default
    timeout=30.0,    # Request timeout in seconds
    max_retries=3,   # Automatic retries for transient errors
)

Environment Variable

Set your API key via environment variable:

export FINWISE_API_KEY="your-api-key"
from finwise import FinWise

# Automatically uses FINWISE_API_KEY
client = FinWise()

Context Manager

Use as a context manager for automatic cleanup:

from finwise import FinWise

with FinWise(api_key="your-api-key") as client:
    accounts = client.accounts.list()
    # Client is automatically closed when exiting the block

Pagination

All list methods return a PaginatedResponse object:

from finwise import FinWise

client = FinWise(api_key="your-api-key")

# Get first page
accounts = client.accounts.list(page_number=1, page_size=50)

print(f"Page {accounts.page_number} of {accounts.total_pages}")
print(f"Showing {len(accounts)} of {accounts.total_count} accounts")

# Iterate through items on this page
for account in accounts.data:
    print(account.name)

# Access by index
first_account = accounts[0]  # or accounts.data[0]

# Check for more pages
if accounts.has_next:
    next_page = client.accounts.list(
        page_number=accounts.page_number + 1,
        page_size=50,
    )

API Reference

Client

Method Description
FinWise(api_key, ...) Create a new client
client.close() Close the client

Accounts (client.accounts)

Method Description
create(name, type, ...) Create a new account
retrieve(account_id) Get an account by ID
update(account_id, ...) Update an account
list(page_number, page_size) List all accounts
archive(account_id) Archive an account

Transactions (client.transactions)

Method Description
create(account_id, amount, ...) Create a transaction
list(account_id, start_date, ...) List transactions
aggregated(start_date, end_date, ...) Get aggregated summary
archive(transaction_id) Archive a transaction

Account Balances (client.account_balances)

Method Description
create(account_id, balance, ...) Create a balance record
list(account_id, ...) List balance records
aggregated(as_of_date, ...) Get aggregated balance
archive(balance_id) Archive a balance record

Transaction Categories (client.transaction_categories)

Method Description
create(name, color, ...) Create a category
list(parent_id, ...) List categories
delete(category_id) Delete a category

Requirements

  • Python 3.9+
  • httpx
  • pydantic

License

MIT License - see LICENSE for details.

Links

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

finwise_python-1.1.2.tar.gz (21.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

finwise_python-1.1.2-py3-none-any.whl (27.4 kB view details)

Uploaded Python 3

File details

Details for the file finwise_python-1.1.2.tar.gz.

File metadata

  • Download URL: finwise_python-1.1.2.tar.gz
  • Upload date:
  • Size: 21.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for finwise_python-1.1.2.tar.gz
Algorithm Hash digest
SHA256 f6660a9c611c60cde0b6aa56ade4fb6cc95efa1d9cf4c3da71972c77d4892102
MD5 3aff3f86d740db430b527c293e9b4896
BLAKE2b-256 6ca710a6763901db47b24f06da4af86584d4686f1e47002424a4ed5996ccf055

See more details on using hashes here.

Provenance

The following attestation bundles were made for finwise_python-1.1.2.tar.gz:

Publisher: release.yml on rameezk/finwise-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file finwise_python-1.1.2-py3-none-any.whl.

File metadata

  • Download URL: finwise_python-1.1.2-py3-none-any.whl
  • Upload date:
  • Size: 27.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for finwise_python-1.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 40ec3f263a3d054ea4aef026982516d2151ee6be569227b1909c27b31511923b
MD5 bad5be2a0cc30860cf14f8f73e3f0f17
BLAKE2b-256 e6f6afb7d6306b92e4028b88e6b8cb695b90c6d842bcb1d76881dbf116fffda0

See more details on using hashes here.

Provenance

The following attestation bundles were made for finwise_python-1.1.2-py3-none-any.whl:

Publisher: release.yml on rameezk/finwise-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page