Beginner’s Guide to FastAPI
FastApi is a contemporary web framework designed for creating RESTful APIs with Python 3.8 or later.

FastAPI was introduced and developed in 2018 by Sebastian Ramirez. It is a contemporary web framework designed for creating RESTful APIs with Python 3.8 or later. It depends on Pydantic for data validation, serialization, and deserialization.
Before FastAPI, several web frameworks were commonly used in Python to develop APIs. Two of the most popular were Flask and Django.
- Flask is known for its simplicity and flexibility. It allows developers to start with a small application and scale up as needed. Flask's simplicity still has its drawbacks as well. As applications expand, they may become more difficult to manage routes, handle complicated data validation, and integrate access and authentication.
- On the other hand, Django is a feature-rich web framework that comes with a number of built-in functionality, including an admin interface, authentication, and an ORM. Its vast capability makes it ideal for rapidly building bigger applications.
FastAPI was created to combine the finest aspects of both worlds in order to overcome these problems. It has many of the strong features of Django with the ease and adaptability of Flask. Using type hints and other contemporary Python capabilities to build a highly performance and user-friendly framework was one of the main driving forces behind the creation of FastAPI.
The asynchronous features of FastAPI are yet another important benefit. FastAPI is made to easily handle asynchronous operations, in contrast to Flask and Django, which are synchronous by default. Because of this, it is perfect for applications that handle several connections at once, such data-intensive APIs or real-time chat programs.
Key Features of FastAPI
FastAPI comes with many features that make development easier and faster for developers. These include high performance, rapid development, reduced bugs, intuitive, standards-based, user-friendly, etc. A detailed explanation is provided below.
- High performance: FastAPI offers performance comparable to NodeJS and Go, largely due to its foundation on Starlette and Pydantic. Which makes it one of the fastest Python frameworks available
- Rapid development: Increases development speed by approximately 200% to 300%
- Reduced bugs: Decreases developer-induced errors by around 40%
- Intuitive: FastAPI provides excellent editor support with comprehensive code completion, resulting in less debugging time
- Standards-based: It is fully compatible with open API standards, including OpenAPI (formerly Swagger) and JSON Schema
- User-friendly: Designed for ease of use and learning, requiring less time to read documentation
Installing FastAPI
To install FastAPI, open your terminal or command prompt and run the following commands.
pip install fastapi
pip install uvicorn
Uvicorn is the server that we will use to test and run our FastAPI applications.
“Ensure you have Python 3.8+ installed on your machine. You can download it from the official Python website.”
Building a Basic Application with a single Route
- Create a New Python File: Let's call it
main.py - Write your first FastAPI code
from fastapi import FastAPI
# Create an instance of the FastAPI class
app = FastAPI()
# Define a root route
@app.get("/")
async def read_root():
return {"message": "hello, world!"}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="127.0.0.1", port=8000)
Explanation :
- Import FastAPI: Import the
FastAPIclass from thefastapimodule - Create an app instance: Instantiate
FastAPI. This instance will be the main point of interaction for our web application - Define a route: Use the
@app.get("/")decorator to define a GET endpoint at the root URL (/). Theasync deffunctionread_rootreturns a simple JSON response - Run the server: If the script is run directly, use
uvicorn.runto start the ASGI server with the app instance
Run Your Application
- To run the application, type the following command in the terminal
uvicorn main:app --reload
This command tells Uvicorn to run the app instance in the main module. The --reload flag enables automatic code reloading.
To access your application, open your browser and go to http://127.0.0.1:8000. You should see the JSON response {"message": "Hello, World!"}

