HOLIDAY SALE! Save 50% on Membership with code HOLIDAY50. Save 15% on Mentorship with code HOLIDAY15.

7) APIs and Databases Lesson

REST API Integration with Python requests Package

23 min to complete · By Martin Breuss

Intro to APIs with Python

You've probably heard about APIs before you knew you needed to or even wanted to! Luckily we are about to uncrack the mysterious code of APIs and find out how we can use the Python skills we have acquired thus far to interact with the vast network of APIs.

Once you know the components of RESTful API request and responses as learned in the API section, Python makes those interactions quite straight-forward.

In this section we will take a look at how starting with a few lines of code:

# python

import requests

base_url = "http://demo.codingnomads.co:8080/tasks_api/users"
request = requests.get(base_url)

We can start to interact with some of the most powerful applications around the world.

Python requests package

In this section, we will be using one of the most common API packages, the requests package. 

Installing the requests package

For this project, either create a new project with a new virtual or make sure you are in a project with an activated virtual environment. Once the virtual environment is activate we can install the requests package:

pip install requests

Note: There is no problem with installing this package to your computer, however, for easy removal, we will use a virtual environment.

What is the requests package?

The requests package allows you to send HTTP compliant requests using simple Python. It also allows you to easily access response data and work with information that is returned.

Video: The requests package

Making a GET Request

GET Requests are for reading data from the server/API. (Much like a SELECT query is for reading data from a database.)

