A Python library for the Monzo Developer API.
Features
- 📦 Trusted PyPI publishing
- 🌐 Full Monzo API coverage
- 🔐 Simple OAuth2 authentication flow
- 🔒 Type-safe with Pydantic models
- ⚡ Async/await support with httpx
- ✅ Well-tested and documented
- ⚠️ Comprehensive error handling
Installation
uv add monzoh
Quick Start
- Create an OAuth2 client on the Monzo Developers Portal. Redirect URL must be
http://localhost:8080/callbackand Confidentiality must beConfidential. - Run
monzo-authand complete the login flow. - Authorise access on the Monzo app.
You can now use the API:
from monzoh import MonzoClient
client = MonzoClient() # Uses cached access token and handles refresh
account = client.accounts.list()[0]
balance = account.get_balance()
print(f"Balance: £{balance.balance}")
transactions = account.list_transactions(limit=10)
for transaction in transactions:
if transaction.amount < -50: # Transactions over £50
transaction.annotate({"notes": "#large_expense"})
transactions[0].upload_attachment("image.jpg")
pots = account.list_pots()
for pot in pots:
if pot.name == "Savings":
pot.deposit(10.00)
break
Asynchronous API
import asyncio
from monzoh import AsyncMonzoClient
async def main():
async with AsyncMonzoClient() as client:
account = (await client.accounts.list())[0]
balance = await account.aget_balance()
print(f"Balance: £{balance.balance}")
transactions = await account.alist_transactions(limit=10)
for transaction in transactions:
if transaction.amount < -50:
await transaction.aannotate({"notes": "#large_expense"})
pots = await account.alist_pots()
for pot in pots:
if pot.name == "Savings":
await pot.adeposit(10.00)
break
asyncio.run(main())
Why not call the API directly?
It's much simpler with Monzoh! As an example, here's what uploading an attachment looks like, compared with using the API directly:
With monzoh
from monzoh import MonzoClient
client = MonzoClient()
account = client.accounts.list()[0]
transaction = account.list_transactions(limit=1)[0]
attachment = transaction.upload_attachment("receipt.jpg")
Without monzoh
import requests
from pathlib import Path
accounts_response = requests.get(
"https://api.monzo.com/accounts",
headers={"Authorization": f"Bearer {access_token}"}
)
account_id = accounts_response.json()["accounts"][0]["id"]
transactions_response = requests.get(
"https://api.monzo.com/transactions",
headers={"Authorization": f"Bearer {access_token}"},
params={"account_id": account_id, "limit": 1}
)
transaction_id = transactions_response.json()["transactions"][0]["id"]
response = requests.post(
"https://api.monzo.com/attachment/upload",
headers={"Authorization": f"Bearer {access_token}"},
data={
"file_name": "receipt.jpg",
"file_type": "image/jpeg",
"content_length": str(len(Path("receipt.jpg").read_bytes()))
}
)
upload_info = response.json()
file_data = Path("receipt.jpg").read_bytes()
requests.put(
upload_info["upload_url"],
data=file_data,
headers={
"Content-Type": "image/jpeg",
"Content-Length": str(len(file_data))
}
)
requests.post(
"https://api.monzo.com/attachment/register",
headers={"Authorization": f"Bearer {access_token}"},
data={
"external_id": transaction_id,
"file_url": upload_info["file_url"],
"file_type": "image/jpeg"
}
)
Release files for monzoh 1.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| monzoh-1.2.0.tar.gz | 5.2 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| monzoh-1.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size:5.2 MB
Release files / monzoh-1.2.0.tar.gz
| Download URL | monzoh-1.2.0.tar.gz |
|---|---|
| Size | 5.2 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
0a38fc07428e15e395b7dbc92cb0ef4fb7de8bd57ae91bd93e4a9f179f033d7f
|
|
BLAKE2b-256 checksum How to use checksums |
0a9bcfd0c78c6f6dec744ab7b90073a7fc545909bd91c4fd39d448f48e03f996
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 12, 2025.
Transparency logRelease files / monzoh-1.2.0-py3-none-any.whl
| Download URL | monzoh-1.2.0-py3-none-any.whl |
|---|---|
| Size | 51.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
06675f040e86285e486b602d9a3ae342571c450676ba590c751b2923e3cfbbdb
|
|
BLAKE2b-256 checksum How to use checksums |
5e2c7ddaf8aa87587ae43fb293f5926f8f1ab4501a64e2bda6b6eed5774fe342
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 12, 2025.
Transparency log