Skip to main content

Project Overview

In this project, we’ll build a simple Employee Management System. To keep the focus on FastAPI concepts, we’ll store data in Python lists instead of a database. By completing this project, you’ll learn how to build a real REST API using FastAPI.

What You’ll Build

Our application manages two resources:
  • Employees
  • Departments
Each employee belongs to one department. Example:

APIs We’ll Build

Employee APIs

Department APIs

Later we’ll enhance the Employee API with filtering. Example:

Concepts We’ll Learn

During this project we’ll gradually introduce:
  • APIRouter
  • Dependency Injection
  • Request Models
  • Response Models
  • Request Body Validation
  • Path Parameter Validation
  • Query Parameter Validation
  • Exception Handling
  • HTTP Status Codes
Don’t worry if some of these terms are unfamiliar—we’ll learn them step by step.

Project Structure

Development Plan

We’ll build the project one feature at a time. At every step:
  • Read the task.
  • Try it yourself.
  • Test it in Swagger UI.
  • Open the solution only if needed.
By the end of this project, you’ll have built a complete Employee Management API using only FastAPI fundamentals.

Step 2 - Create the Models

Task

Before writing any APIs, define the data our application will manage. Based on the project requirements, create models for the following resources. Try implementing them yourself before opening the solution.

Employee Structure

Example

Department Structure

Example

Models to Create

Before opening the solution, think about this:
Should the client send the employee id while creating a new employee?
If your answer is No, which model should contain the id field?

Solution

Employee Request Model

Used while creating or updating an employee. Notice that the client does not send the employee ID.

Employee Business Model

Represents an employee inside the application.

Employee Response Model

Returned to the client.

Department Request Model

Used while creating or updating a department.

Department Business Model

Represents a department inside the application.

Department Response Model

Returned to the client.

Model Flow

Why Three Models?

For example, when creating an employee, the client sends:
The application stores it as:
Finally, the API returns:
Notice that the client never sends the id. It is generated by the application.

Key Takeaways

  • Use Request Models to validate client input.
  • Use Business Models to represent data inside the application.
  • Use Response Models to control API responses.
  • Separating models keeps the application clean and makes it easier to evolve as requirements change.

Step 3 - Create the In-Memory Database

Task

Before implementing the APIs, we need a place to store our data. Instead of using a real database, we’ll use Python lists as an in-memory database. This allows us to focus on learning FastAPI without worrying about database configuration. Later, we can replace these lists with a real database without changing the API design.

Data Structure

We’ll maintain two collections:
  • EMPLOYEES – Stores employee records.
  • DEPARTMENTS – Stores department records.
The employee’s department_id should refer to an existing department.

Sample Data

Create a file named data.py.

Data to Store

Departments

Create the following department objects.

Employees

Create the following employee objects. Using these values, create two Python lists:
  • DEPARTMENTS
  • EMPLOYEES
Each list should contain objects of the appropriate business model (Department and Employee). Try creating the lists yourself before viewing the solution.

Sample Data

Create a file named data.py.

Step 4 - Create the Routers

Task

Create separate routers for managing employees and departments. Instead of placing every endpoint inside main.py, we’ll organize related endpoints into separate files. This approach makes the application easier to read, maintain, and extend. By the end of this step, your project structure should look like this:

Router Responsibilities

Each router is responsible for a single resource.

Create the Employee Router

Create a file named routers/employees.py. Try creating the router yourself before viewing the solution.

Create the Department Router

Create a file named routers/departments.py. Try creating the router yourself before viewing the solution.

Register the Routers

Now connect both routers to the FastAPI application. Open main.py and register them. Try implementing it before viewing the solution.

Understanding APIRouter

The router is created using:

prefix

The prefix is automatically added to every endpoint inside the router. For example,
becomes
Similarly,
becomes

tags

The tags parameter groups related endpoints together in the Swagger UI. Instead of displaying all APIs in one long list, Swagger organizes them into sections.

What We’ve Accomplished

At this stage:
  • The application is modular.
  • Employee APIs have their own router.
  • Department APIs have their own router.
  • Both routers are registered with the FastAPI application.
  • Swagger will automatically organize the endpoints by resource.
