Last Updated on October 4, 2021
Table of Contents
- What is the IEX API?
- Is the IEX API free?
- Why should I use the IEX API?
- Why shouldn’t I use the IEX API?
- What are some of the alternatives to the IEX API?
- How do I get started with the IEX API?
- Is there a Python library for the IEX API?
- How do I get historical data using the IEX API?
- What is the IEX API testing sandbox?
- What are IEX messages?
- How can I check which companies are reporting earnings today?
- How do I get the latest news from the IEX API?
- What is Investor Exchange data?
- Final Thoughts
What is the IEX API?
The IEX API allows you to quickly access financial data using your favorite programming language. IEX offers a free tier, a paid option, and also a pay as you go model.
This particular API stands out as it is much more comprehensive than other similar products. In addition to accessing historical data, you can get earnings data, news, financial statements, and a whole lot more.
Is the IEX API free?
IEX offers a free tier that utilizes a message system to calculate API rate limits. The message system renews every month, and as long as you can stay within the limits, it is completely free.
Certain data carries a larger ‘weight’ and you will be able to get less of it on the free tier.
In other words, you can still get quite a fair amount of data on the free tier, but the type of data you are after will determine how much of it you can get under the free monthly allowance.
In addition to the free tier, IEX also has paid and pay as you go options.
Paid plans start at $9 per month for individuals and provide a core 5 million messages compared to the 500,000 messages included in the free tier. You can purchase additional messages at a cost of $1 per million messages in this tier.
We will talk a bit more about how the message system works later in this guide.
It should be noted that there are a number of endpoints that cannot be accessed with the free tier.
There are also a few endpoints that are completely free and they do not count towards your message allowance.
» Here are some alternative (mostly) free data sources and guides:
Why should I use the IEX API?
There is a bit of important history when it comes to IEX, those that have read the book Flash Boys by Michael Lewis might be familiar with it.
The book details different methods previously used by high-frequency traders to front-run orders which were shady at best. The Investor Exchange (IEX) was created to remove this unfair advantage.
IEX also solved another big problem by not providing rebates to brokers. This was a common practice several years ago to entice brokers to route their orders to certain exchanges, even if it wasn’t favorable for their customers to do so.
Here are a few other reasons why IEX makes for a good data provider:
- Free – the free tier offers a generous amount of data with unlimited access to Investor Exchange data.
- Extensive Data – IEX has much more variety in the type of data it offers compared to its competitors. So much so that it doesn’t make sense to list their complete offering here. Have a look at their API documentation for a list of the endpoints available.
- Speed – IEX has the option to query multiple symbols at the same time. Not all API data providers offer this and it can result in a major performance upgrade if you are querying several symbols at once. Further, since their limits are messaged based, it’s possible to use asynchronous methods or utilize threading in querying their API.
Why shouldn’t I use the IEX API?
- Complicated rate limits – While it’s great that IEX has such an extensive offering, if you don’t need all the various data they offer, it can complicate things going through their documentation to try and figure out their API. More importantly, the message based rate limit requires calculations for each endpoint to ensure you stay within your desired limits.
- No official library – This might not be a big issue but it’s worth mentioning. While IEX does not have an official library, they have published a list of 3rd party libraries. We will go through some of the pros and cons of using these libraries later in this guide.
What are some of the alternatives to the IEX API?
The IEX API is unique in that the data is coming directly from an exchange. Further, with their extensive offering, it might be difficult to find another provider that offers the same data.
Having said that, several providers offer historical data and a few additional datasets. Alpha Vantage is a good choice as it offers a generous rate limit and its documentation is fairly straight forward. Check out our Alpha Vantage introduction guide for more details.
Worldtradingdata.com is another alternative that offers a free tier with a limit of 250 requests per day.
Polygon.io is also popular although they currently do not offer a free tier. However, you can access the Polygon API for free if you open a live account with Alpaca which is a broker that offers commission-free trading.
How do I get started with the IEX API?
The first step to getting started with the IEX API is to obtain your API keys. We will then store those keys as an environment variable, which is optional but highly recommended. We will then test for a successful connection.
Sign up with IEX to get your API keys
To create an account with IEX, navigate over to https://iexcloud.io/cloud-login#/register and follow the instructions to create an account.
Once you’ve signed up, you will be able to login to the IEX Cloud console. From here, click on API Tokens where you will be able to generate your secret key. This is the key that we will need to pass through when calling the API.
Note the section here that says sandbox testing on the bottom left. This is useful when getting familiar with the API as it allows you to query the API without it counting against your messages. We will discuss this in more detail later in the guide.
Store API keys as environment variables
It a good idea to have your API keys hidden rather than in plain text, visible in your code. The latter presents a security issue and there have been cases where people have uploaded their code to GitHub only to have their keys published to the public.
The best practice is to store your keys as environment variables and then access them from within your Python code. We will show you how to do that in Windows, on a Mac, and in Linux.
Storing your API key as an environment variable on Windows
Click on Start and then type in environment variable, from there click on the second option – Edit environment variables for your account.
A new window will pop up with two boxes. The upper box contains user variables which is what we are after. Click on new directly below the box.
In the new box that pops up, type in IEX_TOKEN as your variable name. The two libraries that we will go through utilize this variable name but if you plan not to use a library, you can use any variable name you want.
In the variable value box type in your API secret key. Remember that you will have to generate this key from within the IEX console, as mentioned earlier in this guide.
import os
print(os.environ.get('IEX_TOKEN'))
You can test to make sure the new variable is accessible within Python using the above code snippet. If it doesn’t work, try restarting your code editor.
Storing your API key as an environment variable on Linux or a Mac
The steps for storing an environment variable on a Linux machine or a Mac are the same. Simply open up your terminal and type in the following.
export IEX_TOKEN=your_key_goes_here
You can then check to make sure the environment variable was saved by typing in:
echo $IEX_TOKEN
If it worked, the terminal should output the value of IEX_TOKEN. You can also open up Python from the terminal and check there to make sure everything is working as shown in the image below.
Check for a valid connection
Now that we have our API keys, we can check to see if we can connect to the IEX Cloud server.
Our first step is to import the OS and Requests libraries.
We will be using Jupyter Notebook for the examples in this guide. If you’d like to follow along, the code snippets are available on GitHub in both Jupyter Notebook format as well as the traditional Python script.
We will use the OS library to access the API key stored in the environment variable and the Requests library to query the API.
import os
import requests
The next step is to store a few things that we will be using a lot into Python variables.
base_url = 'https://cloud.iexapis.com/v1'
sandbox_url = 'https://sandbox.iexapis.com/stable'
token = os.environ.get('IEX_TOKEN')
params = {'token': token}
Here we’ve stored the base URL string. We also grabbed the API key from the environment variable so that we can use it in our Python script.
There are several different libraries that we can use to query the IEX API. The Requests library is a popular one so that is the one we will use. One of the features of this library is that we can pass through parameters into our requests.
Some API’s allow you to pass a lot of variables through as parameters. IEX, however, has set things up a bit differently. It uses different endpoints for different data and the only query parameter that gets passed through is the API key. Here is an example.
We will use the same base URL for all of our queries. The endpoint will change depending on what kind of data we are after. The only query parameter we will use, for the most part, is the API key, or otherwise known as the access token. We have stored the key in a Python dictionary with the variable name params
.
Our next step is to check the status of the IEX API. This is a simple way to check that everything is working and that we can make a connection to the IEX servers at this point.
We can look up the URL for the status endpoint that we need to query in the documentation. In this case, it’s simply /status
.
resp = requests.get(base_url + '/status')
The above code snippet uses the requests library to make a call to the URL we’ve specified. In this case, we’ve specified – https://cloud.iexapis.com/v1/status which is the base URL plus the /status
endpoint.
The returned response from the IEX server will be saved in the resp variable.
If we print out the resp variable, it should show us a response code of 200 which confirms that the call was successful. We can also view the response by utilizing the json()
function which is built into the requests library.
If you received a response code other then 200, check to make sure the URL is correct. Otherwise, if you’ve received an exception at this point, make sure the requests library is properly imported and that your syntax is correct.
Is there a Python library for the IEX API?
While there isn’t an official Python library for the IEX API, there are several that have been created to make the API easier to interact with. IEX has recommended three of them and we will briefly discuss some of the pros and cons of the libraries they’ve recommended.
The decision to use a library comes down to personal preference and is dependent on what data you are after.
One of the recommended libraries is FinMesh. It offers the added capability of querying data from the US treasury, US Federal Reserve economic data, as well as the SEC EDGAR system. It also had built-in Pandas support which can simplify and streamline processing data.
The two other libraries that are recommended are iexfinance and pyEX. Both also offer additional capabilities such as the automatic creation of a Pandas DataFrame. PyEX takes it one step further with enhancements such as a Zipline integration as well as an integration with TA-lib to quickly and automatically perform technical analysis on returned data.
All three libraries can also automatically grab your API token from the environment variable that we created earlier on in this tutorial. With the added functionality that these libraries bring, you’ll be able to accomplish a lot with just a few lines of code.
At this time, the iexfinance library seems to be a bit the most popular on GitHub. For this reason, we recommend checking out the iexfinance library. With more people using it and contributing to it, there are better chances bugs will be spotted and fixed quicker in this library.
A big disadvantage of using a library is that you might spend a lot of time getting familiar with it. If you decide at a later date to change data providers you’ll be back at square one.
As an example, pyEX makes it easy to check for correlations, it only takes one line of code. But if you use a more generic library such as Pandas, you’ll still be able to access correlations with one line of code.
The added benefit is that you’re not committed to IEX as a data provider and can easily migrate to a different provider at a later date if you decide to do so without completely rewriting your code.
There are several generic and native libraries you can use to access the IEX API. The popular ones include requests, http.client, and unirest.
How do I get historical data using the IEX API?
There are a few different endpoints that can be used to obtain historical data. The popular ones are the historical data endpoint and the intraday endpoint. If you’re looking for hourly or minute data, the latter is the one to go with.
We will go through an example that pulls historical data for Apple’s daily stock price.
The first step is to look at the documentation for the historical prices endpoint.
As you can see in the image above, the documentation gives us the exact structure that we need to make a query. We simply attach this to our base URL and pass in our API token in our request.
If at any time you find the documentation unclear, keep in mind that several examples are provided that show how the URL should be structured. This is usually found near the bottom of the paragraph for the particular endpoint you are looking at.
Building on our previous example, we’ve already imported our libraries and created variables for our API token and commonly used endpoints.
resp = requests.get(base_url+'stock/AAPL/chart'+'?token=YOUR-TOKEN-HERE')
At this point, we can simply use the above code snippet to query for our historical Apple data.
But this is not a very ‘Pythonic’ way of doing things. Let’s clean up our code a bit. Recall that we already saved our token as a dictionary to the variable params
.
resp = requests.get(base_url+'stock/AAPL/chart', params=params)
In our previous example, we printed out the resp variable to make sure that we had an HTTP response of 200 which indicates that the call was made successfully.
You can also print out the HTTP response by printing resp.status_code
and then checking to see if that produces an integer of 200 before proceeding further.
We can also raise an exception if the request was not successful. We do this simply by using the following code after making our request.
resp.raise_for_status()
This is a built-in function of the requests library. The advantage of this method is that we can log the exception if desired and we can also stop our code from proceeding if the data call was not valid.
This is what your result should look like:
At this point, we can easily convert our response into a Pandas DataFrame. Here is the code to do so:
import pandas as pd
df = pd.DataFrame(resp.json())
And this is what your output should look like:
A Pandas DataFrame makes it easy to do things like calculate a moving average, plot a chart, or calculate a correlation coefficient.
Note that the data returned contains a close price and a uClose price. The close price is adjusted for splits and that is the one you will want to use.
If you plan to use this same endpoint a few times, it makes sense to create a function to avoid repeating code. Here is an example:
def historical_data(_symbol, _range=None, _date=None):
endpoint = f'{base_url}/stock/{_symbol}/chart'
if _range:
endpoint += f'/{_range}'
elif _date:
endpoint += f'/date/{_date}'
resp = requests.get(endpoint, params=params)
resp.raise_for_status()
return pd.DataFrame(resp.json())
Recall that the historical prices endpoint also had the option to use a range
or date
parameter. Our function has included this and will modify the endpoint accordingly if one of those parameters is passed in.
We’ve also added in some code that will automatically convert and return the response in a Pandas DataFrame.
If we want to retrieve the last 3 months of AAPL daily price data using our new function, we can simply use this one line of code:
appl_3m_df = historical_data('AAPL', _range='3m')
And this is what your output should look like:
We can just as easily pass in a date parameter like this:
appl_april_20_df = historical_data('AAPL', _date=20200420)
The interesting thing about the above code is that you would expect it to return all data since April 20, 2020. But rather, it returns minute data for that specific date.
IEX has noted in their documentation that this particular endpoint may face some changes in the future. We suspect the functionality of the date endpoint is likely to change when this happens to make it more consistent.
What is the IEX API testing sandbox?
When you’re getting to know an API you’re bound to do some testing which involves several calls to the API. You don’t want this to eat into your message allowance and a good way to get around that is to use the sandbox.
The sandbox essentially acts the same as the normal API except that it throws out sample data. It’s a good idea to use the sandbox while you’re testing and working out bugs in your code.
There are three steps to use it. First, change the option in the IEX console. This is the same place where you obtained your API keys. There is a slider option towards the bottom left, turn the sandbox on from here.
The second step is to generate a new API key for the sandbox environment. This is done in the same way you generated your key for the live environment.
The last step is to switch out your base URL to the sandbox URL. Recall when we initially started writing out code, we created a variable for both? Switching them out is as easy as changing our code like this.
Original code:
resp = requests.get(base_url+'/stock/AAPL/chart', params=params)
Sandbox code:
resp = requests.get(sandbox_url+'/stock/AAPL/chart', params=sandbox_params)
We’ve substituted the base URL for the sandbox URL that we created earlier on. We also need to create a new params dictionary that contains the sandbox API token. You can do so like this:
sandbox_params = {'token': 'your_sandbox_api_token'}
Once again, it is recommended to save your token as an environment variable. There is less of a risk with the sandbox token as it doesn’t produce real data. Nevertheless, it is a good idea to safeguard it.
What are IEX messages?
We’ve gone through using the sandbox environment to cut down on message usage during testing. At this point, you may be wondering, what are IEX messages?
Every API will try to limit usage, especially when it comes to free tiers. There are server and other costs to consider after all.
Most API’s will do this by setting a hard limit. It might be 10 requests per minute for example or 500 requests per day.
IEX has taken a different approach and weighs each endpoint differently. To determine how much an endpoint is worth, they’ve indicated how many “messages” you will use to access it.
Free accounts will start with 500,000 messages each month. Every time you access an endpoint, the appropriate number of messages will be deducted from your message allowance.
The documentation will let you know how many messages are required for each endpoint. The image below, as an example, shows the message requirements for hitting the historical prices endpoint.
From here, we can make estimates as to how many requests we can make to keep within a message “budget”.
You can also see for this particular endpoint that we can save a lot of messages by requesting only adjusted close data. This costs only 2 messages versus the 10 messages to get both adjusted and unadjusted data.
IEX offers a helpful message calculator that can help estimate how many messages it will take to query certain endpoints.
The above image shows that we can get stock quotes updated every second for 10 tickers and still stay within the base plan which offers 5 million messages for $9 per month.
How can I check which companies are reporting earnings today?
Earnings data can cause big swings in volatility and it’s a good idea to be aware of which companies are reporting earnings, especially if it is a company that you actively trade.
We can use the earnings today endpoint to get a list of upcoming earnings reports for the day ahead. Here is the code:
endpoint = '/stock/market/today-earnings'
resp = requests.get(base_url+endpoint, params=params)
This will return a list of all the companies that are reporting before the market open, during the day, and after the bell.
The only thing to keep in mind with this method is that it uses 1000 messages for each symbol returned. In earnings season, you’re going to have a lot of companies reporting which can weigh on your message allowance.
How do I get the latest news from the IEX API?
You can get news from 3,000 different media outlets using the IEX API. You can even get historical news dating back to January 2019. This could be useful if you’re trying to do sentiment analysis.
The news endpoint returns the last 50 results by default. Here is an example of how to access it:
endpoint = '/stock/TSLA/news'
resp = requests.get(base_url+endpoint, params=params)
You may have noticed a pattern at this point. We are essentially using the same code and just swapping out the endpoint.
In this case, we included a ticker symbol in the endpoint to specify that we are looking for news related to Tesla.
This is what your output should look like:
We can change the results by passing in different parameters. For example, if we used this endpoint –
endpoint = '/stock/TSLA/news/last/5'
This will return just the last 5 news items related to Tesla. The good thing about this endpoint is that each news item takes only 1 message.
What is Investor Exchange data?
Since IEX is an exchange, it offers several endpoints for data related to trades conducted on it.
The best part of this is that these endpoints are free of charge as they are not counted towards your message allowance. You do still need an API token to access them.
For the most part, these endpoints are split into two parts. There is DEEP data and TOPS data.
DEEP is a more in-depth view of the order book while TOPS offers top of the book data.
There are several endpoints available for Investor Exchange data, we will take a look at the last
endpoint.
This is a lightweight endpoint that returns the last price an asset has traded at, the number of shares that were exchanged as well as the time the transaction was conducted.
This endpoint is slightly different from the previous examples that we’ve gone through. It uses a unique endpoint but it also requires you to pass through your ticker symbols as a query parameter.
Let’s go through the code step by step.
First, we will make a copy of our params dictionary and call it payload.
payload = params.copy()
This way we can make changes to the query parameters but still have our original params dictionary remain intact in case we need to use it later.
We can now create a new dictionary item. The dictionary key for this will be symbols
. We can add several ticker symbols here, just make sure to separate them by a comma.
payload['symbols'] = 'TSLA, NFLX'
And that’s basically it. The last step is to make a request like we normally do. We have modified the endpoint and will use the new payload dictionary.
resp = requests.get(base_url+'/tops/last', params=payload)
Your results should look something like this:
Final Thoughts
The IEX API offers a lot of data and can even be useful to those that already have an existing data provider as it can fill some of the gaps. The message system may seem tricky at first, but once you’ve established a routine in your API calls it should not be much of a problem.
There are several third-party libraries available but considering that most of the IEX endpoints follow a similar structure, the API can easily be accessed by a generic library such as requests.
Most of our examples used the same format –
endpoint = 'endpoint_goes_here'
resp = requests.get(base_url+endpoint, params=params)
resp.raise_for_status()
resp.json()
You should be able to continue using this template to access most of the endpoints in the IEX API. There are some exceptions that use a query string. In that case, you can either pass in the query string in the endpoint or modify your params dictionary and pass it through there.
There is a lot of data that the IEX API can offer. We strongly recommend looking at their documentation so that you can get a better idea of what is available.