Overview
ThePotsAPI
provides methods to manage Monzo savings pots, including listing pots, depositing money, and withdrawing funds. All pot operations are accessed through the client.pots
property.
Methods
list()
List all savings pots for the authenticated user.Copy
def list(self) -> list[Pot]:
"""List all pots owned by the current user."""
list[Pot]
- List of pot objects
Example:
Copy
from monzoh import MonzoClient
client = MonzoClient()
# Get all pots
account = client.accounts.list()[0] # Get first account
pots = account.list_pots()
print(f"Found {len(pots)} pots")
for pot in pots:
if pot.deleted:
continue # Skip deleted pots
balance = pot.balance / 100
print(f"🐷 {pot.name}: £{balance:.2f}")
# Alternative: client-style method gets all user pots
# pots = client.pots.list()
if pot.goal_amount:
goal = pot.goal_amount / 100
progress = (balance / goal) * 100
print(f" 🎯 Goal: £{goal:.2f} ({progress:.1f}% complete)")
if pot.round_up:
print(" 🔄 Round-up enabled")
deposit()
Deposit money into a savings pot.Copy
def deposit(
self,
pot_id: str,
account_id: str,
amount: int | float | Decimal | str
) -> dict:
"""Deposit money into a pot."""
pot_id
: The unique pot identifieraccount_id
: The source account identifieramount
: Amount to deposit in major units (e.g., 1.50 for £1.50)
dict
- Deposit confirmation details
Example:
Copy
# Get accounts and pots
accounts = client.accounts.list()
current_account = accounts[0]
pots = current_account.list_pots()
savings_pot = next(pot for pot in pots if not pot.deleted)
# Deposit £25.00 into the pot
result = savings_pot.deposit(amount=25.00)
print(f"✅ Deposited £25.00 into {savings_pot.name}")
withdraw()
Withdraw money from a savings pot.Copy
def withdraw(
self,
pot_id: str,
account_id: str,
amount: int | float | Decimal | str
) -> dict:
"""Withdraw money from a pot."""
pot_id
: The unique pot identifieraccount_id
: The destination account identifieramount
: Amount to withdraw in major units (e.g., 1.50 for £1.50)
dict
- Withdrawal confirmation details
Example:
Copy
# Withdraw £10.00 from the pot
result = savings_pot.withdraw(amount=10.00)
print(f"✅ Withdrew £10.00 from {savings_pot.name}")
Pot Management Examples
Automated Savings
Implement automated savings rules:Copy
from decimal import Decimal
from datetime import datetime, timedelta
class AutoSavings:
def __init__(self):
self.client = MonzoClient()
self.accounts = self.client.accounts.list()
self.current_account = self.accounts[0]
self.pots = self.client.pots.list()
self.active_pots = [p for p in self.pots if not p.deleted]
def round_up_savings(self, max_amount_pounds=50):
"""Implement round-up savings on recent transactions."""
# Get recent transactions
transactions = self.client.transactions.list(
account_id=self.current_account.id,
limit=20
)
total_roundup = Decimal('0')
roundup_transactions = []
for txn in transactions:
if txn.amount < 0: # Spending transaction
amount = abs(txn.amount) / 100
rounded = int(amount) + 1
roundup = Decimal(str(rounded)) - Decimal(str(amount))
if roundup > 0:
total_roundup += roundup
roundup_transactions.append({
'description': txn.description,
'amount': amount,
'roundup': float(roundup)
})
# Apply maximum limit
if total_roundup > max_amount_pounds:
total_roundup = Decimal(str(max_amount_pounds))
print(f"💰 Round-up savings opportunity: £{total_roundup:.2f}")
print(f"📊 From {len(roundup_transactions)} transactions")
if total_roundup > 0 and self.active_pots:
# Use first available pot
savings_pot = self.active_pots[0]
try:
result = savings_pot.deposit(amount=float(total_roundup))
print(f"✅ Deposited £{total_roundup:.2f} into {savings_pot.name}")
return True
except Exception as e:
print(f"❌ Failed to deposit: {e}")
return False
return False
def goal_based_saving(self, target_weekly_amount=20):
"""Save a target amount weekly towards goals."""
goal_pots = [p for p in self.active_pots if p.goal_amount and p.goal_amount > 0]
if not goal_pots:
print("No pots with goals found")
return
print(f"🎯 Goal-based savings (£{target_weekly_amount}/week)")
print("="*50)
for pot in goal_pots:
balance = pot.balance / 100
goal = pot.goal_amount / 100
remaining = goal - balance
print(f"\n🐷 {pot.name}")
print(f" Current: £{balance:.2f}")
print(f" Goal: £{goal:.2f}")
print(f" Remaining: £{remaining:.2f}")
if remaining > 0:
# Calculate weekly contribution needed
# Assume 12 weeks to goal for simplicity
weeks_remaining = 12
weekly_needed = remaining / weeks_remaining
# Use the smaller of target amount or amount needed
weekly_contribution = min(target_weekly_amount, weekly_needed)
if weekly_contribution >= 1: # Minimum £1
try:
result = pot.deposit(amount=weekly_contribution)
new_balance = balance + weekly_contribution
progress = (new_balance / goal) * 100
print(f" ✅ Deposited £{weekly_contribution:.2f}")
print(f" 📊 Progress: {progress:.1f}%")
if progress >= 100:
print(" 🎉 Goal achieved!")
except Exception as e:
print(f" ❌ Deposit failed: {e}")
else:
print(" ℹ️ Goal nearly complete, no deposit needed")
else:
print(" 🎉 Goal already achieved!")
def emergency_fund_check(self, target_months=6):
"""Check emergency fund status and suggest contributions."""
# Calculate monthly expenses from recent transactions
since = datetime.now(tz=datetime.timezone.utc) - timedelta(days=30)
transactions = self.client.transactions.list(
account_id=self.current_account.id,
since=since,
limit=200
)
monthly_expenses = sum(
abs(txn.amount) for txn in transactions
if txn.amount < 0 and txn.category not in ['transfers', 'savings']
) / 100
target_emergency_fund = monthly_expenses * target_months
# Find emergency fund pot (by name)
emergency_pot = next(
(p for p in self.active_pots if 'emergency' in p.name.lower()),
None
)
print(f"🚨 Emergency Fund Analysis")
print("="*30)
print(f"Monthly expenses: £{monthly_expenses:.2f}")
print(f"Target fund ({target_months} months): £{target_emergency_fund:.2f}")
if emergency_pot:
current_fund = emergency_pot.balance / 100
shortfall = target_emergency_fund - current_fund
print(f"Current fund: £{current_fund:.2f}")
print(f"Shortfall: £{shortfall:.2f}")
if shortfall > 0:
# Suggest monthly contribution
monthly_contribution = shortfall / 12 # Spread over 12 months
print(f"💡 Suggested monthly contribution: £{monthly_contribution:.2f}")
return {
'pot': emergency_pot,
'shortfall': shortfall,
'suggested_monthly': monthly_contribution
}
else:
print("❌ No emergency fund pot found")
print("💡 Consider creating an emergency fund pot")
return None
# Usage
auto_saver = AutoSavings()
# Run automated savings
auto_saver.round_up_savings(max_amount_pounds=25)
auto_saver.goal_based_saving(target_weekly_amount=20)
emergency_status = auto_saver.emergency_fund_check(target_months=6)
Pot Performance Tracking
Track savings progress over time:Copy
import json
from datetime import datetime, timedelta
class PotTracker:
def __init__(self, history_file="pot_history.json"):
self.client = MonzoClient()
self.history_file = history_file
self.load_history()
def load_history(self):
"""Load historical pot data."""
try:
with open(self.history_file, 'r') as f:
self.history = json.load(f)
except FileNotFoundError:
self.history = {}
def save_history(self):
"""Save historical pot data."""
with open(self.history_file, 'w') as f:
json.dump(self.history, f, indent=2)
def record_snapshot(self):
"""Record current pot balances."""
pots = self.client.pots.list()
timestamp = datetime.now(tz=datetime.timezone.utc).isoformat()
snapshot = {}
for pot in pots:
if not pot.deleted:
snapshot[pot.id] = {
'name': pot.name,
'balance': pot.balance,
'goal': pot.goal_amount
}
self.history[timestamp] = snapshot
self.save_history()
print(f"📸 Recorded snapshot of {len(snapshot)} pots")
def analyze_growth(self, days=30):
"""Analyze pot growth over the last N days."""
if len(self.history) < 2:
print("Need at least 2 snapshots to analyze growth")
return
# Get timestamps within the date range
cutoff_date = datetime.now(tz=datetime.timezone.utc) - timedelta(days=days)
recent_timestamps = [
ts for ts in self.history.keys()
if datetime.fromisoformat(ts) >= cutoff_date
]
if len(recent_timestamps) < 2:
print(f"Need at least 2 snapshots in the last {days} days")
return
# Compare earliest and latest in range
earliest_ts = min(recent_timestamps)
latest_ts = max(recent_timestamps)
earliest_data = self.history[earliest_ts]
latest_data = self.history[latest_ts]
print(f"💹 Pot Growth Analysis ({days} days)")
print("="*40)
print(f"From: {earliest_ts[:10]}")
print(f"To: {latest_ts[:10]}")
print()
total_growth = 0
for pot_id in latest_data:
if pot_id in earliest_data:
pot_name = latest_data[pot_id]['name']
old_balance = earliest_data[pot_id]['balance'] / 100
new_balance = latest_data[pot_id]['balance'] / 100
growth = new_balance - old_balance
total_growth += growth
if growth != 0:
print(f"🐷 {pot_name}")
print(f" From: £{old_balance:.2f}")
print(f" To: £{new_balance:.2f}")
print(f" Growth: £{growth:+.2f}")
if latest_data[pot_id]['goal']:
goal = latest_data[pot_id]['goal'] / 100
progress = (new_balance / goal) * 100
print(f" Goal progress: {progress:.1f}%")
print()
print(f"📊 Total portfolio growth: £{total_growth:+.2f}")
if total_growth > 0:
daily_average = total_growth / days
print(f"📅 Daily average: £{daily_average:.2f}")
def savings_rate_analysis(self):
"""Analyze savings rate based on income vs pot deposits."""
# Get account transactions to estimate income
accounts = self.client.accounts.list()
current_account = accounts[0]
# Get last month's transactions
since = datetime.now(tz=datetime.timezone.utc) - timedelta(days=30)
transactions = self.client.transactions.list(
account_id=current_account.id,
since=since,
limit=200
)
# Estimate income (positive transactions, excluding transfers)
income_transactions = [
txn for txn in transactions
if txn.amount > 0 and txn.category not in ['transfers', 'internal_transfer']
]
total_income = sum(txn.amount for txn in income_transactions) / 100
# Calculate pot deposits (negative current account transactions to pots)
pot_deposits = [
txn for txn in transactions
if txn.amount < 0 and 'pot' in txn.description.lower()
]
total_saved = sum(abs(txn.amount) for txn in pot_deposits) / 100
if total_income > 0:
savings_rate = (total_saved / total_income) * 100
print(f"💰 Savings Rate Analysis (30 days)")
print("="*35)
print(f"Estimated income: £{total_income:.2f}")
print(f"Amount saved to pots: £{total_saved:.2f}")
print(f"Savings rate: {savings_rate:.1f}%")
# Provide feedback
if savings_rate >= 20:
print("🌟 Excellent savings rate!")
elif savings_rate >= 10:
print("👍 Good savings rate")
elif savings_rate >= 5:
print("📈 Room for improvement")
else:
print("💡 Consider increasing your savings rate")
else:
print("Unable to calculate savings rate - no income detected")
# Usage
tracker = PotTracker()
# Record regular snapshots (run daily/weekly)
tracker.record_snapshot()
# Analyze growth trends
tracker.analyze_growth(days=30)
tracker.savings_rate_analysis()
Smart Pot Allocations
Automatically allocate money across different pots based on priorities:Copy
class SmartPotAllocator:
def __init__(self):
self.client = MonzoClient()
self.accounts = self.client.accounts.list()
self.current_account = self.accounts[0]
self.pots = [p for p in self.client.pots.list() if not p.deleted]
def allocate_surplus(self, target_current_balance=500):
"""Allocate surplus money above target current account balance."""
balance = self.client.accounts.get_balance(
account_id=self.current_account.id
)
current_balance = balance.balance / 100
surplus = current_balance - target_current_balance
print(f"💳 Current account balance: £{current_balance:.2f}")
print(f"🎯 Target balance: £{target_current_balance:.2f}")
print(f"💰 Surplus available: £{surplus:.2f}")
if surplus <= 0:
print("No surplus to allocate")
return
# Define allocation priorities and percentages
allocation_rules = [
{'name_contains': 'emergency', 'priority': 1, 'max_percentage': 0.5},
{'name_contains': 'holiday', 'priority': 2, 'max_percentage': 0.3},
{'name_contains': 'house', 'priority': 3, 'max_percentage': 0.4},
{'name_contains': 'car', 'priority': 4, 'max_percentage': 0.2},
]
# Find matching pots and sort by priority
eligible_pots = []
for rule in allocation_rules:
matching_pots = [
p for p in self.pots
if rule['name_contains'].lower() in p.name.lower()
]
for pot in matching_pots:
eligible_pots.append({
'pot': pot,
'priority': rule['priority'],
'max_percentage': rule['max_percentage']
})
# Sort by priority
eligible_pots.sort(key=lambda x: x['priority'])
print(f"\n📋 Allocation Plan:")
print("-" * 30)
remaining_surplus = surplus
for allocation in eligible_pots:
pot = allocation['pot']
max_percentage = allocation['max_percentage']
# Calculate allocation amount
max_allocation = surplus * max_percentage
allocation_amount = min(remaining_surplus, max_allocation)
if allocation_amount >= 1: # Minimum £1
print(f"🐷 {pot.name}: £{allocation_amount:.2f}")
# Perform the transfer
try:
result = pot.deposit(amount=allocation_amount)
remaining_surplus -= allocation_amount
print(f" ✅ Transferred successfully")
except Exception as e:
print(f" ❌ Transfer failed: {e}")
if remaining_surplus <= 1:
break
print(f"\n📊 Remaining surplus: £{remaining_surplus:.2f}")
if remaining_surplus > 1:
print("💡 Consider creating additional savings pots for remaining surplus")
# Usage
allocator = SmartPotAllocator()
allocator.allocate_surplus(target_current_balance=500)
Best Practices
- Check pot status: Always verify a pot is not deleted before performing operations
- Handle minimum amounts: Monzo may have minimum transfer amounts (typically £1)
- Error handling: Wrap pot operations in try/catch blocks for robust error handling
- Balance validation: Check account balance before attempting large withdrawals
- Goal tracking: Use pot goals to implement automatic savings strategies