Skip to content

Loan API

This document provides information about the Loan API endpoints in the UBU Finance backend.

Overview

The Loan API allows you to create, retrieve, update, and manage loans within the UBU Finance system. Loans represent financial products that allow users to borrow money with specific terms and repayment schedules.

Authentication

All Loan API endpoints require authentication. You must include a valid JWT token in the Authorization header of your requests.

Authorization: Bearer <your_token>

Endpoints

List Loans

Retrieves a list of loans with optional filtering.

Endpoint: GET /api/loans

Query Parameters:

Parameter Type Description
page integer Page number for pagination (default: 1)
limit integer Number of items per page (default: 10, max: 100)
loan_id UUID Filter by loan ID
customer_id UUID Filter by customer ID
loan_type_id UUID Filter by loan type ID
status string Filter by loan status (e.g., 'pending', 'approved', 'active', 'closed')
min_amount decimal Filter loans with amount greater than or equal to this value
max_amount decimal Filter loans with amount less than or equal to this value
min_term integer Filter loans with term months greater than or equal to this value
max_term integer Filter loans with term months less than or equal to this value
min_interest_rate decimal Filter loans with interest rate greater than or equal to this value
max_interest_rate decimal Filter loans with interest rate less than or equal to this value
disbursed_after datetime Filter loans disbursed after this date and time (ISO 8601 format)
disbursed_before datetime Filter loans disbursed before this date and time (ISO 8601 format)

Response:

{
  "items": [
    {
      "loan_id": "550e8400-e29b-41d4-a716-446655440001",
      "loan_number": "LOAN-12345",
      "user_id": "550e8400-e29b-41d4-a716-446655440010",
      "loan_type": "personal",
      "amount": 10000.00,
      "currency": "RWF",
      "interest_rate": 5.5,
      "term_months": 24,
      "status": "active",
      "disbursement_date": "2025-01-15T12:00:00Z",
      "maturity_date": "2027-01-15T12:00:00Z",
      "created_at": "2025-01-10T12:00:00Z",
      "updated_at": "2025-01-15T12:00:00Z"
    }
  ],
  "total": 1,
  "page": 1,
  "limit": 10,
  "pages": 1
}

Get Loan

Retrieves details of a specific loan.

Endpoint: GET /api/loans/{loan_id}

Path Parameters:

Parameter Type Description
loan_id UUID The ID of the loan to retrieve

Response:

{
  "loan_id": "550e8400-e29b-41d4-a716-446655440001",
  "loan_number": "LOAN-12345",
  "user_id": "550e8400-e29b-41d4-a716-446655440010",
  "loan_type": "personal",
  "amount": 10000.00,
  "currency": "RWF",
  "interest_rate": 5.5,
  "term_months": 24,
  "status": "active",
  "disbursement_date": "2025-01-15T12:00:00Z",
  "maturity_date": "2027-01-15T12:00:00Z",
  "remaining_balance": 9500.00,
  "next_payment_date": "2025-02-15T12:00:00Z",
  "next_payment_amount": 438.71,
  "created_at": "2025-01-10T12:00:00Z",
  "updated_at": "2025-01-15T12:00:00Z",
  "metadata": {
    "purpose": "home renovation",
    "collateral": "none"
  }
}

Apply for Loan

Submits a loan application.

Endpoint: POST /api/loans/apply

Request Body:

{
  "user_id": "550e8400-e29b-41d4-a716-446655440010",
  "loan_type": "personal",
  "amount": 10000.00,
  "currency": "RWF",
  "term_months": 24,
  "purpose": "home renovation",
  "income": 5000.00,
  "employment_status": "full-time",
  "employer": "ACME Corp",
  "collateral": {
    "type": "none"
  }
}

Response:

{
  "application_id": "550e8400-e29b-41d4-a716-446655440020",
  "user_id": "550e8400-e29b-41d4-a716-446655440010",
  "loan_type": "personal",
  "amount": 10000.00,
  "currency": "RWF",
  "term_months": 24,
  "status": "pending",
  "created_at": "2025-01-10T12:00:00Z",
  "updated_at": "2025-01-10T12:00:00Z",
  "estimated_interest_rate": 5.5,
  "estimated_monthly_payment": 438.71
}

List Loan Applications

Retrieves a list of loan applications with optional filtering.

Endpoint: GET /api/loans/applications

Query Parameters:

