hammem / monarchmoney Goto Github PK
View Code? Open in Web Editor NEWPython API for Monarch Money
License: MIT License
Python API for Monarch Money
License: MIT License
I'd like to see the ability to search by Merchant and Amount.
I'm trying to write a script to categorize my amazon transactions based on my downloaded amazon history. Finding a transaction by date, merchant and amount should allow me to identify most transactions programmatically.
When I run the following:
import asyncio
from monarchmoney import MonarchMoney
import traceback
async def main():
email = 'email-here'
password = 'password-here'
mm = MonarchMoney()
try:
print("Attempting to login...")
await mm.login(email, password)
print("Login successful")
# Fetch account information
accounts_data = await mm.get_accounts()
print("Accounts fetched successfully")
# Access the list of accounts within the returned dictionary
accounts = accounts_data['accounts']
# Specify the account name you want to find
account_name_to_find = 'test' # Replace with the actual account name
# Search for the account by name
account_id_to_update = None
for account in accounts:
if account['displayName'] == account_name_to_find:
account_id_to_update = account['id']
break
if account_id_to_update:
print(f"Account ID for '{account_name_to_find}' found: {account_id_to_update}")
# Attempt to update account balance
print("Attempting to update account balance...")
new_balance = 1000.0 # Replace with the new balance you want to set
try:
update_response = await mm.update_account(account_id_to_update, balance=new_balance)
print(f"\nAccount update response: {update_response}")
except Exception as e:
print(f"An error occurred while updating the account: {e}")
traceback.print_exc() # Print the full traceback for bug reporting
else:
print(f"Account with name '{account_name_to_find}' not found.")
except Exception as e:
print(f"An error occurred: {e}")
traceback.print_exc() # Print the full traceback for bug reporting
# Run the main function
asyncio.run(main())
It spits out an error stating 'MonarchMoney' object has no attribute 'update_account':
Traceback (most recent call last):
File "/Users/trevoroler/Desktop/antminer/./monarch.py", line 41, in main
update_response = await mm.update_account(account_id_to_update, balance=new_balance)
^^^^^^^^^^^^^^^^^
AttributeError: 'MonarchMoney' object has no attribute 'update_account'. Did you mean: 'delete_account'?
I even tried checking the attributes:
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_get_current_date', '_get_end_of_current_month', '_get_graphql_client', '_get_start_of_current_month', '_headers', '_login_user', '_multi_factor_authenticate', '_session_file', '_timeout', '_token', 'create_manual_account', 'create_transaction', 'create_transaction_category', 'create_transaction_tag', 'delete_account', 'delete_session', 'delete_transaction', 'delete_transaction_categories', 'delete_transaction_category', 'get_account_history', 'get_account_holdings', 'get_account_snapshots_by_type', 'get_account_type_options', 'get_accounts', 'get_aggregate_snapshots', 'get_budgets', 'get_cashflow', 'get_cashflow_summary', 'get_institutions', 'get_recent_account_balances', 'get_recurring_transactions', 'get_subscription_details', 'get_transaction_categories', 'get_transaction_category_groups', 'get_transaction_details', 'get_transaction_splits', 'get_transaction_tags', 'get_transactions', 'get_transactions_summary', 'gql_call', 'interactive_login', 'is_accounts_refresh_complete', 'load_session', 'login', 'multi_factor_authenticate', 'request_accounts_refresh', 'request_accounts_refresh_and_wait', 'save_session', 'set_budget_amount', 'set_timeout', 'set_token', 'set_transaction_tags', 'timeout', 'token', 'update_transaction', 'update_transaction_splits', 'upload_account_balance_history']
I do not see the attribute anywhere. I even tried to take the login token and request the data directly from the API and nothing. Was this function removed?
Thanks for creating this library. I just finished creating a custom component for Home Assistant using this library. Would you be interested in publishing this as a package on pypi.org, so I can use it as a dependency?
You can find my custom component here - https://github.com/sanghviharshit/ha-monarchmoney
Passwords such as the following cause login to fail with a 404 (not my real password, but an example that actually fails):
Ab[1C*[Def`'&]2g,/H%3I}J'_KLmn`o
I had to change my password to alphanumeric (i.e., no symbols) to get login to work properly. The example password has both quotes and a forward slash, so that might be the cause.
Add the ability to split a transaction
Would it be possible to add an account ID/name to the get_transactions() function? I have tried to play around with it myself and haven't found a way to do it, but I have never worked with gql, so I'm hoping your expertise can resolve it.
If adding a new field isn't an option, would pulling transactions for specific account IDs be an option?
Not trying to add onto your plate. I'm volunteering myself to implement this endpoint. I'm just not a Python expert like you all; I'm more of a Node.js developer myself. Upon reviewing the code, it seems that we need to define the endpoint inside MonarchMoneyEndpoints:
@classmethod
def getAccountTransactionHistoryUploadEndpoint(cls) -> str:
return cls.BASE_URL + "/account-transaction-history/upload/"
and just copy/paste and rename the async def upload_account_balance_history
method to new
async def upload_account_transaction_history`. is that correct? Am I missing anything?
Adds the ability to add a tag to a transaction
Along with adding unit testing that mocks gql
responses (#48) and runs on every PR, it would be helpful for us to have integration test coverage. It would be run in one of two ways:
How it would work is:
INTEG-1234567890abcdef
) that is not visible in any way.INTEG-[0-9]+
regex, along with everything inside (we could also delete all dummy accounts at the beginning of the test run)Running it locally is fairly straightforward; the contributor just needs to provide their own credentials, and the testing will happen in their own account. The testing should clean itself up, and the manual account should not be included in budgets, cashflow, etc based on the configuration, so the user shouldn't be affected if artifacts inadvertently get left behind.
Running it programmatically as an Action is a bit different... we'd either need:
I think, at least for now, we can forgo automated testing. We should still write the integ tests so that contributors can manually run them prior to publishing a PR, and a maintainer can manually run them prior to a release.
As this library grows and matures, it's going to need unit (and likely integration) tests. Otherwise, I'm sure I'll release a version to PyPI that breaks things for everyone!
I'm flexible on testing regimes we use. Resolving this issue should include tests for:
Also, setup a workflow to run the tests when folks put up a PR or create a release.
For security purposes, should add a delete_session function to the class MonarchMoney to enabling deleting the saved session file.
I'm new to Python/Git, but I think this is probably really straightforward:
def delete_session_file(self,filename: str = SESSION_FILE) -> None:
"""
Deletes Python pickle file of saved session info if it exists.
"""
if os.path.isfile(filename):
os.remove(filename)
When using interactiveLogin, if no email or password is provided an exception doesn't get raised by login. This like like it's due to the fact that input() is used to retrieve those values and entering nothing results in the variable being an empty string (i.e. '') instead of None.
In login():
...
if email is None or password is None:
raise LoginFailedException(
"Email and password are required to login when not using a saved session."
)
looks like this can be fixed by updating to check the variables being == '' instead of None, but not sure if there's something else going wrong prior to that
Please add addHolding API for brokerage accounts
Does this api have methods to list the Categories and delete some of them? I've imported my Mint data into Monarch and ended up with 3000 custom categories in "Other" group. Their support isn't helpful to clean it up.
Not sure if I'm doing it incorrectly or if the API is not performing as intended. I successfully created a CSV file with my code and uploaded it to the browser client, reading the data without any issues. However, I am unable to update the history with the provided csv_content
. Also, I'm not receiving any errors after making the API call.
here is the format:
Date,Amount
2023-12-14,5424.360000000001
2023-12-15,10422.85
2023-12-17,15422.05
2023-12-18,20446.09
2023-12-19,25430.87
2023-12-20,30403.879999999997
2023-12-21,35318.729999999996
2023-12-22,40147.06999999999
2023-12-30,45135.23999999999
2024-01-02,50215.149999999994
2024-01-03,55224.479999999996
2024-01-08,60214.579999999994
2024-01-12,65208.729999999996
2024-01-14,70198.98
2024-01-16,75194.69
2024-01-17,80184.07
2024-01-18,85174.02
2024-01-20,90181.01000000001
Using the following code:
import asyncio
from monarchmoney import MonarchMoney
async def main():
mm = MonarchMoney()
try:
print("Attempting interactive login...")
await mm.interactive_login()
print("Login successful")
# Fetch account information
accounts = await mm.get_accounts()
print("Accounts fetched successfully")
# Print account details
for account in accounts:
print(f"Account Name: {account['name']}")
print(f"Balance: {account['balance']}")
print("-" * 20)
except Exception as e:
print(f"An error occurred: {e}")
# Run the main function
asyncio.run(main())
When ran, I get the following error:
An error occurred: HTTP Code 404: Not Found
Edit:
Error happens between print("Attempting interactive login...")
and print("Login successful")
If merchants or vendors have logos associated, the logoURL parameter in the GraphQL query pulls that in as (presumably) base64 encoded content in the query response, which are massive strings that are probably not going to be used for much of anything for most use cases of the various methods so all it's doing is greatly increasing the size of the response payload/memory consumption.
Feels like it makes sense for those to be excluded by default with an optional parameter in the function to include them.
I've noticed that when exporting transactions from Mint, if there are any line feeds in the Description or Original Description fields in the .csv that it will not export properly. The fields are double quoted but the '\n' in those fields is not escaped properly and hence causes problems in the exported file.
Add the ability to edit a transaction
Part of the response to a question that came up on Reddit: https://www.reddit.com/r/MonarchMoney/comments/180hb5j/comment/kpnqr4i/?context=3
Add functions to pull recurring merchants, as well as recurring transactions.
Make sure to document the process of how to reverse engineer the GraphQL calls in this issue discussion.
I'm not sure what Monarch's API rate limits are, but I'm getting frequent 404's on login:
Traceback (most recent call last):
File "/var/lib/homebridge/monarch.py", line 26, in <module>
asyncio.run(main(), debug=True)
File "/usr/lib/python3.9/asyncio/runners.py", line 44, in run
return loop.run_until_complete(main)
File "/usr/lib/python3.9/asyncio/base_events.py", line 642, in run_until_complete
return future.result()
File "/var/lib/homebridge/monarch.py", line 14, in main
await mm.login(
File "/home/pi/.local/lib/python3.9/site-packages/monarchmoney/monarchmoney.py", line 108, in login
await self._login_user(email, password, mfa_secret_key)
File "/home/pi/.local/lib/python3.9/site-packages/monarchmoney/monarchmoney.py", line 768, in _login_user
raise LoginFailedException(
monarchmoney.monarchmoney.LoginFailedException: HTTP Code 404: Not Found
I'm speculating that this is hitting some sort of rate limit, but I am not sure if that's actually what's happening. Regardless, handling this more gracefully would be nice, or at least documenting the default API rate limits.
Code I used:
import asyncio
from monarchmoney import MonarchMoney
with open("monarch-creds.json", "r") as f:
creds = json.load(f)
async def main():
mm = MonarchMoney()
await mm.login(
email=creds["email"],
password=creds["password"],
save_session=False,
use_saved_session=False,
mfa_secret_key=creds["mfa_secret_key"],
)
asyncio.run(main(), debug=True)
Transfer categories are present in ManageGetCategoryGroups
response, if requested:
query ManageGetCategoryGroups {
categoryGroups {
id
name
order
type
__typename
}
categories(includeDisabledSystemCategories: true) {
id
name
order
icon
isSystemCategory
systemCategory
isDisabled
group {
id
type
name
__typename
}
__typename
}
}
It would be useful to be able to add a transaction to an account. This would basically open the door for custom syncing of external accounts programmatically.
(For me, modifying/deleting transactions are less important. My plan is to just add a "Balance Adjustment" transaction nightly to track the value of an asset.)
Add the ability to delete a transaction
Recently, after an API change, I've been getting an error when calling get_transactions
. Can anyone else confirm if they're getting errors as well? After testing around with it, I've found that removing the account in the graphql query fixed the error but meaning the account is no longer in the response.
https://github.com/hammem/monarchmoney/blob/main/monarchmoney/monarchmoney.py#L1239
Stacktrace:
Traceback (most recent call last):
File "C:\Users\cchan\PycharmProjects\monarchmoney\monarchmoney\monarchmoney.py", line 1321, in get_transactions
return await self.gql_call(
^^^^^^^^^^^^^^^^^^^^
File "C:\Users\cchan\PycharmProjects\monarchmoney\monarchmoney\monarchmoney.py", line 2634, in gql_call
return await self._get_graphql_client().execute_async(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\cchan\PycharmProjects\monarchmoney\.venv\Lib\site-packages\gql\client.py", line 285, in execute_async
return await session.execute(
^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\cchan\PycharmProjects\monarchmoney\.venv\Lib\site-packages\gql\client.py", line 1231, in execute
raise TransportQueryError(
gql.transport.exceptions.TransportQueryError: {'message': "Something went wrong while processing: ['allTransactions', 'results', 4] on request_id: 107af4308b774b779d356d241c6d37ca.", 'locations': [{'line': 4, 'column': 5}], 'path': ['allTransactions', 'results', 4]}
if MonarchMoney marks a transaction as Recurring, it does not come down as part of the get_transactions function and you have to call get_transactions twice: once with is_recurring=true and once with it as false in order to get all transactions.
Is there a way to make get_transactions NOT filter on recurring if thats what the user wants?
Similar issue on all of the Boolean parameters to get_transactions: has_attachments, has_notes, hidden_from_reports, is_split
But only recurring seems to be something that MonarchMoney sets by itself on a transaction, the rest get downloaded unless I have done something to the transaction, so I can control that.
I use 'Continue with Google' to sign-in - any thoughts on how to accommodate this?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.