A Beginner’s Guide to the Gmail API and Its Documentation
Tags: python, api, beginners
Published: 2019-09-08 21:02:58

A crucial part of programming is the ability to communicate with different Application Programming Interfaces (APIs). If you visit [Google API Explorer](https://cloud.google.com/monitoring/api/apis-explorer), you will find a huge library of APIs, including all of their well-known applications like Gmail, Drive, and Calendar. Simply put, an API allows you to fetch or send data to the services via HTTP requests.

The usage and documentation of these APIs might be a bit tricky at first, but once you learn it, you‘ll be able to apply your knowledge to most Google applications.

I decided to write a beginner’s guide for how to use and understand the Gmail API. The guide is based on the documentation, meaning you’ll learn what to look for and how to read it instead of just copying code. As most of the other Google API references documents are alike, you’ll see that adapting to them is much easier once you know how to actually read the docs. This will allow you to write your own code and actually understand what you’re doing.

Python 3 is used in this guide, but the usage should look quite similar in other languages as well.

## Quickstart

Google usually offers a quickstart guide to make authorization easier. This guide will use the authorization from the quickstart guide, which means it’ll come with some limitations, but it’s sufficient for our purposes. The other way to get the API key is to create a new project, which is a bit trickier.

The Python quickstart guide can be accessed [at this link](https://developers.google.com/gmail/api/quickstart/python), but I’ll follow along and show you how everything is done here.

Here’s what the quickstart looks like:

![](https://cdn-images-1.medium.com/max/2788/1*ZM4CSq5j9b7kNr7ZCnhGwQ.png)

## Turn on the Gmail API

The first step is to enable the API and download the credentials to use in our project. By pressing the “enable the Gmail API”* *button, we open a new window with our credentials.

![](https://cdn-images-1.medium.com/max/2000/1*zdsZCQWFkIXWjdbrq5-DHg.png)

Our Client ID and Client Secret will be shown. Choose the client configuration for download. A file will be saved, called credentials.json. We’ll save this to the same folder our code will be in.

![](https://cdn-images-1.medium.com/max/2000/1*4Ve-ijpUOxE6J1Y9ThepdA.png)

## Installing the Libraries

![](https://cdn-images-1.medium.com/max/2000/1*GPmZbjJSEtQGtw84EdMAcg.png)

Installing the required libraries is done with a simple pip command, provided by Google. I pasted it below as well. I would recommend doing it in a [virtual environment](https://realpython.com/python-virtual-environments-a-primer/). That is, however, not covered in this guide.

    pip install — upgrade google-api-python-client google-auth-httplib2 google-auth-oauthlib

## First Run — Allow Access

Before we continue following the guide, we’ll need to allow access to the Gmail API for our script. Let’s start by making the actual script.

Create a *.py* file in the project directory (same as the directory with credentials.json). For the sake of it, let’s call it gmail.py.

Copy the example code from the Python quickstart to the gmail.py* *file. Ignore the code for now, we’ll dive into that later. We only need to allow access on the first run — it will be saved for all later runs as well.

Just run the file as you normally would, and you’ll be able to sign in to your Google account in the web browser.

    python gmail.py

Login to your account. A warning saying that the app is not verified will be shown. As we are using the quickstart method, our app is not yet verified. Just click the link shown on the picture to continue for now and allow access.

![](https://cdn-images-1.medium.com/max/2000/1*G-MWaFDYhIQ1573iRCGwtg.png)

![](https://cdn-images-1.medium.com/max/2000/1*bS5oC8evV6jqKNFtwnTmvw.png)

![](https://cdn-images-1.medium.com/max/2000/1*2wqor9ubBbVY1eevIOdddQ.png)

## Understanding the Code

The example code may look overwhelming at first, but I’ll divide it into smaller parts to keep it simple. By the end, you’ll see that it actually isn’t that difficult.

### **Import and scopes**

![](https://cdn-images-1.medium.com/max/3332/1*DaHBPVvcjHKHZcCKePZ6ww.png)

As with any other Python script, we’ll start with the imports. Most imports are used for authorization with the credentials.json file. All of these are provided by default so we don’t need to change anything.

Scopes are, however, the most important part. This variable will be modified later, but for now, we’ll settle for the default scope provided.

What this is saying is that it will allow us to access data from the gmail.readonly scope. There are many more scopes, and this allows for a set of actions and requests we can make to the Gmail API. Some other requests require other scopes.

Later on, we will add another scope to use other functionalities.

### **Credentials**

![](https://cdn-images-1.medium.com/max/3332/1*_d1IOUoZlQpTSGrCtJ8hsA.png)

The authorization is probably to the most advanced part of the script. We will not dive too much into that for now, as it’s already configured to work from the box.

This is the part the gets the credentials you downloaded from credentials.json. First, it looks for a token.pickle file. That is the file that is created once you have allowed access to your account the first time. If the file already exists, it gets the credentials from it, meaning you don’t have to allow access several times.

If the token.pickle file doesn’t exist, it loads the credentials from your credentials.json file instead. This requires that you allow access via the web browser, which you did before.

The credentials are, in either case, saved in the creds variable for later use.

### **API**

![](https://cdn-images-1.medium.com/max/3332/1*FGXnbjWbRSYwinAkXhavDg.png)

This is the fun part of the script: The part the fetches the data from the Gmail API. As you can see, it’s actually not that advanced. This is the part that we’ll look deeper into.

The service is built using the earlier imported build function. The credentials that we got earlier are passed as an argument to it.

service is then used to fetch all Gmail labels for the account that was authorized. The data is saved to the results variable.

The last line saves all labels to the labels variable. They are formatted as a list, therefore a default value ( [] ) is specified if the list is empty.

The next part of this guide will look at the documentation to make some sense of this.

### **Result**

![](https://cdn-images-1.medium.com/max/3332/1*l2mDGxSl5GlFyvJ_6pJyeA.png)

At the end, the label names are printed (if there are any).

## Understanding the Documentation

So that was the quickstart example code. However, it doesn’t make much sense without reading the documentation. This part will show you how to actually understand what is written in the code, and how you’ll use the documentation to write your own code.

First, let's go to the “Reference”** **tab to access the docs.

![](https://cdn-images-1.medium.com/max/2000/1*cKX-uX8EnrqbFIhZhJ91Lg.png)

To the left, a large summary menu is shown. It’s full of a lot of information, but it’ll be extremely useful in the upcoming step.

As we’re working with labels, let's choose the Users.labels section, and the Overview part to get some basic information about labels.

![](https://cdn-images-1.medium.com/max/2000/1*L-0XnE0WLYAXeGioiY1vig.png)

We are greeted by this screen:

![](https://cdn-images-1.medium.com/max/2000/1*4bfXKfw7KX1W_GkZJwj3vw.png)

A text saying that that list of methods is at the end of the page, as well as the *resource representations*** **of the label. Information is usually sent as JSON, which is handled like dictionaries in Python.

This is the information that each label we fetch holds. If we scroll down further, we should see a table that provides information about each property in the dictionary.

![](https://cdn-images-1.medium.com/max/2000/1*9YXrKqRLQdCmMyCFkX2Olw.png)

I have highlighted the name part because we’ve used it before. We accessed the name of the label when we printed the labels earlier. Like this:

![](https://cdn-images-1.medium.com/max/3332/1*cSISXp-VSOnfK3I1iI5OdQ.png)

The label is, in this case, a dictionary, and we access the name property within it. We could access any other property that is named above, but for now, name is fine.

It’s important to note that name is a string, but some values might be integers. It’s easy to find in the documentation.

If we continue to scroll down to the bottom of the page, we’ll see all methods. A short description of each method is presented, as well as a hyperlink to the documentation.

![](https://cdn-images-1.medium.com/max/2064/1*9fiTsokRfDRgpO9JpcgEbw.png)

You’ll use different methods depending on what you want to do. The quickstart example uses the list method to fetch all labels on the Gmail account. If we wanted to create a new label, we’d use the create method, which we’ll actually do later.

If we go back up to the top and look at the overview at our left, you’ll see that each method has its own menu button.

![](https://cdn-images-1.medium.com/max/2000/1*-L0nw6sol46cDfw5CfOJhA.png)

### **List Method**

Let’s take a closer look at the list method, which we used before by clicking list on the menu bar.

![](https://cdn-images-1.medium.com/max/2000/1*LNvvhombnBYy1EfrZGvMOQ.png)

This provides a lot of useful information. For starters, an HTTP GET request is sent to the labels URL to fetch all the labels:

    https://www.googleapis.com/gmail/v1/users/userId/labels

We could do this manually using, for example, the requests library in Python. However, we’ll use the provided Google library in this guide.

Authorization is required, but we already took care of that part earlier.

And last, but not least, the parameters we can pass to the list method. As you can see, userId is the only one we can pass.

The userId is a string that represents the user's email address. The value me can be used instead to indicate the authenticated user. We actually used the me value in the example code.

We’ll soon go deeper into this, but first, we’ll read through the other parts of the list method documentation.

### **Authorization and scope**

![](https://cdn-images-1.medium.com/max/2000/1*LtM3AI9S7ROYG7-dFy1yuA.png)

Scopes may sound familiar, that’s because we touched briefly on it earlier. To access the list method, at least one of the provided scopes are required.

As you can see, we have already added the gmail.readonly scope at the top of our code.

![](https://cdn-images-1.medium.com/max/3332/1*QiNaL9tlnQUZGV03vhK3tw.png)

### **Response**

![](https://cdn-images-1.medium.com/max/2000/1*8ScFzWLx1vzS73TBLVkDUg.png)

The last part shows us what a successful request would return: a body in the JSON format. All labels are stored as a list that can be accessed with the labels key. Basically this:

    list_of_labels = response["labels"]

Exactly like you would use a normal dictionary in Python.

## Making the List Request

Let’s look back at the API part of our code now that we have gathered some more information from the documentation.

First, the service is built with our credentials. This is simply the base that is used for making requests (using the methods we previously saw).

![](https://cdn-images-1.medium.com/max/3332/1*X_MsWsepVs5Y51nPLlDqnw.png)

Next, we actually make the request using the list method with this code. It might look a bit more familiar now once we have looked through the docs.

![](https://cdn-images-1.medium.com/max/2856/1*91CEaMVUGVNuAnxWns-pVQ.png)

To easier show you how the syntax is built, I have color-coded the code along with the menu to show you how the API is working.

![](https://cdn-images-1.medium.com/max/2000/1*W_C0IJhZpD8fsUIPOZvQ0Q.png)

![](https://cdn-images-1.medium.com/max/2856/1*yWPFL2hijRc_ms7Wg_vUgw.png)

We start off with the service variable. By simply following the tree-like structure, method by method, we’ll finally get to the list method.

Let’s actually take a closer look at the list method, and especially the familiar userId parameter that has me passed as an argument.

![](https://cdn-images-1.medium.com/max/2856/1*KojfZwqfQdWnNnJEI2yVNw.png)

If we scroll back up to the top of the list method documentation, we’ll see the summary of the parameters that we talked about earlier. The userId parameter is specified, in case we don’t know what it is.

![](https://cdn-images-1.medium.com/max/2000/1*chQYaFuL3HKx57PNTXrOQA.png)

We simply pass it as an argument to the list method in the code.

As you probably recall, the request should return a dictionary, according to the response part of the documentation. We store it in the results variable.

![](https://cdn-images-1.medium.com/max/2000/1*8ScFzWLx1vzS73TBLVkDUg.png)

To access the labels, we use the .get method of the dictionary. The first argument we pass is the name of what we want to get ( labels ), and the second argument is what we get returned if it doesn’t find anything with that name.

![](https://cdn-images-1.medium.com/max/2856/1*1RHuCGcDTHA9hseyiNH-rw.png)

If there is no key called labels, an empty list will be returned.

So that is basically how the documentation is read, and how the list method works. Let’s try to do something else from start by following the API documentation instead.

## Creating a New Label

Let’s use our newfound knowledge and do something new, something from scratch (almost).

Remove all API-related code from your document. Keep only the imports, the scope, and the credential handling. We’ll try to create a new label via the API.

![](https://cdn-images-1.medium.com/max/2000/1*N0qMsmZcIJGvxrZ-z3JaEw.png)

Let’s head to the Overview page of the labels. Scroll down to the methods to see which one we need to use to create our own method.

![](https://cdn-images-1.medium.com/max/2000/1*Wxk5gAfa3DMuE7sNHE_J6g.png)

![](https://cdn-images-1.medium.com/max/2000/1*46D2EVnXysPTradWR9Qonw.png)

You may have noticed that there is a method that is literally called create that we’ll use. Go to the documentation of that method to see what we need.

Let’s start off with the authorization and the scopes.

![](https://cdn-images-1.medium.com/max/2000/1*aUKVTjr-6qcJa56xk3CEdw.png)

As you can see, we require at least one of the three scopes that are present. However, we do not have any one of them in our code. Let’s add the gmail.labels scope.

![](https://cdn-images-1.medium.com/max/2856/1*1nqtecorR_PVjfMnc0j7og.png)

The SCOPES variable takes a list, meaning that we could simply add the new scope with a comma separation.

As the old authorization was stored in the token.pickle file (and that file is used for authorization as long as it exists), we need to remove it and re-create it with our new scope.

Run the Python app again with python gmail.py to re-authorize, however, a minor change can be seen:

![](https://cdn-images-1.medium.com/max/2000/1*ds0-62GI7iv5MqduIsYKyg.png)

A new dependency is added. You might not understand it because of the Swedish language, but it basically says “Handle Labels.” So the new scope added a new dependency to our application.

### The Code

If we look at the top of the create method documentation, we can see that it is quite similar to the list method. It requires authorization, it makes an HTTP POST request and a userId parameter is needed.

![](https://cdn-images-1.medium.com/max/2000/1*lRRp4YiL4av0dNzJ4Gb3RQ.png)

But somehow we need to pass the actual label in our request. If we scroll down to the request body, we’ll see how to do that.

![](https://cdn-images-1.medium.com/max/2000/1*cf-bScqmtyapkFk9qQutyA.png)

In the body of our request, a label with at least the following properties should be present to create a label:

* labelListVisibility

* messageListVisibility

* name

You can learn about which type they should be in, as well as what they are, in the documentation.

Exactly like we received the data in a dictionary, the data should be sent as a dictionary.

### Creating the label

![](https://cdn-images-1.medium.com/max/2856/1*S7NYvPMJnEvrerP45au8RQ.png)

This is a simple function to create a label. It requires a name and two other optional arguments. If they are not specified, show and labelShow will be used as default.

The label is created as a dictionary, and then returned.

![](https://cdn-images-1.medium.com/max/2856/1*ZVo9q8H4Ttqjyw-On-rWWQ.png)

To create a label with the name Test we would use the syntax above.

### Making the request to the API

Time to make the actual request to the API, and pass our label to our Gmail account. Let’s follow the same procedure as last time.

I have color-coded the path to the create method.

![](https://cdn-images-1.medium.com/max/2000/1*ZDrK7YXkrOQEmZ4wnA3Bgg.png)

We are not changing much compared to our last API call. We start with service, which we created before, and add each method until we reach the create method. We are, however, not completely done there.

![](https://cdn-images-1.medium.com/max/2856/1*X4AvizoiMDFJ21bVKDOkIQ.png)

If we scroll to the Parameters** **part of the documentation, we see that we need to pass userId as a parameter, like our last call.

![](https://cdn-images-1.medium.com/max/2000/1*chQYaFuL3HKx57PNTXrOQA.png)

Let’s use me again, like the documentation suggests.

![](https://cdn-images-1.medium.com/max/2856/1*shmtm6JubEoLe8c7SMs0Zg.png)

We’re still missing something: the actual label. We need to somehow pass the label in our request as well. Let’s scroll down to the request body again.

![](https://cdn-images-1.medium.com/max/2000/1*Auhg-AF_hvawmH2T-rte6w.png)

We’ve already created the label with all the required properties, so we need to pass it in the request body. This is done by simply adding another parameter to the create method called body.

Let’s pass our label object in it.

![](https://cdn-images-1.medium.com/max/3044/1*jLcsDZFcRFP6UtyMwhPl2A.png)

The actual call is done, but to add some error checking, let’s wrap it into a try/except statement.

![](https://cdn-images-1.medium.com/max/3044/1*Mr1KQMjm0ltujEAow6eA5g.png)

If something goes wrong, the error message will be printed in our console. If everything goes as planned, Label created will be printed (and the label will be created).

So let’s look back at the parts of the code we created to make the new API request:

![](https://cdn-images-1.medium.com/max/3044/1*csDxXfIBHowGghU2BG-DUw.png)

The API handling is in fact not that difficult. The actual fetching doesn’t require many lines of code — the tricky part is the authorization, which we don’t even need to handle ourselves.

If we save and run the code with python gmail.py, a new label should be created in our Gmail account.

![](https://cdn-images-1.medium.com/max/2000/1*esN51KWw8J7-nkiZJXkhzw.png)

## **Done!**

We successfully made an API call to Gmail from scratch and created our own label. The same basic principle applies to most other methods in the Gmail API, and other Google APIs, as well.

Feel free to try making other requests just to get the hang of it. The best way to learn is to practice. Once you begin to understand the documentation, creating your own calls isn’t that hard.

Try creating your own mail drafts, or fetch all your inbox messages based on a query — everything is specified in the documentation.

I have provided the [full code](https://github.com/banjoanton/gmail-api-guide/blob/master/gmail.py) on GitHub if you want to look at the final results of our example. Good luck with your projects and happy coding!