8byte.ai
📗 Part 2 of 3 — Backend Documentation

8byte LOS
Backend Documentation

A comprehensive breakdown of the NestJS API server — covering every module, service, database model, API endpoint, queue worker, external integration, and deployment configuration.

NestJS 10
Framework
105
Controllers
174
Services
84
Modules
167
DB Models
25+
External APIs
🎯

About Backend

The engine that powers the entire loan origination system

The 8byte LOS backend is a NestJS REST API that serves as the central brain of the loan origination platform. It handles everything from customer authentication and KYC verification to loan disbursement, repayment collection, and financial reporting — orchestrating dozens of external services along the way.

🏗️ Architecture Pattern

Modular monolith using NestJS's module system. Each domain (loans, payments, KYC) is a self-contained module with its own controller, service, and DTOs. Modules import each other as needed. Two PM2 processes: the main API server and a dedicated cron worker.

🌐 API Design

RESTful API versioned at /api/v1/. Three main namespaces: /web/ for customer-facing endpoints, /partner/brand/:brandId/ for internal staff, and /admin/ for super admins. All secured with JWT guards.

🔄 Multi-Brand Support

Every partner API call includes a brandId in the URL. The backend uses this to filter data, apply brand-specific rules (loan amounts, interest rates, evaluation criteria), and dispatch brand-specific communications.

⚡ Async Processing

Heavy operations (reminder dispatch, audit logging, PDF generation, NOC emails) are offloaded to message queues (RabbitMQ/AWS SQS) and processed by background workers asynchronously — keeping API responses fast.

⚙️

Tech Stack

Every technology, library and tool in the backend

🏗️ Core Framework

NestJS 10.2.1 TypeScript Node.js

NestJS provides the module system, DI container, lifecycle hooks, and decorators. TypeScript enforces strong typing across all 171+ services and 170+ DTOs.

🗄️ Database & ORM

PostgreSQL Prisma ORM 6.15.0 Prisma Studio

Prisma as the type-safe ORM with schema-first approach. All models defined in schema.prisma. Custom GIN/TRGM indexes for full-text search. Migrations managed via Prisma CLI.

🔐 Authentication

JWT (jsonwebtoken) Passport.js bcrypt (12 rounds)

JWT for stateless authentication with access + refresh token pattern. bcrypt for password hashing with 12 salt rounds. Passport strategies for both web (OTP) and partner (password) auth.

⚡ Caching

Redis Custom Cache Interceptors

Redis for response caching of expensive DB queries. Custom @CacheResponse(ttl) decorator on controller methods. Cache invalidated on data mutations.

📬 Message Queues

RabbitMQ AWS SQS

RabbitMQ for internal job queues (reminders, notifications). AWS SQS for audit logs and NOC (No-Objection Certificate) email queues. Workers process jobs asynchronously.

📅 Task Scheduling

Trigger.dev 4.0.2 @nestjs/schedule

Trigger.dev for managed background jobs with retries, monitoring, and scheduling. NestJS Schedule for simple recurring cron jobs (daily reports, reminder dispatch).

📄 PDF Generation

PDFKit Playwright Puppeteer

PDFKit for programmatic PDF creation. Playwright/Puppeteer for HTML-to-PDF rendering (loan agreements, NDC certificates, repayment schedules).

🌐 HTTP & Validation

Axios class-validator class-transformer Joi Helmet Compression

Axios for outgoing HTTP requests to 25+ external APIs. class-validator for DTO validation on every request. Helmet for security headers. Compression middleware for gzip responses.

🧩

NestJS Module System

How modules are organized and interact

NestJS uses a module-based architecture. Each module encapsulates a controller (routes), service (business logic), and DTOs (request/response validation). The AppModule at the root imports all feature modules. Modules declare providers they export so other modules can inject them.

📦 Module Anatomy

Each NestJS module has:

@Module decorator Controller (routes) Service (business logic) DTOs (validation) PrismaService (DB)

Example: LoansModuleLoansController handles HTTP routes, LoansService handles business logic, CreateLoanDto validates incoming data, PrismaService accesses the database.

🔗 Dependency Injection

NestJS's DI container manages service instantiation. A service can inject any other service by declaring it in the constructor:

PrismaService — DB access JwtService — token ops RedisService — caching S3Service — file storage SmsService — SMS sending
🔐

Authentication & Guards

How the backend protects every endpoint

👤 Web Auth (Customers)

1. POST /web/auth/register → create User, send OTP via SMS
2. POST /web/auth/verify-otp → verify OTP, issue JWT tokens
3. Every subsequent request → AuthGuard validates JWT
4. POST /web/auth/refresh-token → issue new tokens on expiry

👔 Partner Auth (Staff)

1. POST /partner/auth/login → verify email + bcrypt password
2. Check brand access + device fingerprint registration
3. Issue JWT with roles, permissions, brandIds embedded
4. Every request → validate JWT + check brandId in URL

🛡️ Guards

AuthGuard: Validates JWT token. Rejects with 401 if missing or expired. Attaches decoded user to request.user.

RolePermissionGuard: Reads @RequireRoleOrPermission() decorator on the route. Checks if the authenticated user's roles/permissions match. Rejects with 403 if not.

🏷️ Key Decorators

@AuthType("partner") @AuthType("web") @RequireRoleOrPermission("ADMIN") @GetPartnerUser() @Public()

