A modern, RESTful API for managing salon operations, appointments, services, and customer relationships.
- Overview
- Features
- Technology Stack
- Installation
- Setup Guide
- API Documentation
- Usage Examples
- Deployment
- Contributing
- License
Salon API is a comprehensive backend solution designed to streamline salon management operations. It provides robust functionality for scheduling appointments, managing services, handling customer profiles, and tracking business metrics. The API is built with scalability and performance in mind, offering a clean and intuitive interface for both web and mobile applications.
- Appointment Management: Efficiently schedule, reschedule, and cancel appointments
- Service Management: Catalog and manage salon services with pricing and duration
- Customer Management: Maintain comprehensive customer profiles and history
- Staff Management: Manage salon staff members, schedules, and specializations
- Business Analytics: Track key metrics and business performance
-
Appointment System
- Book, reschedule, and cancel appointments
- Automated reminders and notifications
- Calendar view with availability management
- Recurring appointment support
- Conflict detection and prevention
-
Service Management
- Comprehensive service catalog
- Dynamic pricing and duration settings
- Service categorization and filtering
- Package and bundle offerings
- Promotional pricing support
-
Customer Management
- Complete customer profiles
- Contact information and preferences
- Appointment history and notes
- Loyalty program integration
- Communication preferences
-
Staff Management
- Staff profiles and specializations
- Schedule and availability management
- Performance tracking
- Commission management
- Role-based access control
-
Business Operations
- Payment processing and invoicing
- Inventory management
- Reporting and analytics
- Multi-location support
- Customizable business rules
- RESTful API with comprehensive endpoints
- Authentication and authorization (JWT-based)
- Rate limiting and API throttling
- Error handling and validation
- Comprehensive logging
- API versioning support
- Runtime: Node.js (v16 or higher)
- Framework: Express.js
- Language: JavaScript/TypeScript
- Database: MongoDB (or your database choice)
- ORM: Mongoose (for MongoDB)
- Authentication: JWT (jsonwebtoken)
- Validation: Joi, express-validator
- Async Management: async/await, Promise-based
- API Documentation: Swagger/OpenAPI
- Testing: Jest, Mocha/Chai
- Code Quality: ESLint, Prettier
- Logging: Winston, Morgan
- Security: bcryptjs, helmet, cors, express-rate-limit
- Containerization: Docker
- Container Orchestration: Kubernetes (optional)
- Cloud Platforms: AWS, Azure, Google Cloud (your choice)
- CI/CD: GitHub Actions, Jenkins, GitLab CI
- Monitoring: Prometheus, ELK Stack
Before installing, ensure you have the following:
- Node.js: v16.x or higher
- npm: v7.x or higher (or yarn)
- MongoDB: v4.4 or higher (local or Atlas)
- Git: Latest version
-
Clone the Repository
git clone https://github.com/renoir01/salon-api.git cd salon-api -
Install Dependencies
npm install
Or if using yarn:
yarn install
-
Verify Installation
npm --version node --version
-
Create Environment File
Create a
.envfile in the project root directory:cp .env.example .env
-
Configure Environment Variables
Edit
.envwith your configuration:# Server Configuration NODE_ENV=development PORT=3000 HOST=localhost # Database Configuration MONGODB_URI=mongodb://localhost:27017/salon-api # Or use MongoDB Atlas: # MONGODB_URI=mongodb+srv://username:password@cluster.mongodb.net/salon-api?retryWrites=true&w=majority # JWT Configuration JWT_SECRET=your_jwt_secret_key_here_change_in_production JWT_EXPIRY=7d # API Configuration API_VERSION=v1 API_PREFIX=/api # CORS Configuration CORS_ORIGIN=http://localhost:3000,http://localhost:3001 # Logging LOG_LEVEL=debug LOG_FORMAT=combined # Email Configuration (for notifications) SMTP_HOST=smtp.gmail.com SMTP_PORT=587 SMTP_USER=your-email@gmail.com SMTP_PASSWORD=your-app-password SMTP_FROM=noreply@salonapi.com # Payment Gateway (if applicable) STRIPE_PUBLIC_KEY=pk_test_xxxxx STRIPE_SECRET_KEY=sk_test_xxxxx # Rate Limiting RATE_LIMIT_WINDOW_MS=900000 RATE_LIMIT_MAX_REQUESTS=100
-
Database Setup
For MongoDB Local Installation:
# Start MongoDB service mongod # Or using MongoDB Compass for GUI management
For MongoDB Atlas:
- Create a cluster on MongoDB Atlas
- Get your connection string
- Add it to the
MONGODB_URIenvironment variable
-
Initialize Database
npm run db:init
Or if using migrations:
npm run migrations:up
-
Seed Initial Data (Optional)
npm run db:seed
Start the development server and verify the setup:
npm run devExpected output:
β Server running on http://localhost:3000
β Database connected successfully
β API ready to accept requests
http://localhost:3000/api/v1
All protected endpoints require a valid JWT token in the Authorization header:
Authorization: Bearer <your_jwt_token>| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
| GET | /appointments |
List all appointments | β |
| POST | /appointments |
Create new appointment | β |
| GET | /appointments/:id |
Get appointment details | β |
| PUT | /appointments/:id |
Update appointment | β |
| DELETE | /appointments/:id |
Cancel appointment | β |
| GET | /appointments/staff/:staffId/availability |
Get staff availability | β |
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
| GET | /services |
List all services | β |
| POST | /services |
Create new service | β |
| GET | /services/:id |
Get service details | β |
| PUT | /services/:id |
Update service | β |
| DELETE | /services/:id |
Delete service | β |
| GET | /services/category/:category |
Filter by category | β |
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
| GET | /customers |
List all customers | β |
| POST | /customers |
Create new customer | β |
| GET | /customers/:id |
Get customer details | β |
| PUT | /customers/:id |
Update customer | β |
| DELETE | /customers/:id |
Delete customer | β |
| GET | /customers/:id/appointments |
Get customer appointments | β |
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
| GET | /staff |
List all staff members | β |
| POST | /staff |
Add new staff member | β |
| GET | /staff/:id |
Get staff details | β |
| PUT | /staff/:id |
Update staff member | β |
| DELETE | /staff/:id |
Remove staff member | β |
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
| POST | /auth/register |
Register new account | β |
| POST | /auth/login |
Login user | β |
| POST | /auth/logout |
Logout user | β |
| POST | /auth/refresh |
Refresh JWT token | β |
| POST | /auth/forgot-password |
Request password reset | β |
| POST | /auth/reset-password/:token |
Reset password | β |
All responses follow a consistent format:
Success Response (200, 201):
{
"success": true,
"data": {
"id": "60d5ec49f1b2c72e8c1a2b3c",
"name": "Hair Cut",
"duration": 30,
"price": 25.00,
"category": "Hair Services"
},
"message": "Service retrieved successfully",
"timestamp": "2025-12-22T21:45:32Z"
}Error Response (4xx, 5xx):
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid input provided",
"details": [
{
"field": "email",
"message": "Email is required"
}
]
},
"timestamp": "2025-12-22T21:45:32Z"
}| Code | Meaning | Use Case |
|---|---|---|
| 200 | OK | Successful GET request |
| 201 | Created | Successful POST request |
| 204 | No Content | Successful DELETE request |
| 400 | Bad Request | Invalid input validation |
| 401 | Unauthorized | Missing or invalid authentication |
| 403 | Forbidden | Insufficient permissions |
| 404 | Not Found | Resource not found |
| 409 | Conflict | Duplicate resource or conflict |
| 429 | Too Many Requests | Rate limit exceeded |
| 500 | Server Error | Internal server error |
Register a new user:
curl -X POST http://localhost:3000/api/v1/auth/register \
-H "Content-Type: application/json" \
-d '{
"email": "manager@salon.com",
"password": "SecurePassword123!",
"firstName": "John",
"lastName": "Doe",
"role": "manager"
}'Login:
curl -X POST http://localhost:3000/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{
"email": "manager@salon.com",
"password": "SecurePassword123!"
}'Response:
{
"success": true,
"data": {
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"user": {
"id": "60d5ec49f1b2c72e8c1a2b3c",
"email": "manager@salon.com",
"firstName": "John",
"lastName": "Doe",
"role": "manager"
}
}
}curl -X POST http://localhost:3000/api/v1/services \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-d '{
"name": "Women Haircut",
"description": "Professional haircut with styling",
"category": "Hair Services",
"duration": 45,
"price": 35.00,
"active": true
}'curl -X POST http://localhost:3000/api/v1/appointments \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-d '{
"customerId": "60d5ec49f1b2c72e8c1a2b3c",
"staffId": "60d5ec49f1b2c72e8c1a2b3d",
"serviceId": "60d5ec49f1b2c72e8c1a2b3e",
"appointmentDate": "2025-12-25T10:00:00Z",
"notes": "Customer prefers shorter layers"
}'# Get all appointments
curl -X GET http://localhost:3000/api/v1/appointments \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
# Get appointments for a specific date
curl -X GET "http://localhost:3000/api/v1/appointments?date=2025-12-25" \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
# Get appointments for a specific staff member
curl -X GET "http://localhost:3000/api/v1/appointments?staffId=60d5ec49f1b2c72e8c1a2b3d" \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
# Get appointments by status
curl -X GET "http://localhost:3000/api/v1/appointments?status=completed" \
-H "Authorization: Bearer YOUR_JWT_TOKEN"curl -X PUT http://localhost:3000/api/v1/appointments/60d5ec49f1b2c72e8c1a2b3f \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-d '{
"appointmentDate": "2025-12-26T14:00:00Z",
"notes": "Rescheduled due to customer request"
}'curl -X DELETE http://localhost:3000/api/v1/appointments/60d5ec49f1b2c72e8c1a2b3f \
-H "Authorization: Bearer YOUR_JWT_TOKEN"curl -X GET http://localhost:3000/api/v1/customers/60d5ec49f1b2c72e8c1a2b3c/appointments \
-H "Authorization: Bearer YOUR_JWT_TOKEN"const axios = require('axios');
const API_BASE = 'http://localhost:3000/api/v1';
// Login and get token
async function login(email, password) {
try {
const response = await axios.post(`${API_BASE}/auth/login`, {
email,
password
});
return response.data.data.token;
} catch (error) {
console.error('Login failed:', error.response.data);
}
}
// Create appointment
async function createAppointment(token, appointmentData) {
try {
const response = await axios.post(
`${API_BASE}/appointments`,
appointmentData,
{
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
}
}
);
return response.data.data;
} catch (error) {
console.error('Failed to create appointment:', error.response.data);
}
}
// Usage
async function main() {
const token = await login('user@salon.com', 'password123');
const appointment = await createAppointment(token, {
customerId: '60d5ec49f1b2c72e8c1a2b3c',
staffId: '60d5ec49f1b2c72e8c1a2b3d',
serviceId: '60d5ec49f1b2c72e8c1a2b3e',
appointmentDate: '2025-12-25T10:00:00Z',
notes: 'Special request'
});
console.log('Appointment created:', appointment);
}
main();- Docker installed (for containerization)
- Cloud platform account (AWS, Azure, Google Cloud)
- CI/CD pipeline set up (GitHub Actions, Jenkins, etc.)
Create Dockerfile:
FROM node:16-alpine
WORKDIR /app
# Copy package files
COPY package*.json ./
# Install dependencies
RUN npm ci --only=production
# Copy application code
COPY . .
# Expose port
EXPOSE 3000
# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD node healthcheck.js
# Start application
CMD ["npm", "start"]Build and run Docker image:
# Build image
docker build -t salon-api:latest .
# Run container
docker run -d \
--name salon-api \
-p 3000:3000 \
-e MONGODB_URI=mongodb://mongo:27017/salon-api \
-e JWT_SECRET=your_secret \
salon-api:latestDocker Compose for local development:
version: '3.8'
services:
api:
build: .
ports:
- "3000:3000"
environment:
- MONGODB_URI=mongodb://mongo:27017/salon-api
- NODE_ENV=development
depends_on:
- mongo
mongo:
image: mongo:5.0
ports:
- "27017:27017"
volumes:
- mongo-data:/data/db
volumes:
mongo-data:Run with Docker Compose:
docker-compose up -dUsing Elastic Beanstalk:
# Install EB CLI
pip install awsebcli
# Initialize EB application
eb init -p "Node.js 16" salon-api
# Create environment and deploy
eb create salon-api-env
eb deployUsing EC2:
# SSH into instance
ssh -i your-key.pem ec2-user@your-instance-ip
# Install Node.js
curl -fsSL https://rpm.nodesource.com/setup_16.x | sudo bash -
sudo yum install -y nodejs
# Clone repository
git clone https://github.com/renoir01/salon-api.git
cd salon-api
# Install and configure
npm install
cp .env.example .env
# Edit .env with production values
# Start application with PM2
npm install -g pm2
pm2 start npm --name "salon-api" -- start
pm2 startup
pm2 saveCreate Kubernetes manifests:
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: salon-api
spec:
replicas: 3
selector:
matchLabels:
app: salon-api
template:
metadata:
labels:
app: salon-api
spec:
containers:
- name: api
image: your-registry/salon-api:latest
ports:
- containerPort: 3000
env:
- name: MONGODB_URI
valueFrom:
secretKeyRef:
name: salon-secrets
key: mongodb-uri
- name: JWT_SECRET
valueFrom:
secretKeyRef:
name: salon-secrets
key: jwt-secret
livenessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 3000
initialDelaySeconds: 5
periodSeconds: 5Deploy to Kubernetes:
# Create secrets
kubectl create secret generic salon-secrets \
--from-literal=mongodb-uri=<your-mongodb-uri> \
--from-literal=jwt-secret=<your-jwt-secret>
# Apply deployment
kubectl apply -f deployment.yaml
# Verify deployment
kubectl get pods
kubectl logs -f deployment/salon-apiProduction .env example:
NODE_ENV=production
PORT=3000
MONGODB_URI=mongodb+srv://prod-user:secure-pass@cluster.mongodb.net/salon-api-prod?retryWrites=true&w=majority
JWT_SECRET=your-very-secure-production-secret-key-minimum-32-characters
JWT_EXPIRY=7d
API_PREFIX=/api
CORS_ORIGIN=https://yourdomain.com,https://app.yourdomain.com
LOG_LEVEL=warn# View logs
npm run logs
# Health check
curl http://localhost:3000/health
# Performance metrics
curl http://localhost:3000/metrics
# Database backup
npm run db:backup
# Database restore
npm run db:restoreRun the test suite:
# Run all tests
npm test
# Run with coverage
npm run test:coverage
# Run specific test file
npm test -- tests/appointments.test.js
# Run in watch mode
npm test -- --watch# Development
npm run dev # Start development server with hot reload
npm run start # Start production server
npm run test # Run test suite
npm run lint # Run ESLint
npm run format # Format code with Prettier
# Database
npm run db:init # Initialize database
npm run db:seed # Seed initial data
npm run db:backup # Backup database
npm run db:restore # Restore database
# Deployment
npm run build # Build for production
npm run docker:build # Build Docker image
npm run deploy # Deploy to productionContributions are welcome! Please follow these steps:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit changes (
git commit -m 'Add amazing feature') - Push to branch (
git push origin feature/amazing-feature) - Open a Pull Request
Please ensure:
- Code follows the project's style guide
- Tests are added for new features
- Documentation is updated
This project is licensed under the MIT License - see the LICENSE file for details.
For support, email support@salonapi.com or open an issue on GitHub.
Last Updated: 2025-12-22
Maintainer: renoir01