We will start by taking a look at the most simple RESTful request, the GET request. We will be using an API provided by yours truly, The CodingNomads Team. The first endpoint we will be looking at is: [http://demo.codingnomads.co:8080/tasks_api/users](http://demo.codingnomads.co:8080/tasks_api/users) (go ahead and click that link). If you remember, when you visit a page in a web browser, you are making a GET request. 

Note: We highly recommend installing a browser extension such as JSON Formatter (or the equivalent for your preferred browser) so that you see the JSON in a nice, formatted view rather than just a big blob of confusing text.

Copy and paste the link in a new tab and check out what it returns. JSON! This is a response to the request you made. It should look something like this:

{  
    "data": [  
        {  
            "id": 1,  
            "first_name": "Demo 1",  
            "last_name": "User 1",  
            "email": "[email protected]",  
            "created_at": 1549131644000,  
            "updated_at": 1549131644000  
        },  
        {  
            "id": 2,  
            "first_name": "Demo 2",  
            "last_name": "User 2",  
            "email": "[email protected]",
            "created_at": 1549131677000,  
            "updated_at": 1549131677000  
        }  
    ],  
    "error":  {  
         "message": "none"  
    },  
    "status": "200 OK"  
}

Now how can we do this in Python?

We first need to import the requests package in our program. We can then use the get() function. In order to verify our request, we will print out the status code of the response:

You should see a status code of 200. If not, there is something wrong.

Now, change the base_url to something incorrect. For example, we will use the path variable /developers instead of /users: [http://demo.codingnomads.co:8080/tasks_api/developers](http://demo.codingnomads.co:8080/tasks_api/developers). You should now get a status code of 404. We get this status code (404 Not Found) because the API does not have a /developers endpoint.

In the next section, we will take a look at what else makes up the response.

Video: Making a GET Request

Query Parameters

Query parameters can be passed as a part of the URL or as a param argument with the URL. Query parameters are used to filter and/or narrow-down the request you're making. Similar to the way a WHERE clause filters the data you get back from a SQL query.

A question mark (?) always indicates the start of the query parameter list. The query parameters are Key-Value pairs. For instance, in the example in the REPL below the key is "email" and the value is "[email protected]". Many API endpoints support multiple query params. Query params are delimited by the "&" symbol. For instance:

http://demo.codingnomads.co:8080/tasks_api/tasks?userId=1&complete=true

In the example above we are passing two query parameters, userId and complete. The query params list starts with a question mark, and the query params are separated by the & symbol. If you pop that URL in the example above into your web browser URL bar and hit ENTER you'll see the response we get back in JSON.

Using requests, we can attach the query params in two ways. Either in the URL itself or as a key-value pair that we pass into the request. The following two examples are functionally equivalent:

import requests

response = requests.get("http://demo.codingnomads.co:8080/tasks_api/[email protected]")
print(response.status_code)

# is the same as 

params = {
    "email": "[email protected]"
}

response = requests.get("http://demo.codingnomads.co:8080/tasks_api/users", params=params)
print(response.status_code)

Video: Query Parameters

Response Formats: JSON and XML

When working with RESTful APIs, or interfacing with them, we will encounter one of three possible formats: JSON, HTML or XML. When information is returned to a user, this is often given in HTML. However, when we are programmatically requesting data from an API for further processing, we will mostly encounter JSON, sometimes also XML.

Let's take a look at these common formats that you should get familiar with when working with APIs.

JSON

"JSON (JavaScript Object Notation) is a lightweight data-interchange format. It is easy for humans to read and write. It is easy for machines to parse and generate. It is based on a subset of the JavaScript Programming Language. JSON is a text format that is completely language independent but uses conventions that are familiar to programmers of the C-family of languages, including C, C++, C#, Java, JavaScript, Perl, Python, and many others. These properties make JSON an ideal data-interchange language."

All of JSON is neatly explained in a one-pager here: https://www.json.org.

Here's a look at an example JSON object:

{
    "first_name" : "Joseph",
    "last_name" : "Gemarsten",
    "email" : "[email protected]"
}

This JSON would map directly to the follow User class in Java:

public class User {
    String first_name;
    String last_name;
    String email;
} 

Or this class in Python:

class User:
    def __init__(first_name, last_name, email):
        self.first_name = first_name
        self.last_name = last_name
        self.email = email

The JSON below shows a collection of User objects (notice the square brackets (which indicate "collection" or "array")

{ 
    "users" : 
	[ 
	    {
	        "first_name" : "Joseph",
		    "last_name" : "Gemarsten",
		    "email" : "[email protected]"
	    }, 
	    {
		    "first_name" : "Daniel",
		    "last_name" : "Gemarsten",
		    "email" : "[email protected]"
	    }, 
	    {
	    	"first_name" : "Lillian",
		    "last_name" : "Gemarsten",
		    "email" : "[email protected]"
	    } 
	]
}

Which would map to following Java class:

public class JsonExample {
	// User being the class created just above
    User[] users;
} 

JSON is just a collection of key-value pairs that can map directly to or from Python/Java/JS Object.

Python's in-built json package is straightforward to use and allows serializing, parsing, and File I/O for JSON: https://docs.python.org/3.6/library/json.html

XML

XML stands for eXtensible Markup Language and has a longer history than JSON. It bears close resemblance to HTML, but is (as the name implies) more extensible than HTML, as well as stricter typed. XML is older and used much less often these days.

Working with XML in python can be more clunky than using JSON, therefore if you have the choice it is typically recommended to use JSON. However, sometimes XML it is, and a useful package to work with this is python's ElementTree: https://docs.python.org/3/library/xml.etree.elementtree.html

Here is the same example as above (the single User) in XML:

<user>
    <first_name>Carson</first_name>
    <last_name>Boston</last_name>
    <email>[email protected]</email>
</user>

And here is a collection of Users in XML:

<users>
	<user>
	    <first_name>Carson</first_name>
	    <last_name>Boston</last_name>
	    <email>[email protected]</email>
	</user>
	<user>
	    <first_name>Shelby</first_name>
	    <last_name>Seattle</last_name>
	    <email>[email protected]</email>
	</user>
	<user>
	    <first_name>Wyatt</first_name>
	    <last_name>Wyoming</last_name>
	    <email>[email protected]</email>
	</user>
</users> 

HTTP Responses

As we have seen, when we make an API request, we get a response. The response is made up of several pieces. We will take a look at the most important ones.

The Content

The content is the meat of the response. It is where the data belongs. On the previous page, when we made a request in our browser, it was the content that was shown on the page.

The Headers

The response headers contain information about the response such as the type of content in the response, the date and time of the response and the encoding. This information varies based on what the API includes in its response.

Other

A response can also include the encoding, the URL, the origin and many other pieces of information.

import requests

base_url = "http://demo.codingnomads.co:8080/tasks_api/users"
response = requests.get(base_url)

print(f"Response Content: {response.content}")
print(f"Response Status Code: {response.status_code}")
print(f"Response Headers: {response.headers}")
print(f"Response Encoding: {response.encoding}")
print(f"Response URL: {response.url}")

Video: HTTP Responses

Working with JSON

Now that we have looked what a response is made up of, we can look at how to work with that information in our python programs.

Python Objects from JSON

Remember, JSON is simply an agreed-upon text format. On the previous page, we looked at how to print out the response content. In raw JSON format, the information in the string is not very accessible.

Luckily, Python makes it really easy to convert JSON to Python datatypes such as dictionaries and lists.

The JSON method

Using the JSON method included in the requests package, we can convert the content of the response to a Python dictionary and access the data. The .json() method turns the JSON response into the appropriate python object. In this example, we are using the pprint package which allows us to print data structures in a readable way.

import requests
from pprint import pprint

base_url = "http://demo.codingnomads.co:8080/tasks_api/users"
response = requests.get(base_url)

data = response.json()
pprint(data)

#what happens if you print data['data'][0]['first_name']
#why is this?

The result of line 8 is the creation of a dictionary. Play around with the dictionary data. How can you access the values of the dictionary?

Video: Working with JSON

Make a POST Request

While all HTTP requests receive a response, not all requests can send data. Unlike a GET request, which we have seen is used to retrieve information, POST requests can send data to the server. To make a POST request we will use the .post() method.

To pass information in a POST request, we can use the json parameter. Using the same API as before, we are now going to create a new user by sending the user information in the body of the POST request. For example:

import requests

base_url = "http://demo.codingnomads.co:8080/tasks_api/users"

body = {
    "first_name": "[YOUR FIRST NAME FIELD]",#add first name inside quotes
    "last_name": "[YOUR LAST NAME FIELD]",#add last name inside quotes
    "email": "[YOUR EMAIL FIELD]"#add email inside quotes
}

response = requests.post(base_url, json=body)

Video: Make a POST Request

Make a PUT Request

Making a PUT request is very similar to a POST request. PUT requests are also used to send information to the server. As you might have guessed, you will instead be using the put() method.

For this particular API, you also need to specify a user id as a path variable in order to update the user record.

Replace YOUR_ID on line 12 with your user id.

import requests

base_url = "http://demo.codingnomads.co:8080/tasks_api/users"

body = {
    "first_name": "[YOUR UPDATED FIELD]",
    "last_name": "[YOUR UPDATED FIELD]",
    "email": "[YOUR EMAIL]"
}

# here we execute the PUT request
response = requests.put(base_url + "/YOUR_ID", json=body)
# print the status code (hopefully it's 200 which means all is well)
print(f"Response Code: {response.status_code}")

# let's make a GET request to retrieve the new data from the server
response = requests.get(base_url)
# print the data - see your updated record?
print(f"Response Content: {response.content}")

Video: Making a PUT Request

Colorful illustration of a light bulb

Info: This video shows a PUT request being submitted with the resource ID in the body of the request. However, the API has since been updated to require the ID param to be placed in the request URL instead. For example: http://demo.codingnomads.co:8080/tasks_api/users/{id} This also means that the resource ID is now optional in the body of the request:

body = { 
"first_name":"first", 
"last_name":"last", 
"email":"[email protected]" 
} 

Make a DELETE Request

The DELETE request is also capable of sending information to the server like a POST or PUT request. To make a DELETE request to the API you have been working on, you do not need to send any information in the body of the request.

As with PUT, you can specify the user you want to delete by utilizing path variables. For example, to delete the user with id 50 you will add the id to the URL as a path variable:

import requests

base_url = "http://demo.codingnomads.co:8080/tasks_api/users"
response = requests.delete(base_url + "/50")
print(response.status_code)

Video: Making a DELETE Request

Exploring the API Docs

We have now seen how to make GET, POST, PUT and DELETE requests. The API we have been using is set up for you to explore. All the examples we have looked at only use the users endpoint. Take a look at the documentation of this API and explore it by creating new tasks and users, updating existing records and removing records. The documentation can be found here.

Summary: REST API Integration with Python

REST APIs are extremely common. Knowing how to integrate your Python application with the wide world of REST APIs increases your reach and ability to build really interesting and data-rich applications.

In this tutorial you have learned how to fully integrate your Python application with a modern REST API. You have learned how to make the followed HTTP requests:

  • GET request
  • POST requests
  • PUT requests
  • DELETE requests

JSON is the prefered data format for more modern REST APIs. Though you still see XML around from time to time.

Using the json() method provided by the requests library is very useful to quickly format the HTTP response body.