We have been able to build a simple application using FastAPI, now, let’s build another application with multiple routes.
Extending the Application with Multiple Routes
We will add more Routes to main.py. In FastAPI, a route (also known as an endpoint) is a specific path in the URL that the application responds to with a particular function or operation. When a client (such as a web browser or a mobile app) requests a specific route, FastAPI executes the associated function and returns the result to the client.
Routes are defined using decorators in FastAPI, which specify the type of HTTP request (GET, POST, PUT, DELETE, etc.) and the path the request should match.
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def read_root():
return {"message": "Hello, World!"}
@app.get("/items/{item_id}")
async def read_item(item_id: int, q: str = None):
return {"item_id": item_id, "q": q}
@app.post("/items/")
async def create_item(item: dict):
return {"item": item}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="127.0.0.1", port=8000)
Let’s break this down so we have a comprehensive explanation.
New route with path parameter:
@app.get("/items/{item_id}")
async def read_item(item_id: int, q: str = None):
return {"item_id": item_id, "q": q}
- Path parameter: The
item_idparameter is part of the URL path and is defined within curly braces ({}). It must be provided in the URL - Query parameter: The
qparameter is optional and is passed as a query string(?q=value) - Return value: This route returns a JSON object containing the
item_idand the optional query parameterq
New route to handle POST requests:
@app.post("/items/")
async def create_item(item: dict):
return {"item": item}
- Handling POST data: This route accepts a JSON body (sent in a POST request) and expects it to be a dictionary. The body is passed to the item parameter
- Return value: This route returns the received item in a JSON response
Run the Extended Application
Start the server
uvicorn main:app --reload
To access the item route with path and query parameter:http://127.0.0.1:8000/items/42?q=example
You can also use a tool like Postman, Curl, or a similar tool to send a POST request:
curl -X POST "http://127.0.0.1:8000/items/" -H "Content-Type: application/json" -d "{\"name\": \"Item 1\", \"price\": 10.99}"
Based on this basic knowledge, you can continue learning more about fastAPI. In the upcoming section, we'll build a more complex project to reinforce and expand on what you've learned.
Building a CRUD Application
Let's build a simple CRUD (Create, Read, Update, Delete) application using FastAPI. We'll go step-by-step, explaining everything along the way. The application will manage a list of items, each with an ID and a name.
Create a new file called main.py, containing our FastAPI application.
Setting Up Data Storage
For simplicity, we'll store our items in an in-memory list. In a real-world application, you'd likely use a database.
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from typing import List, Optional
app = FastAPI()
class Item(BaseModel):
id: int
name: str
items = []
Explanation:
- We're importing the necessary modules. FastAPI to create the app, HTTPException for error handling, BaseModel from Pydantic to define data models, and List and Optional from typing for type hints
- WApp instance:
app = FastAPI()creates a FastAPI instance - Item model: Initiating the item class, we define the structure of the items with each item having its own id and name
- Data storage: We store the items in an in-memory list
Creating the CRUD Routes
To create the CRUD routes, we must review how to create an item, read an item, update an item, and finally delete an item.
Create Item (POST)
@app.post("/items/", response_model=Item)
async def create_item(item: Item):
if any(existing_item.id == item.id for existing_item in items):
raise HTTPException(status_code=400, detail="Item ID already exists")
items.append(item)
return item
Explanation:
- Route definition:
@app.post("/items/")defines a POST route at/items/ - Request handling: The function
create_itemtakes anItemas input - Duplicate check: To prevent duplicates, check if the item ID already exists
- Append item: If the ID is unique, it returns the item to the list
Read Items (GET)
@app.get("/items/", response_model=List[Item])
async def read_items():
return items
Explanation:
- Route definition:
@app.get("/items/")defines a GET route at/items/ - Response: It simply returns the list of items
- Duplicate check: To prevent duplicates, check if the item ID already exists
- Append item: If the ID is unique, it returns the item to the list
Read Single Item (GET)
@app.get("/items/{item_id}", response_model=Item)
async def read_item(item_id: int):
for item in items:
if item.id == item_id:
return item
raise HTTPException(status_code=404, detail="Item not found")
Explanation:
- Route definition:
@app.get("/items/{item_id}")defines a GET route for a single item - Request handling: The function
read_itemtakes anitem_idas a path parameter - Search item: It searches for the item by ID and returns it if found; otherwise, it raises a 404 error
Update Item (PUT)
@app.put("/items/{item_id}", response_model=Item)
async def update_item(item_id: int, updated_item: Item):
for index, item in enumerate(items):
if item.id == item_id:
items[index] = updated_item
return updated_item
raise HTTPException(status_code=404, detail="Item not found")
Explanation:
- Route definition:
@app.put("/items/{item_id}")
defines a PUT route to update an item - Request handling: The function
update_itemtakes an item_id and a updated_item - Search and update: It searches for the item by ID and updates it if found; otherwise, it raises a 404 error
Delete Item (DELETE)
@app.delete("/items/{item_id}", response_model=Item)
async def delete_item(item_id: int):
for index, item in enumerate(items):
if item.id == item_id:
removed_item = items.pop(index)
return removed_item
raise HTTPException(status_code=404, detail="Item not found")
Explanation:
- Route definition:
@app.delete("/items/{item_id}")defines a DELETE route to remove an item - Request handling: The function
delete_itemtakes anitem_id - Search and delete: It searches for the item by ID and removes it if found; otherwise raises a 404 error
Running the Application
To run the application, use the following command:
uvicorn main:app --reload
Accessing the Routes
- Create item: Send a POST request to
http://127.0.0.1:8000/items/with a JSON body like{"id": 1, "name": "Item1"} - Read items: Send a GET request to
http://127.0.0.1:8000/items/ - Read single item: Send a GET request to
http://127.0.0.1:8000/items/1(replace 1 with the desired item ID) - Update item: Send a PUT request to
http://127.0.0.1:8000/items/1with a JSON body like{"id": 1, "name": "UpdatedItem1"} - Delete an item: Send a DELETE request to
http://127.0.0.1:8000/items/1(replace 1 with the desired item ID)
Conclusion
Finally, FastAPI is a very effective web framework for Python RESTful API development. Now that you have the fundamental knowledge needed to construct a more sophisticated CRUD application from simple apps, you may investigate FastAPI further and use its features to create scalable, effective APIs that meet the demands of different project types.
This GitHub repo contains a list or resources related to FastAPI, you can also check out the FastAPI learning page and the official GitHub.
Shittu Olumide is a software engineer and technical writer passionate about leveraging cutting-edge technologies to craft compelling narratives, with a keen eye for detail and a knack for simplifying complex concepts. You can also find Shittu on Twitter.