@GetPartnerUser() is a parameter decorator that extracts the authenticated partner user from the request, making it available directly in the controller method.

🗄️

Database Schema (Prisma)

Core models and their relationships

All models are defined in prisma/schema.prisma. PostgreSQL is the database. Prisma generates fully-typed client code. Custom GIN TRGM indexes are added for full-text search on name/phone/PAN fields.

User

idString (UUID)Primary key
phoneNumberStringUnique, mobile
emailString?Optional email
onboardingStepEnumKYC progress
brandIdStringFK → Brand
isActiveBooleanAccount status
createdAtDateTimeAuto timestamp

PartnerUser

idString (UUID)Primary key
emailStringUnique, login
passwordStringbcrypt hashed
nameStringStaff name
phoneNumberString?Contact
isActiveBooleanAccount enabled
reportingToIdString?FK → self (manager)

Loan

idString (UUID)Primary key
userIdStringFK → User
brandIdStringFK → Brand
amountDecimalLoan principal
tenureIntMonths
statusLoanStatusCurrent status enum
disbursedAtDateTime?Disbursement time
outstandingAmountDecimalRemaining to pay

PaymentCollectionTransaction

idStringPrimary key
loanIdStringFK → Loan
amountDecimalPayment amount
gatewayEnumRazorpay/Cashfree
gatewayRefStringPayment gateway ID
statusEnumSUCCESS/FAILED/PENDING
collectedAtDateTimeCollection timestamp

Brand

idStringPrimary key
nameStringBrand name
subdomainStringURL subdomain
logoUrlString?S3 logo URL
isActiveBooleanBrand enabled
themeJSONColors, fonts

Document

idStringPrimary key
userIdStringFK → User
typeDocumentTypePAN/AADHAAR/SELFIE…
s3KeyStringS3 object key
statusEnumPENDING/VERIFIED/REJECTED
verifiedAtDateTime?Verification time

RepaymentTimeline

idStringPrimary key
loanIdStringFK → Loan
installmentNoIntEMI number
dueDateDateTimePayment due date
amountDecimalEMI amount
principalDecimalPrincipal component
interestDecimalInterest component
isPaidBooleanPayment status

PartnerUserActivitySession

idStringPrimary key
partnerUserIdStringFK → PartnerUser
brandIdStringFK → Brand
loginAtDateTimeSession start
lastActiveAtDateTimeLast ping time
logoutAtDateTime?Session end
The above 8 models are the core. The full schema has 167 models. Critical additional models documented below:

BrandConfig (feature flags per brand)

evaluationVersionStringV1 or V2
dashboard_versionStringV1 or V2 — controls which dashboard UI loads
loan_ops_versionStringV1 or V2
loan_collection_versionStringV1 or V2
isAABooleanAccount Aggregation enabled
is_cam_calculation_requiredBooleanCAM Calculator required
autoAllocationTypeStringLOGIN / MANUAL
skip_user_onboarding_completedBooleanSkip onboarding step
enable_central_dedupBooleanCross-brand deduplication
field_visitBooleanField visit feature enabled
fmsBlockStatusBooleanFMS block enabled
esignExpiryDayCountIntDays before e-sign link expires
salaryThresholdAmountIntMin salary for eligibility
rejectionDurationIntDays before rejected user can re-apply

UserDetails

userIdStringFK → User (1:1)
firstNameString?camelCase — needs double quotes in SQL
lastNameString?
dateOfBirthString?DOB string
genderString?
panNumberString?PAN — verified via Digitap
aadharNumberString?Aadhaar — verified via OTP
addressString?Residential address
pincodeString?PIN code
city / stateString?Auto-derived from pincode
profilePictureString?S3 key

UserBankAccount

userIdStringFK → User
accountNumberStringBank account number
ifscCodeStringBranch IFSC
bankNameString?Auto-fetched from IFSC
beneficiaryNameString?Account holder name
isPennyDropVerifiedBooleanPenny drop status
isPrimaryBooleanPrimary disbursement account

LoanAgreement

loanIdStringFK → Loan
docketIdString?E-sign provider docket ID
agreementS3KeyString?Generated PDF S3 key
signedAgreementS3KeyString?Signed PDF S3 key
statusEnumPENDING / SENT / SIGNED / EXPIRED
esignProviderStringSIGNZY / SIGNDESK
signedAtDateTime?When customer signed

LoanComment

loanIdStringFK → Loan
partnerUserIdStringFK → PartnerUser (author)
commentStringRemark text
createdAtDateTimeTimestamp

CAMCalculator

loanIdStringFK → Loan
userId / partnerUserId / brandIdStringFKs
salaryCreditDate1/2/3String?3 months salary dates
salaryAmount1/2/3Float?3 months salary amounts
avgSalary / actualSalaryFloat?Computed averages
eligibleFoir / foirAchieved / proposedFoirFloat?FOIR metrics
loanApplied / eligibleLoan / loanRecommendedFloat?Amount fields
roi / obligationsFloat?Rate of interest, existing obligations
repaymentDataJSON?Repayment schedule JSON

AAConsentRequest

