Technical DocumentationAPI ApplicationProgressive Auth API

Progressive Authentication API Documentation

This document describes the backend APIs implemented for the progressive authentication flow.

Base URL

http://localhost:5500

Authentication 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:

  • phoneNumber must 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:

  • phoneNumber must be a valid Indian mobile number
  • otp must 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 - Success
  • 401 - Invalid or expired OTP
  • 400 - 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, string
  • lastName - Required, string
  • email - 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 - Success
  • 401 - Unauthorized (missing or invalid token)
  • 400 - Validation error
  • 404 - 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 - Success
  • 401 - Unauthorized (missing or invalid token)
  • 400 - Profile not completed or already verified
  • 404 - 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 - Success
  • 401 - Unauthorized (missing or invalid token)
  • 400 - Verification not completed or invalid verification ID
  • 404 - 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 - Success
  • 401 - 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

  1. Send OTP:
curl -X POST http://localhost:5500/auth \
  -H "Content-Type: application/json" \
  -d '{"phoneNumber": "9876543210"}'
  1. Verify OTP:
curl -X POST http://localhost:5500/auth/verify \
  -H "Content-Type: application/json" \
  -d '{"phoneNumber": "9876543210", "otp": "123456"}'
  1. 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"
  }'
  1. Initiate eKYC Verification:
curl -X POST http://localhost:5500/profile/ekyc \
  -H "Authorization: Bearer <token_from_step_2>"
  1. 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>"}'
  1. 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_verified to true

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_here

Database Schema

User Table Fields

The users table includes the following field for the progressive authentication flow:

FieldTypeDescription
is_profile_verifiedbooleanIndicates if user has verified profile via eKYC (Step 4)

Important Notes:

  • hasCompletedProfile is a derived field (not stored in DB). It is computed based on the presence of first_name, last_name, and email fields.
  • This design ensures data integrity and eliminates the need to maintain a redundant boolean flag.

Security Notes

  1. JWT Token: Expires in 7 days
  2. OTP: Mock OTP should be replaced in production
  3. Password: Currently using OTP-based authentication (passwordless)
  4. CORS: Configured to allow http://localhost:3000 for frontend
  5. Validation: Input validation using class-validator
  6. Guards: JWT authentication guard protects all routes except /auth and /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.ts

Known 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:

  1. Build the @repo/db package separately and update exports to point to dist
  2. Use ts-node with custom loader for development
  3. Switch to commonjs module system
  4. Configure webpack/esbuild for proper bundling

This issue needs to be resolved at the monorepo infrastructure level.