Managing API Keys

Andy Shi


In this post, I’ll address how I like to store and use my API keys.


When using computer software to access secured resources or services, typically over the internet, the software usually requires an API key. The API key is like a password the software to authenticate itself to the resource or service. As an example, I’m a TA for a data science class where we use Github to manage students’ homework assignments. For each homework assignment, each student gets their own private repository that only they and the course staff can see. In order to create and push those repositories, the script I use, Teacher’s pet needs to authenticate itself to Github, and the way it does so is via an API key.

Bad ways to store API Keys

Technically, API keys should be treated like passwords, because if someone has your API key, they could potentially perform operations without your permission. In the case of the data science TA example, an unauthorized user could delete all the students’ homework repositories. Here are some downsides of some common ways API keys are stored:

Using a password manager for API Keys

A lot of programs allow you to pass in the API key as a command line argument. If you’re writing your own program that requires an API key, make it take the API key as a command line argument instead of hard coding it in—this makes it harder for you to accidentally push the API key to Github. (NB: To parse command line arguments, you can use the optparse for R and argparse for Python). Therefore, you can store your API key in a password manager and copy/paste it when you call your program. The password manager will encrypt the API key so it’s more secure than storing it in an unencrypted file or your bashrc. Additionally, if you’re worried about your bash history being saved (in a plaintext file no less), you can prevent certain entries from being recorded. This Stackoverflow post has solutions for both bash and zsh.

Finally, if you can interface with your password manager on the command line, you can forgo the copy/paste step by passing the output of the password decryption step as a command line argument, using command substitution. Here’s an example using the pass password manager:

my_command --apikey=$(pass show api_key/Github)