userId / brandIdStringFKs
consentHandleString?AA provider's consent handle
consentStatusEnumPENDING / APPROVED / REJECTED / REVOKED
clientTransactionIdString?Provider transaction reference
providerStringFINDUIT / CART
consentUrlString?Link sent to customer for consent
expiresAtDateTime?Consent expiry

LeadForm

brandIdStringFK → Brand
email / phone / fullName / cityString?Lead contact info
platformString?Facebook, Instagram, etc.
statusEnumPENDING / PROCESSED / FAILED / DUPLICATE
campaignId / adId / formIdString?Facebook Ad campaign metadata
monthlySalary / panNumberString?From lead form responses
uploadedAt / processedAtDateTime?Processing timestamps

UserReminder

brandId / userIdStringFKs
channelEnumSMS / WHATSAPP / EMAIL
templateCodeStringMessage template identifier
scheduledAtDateTimeWhen to send
statusEnumPENDING / SENT / FAILED / CANCELLED
payloadJSON?Template variable overrides
providerMessageIdString?Provider delivery ID

BrandProvider

brandIdStringFK → Brand
typeEnumSMS / EMAIL / WHATSAPP / ESIGN / BSA / CREDIT_BUREAU / AA / DIALER
providerNameStringe.g. "SIGNZY", "GUPSHUP", "CART"
isPrimaryBooleanFirst to be tried
isActive / isDisabledBooleanEnable/disable per brand
configJSON?Provider-specific credentials/settings

BrandCard

brandIdStringFK → Brand
cardTypeStringProduct type identifier
isActiveBooleanCard product enabled
configJSON?Limits, eligibility, rates per card type

Notification

partnerUserIdStringFK → PartnerUser (recipient)
typeStringNEW_LOAN / PAYMENT_RECEIVED / STATUS_CHANGE / SYSTEM
title / bodyStringNotification content
isReadBooleanRead status
metadataJSON?loanId, userId for deep linking
createdAtDateTimeCreation timestamp
🌐

Web (Customer) API Endpoints

All endpoints under /api/v1/web/

MethodEndpointPurpose
POST/web/auth/registerRegister new customer, send OTP
POST/web/auth/loginLogin with phone (OTP flow)
POST/web/auth/verify-otpVerify OTP, receive JWT
POST/web/auth/resend-otpResend OTP
POST/web/auth/refresh-tokenRefresh JWT token
POST/web/auth/logoutInvalidate tokens
POST/web/kyc/verify-panVerify PAN via Digitap
POST/web/kyc/initiate-aadhaar-otpStart Aadhaar verification
POST/web/kyc/submit-aadhaar-otpComplete Aadhaar verification
POST/web/kyc/verify-mobileMobile OTP verification
GET/web/kyc/documentsList uploaded documents
POST/web/kyc/upload-documentUpload KYC document to S3
POST/web/personal-details/updateUpdate personal info
GET/web/personal-detailsGet personal details
POST/web/employment/addAdd employment record
POST/web/employment/verify-uanVerify UAN via EPFO
POST/web/bank/add-accountAdd bank account
POST/web/bank/verifyPenny drop verification
POST/web/bank/upload-statementUpload bank statement
GET/web/loansGet customer's loans
GET/web/loans/:loanIdGet specific loan details
👔

Partner API Endpoints

All endpoints under /api/v1/partner/brand/:brandId/

📋 Loans

MethodEndpoint (relative)
GET/loans
GET/loans/:loanId
POST/loans/:loanId/status
POST/loans/:loanId/update-with-reasons
POST/loans/:loanId/force-bypass-reports
POST/loans/:loanId/generate-ndc
GET/loans/disbursed-amount
GET/loans/unallocated

💼 Collections

MethodEndpoint (relative)
GET/collection
GET/collection/pre
GET/collection/post
POST/collection/:loanId/repayment-timeline
POST/collection/:loanId/settlement
POST/collection/:loanId/writeoff
POST/collection/allocate

👥 Customers

MethodEndpoint (relative)
GET/customers
GET/customers/:userId
POST/customers/:userId/allocate
POST/customers/:userId/reloan
GET/customers/unallocated
POST/customers/:userId/status

💳 Payments

MethodEndpoint (relative)
GET/payment
POST/payment/process
POST/payment/autopay
GET/payment/approval
POST/payment/approve/:id
POST/payment/reject/:id

📊 Dashboard

MethodEndpoint (relative)
GET/dashboard/stats
GET/dashboard/summary
GET/dashboard/users-by-subdomain
GET/dashboard/collection-analysis
GET/dashboard/disbursement-analysis
GET/dashboard/partner-user-leads-stats

👔 Partner Users

MethodEndpoint (relative)
GET/user
POST/user/create
PUT/user/:userId/update
DELETE/user/:userId
POST/user/:userId/allocate-loans
POST/user/generate-secure-code
GET/user/audit-logs

⚙️ Settings

MethodEndpoint (relative)
GET/settings/brand
PUT/settings/brand
GET/settings/evaluation-items
PUT/settings/evaluation-items
GET/settings/loan-rules
POST/settings/loan-rules
GET/settings/targets
GET/settings/appearance

📊 Reports & Search

MethodEndpoint (relative)
GET/report/:reportType
GET/report/:reportType/csv
GET/report/:reportType/download
GET/reports/login-logs
POST/global-search
GET/completed
GET/completed/settled
GET/completed/writeoff
🛡️

Admin API Endpoints