Parameter Type Description
application_id UUID Filter by application ID
customer_id UUID Filter by customer ID
loan_type_id UUID Filter by loan type ID
status string Filter by application status (e.g., 'pending', 'approved', 'rejected')
min_amount decimal Filter applications with requested amount greater than or equal to this value
max_amount decimal Filter applications with requested amount less than or equal to this value
min_term integer Filter applications with requested term greater than or equal to this value
max_term integer Filter applications with requested term less than or equal to this value
created_after datetime Filter applications created after this date and time (ISO 8601 format)
created_before datetime Filter applications created before this date and time (ISO 8601 format)

Response:

{
  "items": [
    {
      "application_id": "550e8400-e29b-41d4-a716-446655440020",
      "user_id": "550e8400-e29b-41d4-a716-446655440010",
      "loan_type": "personal",
      "requested_amount": 10000.00,
      "currency": "RWF",
      "requested_term": 24,
      "status": "pending",
      "created_at": "2025-01-10T12:00:00Z",
      "updated_at": "2025-01-10T12:00:00Z"
    }
  ],
  "total": 1,
  "page": 1,
  "limit": 10,
  "pages": 1
}

Get Customer Loan Applications

Retrieves a list of loan applications for a specific customer with optional filtering.

Endpoint: GET /api/loans/applications/customer/{customer_id}

Path Parameters:

Parameter Type Description
customer_id UUID The ID of the customer

Query Parameters:

Parameter Type Description
loan_type_id UUID Filter by loan type ID
status string Filter by application status (e.g., 'pending', 'approved', 'rejected')
min_amount decimal Filter applications with requested amount greater than or equal to this value
max_amount decimal Filter applications with requested amount less than or equal to this value
min_term integer Filter applications with requested term greater than or equal to this value
max_term integer Filter applications with requested term less than or equal to this value
created_after datetime Filter applications created after this date and time (ISO 8601 format)
created_before datetime Filter applications created before this date and time (ISO 8601 format)

Response:

{
  "items": [
    {
      "application_id": "550e8400-e29b-41d4-a716-446655440020",
      "user_id": "550e8400-e29b-41d4-a716-446655440010",
      "loan_type": "personal",
      "requested_amount": 10000.00,
      "currency": "RWF",
      "requested_term": 24,
      "status": "pending",
      "created_at": "2025-01-10T12:00:00Z",
      "updated_at": "2025-01-10T12:00:00Z"
    }
  ],
  "total": 1,
  "page": 1,
  "limit": 10,
  "pages": 1
}

Get Loan Application Status

Retrieves the status of a loan application.

Endpoint: GET /api/loans/applications/{application_id}

Path Parameters:

Parameter Type Description
application_id UUID The ID of the loan application

Response:

{
  "application_id": "550e8400-e29b-41d4-a716-446655440020",
  "status": "approved",
  "review_notes": "Application approved based on credit score and income verification",
  "approved_amount": 10000.00,
  "approved_term_months": 24,
  "approved_interest_rate": 5.5,
  "monthly_payment": 438.71,
  "next_steps": "Please sign the loan agreement to proceed with disbursement",
  "updated_at": "2025-01-12T12:00:00Z"
}

Get Loan Repayment Schedule

Retrieves the repayment schedule for a loan.

Endpoint: GET /api/loans/{loan_id}/schedule

Path Parameters:

Parameter Type Description
loan_id UUID The ID of the loan

Response:

{
  "loan_id": "550e8400-e29b-41d4-a716-446655440001",
  "loan_number": "LOAN-12345",
  "total_payments": 24,
  "monthly_payment": 438.71,
  "total_interest": 529.04,
  "total_repayment": 10529.04,
  "schedule": [
    {
      "payment_number": 1,
      "due_date": "2025-02-15T12:00:00Z",
      "payment_amount": 438.71,
      "principal": 396.04,
      "interest": 42.67,
      "remaining_balance": 9603.96,
      "status": "paid"
    },
    {
      "payment_number": 2,
      "due_date": "2025-03-15T12:00:00Z",
      "payment_amount": 438.71,
      "principal": 397.73,
      "interest": 40.98,
      "remaining_balance": 9206.23,
      "status": "pending"
    }
  ]
}

Make Loan Payment

Makes a payment towards a loan.

Endpoint: POST /api/loans/{loan_id}/payments

Path Parameters:

Parameter Type Description
loan_id UUID The ID of the loan

Request Body:

