BACK_TO_LOGS// STEP_7_OF_10
HANDBOOK_GUIDE2026-06-30

Smart Lender: AI-Powered Loan Approval Prediction System ML Guide

By Rayan Syed
50 min read

Part 7: Flask API Backend

Save this script as app.py in your project folder.

7.1 Understanding Backend Web Servers & API Routing

In this phase, we build a local web backend using Flask.

  • API Routing: Routing is the mechanism that maps network URLs (endpoints) to specific Python functions. In Flask, we define routes using @app.route().
  • JSON Exchange: JavaScript on the frontend will capture user entries and package them as JSON. The backend extracts this JSON (request.get_json()), converts the values to floats/integers, and packs them into a NumPy array matching the exact structure used during model training.
  • Making Predictions: The Flask server loads our serialized model weights (joblib.load('models/loan_model.joblib')) in memory. When it receives a request, it calls model.predict() and returns the boolean approved/rejected decision back to the client.
  • Why We Need a Server: You might wonder: why can’t we run predictions directly in browser JavaScript? In real-world applications, machine learning models can weigh several hundred megabytes. Loading these models directly into the user’s web browser would freeze their system or crash the page. Running the model on a dedicated backend server keeps the client lightweight and secure.
from flask import Flask, request, jsonify, render_template
import joblib
import numpy as np
import os

app = Flask(__name__)

# Load the saved model and scaler
MODEL_PATH = 'models/loan_model.joblib'
SCALER_PATH = 'models/scaler.joblib'

if not os.path.exists(MODEL_PATH) or not os.path.exists(SCALER_PATH):
    print("ERROR: Model or Scaler not found! Please run train.py first.")
    exit(1)

model = joblib.load(MODEL_PATH)
scaler = joblib.load(SCALER_PATH)

@app.route('/')
def home():
    return render_template('index.html')

@app.route('/predict', methods=['POST'])
def predict():
    try:
        data = request.get_json()
        
        # Build features list in the exact order the model expects:
        # no_of_dependents, education, self_employed, income_annum, loan_amount,
        # loan_term, cibil_score, residential_assets_value, commercial_assets_value,
        # luxury_assets_value, bank_asset_value
        features_raw = np.array([[
            int(data['dependents']),
            int(data['education']),
            int(data['self_employed']),
            float(data['income']),
            float(data['loan_amount']),
            int(data['loan_term']),
            int(data['cibil_score']),
            float(data['residential_assets']),
            float(data['commercial_assets']),
            float(data['luxury_assets']),
            float(data['bank_assets'])
        ]])
        
        # Scale the features using the saved StandardScaler
        features_scaled = scaler.transform(features_raw)
        
        # Predict target (0 = Approved, 1 = Rejected)
        prediction = model.predict(features_scaled)[0]
        prediction_proba = model.predict_proba(features_scaled)[0]
        
        # Invert label mapping to return approved state
        approved = int(prediction) == 0
        
        return jsonify({
            'approved': approved,
            'approval_probability': float(prediction_proba[0]) * 100,
            'rejection_probability': float(prediction_proba[1]) * 100
        })
    except Exception as e:
        return jsonify({'error': str(e)}), 400

if __name__ == '__main__':
    app.run(port=5000, debug=True)

Checkpoint: Backend Complete

At this stage, your local Flask backend is complete and ready to receive loan applications. However, if you visit the server now, you will see a TemplateNotFound error. This is because we haven’t created the frontend form files yet! In the next part, we will build the user interface files (index.html, style.css, and script.js) that will talk to this Flask backend.