Skip to main content

Record Loan Repayment

Process loan repayment transactions with automated payment allocation across fees, penalties, interest, and principal following the payment hierarchy.

Overview

The Loan Repayment Commands enable secure processing of loan payments through multiple channels. These operations automatically allocate payments according to the configured payment hierarchy (typically: Fees → Penalties → Interest → Principal), update loan schedules, manage account balances, and maintain compliance with loan product rules.

Available Commands

  1. InitiateLoanRepaymentCommand - Process loan repayment from external sources (cash, bank transfer, etc.)
  2. InitiateLoanRepaymentWithDepositCommand - Process loan repayment by debiting a deposit account

Key Capabilities

  • Automatic Payment Allocation: Distributes payments across fees, penalties, interest, and principal
  • Schedule-Based Processing: Updates loan repayment schedules in chronological order
  • Multi-Channel Support: Accepts payments from various transaction channels
  • Partial Payment Handling: Processes payments less than total amount due
  • External Channel Integration: Tracks payments from external institutions
  • Deposit Account Integration: Directly debits customer deposit accounts
  • Backdating Support: Allows backdated repayment transactions
  • Transaction Tracking: Generates unique transaction keys for audit trails
  • State Management: Updates loan and schedule states based on payment application
  • Accounting Integration: Creates appropriate GL entries based on loan product rules

Command 1: InitiateLoanRepaymentCommand

Process loan repayment from external payment channels (cash, bank transfer, mobile money, etc.).

API Endpoint

POST /api/bpm/cmd

Headers

Content-Type: application/json
Authorization: Bearer {access_token}
X-Tenant-ID: {tenant_id}

Request Structure

{
"commandName": "InitiateLoanRepaymentCommand",
"data": {
"accountEncodedKey": "string",
"channelEncodedKey": "string",
"amount": "decimal",
"notes": "string",
"serviceId": "string",
"serviceDescription": "string",
"isBackDated": "boolean",
"backDateValueDate": "string (ISO 8601)",
"isBookingDate": "boolean",
"bookingDate": "string (ISO 8601)",
"repaymentChannelDetails": {
"institutionCode": "string",
"institutionAccount": "string",
"narration": "string",
"reference": "string",
"providerCode": "string",
"note": "string"
}
}
}

Request Fields

FieldTypeRequiredDescriptionValidation
accountEncodedKeystringYesLoan account number or encoded keyMust exist, must be Active or In_Arrears
channelEncodedKeystringYesTransaction channel identifierMust exist in system
amountdecimalYesRepayment amountMust be > 0
notesstringNoPayment description/remarksFree-text notes
serviceIdstringNoService identifierDefaults to "LOAN_REPAYMENT"
serviceDescriptionstringNoService descriptionDefaults to "LOAN REPAYMENT"
isBackDatedbooleanNoWhether transaction is backdatedDefaults to false
backDateValueDatestringConditionalTransaction value dateRequired if isBackDated=true (ISO 8601 format)
isBookingDatebooleanNoWhether to specify booking dateDefaults to false
bookingDatestringConditionalTransaction booking dateRequired if isBookingDate=true (ISO 8601 format)
repaymentChannelDetailsobjectNoExternal channel payment detailsOptional for tracking external payments

Repayment Channel Details Object

FieldTypeRequiredDescription
institutionCodestringNoExternal institution code
institutionAccountstringNoExternal institution account
narrationstringNoPayment narration
referencestringNoExternal payment reference
providerCodestringNoPayment provider code
notestringNoAdditional notes

Response Structure

Success Response

{
"isSuccessful": true,
"message": "Loan repayment has been processed successfully.",
"statusCode": "00",
"data": {
"transactionKey": "8A3F2D1E9B5C4F7A6E8D2C1B3A9F5E7D",
"principalPaid": 50000.00,
"interestPaid": 5000.00,
"feesPaid": 500.00,
"penaltiesPaid": 1000.00,
"totalPaid": 56500.00
}
}

Error Response

{
"isSuccessful": false,
"message": "The loan account has been locked presently and no transaction can be posted until it is unlocked",
"statusCode": "REQUEST_NOT_VALID"
}

Response Fields