Super admin only — /api/v1/admin/

MethodEndpointPurpose
GET/admin/usersList all partner users across all brands
POST/admin/users/createCreate partner user (any brand)
PUT/admin/users/:userIdUpdate any partner user
GET/admin/settingsPlatform-wide settings
PUT/admin/settings/brand/:brandIdConfigure any brand
POST/admin/brandsCreate new lending brand
📄

Loans Service (Core)

The central business logic of the platform

🔄 Loan Lifecycle States

APPLIED UNDER_REVIEW SANCTIONED AGREEMENT_PENDING AGREEMENT_SIGNED DISBURSED OVERDUE SETTLED WRITTEN_OFF COMPLETED REJECTED

⚡ Auto-Allocation

When a new loan application comes in, the autoAllocation service automatically assigns it to an available loan executive based on:

Current workload Availability status Brand assignment Round-robin rotation

📧 Email Reminder System

The loan.email.reminder.service and email.reminder.config.service handle automated email reminders for:

Payment due (3 days before) Payment overdue Reloan eligibility Agreement signing reminder

♻️ Reloan Automation

The reloan.automation.service identifies customers eligible for a new loan (completed previous loan, good repayment history). It automatically creates a pre-populated loan application and notifies the customer.

💳

Payment Service

Multi-gateway payment orchestration

The payment.service acts as an abstraction layer over 5 payment gateways. It decides which gateway to use based on brand config and payment type, handles gateway-specific request formatting, processes webhook callbacks, and updates the loan/transaction records atomically.
💳

Razorpay

Card, UPI, netbanking, wallet. Primary collection gateway. Handles subscriptions for autopay.

Collection
💰

Cashfree

Alternate collection gateway. Used as fallback or for specific brands.

Collection
💵

Paytring

Additional payment option gateway for certain brands.

Collection
🏦

IDFC Bank

Bank transfer disbursement. Used to send loan amount directly to customer's account.

Disbursement
🏧

ICICI Bank

Alternative bank transfer disbursement gateway.

Disbursement
🔄

Razorpay Autopay

Recurring mandate creation. Monthly automatic collection from customer accounts.

Autopay
🧮

Evaluation & Business Rules Engine

Automated loan decisioning

📊 Evaluation Engine

When a loan application is submitted, the evaluation engine scores the application against configured criteria:

Income vs. loan amount ratio Employment stability Bank balance history Previous loan performance Credit score thresholds Document completeness

Each criterion has a configured weight. The total score determines if the loan auto-approves, auto-rejects, or goes to manual review. V2 adds more sophisticated ML-inspired scoring.

⚡ Business Rules Engine (BRE)

The BRE runs against third-party credit reports (CIR Pro V2, Equifax) and applies brand-configured hard rules:

Minimum credit score Maximum DPD count Blacklist check Maximum existing loans Bureau inquiry threshold

If any hard rule fails, the loan is auto-rejected. If all pass, it proceeds to the evaluation engine. Admins can configure thresholds per brand.

📢

Communication Service

Multi-channel messaging with provider failover

The communication layer abstracts SMS, Email, and WhatsApp channels behind a unified interface. Each channel has multiple provider implementations. If the primary provider fails, the system automatically falls back to the next configured provider.

📱 SMS Providers

SMS Gateway Hub Gupshup MSG91 NimbusIT

Used for OTP delivery, payment reminders, disbursement alerts, and collection follow-ups.

📧 Email Providers

SendGrid Brevo Zepto MSG91

Used for loan agreements, payment receipts, reminder emails, and NOC (No-Objection Certificate) delivery.

💬 WhatsApp Provider

AiSensey

Rich message templates for payment reminders, loan status updates, and document collection requests via WhatsApp Business API.

⚙️

Queue System & Background Workers

Async job processing pipeline

🐇 RabbitMQ Jobs

Internal message broker for high-frequency, low-latency jobs:

SMS reminders Email reminders WhatsApp messages Notification creation

Producer: API server publishes jobs. Consumer: reminder-worker process dequeues and sends messages. Failed jobs are retried with exponential backoff.

☁️ AWS SQS Queues

AWS-managed queues for critical, durable jobs:

Audit log events NOC email dispatch Heavy report generation

SQS provides durability guarantees and dead-letter queues. audit-logs-worker processes audit events. NOC emails sent after loan closure.

⏰ Cron Jobs

The dedicated cron worker PM2 process runs scheduled tasks:

Daily payment due reminders Weekly collection reports Overdue loan detection Autopay retry on failure Inactivity alert check Reloan eligibility check

🎯 Trigger.dev Jobs

Managed background jobs with built-in retry, monitoring, and scheduling:

Credit report refresh Bank statement re-analysis Bulk notification dispatch Report pre-computation

Redis Caching Layer

Performance optimization via response caching

Redis is used to cache expensive database queries. The custom @CacheResponse(ttl) decorator is applied to controller endpoints. The cache key is derived from the endpoint path + query parameters + brandId. Cache is invalidated when underlying data changes.

Cached Endpoints

Dashboard statsTTL: 5minExpensive aggregations
Loan listsTTL: 1minPaginated queries
Brand configTTL: 30minRarely changes
Evaluation itemsTTL: 30minSettings data
Credit reportsTTL: 24hrExternal API data

Cache Invalidation

