Checking Your Daily Spending via SMS with Python, Plaid and Twilio

Spending summaries via text message.

Your bank may let you set up SMS alerts for various triggers. It might even give you the option of receiving periodic spending summaries via SMS (mine doesn’t though!). But what about a daily SMS summary of your spending across all your accounts? This summary is harder to come by, but thankfully you can roll your own by combining Plaid, an easy to use financial services API and Twilio SMS with a bit of Python 3. Let’s get going!

Setting Up

We’ll begin creating our app by lining up some of the basic building blocks. Here’s all the code in one place for those following at home and want to save some typing.

Start by nabbing a sandbox account from Plaid and putting your credentials into PLAID_CLIENT_ID, PLAID_SECRET, PLAID_PUBLIC_KEY environment variables. While you’re at it, ask for access the development API (it’ll take a few days to get approved). For now, though, create an environment variable named PLAID_ENV and set it to ‘sandbox’.  This will give us some sample data to work with.

Next, clone the quickstart for Plaid, install from requirements.txt using the pip install -r requirements.txt command then edit the server.py code to include those environment variables.

Run server.py with the python server.py command (unfortunately this part of the example code only works with Python 2 😦) and open http://127.0.0.1:5000 in your browser.

Screenshot 2017-05-31 23.07.00.png

Click “open link”, then log into Chase with the test credentials (“user_good” and “pass_good” as of 5/26/2017) and the application will print an access token to your terminal window. 

Screenshot_2017-05-31_23_28_28.png

Screenshot_2017-05-31_23_08_16.png

Grab the token and put it into a CHASE_ACCESS_TOKEN environment variable. Repeat this for Bank of America and put that access token into BOFA_ACCESS_TOKEN:

Grab your Twilio credentials from the Console (sign up for a free account if you don’t already have one), a Twilio phone number and your own phone number, then add those as environment variables.

Finally, install a couple of project dependencies:

With the basic building blocks in place we can start coding our app.

Obtaining Transactions

A quick way to start working with Plaid is to grab some account transactions and explore the result.  Make a new file called get_some_transactions.py.  In that file create a plaid.Client instance and a new function named get_some_transactions which accepts an access token and the start and end dates of the range of transactions you want to get. Inside the function, call the Plaid client’s Transactions.get function with those parameters. The following code will accomplish these steps.

With that code in place we can start exploring what information Plaid returns. In the same script, call get_some_transactions by adding the following two lines to the end of the file. These pass in the Chase access token and a wide date range.

Run the script using the python get_some_transactions.py command.

When run this code outputs there are 338 total transactions between those dates.  How many transactions were returned from our Plaid API call?

Apparently, get some_transactions returned 100 transactions.  Why only 100?  It seems that’s the default value for count, an optional parameter for Transactions.get, as seen here in the Plaid API documentation.

What sort of data are in a transaction?

This code outputs dict_keys(['account_id', 'account_owner', 'amount', 'category', 'category_id', 'date', 'location', 'name', 'payment_meta', 'pending', 'pending_transaction_id', 'transaction_id', 'transaction_type']).  For our purposes, amount seems to be all we need, but what about category?  We’re not building a full-fledged budget bot, but are there any transactions that would muddy the waters of our spending summary?

This code gives us {'Food and Drink', 'Travel', 'Transfer', 'Airlines and Aviation Services', 'Payment', 'Credit Card', 'Coffee Shop', 'Fast Food', 'Restaurants', 'Deposit'}.  This will be useful to create a choosier get_some_transactions function.  For example, “Transfer” transactions I would argue don’t belong in our daily summaries, since they don’t qualify as spending. Before we refactor, though, let’s see what sort of accounts we’re dealing with, and whether there are any we should exclude.

Leaving out the less relevant fields, this execution results in:

There’s some low-hanging fruit here too: with any luck, we won’t be spending out of our savings or investment accounts — at worst, we’d be doing transfers — so let’s get refactoring!

Getting the Right Transactions

We know we want to exclude transactions with a category of “Transfer”.  “Credit Card”, “Payment” and “Deposit” aren’t going to be useful in gleaning spending activity either, so we’ll refactor our get_some_transactions function to skip transactions with those categories.  As stated earlier, we also want to skip accounts with a subtype of “savings” or “cd”.

While we’re at it, let’s also make sure to get all available transactions by using pagination, not just those default first 100, and hone in on just the transactions item, not any others. Modify get_some_transactions.py with the following code (which can also be found in get_some_transactions.py on GitHub).

Execute the code and it says that there are 265 transactions. Are any of them negative?

Several are, in fact, negative:

Okay, that seems legit- airfare refund, I guess. All the transactions with negative amounts are similar to this, so let’s keep them in.

Pulling It All Together

Now let’s get all the transactions from yesterday, making sure to pull them from both accounts.  Create a new file named get_yesterdays.py and add this code:

As of 5/26/2017, the most recent transactions available in these sandbox accounts are from 5/16/17: Hence, the hardcoded yesterday value above.
Let’s send an SMS to ourselves with the total spent yesterday!  Create another new file named send_summary.py and add this code to it:

Run the code using the python get_send_summary.py command and voila!


Wrapping It Up

We’ve now created an app that aggregates all spending across disparate credit and bank accounts, then pushes that total spend to our phone.  Here’s all the code in one place.  To deploy it, you could create a cron job somewhere to run it every day at a certain time, and never again have to deal with separate alerts/summaries from each spending account.

But that’s just the tip of the iceberg of what you could build with this spending data. I don’t know about you, but having built this proof of concept makes me want a bot that tracks my spending, pinging me to categorize items it can’t categorize itself.  Spreadsheets are a blast and all, but do I need the unpaid part-time job of maintaining one?  Ditto for the existing web apps.

A simpler extension of this app would be to set it up for your grandma and see if you can build a meaningful voice interaction into it.

Put your ideas and questions in the comments below!

  • Brendan Reese

    Great article and Twilio use case. My favorite: “Spreadsheets are a blast and all, but do I need the unpaid part-time job of maintaining one.”

  • Looks like you have “smart quotes” in the snippet :

    pprint(some_transactions[‘transactions’][0].keys())

    • Darn smart quotes… it should be fixed now in the post. Thanks for the heads up Martin.

      Send me an email makai@twilio.com so we can ship you a Twilio t-shirt for your help?