A production-style Employee Management REST API built with FastAPI, SQLModel, Pydantic, dependency injection, CRUD operations, search, filtering, sorting, pagination, Argon2 password hashing, logging, OpenAPI/Swagger, and Docker.
Click to expand
- π Project Overview
- β¨ Features
- ποΈ System Architecture
- π Request Lifecycle
- π Project Structure
- π οΈ Tech Stack
- π Setup & Installation
- π Interactive API Documentation
- π‘ API Endpoints
- π‘οΈ Validation & Error Handling
- π Dependency Injection
- π Password Security
- π³ Docker
- π§ͺ Testing Checklist
- π₯ Project Walkthrough
- πΏ Git & GitHub Workflow
- π Learning Outcomes
- π¨βπ» Author
This project implements a production-style Employee Management REST API using FastAPI and SQLModel.
The API demonstrates common backend engineering patterns including:
- RESTful CRUD operations
- Request and response validation with Pydantic
- SQLModel-based database access
- FastAPI dependency injection
- Search, filtering, sorting, and pagination
- Authentication with Argon2 password hashing
- Centralized exception handling
- Application logging
- Automatic OpenAPI/Swagger documentation
- Docker containerization
The project is structured into separate modules for routes, schemas, models, database access, and security so that each responsibility remains easy to understand and maintain.
- Create employee
- Get all employees
- Get employee by ID
- Update employee with
PUT - Partially update employee with
PATCH - Delete employee
- Search by employee name or email
- Filter by department
- Filter by active/inactive status
- Sort by name or salary
- Ascending/descending order
- Offset/limit pagination
- Combine multiple query parameters
- Pydantic request validation
- Response models
- HTTP status codes
- 404 handling for missing employees
- 409 handling for duplicate users
- 401 handling for invalid login
- Database exception handling
- Logging
- User registration
- Password hashing using Argon2
- Password verification during login
- Dockerfile included
- Docker image build
- Containerized Uvicorn server
flowchart TD
C[π Client / Browser / Postman / Swagger]
subgraph APP[FastAPI Application]
M[main.py]
AR[π Auth Router]
ER[π¨βπΌ Employee Router]
S[π‘οΈ Pydantic Schemas]
D[π get_session Dependency]
SEC[π Argon2 Security]
end
subgraph DATA[Persistence]
ORM[SQLModel]
DB[(SQLite employee.db)]
end
C -->|HTTP Request| M
M --> AR
M --> ER
AR --> S
ER --> S
AR --> SEC
AR --> D
ER --> D
D --> ORM
ORM --> DB
SEC --> DB
Client
β
FastAPI Application
β
APIRouter
β
Pydantic Validation
β
Dependency Injection
β
SQLModel
β
SQLite
β
JSON Response
sequenceDiagram
autonumber
actor Client
participant FastAPI
participant Router as APIRouter
participant Validator as Pydantic
participant DI as Depends(get_session)
participant DB as SQLite
Client->>FastAPI: HTTP Request
FastAPI->>Router: Route request
Router->>Validator: Validate input
alt Invalid input
Validator-->>Client: 422 Validation Error
else Valid input
Validator->>DI: Request DB session
DI->>DB: Open/Yield session
Router->>DB: Execute query
DB-->>Router: Result
Router-->>FastAPI: Response model
FastAPI-->>Client: JSON response
end
employee-mgt-REST_API/
β
βββ app/
β βββ __init__.py
β βββ main.py
β βββ database.py
β β
β βββ models/
β β βββ __init__.py
β β βββ employee_model.py
β β βββ user_model.py
β β
β βββ schemas/
β β βββ auth.py
β β βββ employee_schema.py
β β
β βββ routers/
β β βββ __init__.py
β β βββ employees.py
β β βββ auth.py
β β
β βββ security/
β βββ __init__.py
β βββ security.py
β
βββ Dockerfile
βββ requirements.txt
βββ .env.example
βββ .gitignore
βββ README.md
βββ employee.db # Runtime-generated; should be gitignored
| Layer | Responsibility |
|---|---|
main.py |
Creates FastAPI application and mounts routers |
database.py |
Database engine and session dependency |
models/ |
SQLModel database entities |
schemas/ |
Request and response validation |
routers/ |
API endpoints and route logic |
security/ |
Password hashing and verification |
Dockerfile |
Container image configuration |
| Component | Technology | Purpose |
|---|---|---|
| Language | Python 3.13+ | Application development |
| Framework | FastAPI | REST API framework |
| ORM / Models | SQLModel | Database models and queries |
| Validation | Pydantic v2 | Request/response validation |
| Database | SQLite | Local persistence |
| Password Hashing | pwdlib[argon2] |
Secure password hashing |
| Server | Uvicorn | ASGI application server |
| Containerization | Docker | Reproducible deployment |
| Version Control | Git + GitHub | Source control and project hosting |
| API Documentation | OpenAPI / Swagger / ReDoc | Interactive API documentation |
git clone <YOUR_GITHUB_REPOSITORY_URL>
cd employee-mgt-REST_APIpython3.13 -m venv venv
source venv/bin/activatepython -m venv venv
venv\Scripts\activatepip install --upgrade pip
pip install -r requirements.txtImportant:
pwdlib[argon2]is required because the project uses Argon2 password hashing.
cp .env.example .envExample:
DATABASE_URL=sqlite:///employee.dbuvicorn app.main:app --reload --host 127.0.0.1 --port 8000API:
http://127.0.0.1:8000
FastAPI automatically generates OpenAPI documentation.
| Documentation | URL |
|---|---|
| Swagger UI | http://127.0.0.1:8000/docs |
| ReDoc | http://127.0.0.1:8000/redoc |
| OpenAPI JSON | http://127.0.0.1:8000/openapi.json |
Swagger can be used to send requests directly to the running API.
Base path:
/employee/employees
| Method | Endpoint | Purpose |
|---|---|---|
GET |
/employee/employees/check |
Health/status check |
POST |
/employee/employees/ |
Create employee |
GET |
/employee/employees/ |
List employees |
GET |
/employee/employees/{id} |
Get employee |
PUT |
/employee/employees/{id} |
Full update |
PATCH |
/employee/employees/{id} |
Partial update |
DELETE |
/employee/employees/{id} |
Delete employee |
POST /employee/employees/{
"name": "Vijay Sharma",
"email": "[email protected]",
"department": "Engineering",
"salary": 85000,
"is_active": true
}PATCH /employee/employees/1{
"salary": 92000
}The list endpoint supports multiple query parameters.
GET /employee/employees/
GET /employee/employees/?search=VijaySearch can match employee name or email.
GET /employee/employees/?department=ITGET /employee/employees/?is_active=trueGET /employee/employees/?sort_by=salary&order=descGET /employee/employees/?offset=0&limit=10GET /employee/employees/?offset=10&limit=10The configured limit is capped at a maximum of 50 records per request.
GET /employee/employees/?department=IT&is_active=true&sort_by=salary&order=desc&limit=5&offset=0flowchart LR
A[Employees] --> B[Search]
B --> C[Department Filter]
C --> D[Status Filter]
D --> E[Sort]
E --> F[Pagination]
F --> G[JSON Response]
The authentication subsystem provides user registration and login.
Current implementation note: The existing code currently exposes the authentication routes with the
/auth/...path because the/authprefix is applied at both router and application inclusion levels. The README documents the current behavior rather than hiding it.
| Method | Current Route | Purpose |
|---|---|---|
POST |
/auth/register |
Register user |
POST |
/auth/login |
Authenticate user |
{
"username": "vijay",
"password": "StrongPassword@123"
}Authentication
β
"Who are you?"
β
Username + Password
β
Password Verification
This project demonstrates authentication. It does not currently implement a complete role-based authorization system such as admin/user permissions.
Pydantic validates incoming request data before it reaches the database layer.
Invalid input can result in:
422 Unprocessable Entity
For example, an invalid email format is rejected by the request schema.
A missing employee returns:
404 Not Found
Example:
{
"detail": "999 not found in the records"
}Attempting to register an existing username returns:
409 Conflict
Incorrect credentials return:
401 Unauthorized
Database-related exceptions are handled by the application and logged rather than exposing internal implementation details directly to the client.
The project uses FastAPI dependency injection to provide database sessions to route handlers.
Example:
@router.get("/", response_model=list[EmployeeRead])
def get_employees(
session: Session = Depends(get_session),
search: str | None = None
):
...- Keeps database session creation outside route logic
- Provides a clean session lifecycle
- Reduces duplicated database setup code
- Makes route logic easier to test and maintain
Passwords are not stored as plaintext.
The project uses:
pwdlib[argon2]
flowchart TD
P[Plain Password] --> H[Argon2 Hasher]
H --> DB[(Hashed Password)]
flowchart TD
P[Submitted Password] --> V[Argon2 Verification]
DB[(Stored Hash)] --> V
V -->|Valid| OK[Authenticated]
V -->|Invalid| ERR[401 Unauthorized]
The purpose is to store a password hash rather than the original password.
The API can be packaged and run as a Docker container.
docker build -t employee-management-api .docker run --name employee-api -p 8000:8080 employee-management-apiThis maps:
Host: 8000
β
Docker: 8080
The API is then accessible at:
http://127.0.0.1:8000
docker psdocker logs employee-apidocker stop employee-apidocker rm employee-apiThe following areas were tested during project development.
- Create employee
- Get employee list
- Get employee by ID
- Update employee with
PUT - Partial update with
PATCH - Delete employee
- 404 for non-existent employee
- Search by name
- Search by email
- Filter by department
- Filter by active status
- Sort by salary
- Pagination with offset/limit
- Combined query parameters
- Register user
- Reject duplicate username
- Login with valid password
- Reject incorrect password
- Password stored as Argon2 hash
- Docker image builds
- Container starts successfully
- Uvicorn runs inside container
- Swagger is accessible through mapped host port
- Swagger UI
- ReDoc
- OpenAPI schema
For the project video, demonstrate the project in this order:
Explain:
- What problem the API solves
- Why FastAPI was selected
- Project folder structure
Show:
Client
β
FastAPI
β
APIRouter
β
Pydantic
β
Dependency Injection
β
SQLModel
β
SQLite
Open:
http://127.0.0.1:8000/docs
Demonstrate:
- Create employee
- Get employees
- Get employee by ID
- Update employee
- Patch employee
- Delete employee
- Search
- Filter
- Sort
- Pagination
Demonstrate:
- Register user
- Attempt duplicate registration
- Login with wrong password
- Login with correct password
- Explain Argon2 hashing
Show:
docker build -t employee-management-api .
docker run --name employee-api -p 8000:8080 employee-management-apiThen open Swagger through port 8000.
Recommended workflow:
flowchart LR
A[Code Changes] --> B[git status]
B --> C[git add .]
C --> D[git diff --cached]
D --> E[git commit]
E --> F[git push origin main]
F --> G[GitHub]
git statusgit add .git diff --cachedgit commit -m "Complete employee management REST API"git push origin mainYour .gitignore should exclude:
venv/
.venv/
.env
__pycache__/
*.pyc
*.db
Never commit real passwords, API keys, or other secrets.
This project demonstrates practical understanding of:
- REST API design
- FastAPI routing
APIRouter- Pydantic validation
- Response models
- SQLModel
- SQLite
- Dependency injection
- CRUD operations
- Search and filtering
- Sorting
- Pagination
- Exception handling
- Logging
- Password hashing with Argon2
- Swagger / OpenAPI
- Docker containerization
- Git and GitHub workflow
Vijay Rangvani
Backend & AI Engineering Learner
Built with FastAPI, SQLModel, Python 3.13, SQLite, and Docker.