{
  "amount": 438.71,
  "payment_method": "bank_transfer",
  "source_account_id": "550e8400-e29b-41d4-a716-446655440002",
  "payment_date": "2025-02-15T12:00:00Z",
  "notes": "Regular monthly payment"
}

Response:

{
  "payment_id": "550e8400-e29b-41d4-a716-446655440030",
  "loan_id": "550e8400-e29b-41d4-a716-446655440001",
  "amount": 438.71,
  "payment_method": "bank_transfer",
  "source_account_id": "550e8400-e29b-41d4-a716-446655440002",
  "payment_date": "2025-02-15T12:00:00Z",
  "status": "completed",
  "principal_applied": 396.04,
  "interest_applied": 42.67,
  "remaining_balance": 9603.96,
  "transaction_id": "550e8400-e29b-41d4-a716-446655440040",
  "created_at": "2025-02-15T12:00:00Z"
}

Get Loan Payments

Retrieves payment history for a loan.

Endpoint: GET /api/loans/{loan_id}/payments

Path Parameters:

Parameter Type Description
loan_id UUID The ID of the loan

Query Parameters:

Parameter Type Description
page integer Page number for pagination (default: 1)
limit integer Number of items per page (default: 10, max: 100)

Response:

{
  "items": [
    {
      "payment_id": "550e8400-e29b-41d4-a716-446655440030",
      "loan_id": "550e8400-e29b-41d4-a716-446655440001",
      "amount": 438.71,
      "payment_method": "bank_transfer",
      "payment_date": "2025-02-15T12:00:00Z",
      "status": "completed",
      "principal_applied": 396.04,
      "interest_applied": 42.67,
      "remaining_balance": 9603.96,
      "created_at": "2025-02-15T12:00:00Z"
    }
  ],
  "total": 1,
  "page": 1,
  "limit": 10,
  "pages": 1
}

Client Implementation Examples

Python

import requests
import json

# Configuration
API_URL = "http://localhost:8080"
TOKEN = "your_jwt_token"

headers = {
    "Authorization": f"Bearer {TOKEN}",
    "Content-Type": "application/json"
}

# List loans
def list_loans(user_id=None, status=None, page=1, limit=10):
    params = {
        "page": page,
        "limit": limit
    }

    if user_id:
        params["user_id"] = user_id

    if status:
        params["status"] = status

    response = requests.get(f"{API_URL}/api/loans", headers=headers, params=params)

    if response.status_code == 200:
        return response.json()
    else:
        print(f"Error: {response.status_code}")
        print(response.text)
        return None

# Apply for a loan
def apply_for_loan(user_id, loan_type, amount, currency, term_months, purpose):
    payload = {
        "user_id": user_id,
        "loan_type": loan_type,
        "amount": amount,
        "currency": currency,
        "term_months": term_months,
        "purpose": purpose
    }

    response = requests.post(f"{API_URL}/api/loans/apply", headers=headers, json=payload)

    if response.status_code == 201:
        return response.json()
    else:
        print(f"Error: {response.status_code}")
        print(response.text)
        return None

# Get loan repayment schedule
def get_loan_schedule(loan_id):
    response = requests.get(f"{API_URL}/api/loans/{loan_id}/schedule", headers=headers)

    if response.status_code == 200:
        return response.json()
    else:
        print(f"Error: {response.status_code}")
        print(response.text)
        return None

# Example usage
loans = list_loans(user_id="550e8400-e29b-41d4-a716-446655440010")
print(json.dumps(loans, indent=2))

loan_application = apply_for_loan(
    user_id="550e8400-e29b-41d4-a716-446655440010",
    loan_type="personal",
    amount=10000.00,
    currency="RWF",
    term_months=24,
    purpose="home renovation"
)
print(json.dumps(loan_application, indent=2))

schedule = get_loan_schedule(loan_id="550e8400-e29b-41d4-a716-446655440001")
print(json.dumps(schedule, indent=2))

JavaScript

// Configuration
const API_URL = 'http://localhost:8080';
const TOKEN = 'your_jwt_token';

const headers = {
  'Authorization': `Bearer ${TOKEN}`,
  'Content-Type': 'application/json'
};

