├── requirements.txt ├── import.csv ├── sample form data 2020-05-02.txt ├── sample request header 2020-05-02.txt ├── readme.md ├── import.py └── sample mint category menu 2020-05-02.txt /requirements.txt: -------------------------------------------------------------------------------- 1 | DateTime==4.3 2 | requests==2.24.0 3 | urllib3==1.25.10 4 | -------------------------------------------------------------------------------- /import.csv: -------------------------------------------------------------------------------- 1 | Transaction Date,Post Date,Description,Category,Type,Amount 2 | 07/22/2018,07/23/2018,NORTH PARK PRODUCE,Groceries,Sale,-1.04 3 | 07/22/2018,07/23/2018,LITTLE SHEEP MONGOLIAN,Food & Drink,Sale,-58.29 4 | -------------------------------------------------------------------------------- /sample form data 2020-05-02.txt: -------------------------------------------------------------------------------- 1 | cashTxnType: on 2 | mtCheckNo: 3 | tagXXXXXXX: 0 4 | tagXXXXXXX: 0 5 | tagXXXXXXX: 0 6 | task: txnadd 7 | txnId: :0 8 | mtType: cash 9 | mtAccount: XXXXXXXX 10 | symbol: 11 | note: 12 | isInvestment: false 13 | catId: 1405 14 | category: Auto Insurance 15 | merchant: test 16 | date: 05/02/2020 17 | amount: 0.01 18 | mtIsExpense: true 19 | mtCashSplitPref: 2 20 | token: XXXXXXX -------------------------------------------------------------------------------- /sample request header 2020-05-02.txt: -------------------------------------------------------------------------------- 1 | :authority: mint.intuit.com 2 | :method: POST 3 | :path: /updateTransaction.xevent 4 | :scheme: https 5 | accept: */* 6 | accept-encoding: gzip, deflate, br 7 | accept-language: en-US,en;q=0.9,la;q=0.8 8 | adrum: isAjax:true 9 | content-length: 323 10 | content-type: application/x-www-form-urlencoded; charset=UTF-8 11 | cookie: XXXXXXX 12 | origin: https://mint.intuit.com 13 | referer: https://mint.intuit.com/transaction.event?accountId=XXXXXXX 14 | sec-fetch-dest: empty 15 | sec-fetch-mode: cors 16 | sec-fetch-site: same-origin 17 | user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36 18 | x-requested-with: XMLHttpRequest -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | For a complete overview of how the Mint CSV Importer was developed check out - https://nathanielkam.com/import-transactions-to-mint-using-python/ 2 | 3 | # Run: 4 | Run the code by typing the following from the directory the code is located in 5 | python3 import.py 6 | 7 | ## Pre-requisites needed: 8 | 9 | csv 10 | datetime 11 | os 12 | random 13 | requests 14 | time 15 | urllib.parse 16 | 17 | Virtual Environment Setup (from app repo root) 18 | 1. Make sure you have venv on your system, using the following command based on your python version 19 | - python3 -m pip3 install virtualenv 20 | 2. Make sure you are in repo root \ 21 | - (where import.py and requirements.txt are) 22 | 3. Create a virtual environment 23 | - virtualenv venv 24 | 4. Turn on the virtual environment (these should work on both but depends on your version you may need to explicitly run the sh or bat file) 25 | - Mac / Linux in terminal or bash: venv/Scripts/activate 26 | - Windows in powershell: venv\Scripts\activate 27 | 5. Install Requirements 28 | - pip3 install -r requirements.txt 29 | 30 | 31 | ## Overview: ## 32 | Simulates bulk manual transaction adds to mint.com. Mint manual transactions are submitted as "cash transactions" which 33 | will mean it shows in your cash / all accounts transaction list. You cannot submit manual transactions against credit 34 | cards or other integrated bank accounts (even in Mint's UI this is not possible and ends up as cash transction). 35 | 36 | ## Approach: ## 37 | Simulating manual transactions from UI is based on Nate H's proof of concept from https://www.youtube.com/watch?v=8AJ3g5JGmdU 38 | 39 | ## Python: ## 40 | Credit to https://github.com/ukjimbow for his work on Mint imports for UK users in https://github.com/ukjimbow/mint-transactions 41 | 42 | ## Process: ## 43 | 1. Import CSV 44 | 2. Process date for correct format and HTTP encode result 45 | 3. Process merchant for HTTP encode 46 | 4. Process categories. Change your banks category name into a mint category ID (limited in scope based on the categories needed when I wrote this) 47 | 6. Process amount for positive or negative value indicating income or expense 48 | 7. Send POST Request to mint as new transaction. 49 | 8. Force Randomized Wait Time before starting next request 50 | 51 | ## Instructions: ## 52 | 1. Prepare your data to import using import.csv as an example 53 | 2. Edit import.py and replace the variables set to XXXXX's to values in your browser during a live Mint session 54 | - account is mtaccount and approximately 8 digits 55 | - tag1 is in form of tagXXXXXXX 56 | - tag2 is in form of tagXXXXXXX 57 | - tag3 is in form of tagXXXXXXX 58 | - cookie will be an apprimately 2000 character string 59 | - referrer is likely always 'https://mint.intuit.com/transaction.event' 60 | - token is approximately 50 characters 61 | 3. If you have custom categories, they need to go along others in function category_id_switch() 62 | -------------------------------------------------------------------------------- /import.py: -------------------------------------------------------------------------------- 1 | """ 2 | ################################# 3 | Pre-requisites needed 4 | ################################# 5 | 6 | If you are missing any of the following you can install with: 7 | 8 | pip install $name 9 | Example: pip install csv 10 | 11 | OR if you are using pip3 12 | 13 | pip3 install $name 14 | Example: pip3 install csv 15 | """ 16 | 17 | import csv 18 | import datetime 19 | import os 20 | import random 21 | import requests 22 | import time 23 | import urllib.parse 24 | 25 | """ 26 | ################################# 27 | Overview: 28 | ################################# 29 | 30 | Simulates bulk manual transaction adds to mint.com. Mint manual transactions are submitted as "cash transactions" which 31 | will mean it shows in your cash / all accounts transaction list. You cannot submit manual transactions against credit 32 | cards or other integrated bank accounts (even in Mint's UI this is not possible and ends up as cash transction). 33 | 34 | Approach Credits: 35 | Simulating manual transactions from UI is based on Nate H's proof of concept from https://www.youtube.com/watch?v=8AJ3g5JGmdU 36 | 37 | Python Credits: 38 | Credit to https://github.com/ukjimbow for his work on Mint imports for UK users in https://github.com/ukjimbow/mint-transactions 39 | 40 | Process Documentation: 41 | 1. Import CSV 42 | 2. Process date for correct format and HTTP encode result 43 | 3. Process merchant for HTTP encode 44 | 4. Process cateogories change your banks category name into a mint category ID (limited in scope based on the categories 45 | 5 needed when I wrote this) 46 | 6. Process amount for positive or negative value indicating income or expense 47 | 7. Send POST Request to mint as new transaction. 48 | 8. Force Randomized Wait Time before starting next request 49 | 50 | Future Development: 51 | 1. Replace curl command string generation with parametized curl class constructor 52 | 2. Add support for the rest of the manual transaction items 53 | 54 | """ 55 | 56 | """ 57 | ################################# 58 | Settings 59 | ################################# 60 | """ 61 | csv_name = 'import.csv' # name of csv you you want import to mint [string.csv] 62 | verbose_output = 1 # should verbose messages be printed [0,1] 63 | uk_to_us = 0 # do you need to change dates from UK to US format [0,1] 64 | min_wait = 0 # min wait time in seconds between requests, int[0-n] 65 | max_wait = 2 # max wait time in seconds between requests, int[0-n] 66 | 67 | """ 68 | ################################# 69 | Mint Client Credentials 70 | ################################# 71 | 72 | You will need the tags, cookie, and token to simulate a UI form submission. You can get these by opening developer tools > network analysis tab and doing 73 | a test submission in mint.com. From there look for the post request to "updateTransaction.xevent" and grab the credentials from the header and body 74 | """ 75 | account = 'XXXXXXX' # grab from POST request form body in devtools 76 | tag1 = 'tagXXXXXX' # in form of tagXXXXXXX 77 | tag2 = 'tagXXXXXXX' # in form of tagXXXXXXX 78 | tag3 = 'tagXXXXXXX' # in form of tagXXXXXXX 79 | cookie = 'XXXXXXX' # grab from POST request header in devtools 80 | referrer = 'XXXXXXX' # grab from POST request header in devtools 81 | token = 'XXXXXXX' # grab from POST request form body in devtools 82 | 83 | """ 84 | ################################# 85 | Import CSV using the pythons csv reader 86 | ################################# 87 | """ 88 | csv_object = csv.reader(open(csv_name,'rU')) 89 | next(csv_object) 90 | 91 | for row in csv_object: 92 | 93 | # Initialize Variables 94 | date = (row[0]) 95 | postDate = (row[1]) 96 | merchant = (row[2]) 97 | catName = (row[3]) 98 | typeID = (row[4]) 99 | amount = (float(row[5])) 100 | expense = 'true' 101 | curl_input = 'Error: Did not Generate' 102 | curl_output = 'Error: Did not run' 103 | 104 | """ 105 | ################################# 106 | Process Date for format and HTTP Encode 107 | ################################# 108 | """ 109 | 110 | # Convert Commonwealth to US Date System 111 | if uk_to_us == 1: # based on setting 112 | dateconv = time.strptime(date,"%d/%m/%Y") # not needed for US to US 113 | date = (time.strftime("%m/%d/%Y",dateconv)) # converted new US date format from UK 114 | 115 | # Require "/" for date delimiter and HTTP Encode Character, supports "/", ".", "-" 116 | # We are not using url encode library here because we custom map other delimiters 117 | dateoutput = date.replace("/", "%2F") 118 | dateoutput = date.replace(".", "%2F") 119 | dateoutput = date.replace("-", "%2F") 120 | 121 | """ 122 | ################################# 123 | Process Merchant with HTTP Encode 124 | ################################# 125 | """ 126 | merchant = urllib.parse.quote(merchant) 127 | 128 | """ 129 | ################################# 130 | Process Categories 131 | ################################# 132 | 133 | Support is limited to the categories I needed at the time, if you need to map more you can. To get category ids: 134 | 1. Go to mint 135 | 2. Add a transactions 136 | 3. Right click "inspect-element" on the category you want 137 | 4. The ID is in the