UME Loans API

Backend Documentation

Overview

UME Loans API is a NestJS-based backend service providing RESTful endpoints for the Loan Application Management Portal. It features PostgreSQL storage via Drizzle ORM, Redis caching, AI-powered credit risk assessment, and Swagger documentation.

5
API Endpoints
3
Database Tables
4
Architecture Layers

Tech Stack

TechnologyPurpose
NestJS 11Node.js framework (TypeScript)
Drizzle ORMType-safe database ORM
Neon PostgreSQLServerless database (Sydney region)
Upstash RedisCaching & rate limiting
OpenAI APIAI credit risk assessment
Swagger / OpenAPIInteractive API documentation
DockerContainerized deployment
RailwayCloud deployment platform

Architecture

Clean Architecture with 4 distinct layers:

graph TD Client["Frontend (Next.js)"] -->|HTTP| Controller Controller -->|Validate & Route| Service Service -->|Business Logic| Repository Repository -->|SQL| DB["PostgreSQL (Neon)"] Service -->|Cache| Redis["Redis (Upstash)"] Service -->|AI| Provider["OpenAI Provider"] style Client fill:#fff7ed,stroke:#ea580c style Controller fill:#fef3c7,stroke:#d97706 style Service fill:#dbeafe,stroke:#2563eb style Repository fill:#dcfce7,stroke:#16a34a style DB fill:#f3e8ff,stroke:#9333ea style Redis fill:#fce7f3,stroke:#db2777 style Provider fill:#e0f2fe,stroke:#0284c7
LayerResponsibilityScalability
ControllerRequest validation, routing, Swagger docsAPI versioning (v1/v2)
ServiceBusiness logic, state machine validationWorkflow engine, event publishing
RepositoryData access, query buildingPagination, filtering, full-text search
ProviderExternal service abstraction (AI)Swap AI models, add credit bureau APIs

API Endpoints

GET /api/v1/applications

List all loan applications. Optional filter: ?status=Pending

GET /api/v1/applications/:id

Get a single application with full status history

PATCH /api/v1/applications/:id/status

Update application status. Body: { "status": "Under Review", "notes": "..." }

POST /api/v1/applications/:id/ai-assessment

Run AI credit risk assessment for the application

GET /api/v1/health

Health check endpoint

Database Schema

erDiagram loan_applications ||--o{ status_history : has loan_applications ||--o{ ai_assessments : has loan_applications { varchar id PK varchar applicant_name numeric loan_amount varchar loan_purpose numeric annual_income varchar employment_status int credit_score date application_date varchar current_status timestamp created_at timestamp updated_at } status_history { serial id PK varchar application_id FK varchar status text notes timestamp created_at } ai_assessments { serial id PK varchar application_id FK varchar risk_level text summary text recommendation timestamp created_at }

Status Workflow

stateDiagram-v2 [*] --> Pending Pending --> UnderReview : Start Review UnderReview --> Approved : Approve UnderReview --> Rejected : Reject Approved --> [*] Rejected --> [*]
FromAllowed TransitionsValidation
PendingUnder ReviewService layer enforces
Under ReviewApproved, RejectedService layer enforces
ApprovedNone (terminal)400 Bad Request
RejectedNone (terminal)400 Bad Request

AI Assessment

sequenceDiagram participant Officer participant API participant OpenAI participant DB Officer->>API: POST /applications/:id/ai-assessment API->>DB: Fetch application data DB-->>API: Application details API->>OpenAI: Credit risk prompt OpenAI-->>API: Risk analysis (JSON) API->>DB: Store assessment API-->>Officer: { riskLevel, summary, recommendation }

Provider Pattern

The AI module uses an interface-based provider pattern (AiProvider). The default implementation uses OpenAI (gpt-4o-mini). If no API key is configured, it falls back to a rule-based assessment engine using credit score and debt-to-income ratio. The provider can be swapped without changing any business logic.

Caching & Rate Limiting

Redis Cache

  • Application list cached for 30s
  • Individual application cached for 30s
  • Cache invalidated on status update
  • Graceful degradation when Redis unavailable

Rate Limiting

  • Sliding window: 60 requests per minute
  • Powered by Upstash Ratelimit
  • Analytics enabled
  • Disabled when Redis not configured

CI/CD Pipeline

WorkflowTriggerDescription
CIPush / PR to mainLint, type check, build
SecurityPush / PR + weeklynpm audit + CodeQL analysis
AutomationPR openedAuto-labeling by path and size
Pagesdocs/ changedDeploy documentation to GitHub Pages

Deployment

graph LR Push["git push main"] --> CI["CI Pipeline"] CI --> Build["Docker Build"] Build --> Railway["Railway Deploy"] Railway --> Health["/api/v1/health"] style Push fill:#fff7ed,stroke:#ea580c style CI fill:#fef3c7,stroke:#d97706 style Build fill:#dbeafe,stroke:#2563eb style Railway fill:#dcfce7,stroke:#16a34a style Health fill:#f3e8ff,stroke:#9333ea

Platform: Railway (Dockerfile-based deployment)

Health Check: /api/v1/health

Database: Neon PostgreSQL (ap-southeast-2, Sydney)

Swagger Docs: /docs (live interactive API documentation)