Next-Generation KYC Verification System
Intelligent risk scoring • Real-time fraud detection • Enterprise-grade security
Quick Start • Features • API Docs • Examples
|
|
graph LR
A[Client Request] --> B[Validation Layer]
B --> C[Risk Analysis Engine]
C --> D[Decision Engine]
D --> E[Response + Score]
style C fill:#4169E1
style D fill:#339933
- 🛡️ Enterprise Security - Helmet, CORS, input sanitization
- 📊 Smart Pagination - Efficient data retrieval
- 🚨 Custom Middleware - Scalar pollution prevention
- 🏗️ Layered Design - Controllers → Services → Models
- ⚙️ Production Ready - Structured logging & error handling
Get PathGuard API running in less than 2 minutes:
# Clone repository
git clone https://github.com/thmslfb/pathguard-api.git
cd pathguard-api
# Install dependencies
npm install
# Start development server (uses mock data by default)
npm run dev🎮 Live Playground: Open http://localhost:3000/api/v1/docs to interact with the API through Scalar
curl -X POST http://localhost:3000/api/v1/kyc/verifications \
-H "Content-Type: application/json" \
-d '{
"name": "Alice Dupont",
"email": "[email protected]",
"documentType": "id_card"
}'Response:
{
"verification_id": "ver_123e4567-e89b-12d3-a456-426614174000",
"status": "approved",
"risk_score": 0.1,
"checks_performed": ["name", "email", "documentType"],
"timestamp": "2025-10-05T14:30:00.000Z"
}| Category | Technologies |
|---|---|
| Runtime | |
| Framework | |
| Database | |
| Validation | |
| Documentation | |
| Testing | |
| Security |
📋 Prerequisites
Before you begin, ensure you have:
- ✅ Node.js 18+ - Download
- ✅ PostgreSQL - Install Guide
- ✅ Git - Get Started
git clone https://github.com/thmslfb/pathguard-api.git
cd pathguard-apinpm installcp .env.example .envCreate your .env file with the following structure:
# Database Configuration
DATABASE_URL="postgresql://username:password@localhost:5432/pathguard"
# Risk Scoring Thresholds
LOW_THRESHOLD=0.2
HIGH_THRESHOLD=0.5
# Server Configuration
PORT=3000
NODE_ENV=development# Run migrations to create database schema
npm run migrate:apply# Development mode with hot reload
npm run dev
# Production mode
npm start✅ API Ready: http://localhost:3000/api/v1
📚 Scalar Documentation: http://localhost:3000/api/v1/docs
| Method | Endpoint | Description | Status |
|---|---|---|---|
GET |
/api/v1 |
API information & health | ✅ |
GET |
/api/v1/health |
System health check | ✅ |
POST |
/api/v1/kyc/verifications |
Create verification | ✅ |
GET |
/api/v1/kyc/verifications |
List verifications | ✅ |
GET |
/api/v1/kyc/verifications/:id |
List verification by ID | ✅ |
DELETE |
/api/v1/kyc/verifications/:id |
Delete verification by ID | ✅ |
PATCH |
/api/v1/kyc/verifications/:id/status |
Update verification status | ✅ |
GET |
/api/v1/docs |
Scalar documentation | 📚 |
http://localhost:3000/api/v1
POST /api/v1/kyc/verifications
✅ Low Risk - Approved
curl -X POST http://localhost:3000/api/v1/kyc/verifications \
-H "Content-Type: application/json" \
-d '{
"name": "Alice Dupont",
"email": "[email protected]",
"documentType": "id_card"
}'Response (200 OK):
{
"verification_id": "ver_123e4567-e89b-12d3-a456-426614174000",
"status": "approved",
"risk_score": 0.1,
"checks_performed": ["name", "email", "documentType"],
"timestamp": "2025-10-05T14:30:00.000Z"
}🟡 Medium Risk - Pending Review
curl -X POST http://localhost:3000/api/v1/kyc/verifications \
-H "Content-Type: application/json" \
-d '{
"name": "John Smith",
"email": "[email protected]",
"documentType": "passport"
}'Response (200 OK):
{
"verification_id": "ver_234f5678-f90c-23e4-b567-537725285111",
"status": "pending_review",
"risk_score": 0.35,
"checks_performed": ["name", "email", "documentType"],
"timestamp": "2025-10-05T14:35:00.000Z"
}❌ High Risk - Rejected
curl -X POST http://localhost:3000/api/v1/kyc/verifications \
-H "Content-Type: application/json" \
-d '{
"name": "X",
"email": "[email protected]",
"documentType": "passport"
}'Response (200 OK):
{
"verification_id": "ver_345g6789-g01d-34f5-c678-648836396222",
"status": "rejected",
"risk_score": 0.6,
"checks_performed": ["name", "email", "documentType"],
"timestamp": "2025-10-05T14:40:00.000Z"
}Response (400 Bad Request)
- Name error (name too short)
{
"error": "Validation failed",
"details": [
{
"field": "name",
"message": "Name must be at least 2 characters long"
}
]
}- Email Error (invalid format)
{
"error": "Validation failed",
"details": [
{
"field": "email",
"message": "Invalid email format"
}
]
}- Document type error (invalid value)
{
"error": "Validation failed",
"details": [
{
"field": "documentType",
"message": "Invalid option: expected one of \"passport\"|\"id_card\"|\"driver_license\""
}
]
}📋 GET /api/v1/kyc/verifications
Retrieve a list of all KYC verifications with optional pagination support.
curl http://localhost:3000/api/v1/kyc/verifications?limit=10&offset=0Response (200 OK):
[
{
"verification_id": "ver_123e4567-e89b-12d3-a456-426614174000",
"status": "approved",
"risk_score": 0.1,
"created_at": "2025-10-05T14:30:00.000Z"
},
{
"verification_id": "ver_987fcdeb-51a2-43f1-b987-123456789abc",
"status": "approved",
"risk_score": 0.2,
"created_at": "2025-10-05T13:15:00.000Z"
},
{
"verification_id": "ver_456def78-90ab-12cd-34ef-567890abcdef",
"status": "pending_review",
"risk_score": 0.35,
"created_at": "2025-10-05T12:45:00.000Z"
}
]Response (400 Bad Request)
- Invalid type for limit and offset
{
"error": "Validation failed",
"details": [
{
"field": "limit",
"message": "Invalid input: expected number, received NaN"
},
{
"field": "offset",
"message": "Invalid input: expected number, received NaN"
}
]
}- Limit too small
{
"error": "Validation failed",
"details": [
{ "field": "limit", "message": "Too small: expected number to be >=1" }
]
}- Limit too big
{
"error": "Validation failed",
"details": [
{ "field": "limit", "message": "Too big: expected number to be <=1000" }
]
}| Parameter | Type | Default | Description |
|---|---|---|---|
limit |
integer | 100 |
Number of results per page (max: 1000) |
offset |
integer | 0 |
Number of results to skip |
Example:
curl http://localhost:3000/api/v1/kyc/verifications?limit=20&offset=40GET /api/v1/kyc/verifications/:id
Retrieve detailed information about a KYC verification using its unique identifier.
curl http://localhost:3000/api/v1/kyc/verifications/ver_456def78-90ab-12cd-34ef-567890abcdefResponse (200 OK):
{
"verification_id": "ver_456def78-90ab-12cd-34ef-567890abcdef",
"status": "pending_review",
"risk_score": 0.35,
"created_at": "2025-10-05T14:30:00.000Z"
}Response (400 Bad Request)
- Invalid id parameter
{
"error": "Validation failed",
"details": [
{
"field": "id",
"message": "Invalid verification ID format. Must be in format ver_xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}
]
}Response (404 Not Found):
{
"error": "Verification not found"
}DELETE /api/v1/kyc/verifications/:id
Delete a KYC verification using its unique identifier.
curl -X DELETE http://localhost:3000/api/v1/kyc/verifications/ver_456def78-90ab-12cd-34ef-567890abcdefResponse (200 OK):
{
"message": "Verification deleted successfully"
}Response (404 Not Found):
{
"error": "Verification not found"
}GET /api/v1/kyc/verifications/:id/status
Update the status of a KYC verification by its unique identifier.
curl http://localhost:3000/api/v1/kyc/verifications/ver_52042584-e3ff-43c3-a6f0-bb9923dcadb7/status \
--request PATCH \
--header 'Content-Type: application/json' \
--data '{
"status": "approved"
}'Response (200 OK):
{
"verification_id": "ver_52042584-e3ff-43c3-a6f0-bb9923dcadb7",
"status": "approved"
}Response (400 Bad Request)
- Invalid status
{
"error": "Validation failed",
"details": [
{
"field": "status",
"message": "Invalid option: expected one of \"approved\"|\"rejected\"|\"pending_review\""
}
]
}- Invalid id parameter
{
"error": "Validation failed",
"details": [
{
"field": "id",
"message": "Invalid verification ID format. Must be in format ver_xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}
]
}Response (404 Not Found):
{
"error": "Verification not found"
}PathGuard uses a sophisticated multi-factor risk analysis engine to evaluate KYC submissions:
The risk score is calculated by adding penalties for various risk factors:
Risk Score = Name Penalties + Email Penalties + Document Weight
Risk Factors:
- Name too short (< 2 chars): +0.1
- Name too long (> 50 chars): +0.05
- Special characters in name: +0.1
- Invalid email format: +0.2
- Disposable email domain: +0.3
- Generic email domain: +0.15
- Document type weight: +0.1 to +0.2
|
|
|
| Score Range | Status | Action | Visual |
|---|---|---|---|
0.0 - 0.2 |
✅ Approved | Automatic approval | 🟢 |
0.2 - 0.5 |
🟡 Pending Review | Manual verification required | 🟡 |
0.5 - 1.0 |
❌ Rejected | Automatic rejection | 🔴 |
Each verification response includes the following fields:
{
"verification_id": "ver_123e4567-e89b-12d3-a456-426614174000",
"status": "approved",
"risk_score": 0.1,
"checks_performed": ["name", "email", "documentType"],
"timestamp": "2025-10-05T14:30:00.000Z"
}Field Descriptions:
verification_id- Unique identifier with 'ver_' prefixstatus- Verification result (approved/pending_review/rejected)risk_score- Calculated risk score (0.0 - 1.0)checks_performed- List of validation checks executedtimestamp- ISO 8601 timestamp of verification
pathguard-api/
├── controllers/ # HTTP request handlers
├── services/ # Business logic and risk scoring
├── models/ # Database layer with Drizzle ORM
├── middleware/ # Custom middleware (validation, security)
├── routes/ # API route definitions
├── schemas/ # Zod validation schemas
├── utils/ # Utilities and mock data
└── database/ # Database configuration and migrations
sequenceDiagram
participant Client
participant Express
participant Middleware
participant Controller
participant Service
participant Database
Client->>Express: POST /api/v1/kyc/verifications
Express->>Middleware: Validate Input
Middleware->>Controller: Valid Request
Controller->>Service: Process Verification
Service->>Service: Calculate Risk Score
Service->>Database: Save Verification
Database-->>Service: Confirmation
Service-->>Controller: Verification Result
Controller-->>Client: JSON Response
npm run dev # Development with hot reload
npm test # Run test suite with coverage
npm run migrate:generate # Generate new migrations
npm run migrate:apply # Apply database migrations
npm start # Production server| Feature | Implementation |
|---|---|
| 🏛️ Clean Architecture | Separation of concerns (Routes → Controllers → Services → Models) |
| 🔒 Security | Input validation, CORS, Helmet security headers |
| 📖 Documentation | Interactive Scalar Documentation with live examples |
| 🗄️ Database | PostgreSQL with Drizzle ORM and migrations |
| 🛡️ Smart Middleware | Custom Scalar detection prevents doc pollution |
| Centralized error management with proper HTTP codes | |
| ✨ Code Quality | Conventional commits, modular structure |
This project is licensed under the MIT License - see the LICENSE file for details.
We welcome contributions! Here's how you can help:
- 🍴 Fork the repository
- 🌿 Create your feature branch (
git checkout -b feature/amazing-feature) - 💾 Commit your changes (
git commit -m 'feat: add amazing feature') - 📤 Push to the branch (
git push origin feature/amazing-feature) - 🎯 Open a Pull Request
Need help? Please open an issue in the repository.
Built with modern web development best practices and industry-standard tools:
- Express.js - Fast, unopinionated web framework
- Node.js - JavaScript runtime
- PostgreSQL - Advanced open source database
- Drizzle ORM - TypeScript ORM
- Scalar - API documentation
- Zod - TypeScript-first schema validation
- Vitest - Next generation testing framework
⭐ If you found this project helpful, please give it a star!
Made with ❤️ by thmslfb