Loan status updateInvalidate loan list cache
Brand settings updateInvalidate brand config cache
Payment receivedInvalidate dashboard cache
User createdInvalidate customer list cache
☁️

AWS Services

Cloud infrastructure used by the backend

📦

S3 — Public Bucket

Brand logos, public documents, blog images. Publicly accessible via CDN URLs.

🔒

S3 — Private Bucket

KYC documents (PAN, Aadhaar, selfies), bank statements, payslips. Accessed via time-limited presigned URLs only.

📨

SQS — Audit Queue

All API actions are logged as events to this queue. Processed by the audit-logs worker for compliance.

📩

SQS — NOC Queue

No-Objection Certificate dispatch queue. Ensures NDC emails are reliably sent after loan closure.

🔌

External API Integrations

All 25+ third-party services integrated

🆔

Digitap

Aadhaar OTP-based verification, PAN card verification, mobile-to-PAN lookup, pan-details-plus.

KYC
📊

Equifax

Credit bureau report pull. Provides credit score, payment history, inquiry history, account details.

Credit Bureau
📈

CIBIL

India's primary credit information company. Credit score and full report for loan decisioning.

Credit Bureau

CIR Pro V2

Advanced credit assessment with bureau data. Powers the Business Rules Engine decisions.

BRE
🏦

CART

Bank statement analysis. Analyzes PDF bank statements to extract cash flows, salary credits, EMI debits.

BSA
📉

Finbox

Financial analysis from bank data. Alternative bank statement analysis provider.

BSA
🎯

ScoreMe

Credit scoring and BDA (Business Data Analytics) reports. Advanced financial scoring.

Credit Score
🏛️

Account Aggregator

RBI-mandated AA framework. Consent-based bank data sharing directly from banks.

Bank Data

Penny Drop

Re-verify bank account by sending ₹1 and checking recipient name match before disbursement.

Bank Verify
✍️

Signzy V3

Digital e-signature for loan agreements. Sends agreement PDF, customer signs, webhook confirms.

eSign
📝

SignDesk

Alternative e-signature provider. Same workflow as Signzy with different API.

eSign
📋

DigiLocker 2.0

Government document verification platform. Fetch official Aadhaar, PAN, driving license from DigiLocker.

Docs
👷

EPFO / UAN

Phone-to-UAN lookup and UAN-to-employment history from EPFO provident fund records.

Employment
📞

Acefone

VoIP telephony API. Click-to-call, call recording, agent management for collection teams.

VoIP
🗺️

Google Maps / Geocoding

Convert user addresses to GPS coordinates. Verify address plausibility. Field visit routing.

Location
🤝

Lendbox

Partner lender API. Loan creation, disbursement, repayment sync for co-lending arrangements.

Co-lending
📱

Mobile to Address

Verify physical address from mobile number for fraud prevention.

Verify
🎮

Trigger.dev

Background job scheduling platform with dashboard, retries, and observability.

Jobs
🚀

Deployment & Process Management

PM2 configuration and server setup

⚙️ PM2 Processes

los-backend-api

instances2Cluster mode (load balanced)
max_memory4GBPer instance heap
modeclusterMulti-core utilization
port4002API listening port

los-backend-cron-worker

instances1Single fork mode
max_memory3GBCron + queue worker
modeforkDedicated cron process

🏗️ Server Configuration

50MB max body size CORS multi-origin Compression middleware Helmet security headers Throttle rate limiting Global validation pipe Swagger API docs Health check /health Graceful shutdown

Environment: .env.development and .env.production files. ConfigModule loads env vars and makes them injectable via ConfigService. BigInt serializer interceptor handles large number serialization to JSON.

📡

Partner API — Additional Endpoint Groups

API groups not covered in the main partner API section

🏦 Account Aggregation (AA)

MethodEndpoint
POST/aa/consent-request
POST/aa/consent-request/manual
GET/aa/consent-request/:id
GET/aa/user/:userId/consent-requests
GET/aa/consent-request/:id/data-sessions
POST/aa/consent-request/:id/status
POST/aa/user/:userId/send-consent-email
POST/aa/user/:userId/generate-consent-url
POST/aa/fetch-periodic-data
POST/aa/webhook (AA provider callbacks)

⏰ User Reminders

MethodEndpoint (relative to /partner/brand/:brandId/)
GET/user-reminders
POST/user-reminders
GET/user-reminders/:id/audit-logs
GET/user-reminders/dashboard-metrics/view
POST/user-reminders/dashboard-metrics/refresh

✅ Completed Loans

MethodEndpoint (relative to /partner/brand/:brandId/)
GET/completed (all terminal loans)
GET/completed/closed
GET/completed/settled
GET/completed/writeoff

📬 Lead Forms

MethodEndpoint (relative to /partner/brand/:brandId/)
POST/lead-forms/upload (multipart CSV)
GET/lead-forms
GET/lead-forms/stats
POST/lead-forms/sync
DELETE/lead-forms/bulk
GET/lead-forms/:id
PATCH/lead-forms/:id/status
GET/lead-forms/export (CSV blob)

🧮 CAM Calculator

MethodEndpoint
POST/loans/brand/:brandId/cam-calculator/save
GET/loans/cam-calculator/:loanId
GET/loans/user/:userId/brand/:brandId/cam-calculators
DELETE/loans/cam-calculator/:loanId

