A lightweight, educational REST API project demonstrating fundamental API development concepts with interactive Swagger documentation. Perfect for learning REST principles, API design, and documentation best practices.
- Node.js (v14 or higher)
- npm or yarn
-
Clone and navigate:
cd node-swagger-api-beginner -
Install dependencies:
npm install
-
Start development server:
npm run dev
-
Access the API:
- API Base URL: http://localhost:3000
- API Documentation: http://localhost:3000/api-docs
- API Home: http://localhost:3000
This project serves as an excellent entry point for learning:
- REST API fundamentals
- Express.js framework basics
- OpenAPI/Swagger documentation
- Request/response handling
- Error handling patterns
- Route organization
- Controller-based architecture
node-swagger-api-beginner/
├── controllers/
│ └── usersController.js # User management logic (CRUD)
├── routes/
│ └── users.js # User routes with Swagger docs
├── swagger.js # Swagger configuration & setup
├── server.js # Express app & server startup
├── package.json # Dependencies & scripts
└── README.md # This file
Routes (routes/users.js)
↓
Controllers (controllers/usersController.js)
↓
Data Layer (In-memory users array)
GET /api/users
↓
Route Handler (routes/users.js)
↓
Controller Method (getUsers in usersController.js)
↓
Return Response to Client
GET /api/users
Response (200 OK):
[
{
"id": 1,
"name": "adwoa",
"email": "adwoa@example.com"
},
{
"id": 2,
"name": "Kojo",
"email": "kojo@example.com"
}
]GET /api/users/:id
Path Parameter:
id(required) - User ID (integer)
Response (200 OK):
{
"id": 1,
"name": "adwoa",
"email": "adwoa@example.com"
}Response (404 Not Found):
{
"message": "User not found"
}POST /api/users
Content-Type: application/json
Request Body:
{
"name": "John Doe",
"email": "john@example.com"
}Response (201 Created):
{
"message": "User created successfully",
"data": {
"id": 3,
"name": "John Doe",
"email": "john@example.com"
}
}Response (400 Bad Request):
{
"message": "Name and email are required"
}PUT /api/users/:id
Content-Type: application/json
Path Parameter:
id(required) - User ID to update
Request Body:
{
"name": "Updated Name",
"email": "updated@example.com"
}Response (200 OK):
{
"message": "User updated successfully",
"data": {
"id": 1,
"name": "Updated Name",
"email": "updated@example.com"
}
}Response (404 Not Found):
{
"message": "User not found"
}DELETE /api/users/:id
Path Parameter:
id(required) - User ID to delete
Response (200 OK):
{
"message": "User deleted successfully"
}Response (404 Not Found):
{
"message": "User not found"
}Main Express application setup and server initialization.
Key Points:
- Creates Express app instance
- Configures middleware (JSON parser)
- Mounts routes
- Sets up Swagger documentation
- Listens on port 3000
const express = require("express");
const swaggerUi = require("swagger-ui-express");
const swaggerSpec = require("./swagger");
const userRoutes = require("./routes/users");
const app = express();
app.use(express.json());
app.use("/api/users", userRoutes);
app.use("/api-docs", swaggerUi.serve, swaggerUi.setup(swaggerSpec));
app.listen(3000, () => {
console.info(`Server is running on port 3000`);
});Route definitions with embedded Swagger documentation.
Key Points:
- Defines REST endpoints
- Includes JSDoc Swagger annotations
- Calls appropriate controller methods
- RESTful endpoint naming conventions
Swagger Comments:
- Used to auto-generate API documentation
- Describes what each endpoint does
- Documents request/response formats
- Specifies HTTP status codes
Business logic for user operations.
Key Operations:
- getUsers() - Returns all users
- getUserById() - Find user by ID
- createUser() - Add new user with validation
- updateUser() - Modify existing user
- deleteUser() - Remove user from collection
Key Features:
- Input validation
- Error handling with appropriate HTTP status codes
- Consistent response formats
Swagger/OpenAPI configuration and specifications.
Defines:
- API title and description
- API version
- Base path
- Available endpoints
- Contact information
Get all users:
curl http://localhost:3000/api/usersGet user by ID:
curl http://localhost:3000/api/users/1Create new user:
curl -X POST http://localhost:3000/api/users \
-H "Content-Type: application/json" \
-d '{"name":"Jane Doe","email":"jane@example.com"}'Update user:
curl -X PUT http://localhost:3000/api/users/1 \
-H "Content-Type: application/json" \
-d '{"name":"Jane Updated","email":"jane.updated@example.com"}'Delete user:
curl -X DELETE http://localhost:3000/api/users/1- Import endpoints from Swagger documentation
- Test each endpoint with different parameters
- Verify response codes and formats
- Try error cases (missing fields, invalid IDs)
- Navigate to http://localhost:3000/api-docs
- Use the interactive "Try it out" button
- Send requests directly from documentation
- See responses in real-time
- GET - Retrieve resources
- POST - Create resources
- PUT - Update resources
- DELETE - Remove resources
- Proper HTTP status codes (200, 201, 404, 400)
if (!name || !email) {
return res.status(400).json({
message: "Name and email are required"
});
}const user = users.find((user) => user.id === id);
if (!user) {
return res.status(404).json({
message: "User not found"
});
}- Structured JSON responses
- Meaningful status codes
- Descriptive error messages
- Data encapsulation
- Self-documenting code with Swagger JSDoc
- Auto-generated interactive documentation
- Reduces documentation maintenance
-
Client sends request:
POST /api/users Content-Type: application/json { "name": "Alice", "email": "alice@example.com" } -
Express receives request → Parses JSON body
-
Route handler → Calls controller
-
Controller validates → Checks for required fields
-
Controller creates → Generates ID, adds to array
-
Controller responds → Returns 201 with new user data
-
Client receives → User object with assigned ID
Enhance email validation using regex or validator library
Replace in-memory storage with file-based storage (JSON file)
Implement limit/offset pagination for Get All Users
Filter users by name or email in Get All endpoint
Connect to real database (SQLite, PostgreSQL)
Add JWT token authentication to protected endpoints
Implement rate limiting to prevent API abuse
Add logging middleware to track requests
# Start server (production mode)
npm start
# Start server with auto-reload (development)
npm run dev
# Run tests (configured but not yet implemented)
npm test| Package | Version | Purpose |
|---|---|---|
| express | ^5.2.1 | Web framework for Node.js |
| swagger-jsdoc | ^6.2.8 | Convert JSDoc to Swagger/OpenAPI |
| swagger-ui-express | ^5.0.1 | Serve Swagger UI in Express |
| nodemon | ^3.1.14 | Auto-restart server on file changes |
Solution: Change PORT in server.js or kill process on port 3000
Solution: Ensure swagger.js is properly configured and mounted
Solution: Check Content-Type header is application/json
Solution: This is expected - data is in-memory only. Use production-api for persistence.
- Clone the project
- Run
npm install - Start server with
npm run dev - Open http://localhost:3000/api-docs
- Test each endpoint in Swagger UI
- Review route definitions in
routes/users.js - Study controller logic in
controllers/usersController.js - Try adding a new endpoint
- Modify Swagger documentation
- Test with different request bodies
After mastering this project:
- Explore the Production API - See advanced patterns
- Add Database - Replace in-memory storage
- Implement Authentication - Add JWT tokens
- Add Middleware - Error handling, logging
- Deploy - Push to Heroku or similar
| Code | Meaning | When Used |
|---|---|---|
| 200 | OK | Successful GET, PUT, DELETE |
| 201 | Created | Successful POST |
| 400 | Bad Request | Missing required fields |
| 404 | Not Found | User doesn't exist |
| 500 | Server Error | Unhandled errors |
- Use Swagger UI to understand the API before coding
- Always validate input before processing
- Return consistent response formats
- Use appropriate HTTP status codes
- Keep controllers focused on business logic
- Keep routes focused on routing
ISC
Happy Learning!
Start with this project to understand REST fundamentals, then move to production-api for real-world patterns.