On the Internet, there is an incredible amount of information. Many web services, such as YouTube and GitHub, provide an Application Programming Interface (API) that allows Third-Party programs to access their data. The REST Architecture Style is one of the most popular techniques to construct APIs. Python has a number of useful tools for both retrieving data from REST APIs and creating your own Python REST APIs.
In this in-depth article, you will get to know about Python REST APIs, along with the considerations you should have in mind during the process, key modules, and comprehensive examples.
What is REST API?
REST stands for Representational State Transfer, and it’s a Software Architecture style that establishes a paradigm for Client-Server Communication via the Internet. REST is a set of software architecture restrictions that promotes System Performance, Scalability, Simplicity, and Dependability.
The following architectural limitations are defined by REST:
- Stateless: The server will not keep any state between client requests.
- Client-server Architecture: The Client and Server must be divorced from one another so that each can develop independently.
- Cacheable: Data acquired from the Server should be cacheable by either the Client or the Server.
- Standard Interface: Without defining their representation, the server will provide a standard interface for accessing resources.
- Layered System: The client can indirectly access server resources via other layers such as a proxy or load balancer.
- Code on Demand (optional): The server can send executable code to the client, such as JavaScript for a single-page application.
Any Web Service that follows the REST Architecture restrictions is referred to as a REST Web Service. These online services use an API to make their data available to the public. REST APIs allow users to access web service data via public web URLs. Python REST API is one such API.
For example, here’s one of the GitHub REST API’s URLs:
https://api.github.com/users/<username>
You can use this URL to get information on a certain GitHub user. Sending an HTTP request to a specific URL and processing the answer is how you get data from a Python REST API.
Hevo Data, with its robust REST API integration, empowers organizations to seamlessly extract valuable insights from diverse sources. Try Hevo and equip your team to:
- Integrate data from 150+ sources (60+ free sources) and many more with the help of Rest API.
- Utilize drag-and-drop and custom Python script features to transform your data.
- Instantly load and sync your transformed data into your desired destination.
Choose Hevo for a seamless experience and know why Industry leaders like Meesho say- “Bringing in Hevo was a boon.”
Get Started with Hevo for Free
What are HTTP Methods?
To determine which actions to perform on the Web Service’s resources, REST APIs listen for HTTP methods like GET, POST, and DELETE. Any data in the Web Service that can be accessed and altered with HTTP queries to the REST API is referred to as a resource. The HTTP method instructs the API on how to handle the resource.
Although there are numerous HTTP methods, the following five are the most typically used with Python REST APIs:
These five HTTP methods can be used by a Python REST API Client Application to manage the state of resources in the web service.
What are Status Codes?
An HTTP Response is returned by a Python REST API or any API after it receives and executes an HTTP request. An HTTP Status Code is included in this response. This code contains information on the request’s outcomes. The Status can be checked by an application submitting requests to the API, and actions can be taken based on the result. Handling Errors or providing a success message to a user are examples of these actions.
The most frequent status codes returned by Python REST APIs are listed below:
These ten Status Codes are merely a small portion of the total number of HTTP Status Codes accessible. The numbering of Status Codes is based on the category of the result:
When working with Python REST APIs or any APIs, HTTP Status Codes come in handy because you’ll often need to apply various logic depending on the request’s results.
REST Architecture
With REST Architecture comes the elasticity with which professionals implement pagination. REST has a defined set of main (or general) constraints which act vital when developing RESTful APIs. Let’s have a look at them:
- Client-Server: Client and server are independent. Changes to one should not affect the other.
- Stateless: Each request contains all necessary information. Server doesn’t maintain session data.
- Cache: Responses should indicate if and how long data can be cached, improving efficiency.
- Uniform Interface: Consistent interface for client-server communication, allowing independent growth.
- Layered System: System with distinct layers (e.g., models, controllers) for better organization and scalability.
- Code on Demand (Optional): Allows for delivering code over the API (less common due to security and implementation challenges).
What is Python?
Python is a high-level, general-purpose programming language that is interpreted. The use of considerable indentation in its design philosophy emphasizes code readability. Its language elements and object-oriented approach are aimed at assisting programmers in writing clear, logical code for both small and large-scale projects.
Python is garbage-collected and dynamically typed. It supports a variety of programming paradigms, including structured (especially procedural) programming, object-oriented programming, and functional programming. Owing to its extensive standard library, it is often referred to as a “batteries included” language.
How to Consume APIs and Requests
Most Python programmers use requests to send HTTP requests when writing code that interacts with REST APIs which is known as Python REST APIs. The intricacies of making HTTP requests are abstracted away using this Python REST API module. Python REST API is one of the few projects that deserve to be treated as if it belonged in the standard library.
You must first install requests before you can use them. You may install it with pip:
$ python -m pip install requests
You can start sending HTTP requests now that you’ve installed requests.
1) GET
When working with Python REST APIs, one of the most used HTTP methods is GET. You can use this method to get resources from an API. As GET is a read-only method, it should not be used to alter an existing resource.
You’ll use a service named JSONPlaceholder to test out GET and the other methods in this section. This free service generates dummy Python REST API endpoints that return results that can be processed by requests.
To test this, open the Python REPL and run the commands below to submit a GET request to a JSONPlaceholder endpoint:
>>> import requests
>>> api_url = "https://jsonplaceholder.typicode.com/todos/1"
>>> response = requests.get(api_url)
>>> response.json()
{'userId': 1, 'id': 1, 'title': 'delectus aut autem', 'completed': False}
Requests are invoked by this code. use get() to make a GET request to /todos/1, which returns the to-do item with ID 1 as the response. The data returned by the API can then be seen by call.json() on the response object.
JSON, a key-value store comparable to a Python dictionary, is used to format the return data. It’s a widely used data format that most Python REST APIs use as the de facto interchange format.
You can see more information about the answer than just the JSON data from the Python REST API:
>>> response.status_code
200
>>> response.headers["Content-Type"]
'application/json; charset=utf-8'
You may see the HTTP status code by going to response.status code. With response. headers, you may see the HTTP headers of the response. This dictionary stores information about the response, such as the response’s Content-Type.
Integrate REST API to Amazon S3
Integrate REST API to Databricks
Integrate REST API to BigQuery
2) POST
Take a look at how you may build a new resource by using requests to POST data to a Python REST API. You’ll use JSONPlaceholder once more, but this time with JSON data included in the request. Here’s the information you’ll send:
{
"userId": 1,
"title": "Buy milk",
"completed": false
}
A new to-do item is represented by this JSON. To create a new to-do, return to the Python REPL and type the following code:
>>> import requests
>>> api_url = "https://jsonplaceholder.typicode.com/todos"
>>> todo = {"userId": 1, "title": "Buy milk", "completed": False}
>>> response = requests.post(api_url, json=todo)
>>> response.json()
{'userId': 1, 'title': 'Buy milk', 'completed': False, 'id': 201}
>>> response.status_code
201
To add a new to-do in the system, you use requests.post().
To begin, make a dictionary with the data for your to-do. Then you send this dictionary to requests.post() JSON keyword parameter. When you do this, requests.post() sets the HTTP header Content-Type of the request to application/json. It also converts todo into a JSON string, which it adds to the request’s body.
If you don’t use the JSON keyword argument to deliver JSON data, you’ll have to manually define the Content-Type and serialize the JSON. Here’s a replacement for the prior code:
>>> import requests
>>> import json
>>> api_url = "https://jsonplaceholder.typicode.com/todos"
>>> todo = {"userId": 1, "title": "Buy milk", "completed": False}
>>> headers = {"Content-Type":"application/json"}
>>> response = requests.post(api_url, data=json.dumps(todo), headers=headers)
>>> response.json()
{'userId': 1, 'title': 'Buy milk', 'completed': False, 'id': 201}
>>> response.status_code
201
You add a headers dictionary with a single header Content-Type set to application/json in this code. This informs the Python REST API that the request contains JSON data.
Instead of providing to-do to the JSON parameter, you call json.dumps(to-do) to serialize it before using requests.post(). You provide it to the data keyword argument after it’s serialized. The data argument specifies which data should be included in the request. You can also manually set HTTP headers bypassing the headers dictionary to requests.post().
When you use requests.post() like this, you get the same result as before, but you have greater control over the request.
To read the JSON returned by the Python REST API, call response.json(). A created id for the new todo is included in the JSON. A new resource has been created, as shown by the 201 status code.
3) DELETE
Finally, if you wish to totally delete a resource, you can use DELETE. To remove a todo, use the following code:
>>> import requests
>>> api_url = "https://jsonplaceholder.typicode.com/todos/10"
>>> response = requests.delete(api_url)
>>> response.json()
{}
>>> response.status_code
200
Requests are what you name them. Use delete() with an API URL containing the ID of the to-do you want to delete. This sends a DELETE request to the Python REST API, which deletes the resource that matches. The API returns an empty JSON object indicating that the resource has been destroyed after it has been erased.
The requests package is a fantastic tool for working with Python REST APIs and is a must-have in your Python toolbox. You’ll shift gears in the next section and analyze what it takes to create a Python REST API.
4) PUT
Requests support all of the various HTTP methods you’d use with a Python REST API, in addition to GET and POST. The code below makes a PUT request to update an existing todo with new information. Any data submitted with a PUT request will entirely overwrite the todo’s current values.
You’ll use the same JSONPlaceholder endpoint as for GET and POST, but append 10 to the end of the URL this time. This instructs the Python REST API to update the following to-do:
>>> import requests
>>> api_url = "https://jsonplaceholder.typicode.com/todos/10"
>>> response = requests.get(api_url)
>>> response.json()
{'userId': 1, 'id': 10, 'title': 'illo est ... aut', 'completed': True}
>>> todo = {"userId": 1, "title": "Wash car", "completed": True}
>>> response = requests.put(api_url, json=todo)
>>> response.json()
{'userId': 1, 'title': 'Wash car', 'completed': True, 'id': 10}
>>> response.status_code
200
The first thing you do is make a phone call to make a request. To see the contents of an existing to-do, use get(). After that, you make requests. To replace the existing to-do values, use put() with new JSON data. When you call response, you can see the new values with json(). As you are changing an existing resource rather than generating a new one, successful PUT requests always return 200 instead of 201.
5) PATCH
Next, you’ll use requests.patch() to change the value of an existing to-do’s specified field. In contrast, to PUT, PATCH will not totally replace the existing resource. It just changes the values in the JSON that was supplied along with the request. To test requests.patch(), you’ll use the same todo as in the previous example. The current values are as follows:
You can now add a new value to the title:
>>> import requests
>>> api_url = "https://jsonplaceholder.typicode.com/todos/10"
>>> todo = {"title": "Mow lawn"}
>>> response = requests.patch(api_url, json=todo)
>>> response.json()
{'userId': 1, 'id': 10, 'title': 'Mow lawn', 'completed': True}
>>> response.status_code
200
When you use response.json(), you’ll notice that the title has been changed to “Mow lawn”.
How to Build Building REST APIs Using Python?
Python REST API design is a vast subject with several levels. As with most things in technology, there are many different points of view on the best way to develop APIs. This section will go through some suggested procedures to take while developing an API.
1. Choose a Framework
- FastAPI: Modern and high-performance, known for its speed and ease of use.
- Flask: Lightweight and flexible, great for smaller projects and rapid prototyping.
- Django REST Framework: Powerful and feature-rich, suitable for larger projects with more complex requirements.
2. Create a Virtual Environment
python3 -m venv my_venv
source my_venv/bin/activate
3. Install Dependencies
pip install Flask # or Django REST Framework, FastAPI
4. Define Endpoints
The following endpoints are used once the resources in your web service are identified.
HTTP Method | API Endpoint | Description |
GET | /transactions | Get a list of transactions. |
GET | /transactions/<transaction_id> | Get a single transaction. |
POST | /transactions | Create a new transaction. |
PUT | /transactions/<transaction_id> | Update a transaction. |
PATCH | /transactions/<transaction_id> | Partially update a transaction. |
DELETE | /transactions/<transaction_id> | Delete a transaction. |
Next, we have mentioned some examples of endpoints for nested resources. The below-given endpoints are for “guests,” nested under events resources:
HTTP Method | API Endpoint | Description |
GET | /events/<event_id>/guests | Get a list of guests. |
GET | /events/<event_id>/guests/<guest_id> | Get a single guest. |
POST | /events/<event_id>/guests | Create a new guest. |
PUT | /events/<event_id>/guests/<guest_id> | Update a guest. |
PATCH | /events/<event_id>/guests/<guest_id> | Partially update a guest. |
DELETE | /events/<event_id>/guests/<guest_id> | Delete a guest. |
Create a Python file (e.g., app.py
) to define your API routes:
from flask import Flask, jsonify, request
app = Flask(__name__)
# Example: Get a list of users
@app.route('/users', methods=['GET'])
def get_users():
users = [
{'id': 1, 'name': 'Alice'},
{'id': 2, 'name': 'Bob'}
]
return jsonify(users)
# Example: Create a new user
@app.route('/users', methods=['POST'])
def create_user():
data = request.get_json()
# ... (process data and store in database)
return jsonify({'message': 'User created successfully'}), 201
if __name__ == '__main__':
app.run(debug=True)
5. Data Serialization/Deserialization
Use libraries like Marshmallow or Pydantic to:
- Serialize data from Python objects to JSON for API responses.
- Deserialize JSON data from requests into Python objects.
6. Database Integration
Connect to a database (e.g., PostgreSQL, MySQL, MongoDB) using libraries like:
- SQLAlchemy (for relational databases)
- PyMongo (for MongoDB)
7. Error Handling
Implement proper error handling to return informative error messages (e.g., 404 Not Found, 400 Bad Request).
8. Testing
- Write unit tests to ensure your API endpoints function correctly.
- Consider using tools like pytest.
9. Deployment
- Deploy your API to a server (e.g., using Docker, Heroku, AWS).
Example with Flask and a Simple In-Memory Database:
from flask import Flask, jsonify, request
app = Flask(__name__)
users = [
{'id': 1, 'name': 'Alice'},
{'id': 2, 'name': 'Bob'}
]
@app.route('/users', methods=['GET'])
def get_users():
return jsonify(users)
@app.route('/users', methods=['POST'])
def create_user():
user = request.get_json()
user['id'] = len(users) + 1
users.append(user)
return jsonify(user), 201
if __name__ == '__main__':
app.run(debug=True)
How to Handle HTTP Errors With Python Requests?
API calls may not always go as expected, and there are a variety of reasons why API requests may fail, which may be the fault of either the server or the client. To make your code more resilient, if you’re going to utilize a REST API, you must learn how to manage the errors that they report when things go wrong. This section will teach you all you need to know about dealing with HTTP failures using Python Requests.
The Basics of HTTP Status Codes
Before delving into the specifics of Python Requests, we must first understand what HTTP status codes are and how they relate to errors you may encounter.
The status codes are classified into one of five groups.
- 1xx Informational: Request received, client should continue.
- 2xx Successful: Request successful, action accepted.
- 3xx Redirection: Client needs to take further action (e.g., redirect).
- 4xx Client Error: Issue with the client (e.g., invalid request, unauthorized).
- 5xx Server Error: Issue with the server.
How to Check for HTTP Errors With Python Requests?
The status code element of the response objects may be used to check for any issues reported by the API. The following example illustrates how to use this property to check for successful and 404 not found HTTP status codes, although this format may be used for any HTTP status code.
response = requests.get("http://api.open-notify.org/astros.json")
if (response.status_code == 200):
print("The request was a success!")
# Code here will only run if the request is successful
elif (response.status_code == 404:
print("Result not found!")
# Code here will react to failed requests
To test this, remove the final letter from the URL endpoint; the API should return a 404 status code.
If you want Requests to raise an exception for all error codes (4xx and 5xx), use the raise for status() method and catch particular issues with Requests’ built-in exceptions. The next code sample does the same thing as the previous one.
try:
response = requests.get('http://api.open-notify.org/astros.json')
response.raise_for_status()
# Additional code will only run if the request is successful
except requests.exceptions.HTTPError as error:
print(error)
# This code will run if there is a 404 error.
1. TooManyRedirects: The necessity to redirect to a different site for the resource you’re requesting is frequently signaled by 3xx HTTP status codes. This can lead to an endless redirect loop in some cases. To resolve this issue, utilize the TooManyRedirects error in the Python Requests module. To fix this issue, it’s probable that the URL you’re using to access the resource is incorrect and has to be modified.
try:
response = requests.get('http://api.open-notify.org/astros.json')
response.raise_for_status()
# Code here will only run if the request is successful
except requests.exceptions.TooManyRedirects as error:
print(error)
You may specify the maximum number of redirects using the request options:
response = requests.get('http://api.open-notify.org/astros.json', max_redirects=2)
Alternatively, you may deactivate redirecting entirely in your request options:
response = requests.get('http://api.open-notify.org/astros.json', allow_redirects=False)
2. ConnectionError: So far, we’ve only looked at errors generated by a live server. What if you don’t get a response from the server at all? Connection problems can occur for a variety of reasons, including DNS failure, rejected connection, internet connectivity difficulties, or network slowness. When your client is unable to connect to the server, Python Requests throws the ConnectionError exception.
try:
response = requests.get('http://api.open-notify.org/astros.json')
# Code here will only run if the request is successful
except requests.ConnectionError as error:
print(error)
This sort of mistake might be either transitory or permanent. In the first case, you should retry the request to check if the outcome is different. In the latter case, make sure you’re prepared to cope with a protracted inability to obtain data from the API, which may necessitate investigating your own connectivity difficulties.
3. Timeout: Timeout issues occur when you can connect to the API server but it does not finish the request inside the time limit. Python Requests, like the previous problems we’ve looked at, may handle this error using a Timeout exception:
try:
response = requests.get('http://api.open-notify.org/astros.json', timeout=0.00001)
# Code here will only run if the request is successful
except requests.Timeout as error:
print(error)
The timeout, in this case, was set to a fraction of a second using the request parameters. Because most APIs cannot react this rapidly, the code will throw a timeout error. You may avoid this problem by extending your script’s timeouts, optimizing your requests to be smaller, or implementing a retry loop for the request. This can also indicate an issue with the API provider. One last option is to use asynchronous API calls to keep your code from freezing as it waits for bigger answers.
How to Make Robust API Request?
As we’ve seen, the Requests module gracefully handles typical API request problems by leveraging Python’s exception handling. When we combine all of the faults we’ve discussed, we have a rather simple solution to handle any HTTP request error that comes our way:
try:
response = requests.get('http://api.open-notify.org/astros.json', timeout=5)
response.raise_for_status()
# Code here will only run if the request is successful
except requests.exceptions.HTTPError as errh:
print(errh)
except requests.exceptions.ConnectionError as errc:
print(errc)
except requests.exceptions.Timeout as errt:
print(errt)
except requests.exceptions.RequestException as err:
print(err)
Conclusion
This article teaches you about Python REST APIs. It provides in-depth knowledge about the concepts behind every step to help you understand and implement them efficiently. Building a Python REST API connection manually, and using API calls can be challenging especially for a beginner & this is where Hevo saves the day.
Hevo Data provides its users with a simpler platform for integrating data from 150+ Data sources for Analysis. It is a No-code Data Pipeline that can help you combine data from multiple sources. You can use it to transfer data from multiple data sources into your Data Warehouses, Database, or a destination of your choice. It provides you with a consistent and reliable solution to managing data in real-time, ensuring that you always have Analysis-ready data in your desired destination. Sign up for a 14-day free trial to know more.
Share your experience of learning about Python REST APIs! Let us know in the comments section below!
FAQs
1. Can Python be used for REST API?
Yes, Python can be used to build REST APIs with frameworks like Flask, Django REST Framework, and FastAPI.
2. What is the fastest language for REST API?
Languages like Go, Rust, and Node.js are often considered faster for REST APIs due to their performance and low-latency characteristics.
3. Is Python good for building APIs?
Yes, Python is excellent for building APIs due to its simplicity, rich libraries, and frameworks like Flask and FastAPI that make API development quick and efficient.
Harsh is a data enthusiast with over 2.5 years of experience in research analysis and software development. He is passionate about translating complex technical concepts into clear and engaging content. His expertise in data integration and infrastructure shines through his 100+ published articles, helping data practitioners solve challenges related to data engineering.