Skip to main content

Python SDK for the FinWise API

Project description

FinWise Python SDK

PyPI - Version PyPI - Downloads PyPI - License

A simple 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

  • 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.3.tar.gz (23.0 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.3-py3-none-any.whl (27.5 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: finwise_python-1.1.3.tar.gz
  • Upload date:
  • Size: 23.0 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.3.tar.gz
Algorithm Hash digest
SHA256 1eca9b2ed5f5dedcda141e232bba4e9689de3e90433ea4e696a22d47c999b8aa
MD5 16492fb0e6756cd6efe5ff25a3bb576c
BLAKE2b-256 bc44f2e22991b62b562014ee7c02bc62585f13bdd60eb1636dd85d8d0aa30b2d

See more details on using hashes here.

Provenance

The following attestation bundles were made for finwise_python-1.1.3.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.3-py3-none-any.whl.

File metadata

  • Download URL: finwise_python-1.1.3-py3-none-any.whl
  • Upload date:
  • Size: 27.5 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.3-py3-none-any.whl
Algorithm Hash digest
SHA256 67ee5058a545042cd19c4390d30fcdbefb394fe8e68dab31012941d2fc7e0385
MD5 480cc5de2f7db64d7c946b6b92fb8ffa
BLAKE2b-256 36f6d8525e43c240f48204a97a308a554b689964fddaaf685234661b69396007

See more details on using hashes here.

Provenance

The following attestation bundles were made for finwise_python-1.1.3-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