FieldTypeDescription
isSuccessfulbooleanIndicates if repayment was successful
messagestringDescriptive result message
statusCodestringResponse code (00 = success)
transactionKeystringUnique transaction identifier
principalPaiddecimalAmount applied to principal
interestPaiddecimalAmount applied to interest
feesPaiddecimalAmount applied to fees
penaltiesPaiddecimalAmount applied to penalties
totalPaiddecimalTotal amount processed

Command 2: InitiateLoanRepaymentWithDepositCommand

Process loan repayment by debiting funds from a customer's deposit account.

API Endpoint

POST /api/bpm/cmd

Headers

Content-Type: application/json
Authorization: Bearer {access_token}
X-Tenant-ID: {tenant_id}

Request Structure

{
"commandName": "InitiateLoanRepaymentWithDepositCommand",
"data": {
"accountEncodedKey": "string",
"depositAccountEncodedKey": "string",
"amount": "decimal",
"notes": "string",
"serviceId": "string",
"serviceDescription": "string",
"allowPartial": "boolean",
"isBackDated": "boolean",
"backDateValueDate": "string (ISO 8601)",
"isBookingDate": "boolean",
"bookingDate": "string (ISO 8601)"
}
}

Request Fields

FieldTypeRequiredDescriptionValidation
accountEncodedKeystringYesLoan account number or encoded keyMust exist, must be Active or In_Arrears
depositAccountEncodedKeystringYesDeposit account number or encoded keyMust exist, must have sufficient balance
amountdecimalYesRepayment amountMust be > 0
notesstringNoPayment description/remarksFree-text notes
serviceIdstringNoService identifierOptional service tracking
serviceDescriptionstringNoService descriptionHuman-readable service info
allowPartialbooleanNoAllow partial payment if insufficient balanceDefaults to false
isBackDatedbooleanNoWhether transaction is backdatedDefaults to false
backDateValueDatestringConditionalTransaction value dateRequired if isBackDated=true (ISO 8601 format)
isBookingDatebooleanNoWhether to specify booking dateDefaults to false
bookingDatestringConditionalTransaction booking dateRequired if isBookingDate=true (ISO 8601 format)

Response Structure

Same as InitiateLoanRepaymentCommand above.


Sample Requests

1. Basic Cash Loan Repayment

{
"commandName": "InitiateLoanRepaymentCommand",
"data": {
"accountEncodedKey": "LOAN123456789",
"channelEncodedKey": "CHANNEL_CASH",
"amount": 25000.00,
"notes": "Monthly installment payment - December 2024"
}
}

Use Case: Customer makes regular monthly payment at branch with cash.

2. External Bank Transfer Repayment

{
"commandName": "InitiateLoanRepaymentCommand",
"data": {
"accountEncodedKey": "8A3F2D1E9B5C4F7A6E8D2C1B3A9F5E7D",
"channelEncodedKey": "CHANNEL_BANK_TRANSFER",
"amount": 50000.00,
"notes": "Partial loan repayment from external bank",
"serviceId": "BANK_TRANSFER_REPAY",
"serviceDescription": "Bank Transfer Loan Repayment",
"repaymentChannelDetails": {
"institutionCode": "058",
"institutionAccount": "0123456789",
"narration": "Loan repayment for account LOAN123456789",
"reference": "TRF/2024/12/001234",
"providerCode": "GTB",
"note": "Transfer from GTBank"
}
}
}

Use Case: Customer transfers funds from external bank account to repay loan.

3. Mobile Money Repayment

{
"commandName": "InitiateLoanRepaymentCommand",
"data": {
"accountEncodedKey": "LOAN987654321",
"channelEncodedKey": "CHANNEL_MOBILE_MONEY",
"amount": 15000.00,
"notes": "Mobile money payment via MTN",
"serviceId": "MOBILE_MONEY_REPAY",
"serviceDescription": "Mobile Money Loan Repayment",
"repaymentChannelDetails": {
"institutionCode": "MTN",
"institutionAccount": "233240123456",
"reference": "MM2024120112345",
"providerCode": "MTN_GHANA",
"note": "MTN Mobile Money payment"
}
}
}

