Transitioning from TDAmeritrade and tda-api

Note: If you are reading this and you are not a former tda-api user, please see Getting Started.

As of May 13th, 2024, the underlying API that powered tda-api is no longer working. All former tda-api users must now transition to this schwab-py. Fortunately, this library was heavy modeled on tda-api, and so most users will find it a relatively smooth transition. However, there are some important differences. This page will explain them and provide guidance for adjusting.

You must create a new app

TDAmeritrade developer apps created for use with tda-api are not valid for use with schwab-py. In order to use the new library, you must create a new app by following the instructions outlined in Getting Started. Note a few important differences:

Application approval is no longer instant. New apps must be approved by Schwab, and from the outside this process appears to be manual. Once you create your app, you can expect to linger in the “Approved - Pending” state for multiple days. Until your app status changes to “Ready For Use,” you cannot do anything. If you encounter any issues, please check this first before you ask for help on our Discord server.

localhost cannot be used as a callback URL. You can still use your local machine, but you must enter 127.0.0.1 instead.

Old tokens are invalid. Once you create your first app, you cannot re-use your old that worked under tda-api. You must delete that one and create a new one.

Tokens lifetimes are much shorter

When you create a token using tda-api, you had up to ninety days before it would expire and require replacing. What’s more, tda-api implemented a mechanism by which tokens could be refreshed beyond ninety days, meaning for most users tokens were effectively eternal.

This is no longer the case. Schwab’s documentation indicates that tokens are valid for only seven days, after which they must be deleted and regenerated using the login flow described above. There appears to be no equivalent mechanism to the one that allowed for indefinite token use.

If your code works during trading hours, we recommend making a habit of pre-emptively cycling your token on Sunday before the market opens so that you aren’t surprised by an invalid token on Monday morning.

It’s important to underscore: this is a constraint imposed and enforced by Schwab. The library authors have no control over this. Please do not pollute our Discord server with requests to extend token lifecycles.

Some endpoints are gone forever

While most endpoints are have been carried over from the old API, some endpoints were not. In particular, saved orders and watchlists are not provided by Schwab. If did not export your saved orders and watchlists from TDAmeritrade before May 10th, we’re sorry, but we’re pretty sure your data is gone. You’re welcome to contact Schwab to confirm this.

Again, this is not a choice by the library authors. Please do not go to our Discord server asking to recover your data or add this functionality.

Options symbols are formatted differently

Options symbols on Schwab use a different format than they did on TDAmeritrade. Code that manipulates them may need to be updated. schwab-py provides a helper class to make parsing and generating options symbols easier.

Equity index symbols are different

TDAmeritrade used equity index symbols that ended in .X. For instance, the symbol for the S&P 500 index used to be $SPX.X. Now, these indices are referred to without that suffix, so S&P 500 is just $SPX.

schwab-py only supports python 3.10 and up

schwab-py depends heavily on async/await syntax and libraries for both its functionality and development harnesses. The python ecosystem has been migrating from older, less elegant implementations of these concepts for years. At the time of tda-api’s writing (early 2020), support for these features was still being evolving, and so the library was written with many concessions to the older style in mind.

Fast forward to 2024, and the python ecosystem has pretty much fully transitioned to the async/await style. Since schwab-py is a brand-new library with no legacy users, the authors decided to shed all the old code and write it only modern style and libraries. This broke support for versions of python older than 3.10.

If you attempt to pip install schwab-py on a python installation older than 3.10, you will be greeted with something to the effect of Could not find a version that satisfies the requirement schwab-py. You must install a newer version of python before you can use schwab-py. We recommend using pyenv to manage your python installations.

Note further that this library will periodically shed support for obsolete versions of python, as outlined on this page.