The routers are currently empty. In the next step, we’ll implement our first API:
using Dependency Injection to retrieve employee data.

Step 5 - Implement the Get All Employees API

Task

Implement an API to retrieve all employees. Requirements
  • Method: GET
  • URL: /employees
  • Use Depends(get_employee_data)
  • Return all employees
  • Use list[EmployeeResponse] as the response model
Try implementing the endpoint before viewing the solution.

Test

Expected Result
  • Status Code: 200 OK
  • Returns all employees.

Step 6 - Implement the Get Employee by ID API

Task

Implement an API to retrieve a single employee using the employee ID. Requirements
  • Method: GET
  • URL: /employees/{emp_id}
  • Use Depends(get_employee_data)
  • Use Path() validation
  • Return EmployeeResponse
  • Return 404 Not Found if the employee does not exist
Try implementing the endpoint before viewing the solution.

Test

Step 7 - Implement the Create Employee API

Task

Implement an API to add a new employee. Requirements
  • Method: POST
  • URL: /employees
  • Accept EmployeeRequest as the request body
  • Use Depends(get_employee_data)
  • Generate the next employee ID automatically
  • Return the newly created employee
  • Use EmployeeResponse as the response model
  • Return 201 Created
Try implementing the endpoint before viewing the solution.

Test

Sample Request

Sample Response

Step 8 - Implement the Update Employee API

Task

Implement an API to update an existing employee. Requirements
  • Method: PUT
  • URL: /employees/{emp_id}
  • Accept EmployeeRequest as the request body
  • Use Path() validation
  • Use Depends(get_employee_data)
  • Return the updated employee
  • Return 404 Not Found if the employee does not exist
Try implementing the endpoint before viewing the solution.

Test

Sample Request

Sample Response

Step 9 - Implement the Delete Employee API

Task

Implement an API to delete an existing employee. Requirements
  • Method: DELETE
  • URL: /employees/{emp_id}
  • Use Path() validation
  • Use Depends(get_employee_data)
  • Delete the employee if found
  • Return 204 No Content
  • Return 404 Not Found if the employee does not exist
Try implementing the endpoint before viewing the solution.

Test

Sample Request

Expected Response

Step 10 - Filter Employees by Department

Task

Enhance the Get All Employees API to optionally filter employees by department. Requirements
  • Method: GET
  • URL: /employees
  • Accept an optional department_id query parameter
  • Use Query() validation
  • Return all employees if no department is specified
  • Return only matching employees if department_id is provided
Try implementing the endpoint before viewing the solution.

Test

Sample Requests

Step 11 - Search Employees by Name

Task

Enhance the Get All Employees API to search employees by name. Requirements
  • Method: GET
  • URL: /employees
  • Accept an optional name query parameter
  • Use Query() validation
  • Perform a case-insensitive search
  • Return all employees if no name is specified
Try implementing the endpoint before viewing the solution.

Test

Sample Requests

Step 12 - Filter Employees by Minimum Age

Task

Enhance the Get All Employees API to filter employees based on a minimum age. Requirements
  • Method: GET
  • URL: /employees
  • Accept an optional min_age query parameter
  • Use Query() validation
  • Return employees whose age is greater than or equal to the specified age
  • Return all employees if min_age is not specified
Try implementing the endpoint before viewing the solution.

Test

Sample Requests

Step 13 - Add Pagination and Sorting

Task

Enhance the Get All Employees API to support pagination and sorting. Requirements
  • Method: GET
  • URL: /employees
  • Accept skip query parameter
  • Accept limit query parameter
  • Accept sort query parameter
  • Sort by either name or salary
  • Return the requested page of employees
Try implementing the endpoint before viewing the solution.

Test

Sample Requests

Step 15 - Implement the Department APIs

Task

Implement the Department APIs using the concepts you’ve learned in the Employee module. The implementation should follow the same approach.
  • Use APIRouter
  • Use Depends()
  • Use DepartmentRequest
  • Use DepartmentResponse
  • Use Path() validation
  • Use HTTPException
  • Return appropriate HTTP status codes

APIs to Implement

Try implementing all the APIs before viewing the solution.

Test