A secure, modular, and role-based backend API for a parcel delivery system (inspired by Pathao Courier and Sundarban) built with Express.js and MongoDB.
This system enables users to register as senders or receivers and perform parcel delivery operations including creating parcels, tracking status, and managing deliveries. The API implements comprehensive authentication, authorization, and parcel management with embedded status tracking.
- 🔐 JWT-based Authentication with secure password hashing
- 🎭 Role-based Authorization (Admin, Sender, Receiver)
- 📦 Comprehensive Parcel Management with status tracking
- 🧱 Modular Architecture for scalability
- 📊 Real-time Status Updates with embedded logs
- 🔍 Advanced Search & Filtering capabilities
- 🛡️ Secure API Endpoints with proper validation
Role | Permissions |
---|---|
Sender | Create parcels, Cancel parcels (if not dispatched), View own parcels |
Receiver | View incoming parcels, Confirm delivery, View delivery history |
Admin | Full system access, User/parcel management, Status updates |
REQUESTED → APPROVED → PICKUP_SCHEDULED → PICKED_UP → IN_TRANSIT → AT_HUB → OUT_FOR_DELIVERY → DELIVERED
↓ ↓ ↓ ↓ ↓ ↓ ↓
CANCELLED CANCELLED CANCELLED RETURN_REQ RETURN_REQ RETURN_REQ RETURN_REQ
↓ ↓ ↓ ↓
RETURNED RETURNED RETURNED RETURNED
- Backend Framework: Node.js + Express.js
- Database: MongoDB with Mongoose ODM
- Authentication: JWT
- Password Security: bcrypt
- Validation: Zod Schema Validation
- Architecture: Modular Service Pattern
src/
├── modules/
│ ├── auth/
│ │ ├── auth.controller.ts
│ │ ├── auth.routes.ts
│ ├── user/
│ │ ├── user.interface.ts
│ │ ├── user.model.ts
│ │ ├── user.controller.ts
│ │ ├── user.routes.ts
│ │ └── user.service.ts
│ └── parcel/
│ ├── parcel.interface.ts
│ ├── parcel.model.ts
│ ├── parcel.controller.ts
│ ├── parcel.routes.ts
│ ├── parcel.service.ts
│ └── parcel.interface.ts
├── middleware/
│ ├── authGuard.ts
│ ├── globalErrorHandler.ts
│ └── notFound.ts
│ └── validateRequestData.ts
├── config/
│ ├── env.config.ts
├── utils/
│ ├── errorHandlers
│ └── catchAsync.ts
│ └── isValidStatusTransition.ts
│ └── jwtHelper.ts
│ └── jwToken.ts
│ └── sendSuccessResponse.ts
│ └── setCookie.ts
│ └── throwError.ts
├── constants/
│ └── index.ts
├── app.ts
└── server.ts
-
Clone the repository
git clone <repository-url> cd parcel-delivery-api
-
Install dependencies
npm install
-
Environment Setup
Create a
.env
file in the root directory:# Server Configuration PORT=5000 NODE_ENV=development # Database Configuration DB_URI=mongodb+srv://username:password@cluster.mongodb.net/database-name?retryWrites=true&w=majority&appName=Cluster0 # Security Configuration HASHING_SALT_ROUND=10 # JWT Configuration ACCESS_TOKEN_SECRET=your-super-secret-access-token-key ACCESS_TOKEN_EXPIRY=1d REFRESH_TOKEN_SECRET=your-super-secret-refresh-token-key REFRESH_TOKEN_EXPIRY=30d
-
Start the server
# Development mode npm run dev # Production mode npm start
-
Verify installation
curl http://localhost:5000
Method | Endpoint | Description | Access |
---|---|---|---|
POST | /api/v1/auth/register |
User registration | Public |
POST | /api/v1/auth/login |
User login | Public |
POST | /api/v1/auth/logout |
User logout | authenticated |
Method | Endpoint | Description | Access |
---|---|---|---|
POST | /api/v1/user/create |
User registration | Public |
GET | /api/v1/user |
Get all users | Admin |
GET | /api/v1/user/:id |
Get user by ID | Admin/Self |
PATCH | /api/v1/user/:id |
Update user | Admin/Self |
PATCH | /api/v1/user/un-block/:id |
Unblock user | Admin |
Method | Endpoint | Description | Access |
---|---|---|---|
POST | /api/v1/parcel/create |
Create parcel | Sender |
GET | /api/v1/parcel |
Get all parcels | Admin |
GET | /api/v1/parcel/my-sent |
Get sender's parcels | Sender |
GET | /api/v1/parcel/my-received |
Get receiver's parcels | Receiver |
GET | /api/v1/parcel/:id |
Get parcel by ID | Owner/Admin |
PATCH | /api/v1/parcel/cancel/:id |
Cancel parcel | Sender |
PATCH | /api/v1/parcel/status/:id |
Update parcel status | Admin |
PATCH | /api/v1/parcel/confirm-delivery/:id |
Confirm delivery | Receiver |
PATCH | /api/v1/parcel/is-blocked/:id |
Block/Unblock parcel | Admin |
PATCH | /api/v1/parcel/track/:id |
Track parcel by ID | Sender-Receiver-Admin |
{
name: String,
email: String (unique),
password: String (hashed),
role: Enum ['ADMIN', 'SENDER', 'RECEIVER'],
phone: String,
isDeleted: Boolean
isBlocked: Boolean,
}
{
trackingId: String (unique, auto-generated),
type: String,
weightKg: Number,
fee: Number,
sender: {
user: ObjectId,
snapshot: AddressSnapshot
},
receiver: {
user: ObjectId,
snapshot: AddressSnapshot
},
status: Enum (ParcelStatus),
statusLogs: [StatusLog],
expectedDeliveryDate: Date,
dispatchedAt: Date,
deliveredAt: Date,
isBlocked: Boolean,
isCancelled: Boolean
cancelReason: String
}
- Text Search: Search by tracking ID, names, addresses
- Status Filter: Filter by parcel status
- Date Range: Filter by creation/delivery dates
- Email Search: Find parcels by user email
- Weight/Fee Range: Filter by weight or fee ranges
{
"meta": {
"total": 150,
"page": 1,
"limit": 10,
"totalPages": 15,
}
}
Each parcel maintains a comprehensive status log:
{
"statusLogs": [
{
"status": "REQUESTED",
"note": "Parcel created by sender",
"location": "",
"updatedBy": "64f123...",
"at": "2025-08-27T10:00:00Z"
}
]
}
- Password Encryption: bcrypt with configurable salt rounds
- JWT Authentication: Access token mechanism
- Role-based Access Control: Endpoint-level permission checking
- Input Validation: Zod schema validation
- Data Sanitization: Secure data handling
{
"statusCode": 200,
"success": true,
"message": "Operation successful",
"meta": {
"total": 10,
"page": 1,
"limit": 10,
"totalPages": 1
},
"data": { /* Response data */ }
}
{
"statusCode": 400,
"success": false,
"message": "Validation error",
"error": {
"details": "Specific error information"
}
}
NODE_ENV=production
PORT=5000
DB_URI=your-production-mongodb-uri
ACCESS_TOKEN_SECRET=your-production-access-secret
REFRESH_TOKEN_SECRET=your-production-refresh-secret
- 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
This project is licensed under the MIT License - see the LICENSE file for details.
Ariyan Rahman Anas
- Portfolio: https://ariyanrahmananas.vercel.app/
- LinkedIn: Connect with me
- Email: anas.hllw@gmail.com
⭐ If you found this project helpful, please consider giving it a star!
Built with ❤️ by Ariyan Rahman Anas