Use Case: Customer uses mobile money service to repay loan.

4. Loan Repayment from Deposit Account

{
"commandName": "InitiateLoanRepaymentWithDepositCommand",
"data": {
"accountEncodedKey": "LOAN123456789",
"depositAccountEncodedKey": "SAV987654321",
"amount": 30000.00,
"notes": "Automatic monthly repayment from savings",
"serviceId": "AUTO_DEBIT_REPAY",
"serviceDescription": "Automatic Loan Repayment"
}
}

Use Case: Automated monthly deduction from customer's savings account.

5. Backdated Repayment Correction

{
"commandName": "InitiateLoanRepaymentCommand",
"data": {
"accountEncodedKey": "LOAN555666777",
"channelEncodedKey": "CHANNEL_BRANCH",
"amount": 20000.00,
"notes": "Backdated payment correction - received on Dec 15",
"isBackDated": true,
"backDateValueDate": "2024-12-15T00:00:00Z",
"isBookingDate": true,
"bookingDate": "2024-12-18T00:00:00Z"
}
}

Use Case: Recording a payment that was received earlier but not immediately posted.

6. Partial Repayment from Deposit (Allow Partial)

{
"commandName": "InitiateLoanRepaymentWithDepositCommand",
"data": {
"accountEncodedKey": "LOAN888999000",
"depositAccountEncodedKey": "CHK111222333",
"amount": 40000.00,
"notes": "Partial payment from checking account",
"allowPartial": true,
"serviceId": "PARTIAL_REPAY",
"serviceDescription": "Partial Loan Repayment"
}
}

Use Case: Process whatever amount is available in deposit account, even if less than requested amount.


Business Logic

Payment Allocation Hierarchy

Loan repayments are automatically allocated in this order:

Processing Workflow

  1. Validation Phase

    • Verify loan account exists and is active (Active or In_Arrears state)
    • Check loan is not locked
    • Validate transaction channel exists
    • Verify amount is greater than zero
    • For deposit-based: Check deposit account balance
  2. Transaction Creation

    • Generate unique transaction key
    • Create CBS transaction record
    • Set transaction type as "Repayment"
    • Apply value date and booking date logic
  3. Schedule Processing (in chronological order)

    • Retrieve all schedules with outstanding balances
    • Order schedules by due date (earliest first)
    • For each schedule:
      • Calculate outstanding amounts (fees, penalties, interest, principal)
      • Allocate payment according to hierarchy
      • Update schedule paid amounts
      • Mark schedule as "Paid" if fully cleared
      • Update schedule state (Due, Late, etc.) if partially paid
  4. Account Updates

    • Recalculate loan balances
    • Update loan state if fully paid
    • Create GL entries based on loan product accounting rules
    • Record external channel details (if provided)
  5. Response Generation

    • Return transaction key
    • Provide breakdown of payment allocation
    • Confirm total amount processed

State Transitions

Loan States:

  • Active → Remains Active (if balance outstanding)
  • Active → Closed (if fully paid)
  • In_Arrears → Active (if brought current)
  • In_Arrears → Closed (if fully paid)
  • Locked → Cannot process payment (error returned)

Schedule States:

  • Pending → Paid (if schedule fully cleared)
  • Due → Paid (if schedule fully cleared)
  • Late → Paid (if schedule fully cleared)
  • Late → Remains Late (if partially paid, still past due)
  • Upfront → Not affected by repayments

Validation Rules

Common Validations (Both Commands)

ValidationError MessageStatus Code
Loan account not found"The supplied loan account or encoded key is not valid."CODE_DOES_NOT_EXIST
Loan not active"The loan - [accountNumber] is no longer active. The present state is [state]."REQUEST_NOT_VALID
Loan is locked"The loan account has been locked presently and no transaction can be posted until it is unlocked"REQUEST_NOT_VALID
Amount less than or equal to 0"The repayment amount must be greater than 0."REQUEST_NOT_VALID
Channel not found"The selected transaction channel cannot be found."-
Backdate without date"The backdate is required"DO_NOT_HONOR
Booking date without date"The book date is required"DO_NOT_HONOR
Duplicate transaction"A transaction already exists with the same transaction reference."DUPLICATE_RECORD

