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.
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.