📞 Acefone Dialer

MethodEndpoint
POST/acefone/dialer/initiate
GET/acefone/dialer/user/:userId/calls
GET/acefone/dialer/partner/:partnerUserId/calls
GET/acefone/dialer/call/:callId
PATCH/acefone/dialer/call/:callId/end
GET/acefone/dialer/user/:userId/stats
GET/acefone/dialer/partner/:partnerUserId/stats

📊 Reports (all types)

MethodEndpoint (relative to /partner/brand/:brandId/)
GET/report/master-report?fromDate&toDate
GET/report/marketing-report?fromDate&toDate
GET/report/completed-no-repayment-report?fromDate&toDate
GET/report/:reportType/csv (CSV export)
GET/report/:reportType/download

⚙️ Settings Sub-Routes

MethodSub-path (under /settings/)
GET/PUT/appearance
GET/POST/DELETE/blocklist
GET/POST/PUT/DELETE/brand-cards
GET/POST/PUT/DELETE/brand-bank-accounts
GET/POST/PUT/DELETE/brand-providers
GET/POST/DELETE/non-repayment-dates
GET/POST/DELETE/partner-unavailability-dates
GET/PUT/brand-paths
GET/POST/PUT/DELETE/blogs
GET/POST/PUT/DELETE/brand-coupons
GET/POST/PUT/DELETE/reloan-configs
GET/POST/PUT/DELETE/brand-status-reasons
GET/POST/PUT/DELETE/brand-rating-matrix
GET/POST/PUT/DELETE/partner-user-rating-matrix
⚙️

Settings Module — 20 Sub-Modules

All setting sub-modules under app/partner/settings/

The settings parent module at app/partner/settings/ is a large composite module with 20 sub-modules, each handling a distinct configuration domain for a brand. All routes require ADMIN permission and are brand-scoped.

🎨 Appearance

Manages brand theme: primary/secondary colors, font family, logo URL, dark mode, rounded corners, full color token set (hover, active, focus, light, contrast variants). Injected as CSS variables by the frontend.

🚫 Blocklist

Manage PAN / Aadhaar / phone blocklist. Any loan application matching a blocked identifier auto-rejects at BRE stage. CRUD operations with reason logging.

🃏 Brand Cards

Card product configurations shown to customers. Each card has type, eligibility criteria, credit limit, and interest rates. BrandCard model — this model was completely missing from the database documentation.

🏦 Brand Bank Accounts

Brand's own bank accounts for disbursement and repayment. IFSC, account number, beneficiary name, account type. Multiple accounts supported per brand (e.g., IDFC for disbursement, Razorpay settlement for collection).

📝 Brand Blogs

Blog content management for the customer-facing web app. Title, body (markdown/HTML), featured image S3 key, published flag, and SEO metadata. Fetched by the customer web app to display educational content.

🎫 Brand Coupons

Discount coupons applied to loan processing fees or interest. Coupon code, discount type (flat/percent), discount value, max uses, expiry, and eligible product types.

📋 Brand Evaluation Items

Criteria used by the evaluation engine. Each item has: name, weight, threshold value, pass/fail logic, and whether it's a hard reject or soft flag. Supports both V1 and V2 evaluation engines.

📅 Brand Non-Repayment Dates

Public holidays and bank non-working days. When a due date falls on one of these days, the backend shifts the due date automatically. Affects NDC generation and overdue detection.

🔗 Brand Policy Links

T&C URL, privacy policy URL, FAQ URL. These are embedded in loan agreements and shown during customer onboarding. Brand-level overrides of the platform defaults.

🔌 Brand Provider

Third-party provider registry per brand. Type (SMS/EMAIL/WHATSAPP/ESIGN/BSA/CREDIT_BUREAU/AA/DIALER), provider name, isPrimary, isActive, isDisabled, and a JSON config blob with provider-specific API keys and settings. The communication service reads this to route to the correct provider.

🔄 Brand Reloan Configs

Rules for when a customer is eligible for a reloan: minimum days since last loan closure, minimum repayment rating, maximum active loans, and auto-create flag (auto-generate reloan application).

❌ Brand Status Reasons

Brand-customized rejection/status change reasons shown in the partner portal dropdowns. Each reason has a code, display label, and the loan statuses it applies to (REJECTED, WRITTEN_OFF, SETTLED, etc.).

⭐ Brand Rating Matrix

Brand-level customer scoring matrix. Criteria with weights and score ranges. Used to compute an overall customer rating that influences auto-allocation priority and reloan eligibility.

🏖️ Partner Unavailability Dates

Days when partner operations are paused (internal holidays, system maintenance). Auto-allocation, reminder scheduling, and cron-based tasks skip these dates.

⭐ Partner User Rating Matrix

Individual staff performance matrix. Tracks collection recovery rates, TAT, conversion ratios. Used for performance reviews and manager-level dashboards. Separate from the brand-level rating matrix.

📏 Loan Rules

Product configuration: min/max loan amount, tenure options, interest rate (flat/reducing), processing fee (flat/percent), risk category mapping. Multiple rules per brand for different product types.

🎯 Brand Targets

Monthly/quarterly targets at brand, team, and individual levels: disbursement amount targets, collection recovery targets, new customer targets. Used in dashboard performance widgets.