// List loans
async function listLoans(params = {}) {
  const queryParams = new URLSearchParams();

  for (const [key, value] of Object.entries(params)) {
    if (value !== undefined && value !== null) {
      queryParams.append(key, value);
    }
  }

  const url = `${API_URL}/api/loans?${queryParams.toString()}`;

  try {
    const response = await fetch(url, {
      method: 'GET',
      headers
    });

    if (!response.ok) {
      throw new Error(`HTTP error! Status: ${response.status}`);
    }

    return await response.json();
  } catch (error) {
    console.error('Error listing loans:', error);
    throw error;
  }
}

// Apply for a loan
async function applyForLoan(loanData) {
  try {
    const response = await fetch(`${API_URL}/api/loans/apply`, {
      method: 'POST',
      headers,
      body: JSON.stringify(loanData)
    });

    if (!response.ok) {
      throw new Error(`HTTP error! Status: ${response.status}`);
    }

    return await response.json();
  } catch (error) {
    console.error('Error applying for loan:', error);
    throw error;
  }
}

// Make a loan payment
async function makeLoanPayment(loanId, paymentData) {
  try {
    const response = await fetch(`${API_URL}/api/loans/${loanId}/payments`, {
      method: 'POST',
      headers,
      body: JSON.stringify(paymentData)
    });

    if (!response.ok) {
      throw new Error(`HTTP error! Status: ${response.status}`);
    }

    return await response.json();
  } catch (error) {
    console.error('Error making loan payment:', error);
    throw error;
  }
}

// Example usage
async function exampleUsage() {
  try {
    // List loans for a specific user
    const loans = await listLoans({
      user_id: '550e8400-e29b-41d4-a716-446655440010',
      status: 'active',
      page: 1,
      limit: 10
    });
    console.log('Loans:', loans);

    // Apply for a new loan
    const loanApplication = await applyForLoan({
      user_id: '550e8400-e29b-41d4-a716-446655440010',
      loan_type: 'personal',
      amount: 10000.00,
      currency: 'RWF',
      term_months: 24,
      purpose: 'home renovation'
    });
    console.log('Loan application:', loanApplication);

    // Make a loan payment
    const payment = await makeLoanPayment('550e8400-e29b-41d4-a716-446655440001', {
      amount: 438.71,
      payment_method: 'bank_transfer',
      source_account_id: '550e8400-e29b-41d4-a716-446655440002',
      payment_date: new Date().toISOString()
    });
    console.log('Payment:', payment);
  } catch (error) {
    console.error('Example usage error:', error);
  }
}

exampleUsage();

cURL

# Set your JWT token
TOKEN="your_jwt_token"

# List loans
curl -X GET "http://localhost:8080/api/loans?page=1&limit=10" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json"

# Get a specific loan
curl -X GET "http://localhost:8080/api/loans/550e8400-e29b-41d4-a716-446655440001" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json"

# Apply for a loan
curl -X POST "http://localhost:8080/api/loans/apply" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "user_id": "550e8400-e29b-41d4-a716-446655440010",
    "loan_type": "personal",
    "amount": 10000.00,
    "currency": "RWF",
    "term_months": 24,
    "purpose": "home renovation"
  }'

# Get loan repayment schedule
curl -X GET "http://localhost:8080/api/loans/550e8400-e29b-41d4-a716-446655440001/schedule" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json"

# Make a loan payment
curl -X POST "http://localhost:8080/api/loans/550e8400-e29b-41d4-a716-446655440001/payments" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 438.71,
    "payment_method": "bank_transfer",
    "source_account_id": "550e8400-e29b-41d4-a716-446655440002"
  }'

Error Handling

The Loan API returns standard HTTP status codes:

Status Code Description
200 OK - The request was successful
201 Created - A new resource was created
400 Bad Request - The request was invalid
401 Unauthorized - Authentication is required
403 Forbidden - The user does not have permission
404 Not Found - The resource was not found
409 Conflict - The request could not be completed due to a conflict
422 Unprocessable Entity - The request was well-formed but could not be processed
500 Internal Server Error - An error occurred on the server

Error responses include a JSON body with details:

{
  "error": {
    "code": "insufficient_credit_score",
    "message": "Loan application denied due to insufficient credit score",
    "details": {
      "required_score": 650,
      "actual_score": 580
    }
  }
}

Rate Limiting

The Loan API is subject to rate limiting. See the Rate Limiting documentation for details.

Security Considerations

  • All Loan API endpoints are protected by authentication
  • Sensitive operations require appropriate permissions
  • All requests are logged for audit purposes
  • Loan applications and disbursements are subject to additional verification
  • IP whitelisting may be enforced for sensitive operations

For more information on security features, see the Security Overview.