Progressive Authentication API Documentation
This document describes the backend APIs implemented for the progressive authentication flow.
Base URL
http://localhost:5500Authentication Flow
1. Send OTP
Endpoint: POST /auth
Description: Initiates the authentication process by sending an OTP to the provided phone number.
Request Body:
{
"phoneNumber": "9876543210"
}Validation:
phoneNumbermust be a valid Indian mobile number (10 digits starting with 6-9)
Response:
{
"message": "OTP sent successfully"
}Mock Behavior:
- Generates a mock OTP:
123456 - Logs the OTP to console (for development)
- OTP expires in 10 minutes
2. Verify OTP
Endpoint: POST /auth/verify
Description: Verifies the OTP and authenticates the user. Creates a new user if the phone number doesn’t exist.
Request Body:
{
"phoneNumber": "9876543210",
"otp": "123456"
}Validation:
phoneNumbermust be a valid Indian mobile numberotpmust be exactly 6 digits
Response (New User):
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"user": {
"id": 1,
"phone": "9876543210",
"firstName": null,
"lastName": null,
"email": null,
"role": "landlord",
"hasCompletedProfile": false,
"hasVerifiedProfile": false
},
"status": "NEEDS_PROFILE_COMPLETION"
}Response (Existing User - Profile Incomplete):
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"user": {
"id": 1,
"phone": "9876543210",
"firstName": "John",
"lastName": "Doe",
"email": "john@example.com",
"role": "landlord",
"hasCompletedProfile": true,
"hasVerifiedProfile": false
},
"status": "NEEDS_VERIFICATION"
}Response (Fully Onboarded User):
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"user": {
"id": 1,
"phone": "9876543210",
"firstName": "John",
"lastName": "Doe",
"email": "john@example.com",
"role": "landlord",
"hasCompletedProfile": true,
"hasVerifiedProfile": true
},
"status": "LOGIN_SUCCESSFUL"
}Status Codes:
200- Success401- Invalid or expired OTP400- Validation error
Profile Management
3. Complete Profile
Endpoint: PUT /profile/complete
Description: Completes the user’s profile information. Requires JWT authentication.
Headers:
Authorization: Bearer <access_token>Request Body:
{
"firstName": "John",
"lastName": "Doe",
"email": "john@example.com"
}Validation:
firstName- Required, stringlastName- Required, stringemail- Required, valid email format
Response:
{
"message": "Profile completed successfully",
"user": {
"id": 1,
"phone": "9876543210",
"firstName": "John",
"lastName": "Doe",
"email": "john@example.com",
"role": "landlord",
"hasCompletedProfile": true,
"hasVerifiedProfile": false
}
}Status Codes:
200- Success401- Unauthorized (missing or invalid token)400- Validation error404- User not found
eKYC Verification
4. Initiate eKYC Verification
Endpoint: POST /profile/ekyc
Description: Initiates eKYC verification via third-party provider (Setu). Requires JWT authentication and completed profile.
Headers:
Authorization: Bearer <access_token>Request Body:
{}Response:
{
"message": "eKYC verification initiated",
"verificationId": "ekyc_1234567890",
"verificationUrl": "https://mock-ekyc-provider.com/verify",
"status": "initiated"
}Mock Behavior:
- Simulates eKYC initiation with Setu
- Returns mock verification ID and URL
- In production, this would integrate with the real Setu eKYC API
Status Codes:
200- Success401- Unauthorized (missing or invalid token)400- Profile not completed or already verified404- User not found
5. Complete eKYC Verification
Endpoint: POST /profile/ekyc/complete
Description: Completes eKYC verification after user completes the process. Requires JWT authentication.
Headers:
Authorization: Bearer <access_token>Request Body:
{
"verificationId": "ekyc_1234567890"
}Response:
{
"message": "eKYC verification completed successfully",
"user": {
"id": 1,
"phone": "9876543210",
"firstName": "John",
"lastName": "Doe",
"email": "john@example.com",
"role": "landlord",
"hasCompletedProfile": true,
"hasVerifiedProfile": true
}
}Mock Behavior:
- Simulates successful eKYC verification completion
- In production, this would verify the callback from Setu and update user status
Status Codes:
200- Success401- Unauthorized (missing or invalid token)400- Verification not completed or invalid verification ID404- User not found
Dashboard
6. Get Dashboard
Endpoint: GET /dashboard
Description: Returns dashboard data for the authenticated user. Requires JWT authentication and full onboarding.
Headers:
Authorization: Bearer <access_token>Response:
{
"user": {
"id": 1,
"phone": "9876543210",
"firstName": "John",
"lastName": "Doe",
"email": "john@example.com",
"role": "landlord",
"hasCompletedProfile": true,
"hasVerifiedProfile": true
},
"stats": {
"totalProperties": 0,
"totalTenants": 0,
"pendingPayments": 0,
"maintenanceRequests": 0
},
"recentActivity": []
}Status Codes:
200- Success401- Unauthorized (missing or invalid token)
Error Responses
All endpoints return errors in the following format:
{
"statusCode": 400,
"message": "Validation failed",
"error": "Bad Request"
}or for validation errors:
{
"statusCode": 400,
"message": [
"phoneNumber must be a valid Indian mobile number",
"otp must be exactly 6 digits"
],
"error": "Bad Request"
}Testing the APIs
Example Flow
- Send OTP:
curl -X POST http://localhost:5500/auth \
-H "Content-Type: application/json" \
-d '{"phoneNumber": "9876543210"}'- Verify OTP:
curl -X POST http://localhost:5500/auth/verify \
-H "Content-Type: application/json" \
-d '{"phoneNumber": "9876543210", "otp": "123456"}'- Complete Profile:
curl -X PUT http://localhost:5500/profile/complete \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <token_from_step_2>" \
-d '{
"firstName": "John",
"lastName": "Doe",
"email": "john@example.com"
}'- Initiate eKYC Verification:
curl -X POST http://localhost:5500/profile/ekyc \
-H "Authorization: Bearer <token_from_step_2>"- Complete eKYC Verification:
curl -X POST http://localhost:5500/profile/ekyc/complete \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <token_from_step_2>" \
-d '{"verificationId": "<verification_id_from_step_4>"}'- Access Dashboard:
curl -X GET http://localhost:5500/dashboard \
-H "Authorization: Bearer <token_from_step_2>"Mock Services
OTP Service (OtpService)
Location: src/integrations/communications/otp.service.ts
Mock Behavior:
- Always generates OTP:
123456 - Stores OTPs in-memory
- OTP expiry: 10 minutes
- Logs OTP to console
Production Replacement:
- Replace with SMS/WhatsApp provider (Twilio, AWS SNS, etc.)
- Implement real OTP generation
- Add rate limiting
- Add proper error handling
eKYC Service (EkycService)
Location: src/integrations/ekyc/ekyc.service.ts
Mock Behavior:
- Simulates successful eKYC verification initiation
- Returns mock verification ID and URL
- Simulates successful verification completion
- Updates
is_profile_verifiedtotrue
Production Replacement:
- Integrate with Setu eKYC API
- Implement OAuth flow for Aadhaar verification
- Handle webhooks/callbacks from Setu
- Fetch and securely store verified user documents
- Add proper error handling and retry logic
- Implement rate limiting
Environment Variables
Required environment variables in .env.development:
# Server Configuration
PORT=5500
# Database Configuration
DB_HOST=localhost
DB_PORT=5432
DB_USERNAME=postgres
DB_PASSWORD=postgres
DB_NAME=landlordx_dev
# Authentication
SUPABASE_JWT_SECRET=your_jwt_secret_hereDatabase Schema
User Table Fields
The users table includes the following field for the progressive authentication flow:
| Field | Type | Description |
|---|---|---|
is_profile_verified | boolean | Indicates if user has verified profile via eKYC (Step 4) |
Important Notes:
hasCompletedProfileis a derived field (not stored in DB). It is computed based on the presence offirst_name,last_name, andemailfields.- This design ensures data integrity and eliminates the need to maintain a redundant boolean flag.
Security Notes
- JWT Token: Expires in 7 days
- OTP: Mock OTP should be replaced in production
- Password: Currently using OTP-based authentication (passwordless)
- CORS: Configured to allow
http://localhost:3000for frontend - Validation: Input validation using
class-validator - Guards: JWT authentication guard protects all routes except
/authand/auth/verify
Module Structure
src/
├── core/ # Infrastructure
│ └── auth-strategies/
│ └── jwt.strategy.ts
├── common/ # Shared utilities
│ └── decorators/
│ └── current-user.decorator.ts
├── integrations/ # External services
│ ├── communications/
│ │ └── otp.service.ts
│ └── ekyc/
│ ├── ekyc.module.ts
│ └── ekyc.service.ts
└── modules/ # Business modules
├── auth/
│ ├── guards/
│ │ └── jwt-auth.guard.ts
│ ├── dtos/
│ │ ├── send-otp.dto.ts
│ │ └── verify-otp.dto.ts
│ ├── auth.controller.ts
│ ├── auth.service.ts
│ └── auth.module.ts
├── profile/
│ ├── dtos/
│ │ ├── complete-profile.dto.ts
│ │ └── complete-ekyc.dto.ts
│ ├── profile.controller.ts
│ ├── profile.service.ts
│ └── profile.module.ts
├── dashboard/
│ ├── dashboard.controller.ts
│ ├── dashboard.service.ts
│ └── dashboard.module.ts
└── user/
├── user.service.ts
└── user.module.tsKnown Issues
Module Resolution Error
The monorepo currently has a module resolution issue with NodeNext and ES modules that affects both the base code and new implementations. This is a pre-existing infrastructure issue, not related to the authentication APIs.
Error:
Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/path/to/packages/db/src/config/database.config'Workaround Options:
- Build the
@repo/dbpackage separately and update exports to point to dist - Use ts-node with custom loader for development
- Switch to commonjs module system
- Configure webpack/esbuild for proper bundling
This issue needs to be resolved at the monorepo infrastructure level.