⚙️ General / Brand Config

Master brand configuration via UpdateBrandConfigDto: salary threshold, rejection duration, bank statement months, e-sign settings, section manager info, all version flags (dashboard/loan-ops/collection), CAM requirement, AA flag, field visit, auto-allocation type, age limits, central dedup, etc.

🆔

KYC & Document Service

Customer identity verification pipeline

KYC is a multi-step verification pipeline. Each step updates the customer's onboardingStep enum. The brand's BrandConfig controls which steps are mandatory. Steps: PAN → Aadhaar → Mobile → Selfie → Bank Account (penny drop) → Employment → Bank Statement → Evaluation.

🆔 PAN Verification

Customer enters PAN. Backend calls Digitap pan-details-plus API. Returns name, DOB, type (Individual/Company). PAN is stored and marked verified. If isAadhaarNumberRequired flag is set, the name from PAN must match Aadhaar name.

🏛️ Aadhaar Verification

OTP-based e-KYC via Digitap. Step 1: initiate-aadhaar-otp sends OTP to Aadhaar-linked mobile. Step 2: submit-aadhaar-otp validates OTP, returns masked Aadhaar details (name, address, DOB, photo). Address auto-filled from Aadhaar response.

📱 Mobile Verification

Separate OTP verification for the phone number used to register. Uses the mobile-verification module via EPFO / telecom APIs. Required for brands with isAlternateNumber enabled.

📋 Document Upload

All documents uploaded to S3 private bucket via pre-signed URLs. Document types: PAN_CARD, AADHAAR_FRONT, AADHAAR_BACK, SELFIE, SALARY_SLIP, BANK_STATEMENT, OTHER. Status: PENDING → VERIFIED / REJECTED. Partner can verify or reject with reason.

💰 Penny Drop

After customer adds bank account, a ₹1 transfer is initiated via Razorpay / external penny drop API. The beneficiary name returned is matched against the customer's name. If matched, account is marked isPennyDropVerified = true. Required before disbursement.

🏢 Employment Verification

Customer enters employer name, UAN, monthly salary. Backend calls EPFO via phoneToUanuanToEmployment chain to fetch employment history, current employer, and salary credits. Employment is verified against EPFO records.

✍️

E-sign Service

Digital loan agreement signing via Signzy / SignDesk

Controller: features/esign/esign.controller.ts. The brand's primary e-sign provider is configured in BrandProvider. Agreement PDF is generated with brand header/footer, customer details, and loan terms, then sent to the e-sign provider's docket system.

📄 Agreement Generation

When a loan is sanctioned, the backend generates the loan agreement PDF using Playwright/Puppeteer from an HTML template. The template uses brand-configured header/footer text from BrandConfig.loanAgreementHeader/Footer. The PDF is stored in S3 private bucket.

✍️ E-sign Initiation

