A comprehensive RESTful API for managing appointment bookings between clients and service providers with real-time WebSocket notifications.
- Features
- Tech Stack
- Prerequisites
- Installation
- Configuration
- Database Setup
- Running the Application
- API Documentation
- Project Structure
- Available Scripts
- Testing
- WebSocket Integration
- API Endpoints Overview
- Error Handling
- Security
- Contributing
- License
- User Authentication & Authorization - JWT-based authentication with role-based access control (client/provider)
- User Management - Complete profile management for clients and providers
- Provider Management - Service provider profiles with specializations and descriptions
- Time Slot Management - CRUD operations for provider availability scheduling
- Appointment Booking - Seamless appointment booking with automatic time slot management
- Appointment Management - View, cancel, and complete appointments with proper authorization
- Real-Time Notifications - WebSocket-based instant notifications for all appointment events
- RESTful API Design - Clean and consistent API structure
- Interactive API Documentation - Swagger/OpenAPI documentation with try-it-out feature
- Database Transactions - Ensures data consistency for critical operations
- Input Validation - Comprehensive request validation using Joi
- Error Handling - Structured error responses with meaningful messages
- Logging - Winston-based logging for debugging and monitoring
- Security - Helmet.js, CORS, password hashing with bcrypt
- Database Seeding - Sample data for quick testing and development
- Runtime: Node.js v18+
- Framework: Express.js v5.2
- Database: PostgreSQL v12+
- Authentication: JWT (jsonwebtoken)
- Real-Time: Socket.io v4.8
- Validation: Joi v18
- Password Hashing: bcryptjs v3
- Documentation: Swagger (swagger-jsdoc, swagger-ui-express)
- Testing: Jest v30 + Supertest
- Process Manager: Nodemon
- Logging: Winston v3
- Security: Helmet.js, CORS
Before you begin, ensure you have the following installed:
- Node.js v18.0.0 or higher (Download)
- PostgreSQL v12.0 or higher (Download)
- npm v8.0.0 or higher (comes with Node.js)
- Git (optional, for version control)
You can verify your installations:
node --version # Should show v18.0.0 or higher
npm --version # Should show v8.0.0 or higher
psql --version # Should show PostgreSQL 12 or highergit clone <repository-url>
cd appointment-booking-apinpm installThis will install all required packages including:
- Express.js and middleware
- PostgreSQL client
- Socket.io for WebSocket
- JWT for authentication
- Joi for validation
- Swagger for documentation
- Winston for logging
- And more...
Create a .env file in the root directory with the following configuration:
# Server Configuration
PORT=3000
NODE_ENV=development
# Database Configuration
# You can provide a single connection string via DATABASE_URL, or provide the DB_* variables.
# Example DATABASE_URL: postgres://user:password@localhost:5432/appointment_system
DATABASE_URL=
DB_HOST=localhost
DB_PORT=5432
DB_NAME=appointment_system
DB_USER=postgres
DB_PASSWORD=your_secure_password
DB_SSL=false
# JWT Configuration
JWT_SECRET=your_super_secret_jwt_key_here_change_in_production
JWT_EXPIRES_IN=24h
# Password Hashing
HASH_SALT=10| Variable | Description | Default | Required |
|---|---|---|---|
PORT |
Server port | 3000 | No |
NODE_ENV |
Environment (development/production/test) | development | No |
DB_HOST |
PostgreSQL host address | localhost | Yes |
DB_PORT |
PostgreSQL port | 5432 | Yes |
DB_NAME |
Database name | appointment_system | Yes |
DB_USER |
Database username | postgres | Yes |
DB_PASSWORD |
Database password | - | Yes |
JWT_SECRET |
Secret key for JWT signing | - | Yes |
JWT_EXPIRES_IN |
JWT token expiration time | 24h | Yes |
DATABASE_URL |
Postgres connection string (optional) | - | No* |
DB_SSL |
Enable SSL for DB in production (true) | false | No |
.env file to version control. Always use strong, unique values for JWT_SECRET and DB_PASSWORD in production.
# Connect to PostgreSQL
psql -U postgres
# Create the database
CREATE DATABASE appointment_system;
# Exit psql
\qAlternatively, use the command line:
createdb -U postgres appointment_systemThe application automatically creates the following tables on first run:
Tables Created:
users- User accounts (clients and providers)service_providers- Provider profiles with specializationstime_slots- Available time slots for appointmentsappointments- Appointment bookings
Note: The database schema is managed by the application. You don't need to run SQL scripts manually.
To populate the database with sample providers and time slots:
npm run seedThis creates:
- 4 sample providers with different specializations
- Dr. Sarah Johnson (General Practitioner)
- Dr. Michael Chen (Dentist)
- Emma Williams (Licensed Therapist)
- Dr. James Rodriguez (Dermatologist)
- Time slots for the next 7 days (morning and afternoon slots)
Sample Provider Credentials:
- Email:
sarah.johnson@example.com - Password:
Provider123
(Same password for all seeded providers)
Start the server with auto-reload on file changes:
npm start
# or
npm run devThe server will start on http://localhost:3000 (or the port specified in .env)
For production deployment:
NODE_ENV=production node ./bin/wwwThe WebSocket server starts automatically with the application. No additional configuration needed.
You should see output similar to:
Server listening on port 3000
Database connected successfully
WebSocket server initialized
Visit http://localhost:3000/api-docs to access the Swagger documentation.
Access the interactive API documentation at:
http://localhost:3000/api-docs
Features:
- Try it out - Test endpoints directly from the browser
- Request/Response Examples - See sample requests and responses
- Schema Documentation - Complete data models
- Authentication - Test with JWT tokens
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
| POST | /auth/register |
Register new user | No |
| POST | /auth/login |
User login | No |
| GET | /users/profile |
Get user profile | Yes |
| PUT | /users/profile |
Update profile | Yes |
| GET | /providers |
List all providers | Yes |
| GET | /providers/:id |
Get provider details | Yes |
| GET | /time-slots |
List time slots | Yes |
| POST | /time-slots |
Create time slot | Yes (Provider) |
| POST | /appointments |
Book appointment | Yes (Client) |
| GET | /appointments/my-appointments |
Get user's appointments | Yes |
| PUT | /appointments/:id/cancel |
Cancel appointment | Yes |
| PUT | /appointments/:id/complete |
Complete appointment | Yes (Provider) |
appointment-booking-api/
βββ bin/
β βββ www # Server entry point
β
βββ scripts/
β βββ seed.js # Database seeding script
βββ src/
β βββ app.js # Express app configuration
β βββ config/
β β βββ database.js # PostgreSQL connection pool
β β βββ swagger.js # Swagger configuration
β β βββ swagger-annotations.js # Swagger schema definitions
β βββ middleware/
β β βββ auth.middleware.js # JWT authentication & authorization
β β βββ index.js # Middleware exports
β βββ modules/
β β βββ appointments/ # Appointment management
β β β βββ appointment.controller.js
β β β βββ appointment.routes.js
β β β βββ appointment.service.js
β β β βββ appointment.validation.js
β β βββ auth/ # Authentication
β β β βββ auth.controller.js
β β β βββ auth.routes.js
β β β βββ auth.services.js
β β β βββ auth.test.js
β β β βββ auth.validation.js
β β βββ providers/ # Provider management
β β β βββ provider.controller.js
β β β βββ provider.routes.js
β β β βββ provider.service.js
β β β βββ provider.validation.js
β β βββ timeSlots/ # Time slot management
β β β βββ timeSlot.controller.js
β β β βββ timeSlot.routes.js
β β β βββ timeSlot.service.js
β β β βββ timeSlot.validation.js
β β βββ users/ # User management
β β βββ user.controller.js
β β βββ user.routes.js
β β βββ user.service.js
β β βββ user.validation.js
β βββ services/
β β βββ notification.service.js # WebSocket notification service
β βββ socket/
β β βββ socket.handler.js # Socket.io event handlers
β βββ tests/
β β βββ database.test.js # Database tests
β βββ utils/
β βββ logger.js # Winston logger configuration
β βββ seeders.js # Database seeder functions
βββ .env # Environment variables (not in repo)
βββ .gitignore # Git ignore rules
βββ jest.config.mjs # Jest testing configuration
βββ package.json # Project dependencies
βββ README.md # This file
The project follows a modular architecture with clear separation of concerns:
- Routes - Define API endpoints and apply middleware
- Controllers - Handle HTTP requests and responses
- Services - Contain business logic and database operations
- Validation - Validate request data using Joi schemas
- Middleware - Authentication, authorization, and error handling
| Script | Command | Description |
|---|---|---|
| Start | npm start |
Start development server with nodemon (auto-reload) |
| Dev | npm run dev |
Same as start (alias) |
| Test | npm test |
Run Jest tests in test environment |
| Seed | npm run seed |
Populate database with sample data |
npm start- Starts server with nodemon
- Automatically restarts on file changes
- Enables debug logging
- Uses development environment
npm test- Runs all Jest tests
- Uses test database (configure in
.env) - Runs tests sequentially (--runInBand)
- Includes coverage reports (optional)
npm run seed- Creates 4 sample providers
- Generates time slots for next 7 days
- Safe to run multiple times (checks for existing data)
- Uses credentials:
passwordfor all seeded users
# Run all tests
npm test
# Run tests in watch mode
npm test -- --watch
# Run tests with coverage
npm test -- --coverage
# Run specific test file
npm test -- auth.test.jsCreate a .env.test file for test-specific configuration:
DB_NAME=appointment_system_test
NODE_ENV=test
JWT_SECRET=test_secret_key| Endpoint | Method | Description | Auth |
|---|---|---|---|
/auth/register |
POST | Register new user | No |
/auth/login |
POST | User login | No |
| Endpoint | Method | Description | Auth |
|---|---|---|---|
/users/profile |
GET | Get current user profile | Yes |
/users/profile |
PUT | Update user profile | Yes |
/users/:id |
GET | Get user by ID | Yes |
| Endpoint | Method | Description | Auth |
|---|---|---|---|
/providers |
GET | List all providers | Yes |
/providers/:id |
GET | Get provider by ID | Yes |
/providers |
POST | Create provider profile | Yes (Provider) |
/providers/:id |
PUT | Update provider profile | Yes (Provider) |
| Endpoint | Method | Description | Auth |
|---|---|---|---|
/time-slots |
GET | List time slots | Yes |
/time-slots/my-slots |
GET | Get provider's slots | Yes (Provider) |
/time-slots |
POST | Create time slot | Yes (Provider) |
/time-slots/:id |
PUT | Update time slot | Yes (Provider) |
/time-slots/:id |
DELETE | Delete time slot | Yes (Provider) |
| Endpoint | Method | Description | Auth |
|---|---|---|---|
/appointments |
POST | Book appointment | Yes (Client) |
/appointments/my-appointments |
GET | Get user's appointments | Yes |
/appointments/provider/:id |
GET | Get provider's appointments | Yes |
/appointments/:id |
GET | Get appointment by ID | Yes |
/appointments/:id/cancel |
PUT | Cancel appointment | Yes |
/appointments/:id/complete |
PUT | Complete appointment | Yes (Provider) |
Time Slots:
?provider_id=1- Filter by provider?is_booked=false- Filter by availability?date=2026-02-15- Filter by date
Appointments:
?status=booked- Filter by status (booked, cancelled, completed)
All errors follow a consistent format:
{
"success": false,
"message": "Error description",
"error": "Detailed error (development only)"
}| Code | Description | Common Causes |
|---|---|---|
| 200 | OK | Successful request |
| 201 | Created | Resource created successfully |
| 400 | Bad Request | Validation error, invalid input |
| 401 | Unauthorized | Missing or invalid JWT token |
| 403 | Forbidden | Insufficient permissions |
| 404 | Not Found | Resource doesn't exist |
| 409 | Conflict | Duplicate resource (e.g., email exists) |
| 500 | Internal Server Error | Server-side error |
Developed by: MUEGHE ABUEMKEZE CHU
Connect with me:
- π GitHub: @chu29
- π¦ Twitter: @unku_chu
- πΌ LinkedIn: MUEGHE ABUEMKEZE CHU
- π§ Email: chu.amk22@gmail.com