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
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.