The generated PDF is sent to Signzy V3 or SignDesk (based on brand's provider config). A docket is created with signatories (customer). The customer receives an SMS/email with the signing link. Docket ID stored in LoanAgreement.docketId.

🔔 Webhook Callback

When the customer signs (or the docket expires), the e-sign provider sends a webhook to /webhook/esign. The webhook handler: validates signature, updates LoanAgreement.status, stores the signed PDF S3 key, and triggers loan status transition to AGREEMENT_SIGNED. NOC email queued to SQS.

📋 E-sign Config

Per brand: esignDocketTitle, esignExpiryDayCount, esignFinalCopyRecipients (email list for final signed copy), esignNotificationEmailList (CC list). Configured in BrandConfig via General Settings.

🔔

Webhook Handler

Inbound callbacks from payment gateways and e-sign providers

Controller: core/webhooks/webhook.controller.ts. All webhook endpoints are public (no JWT required) but verify provider signatures via HMAC/secret. Each provider has its own signature validation logic.

💳 Razorpay Webhook

Receives payment.captured, payment.failed, subscription.charged, subscription.cancelled events. On payment.captured: creates PaymentCollectionTransaction, updates loan outstanding, checks if fully repaid → triggers COMPLETED status. Signature verified via Razorpay webhook secret.

💰 Cashfree Webhook

Receives payment success/failure events from Cashfree gateway. Same post-processing as Razorpay: transaction creation, outstanding update, status check. Signature verified via Cashfree's HMAC-SHA256.

✍️ E-sign Webhook

Receives signing completion or expiry events from Signzy/SignDesk. On completion: downloads signed PDF, stores in S3, updates LoanAgreement.status = SIGNED, moves loan to AGREEMENT_SIGNED. On expiry: marks agreement as EXPIRED, alerts partner via notification.

🏦 AA Webhook (external/aa/aa.webhook.controller.ts)

Receives consent status updates from the AA provider (FINDUIT/CART). On consent approval: updates AAConsentRequest.consentStatus, triggers fetchPeriodicData to pull bank statement data. On revocation: marks consent as REVOKED.

🔔

Notification Service

In-app notifications for partner staff

Controller: features/notification/notification.controller.ts. Notifications are created server-side on business events and stored in the Notification table. Partner users poll the notification endpoint or receive real-time updates.

📋 Notification Types

Notifications are created for: new loan application assigned, payment received on your loan, loan status changed, customer document uploaded, system alerts (partner user inactivity, version update). Each notification carries metadata JSON with deep-link data (loanId, userId) for frontend navigation.

🔔 API Endpoints

GET /notifications — fetch unread count + list for the authenticated partner user. PATCH /notifications/:id/read — mark single notification as read. PATCH /notifications/read-all — bulk mark all as read. DELETE /notifications/:id — dismiss. Supports pagination with ?page&limit.

⏱️

Activity Tracking Service

Partner user session and activity monitoring

Controller: app/partner/activity-tracking/partner.activity-tracking.controller.ts. Tracks partner user activity to detect inactivity, measure engagement, and support compliance audits.

📡 Activity Ping

Frontend's ActivityTrackerContext sends periodic pings (on mouse move, keypress, scroll). Backend receives these at the activity-tracking endpoint, updates PartnerUserActivitySession.lastActiveAt. If gap between pings exceeds threshold, the session is marked idle. Idle detection triggers alert to managers.

📋 Session Logging

Each login creates a new PartnerUserActivitySession record with loginAt. On logout, logoutAt is set. Admins can query session history to see when each staff member was active, total session durations, and idle periods. Used for compliance and productivity tracking.

🧠

ScoreMe BDA Service

Bureau Data Analysis for enhanced credit scoring

Controller: features/scoreMeBda/scoreMeBda.controller.ts. ScoreMe is a credit analytics provider that augments standard bureau data (CIBIL/Equifax) with additional behavioural scoring models.

When triggered (manually by credit executive or automatically post-evaluation), the backend calls ScoreMe's BDA API with the customer's PAN and bureau data. ScoreMe returns an enhanced report including:

Proprietary credit score (separate from CIBIL) Repayment behaviour analysis Credit utilization patterns Delinquency prediction score BDA report PDF

Results are stored against the customer and shown in the Credit Report tab of the customer detail page. The BDA report is accessible via the scoreMeBDA.ts frontend API service.

🤝

Lendbox Co-lending Feature

14 controllers for the Lendbox partner lender integration

Directory: features/Lendbox/controllers/. Lendbox is a co-lending marketplace. When a brand participates in Lendbox co-lending, certain loans are originated through Lendbox's platform. The integration has 14 dedicated controllers covering the full Lendbox loan lifecycle.

📋 Lendbox Controllers

lendbox-loan-creation lendbox-fetch-lbuserid lendbox-borrower-rps lendbox-get-borrower-rps lendbox-document-upload lendbox-get-uploaded-docs-list lendbox-esign lendbox-disbursal-utr lendbox-credit-order-callback lendbox-transaction-status lendbox-update-loan-status lendbox-wallet-orders lendbox-foreclosure-amount lendbox-download-noc

🔄 Lendbox Flow

1. Loan creation — send borrower data to Lendbox, receive Lendbox borrower ID. 2. Document upload — upload KYC docs to Lendbox system. 3. E-sign — Lendbox-managed e-sign flow. 4. Disbursal UTR — receive bank transfer reference from Lendbox. 5. Repayment — wallet orders and transaction status sync. 6. Foreclosure — compute foreclosure amount. 7. NOC — download no-objection certificate from Lendbox on loan closure. All callbacks come via lendbox-credit-order-callback.

🔑

API Key Management

External system access keys for the LOS platform

Controller: features/api-key/api-key.controller.ts. Allows brands to issue API keys for external systems (e.g., their own mobile apps, partner integrations) to call the LOS backend with brand-scoped access.

Operations: Create (generates a secure random key, hashed before storage), List (shows key metadata — last 4 chars only, creation date, last used), Revoke (soft delete), Rotate (create new + revoke old in one transaction). API keys bypass JWT auth but are validated by a dedicated ApiKeyGuard that checks the X-API-Key header against the brand's active keys. Scoped to the brand they were created for.

🛡️

Global Interceptors, Filters & Middleware

Cross-cutting concerns applied to every request

⚙️ Global Interceptors

BigIntSerializerInterceptor CacheResponseInterceptor LoggingInterceptor

BigIntSerializerInterceptor: PostgreSQL returns BigInt for certain count queries; JSON.stringify() throws on BigInt — this interceptor converts BigInt to String before serialization. CacheResponseInterceptor: Works with @CacheResponse(ttl) decorator to cache GET responses in Redis. LoggingInterceptor: Logs request method, URL, response time for every API call.

🚨 Global Exception Filter

A global NestJS exception filter catches all unhandled exceptions and normalizes them into a consistent error response shape: { statusCode, message, error, timestamp, path }. Prisma errors (P2002 unique violation, P2025 not found) are mapped to readable HTTP errors (409 Conflict, 404 Not Found). Validation errors from class-validator are returned as an array of field-level messages.

🛡️ Middleware

BrandValidationMiddleware RequestLoggingMiddleware Helmet (security headers) Compression (gzip) CORS (multi-origin)

BrandValidationMiddleware: On every /partner/brand/:brandId/ request, validates that the brandId in the URL actually exists and is active. Returns 404 if not. This prevents partner users from guessing brandIds.

✅ Health Check

Endpoint: GET /health (controller: common/health/health.controller.ts). Returns a JSON health report: database connectivity (Prisma ping), Redis connectivity, and process uptime. Used by load balancers and monitoring tools (UptimeRobot, AWS ELB health checks) to determine if an instance is healthy before routing traffic to it.