InitiateLoanRepaymentWithDepositCommand Specific

ValidationError Message
Deposit account not found"The supplied deposit account or encoded key is not valid."
Deposit account insufficient balance"The source account does not have sufficient balance."
Deposit account locked/frozen"The deposit account is currently locked/frozen and cannot be debited."
Deposit account closed"Cannot debit from a closed account."
Currency mismatch"Loan and deposit accounts must have the same currency."

Error Codes

Status CodeDescriptionResolution
00SuccessPayment processed successfully
CODE_DOES_NOT_EXISTAccount not foundVerify account number/encoded key
REQUEST_NOT_VALIDInvalid requestCheck loan state and amount
DO_NOT_HONORCannot processReview backdating/booking date requirements
DUPLICATE_RECORDDuplicate transactionUse different transaction reference
INSUFFICIENT_BALANCEInsufficient fundsEnsure deposit account has adequate balance

Integration Examples

Example 1: Automated Loan Repayment from Salary Account

{
"commandName": "InitiateLoanRepaymentWithDepositCommand",
"data": {
"accountEncodedKey": "LOAN456789123",
"depositAccountEncodedKey": "SAL123456789",
"amount": 35000.00,
"notes": "Monthly salary deduction for loan repayment",
"serviceId": "SALARY_DEDUCTION",
"serviceDescription": "Salary-Based Loan Repayment"
}
}

Scenario: On salary payment day, automatically deduct loan installment from employee's salary account.

Example 2: USSD Mobile Banking Repayment

{
"commandName": "InitiateLoanRepaymentCommand",
"data": {
"accountEncodedKey": "LOAN777888999",
"channelEncodedKey": "CHANNEL_USSD",
"amount": 12500.00,
"notes": "USSD payment via *737# code",
"serviceId": "USSD_REPAY",
"serviceDescription": "USSD Loan Repayment"
}
}

Scenario: Customer dials USSD code to make loan payment from any mobile phone.

Example 3: Agent Banking Repayment

{
"commandName": "InitiateLoanRepaymentCommand",
"data": {
"accountEncodedKey": "LOAN321654987",
"channelEncodedKey": "CHANNEL_AGENT",
"amount": 18000.00,
"notes": "Payment collected by agent AG-1234",
"serviceId": "AGENT_REPAY",
"serviceDescription": "Agent Banking Repayment",
"repaymentChannelDetails": {
"institutionCode": "AGENT",
"institutionAccount": "AG-1234",
"reference": "AGT/2024/12/5678",
"note": "Collected by agent John Doe"
}
}
}

Scenario: Agent collects cash payment on behalf of the bank and remits to customer's loan.


Best Practices

For Operations Teams

  1. Payment Verification: Always verify customer details before processing repayment
  2. Receipt Generation: Issue payment receipts immediately after successful transaction
  3. Balance Confirmation: Confirm remaining loan balance with customer
  4. Documentation: Keep records of external payment references for reconciliation
  5. Exception Handling: Use backdating only for genuine corrections with proper authorization

For IT Integration

  1. Idempotency: Check for duplicate transaction keys before retrying failed payments
  2. Balance Checks: For deposit-based repayments, verify balance before initiating transaction
  3. Error Handling: Implement proper retry logic with exponential backoff
  4. Channel Tracking: Always provide channel information for payment source tracking
  5. Webhook Notifications: Set up webhooks to receive payment status updates
  6. Reconciliation: Store transaction keys for end-of-day reconciliation

For Customers

  1. Payment Confirmation: Always request and save payment confirmation receipt
  2. Account Monitoring: Check loan balance after payment to confirm posting
  3. Early Payments: Know your loan product's policy on early/advance payments
  4. Multiple Channels: Use the most convenient payment channel available
  5. Schedule Awareness: Understand your repayment schedule and due dates

APIRelationshipDescription
Create LoanRelatedCreate the loan account
Get Loan DetailsRelatedRetrieve loan balance and schedule
Loan Pay OffAlternativeFull early repayment
Initiate TransferRelatedTransfer funds between accounts
Teller DepositAlternativeProcess repayment through teller

Next Steps