Operations
Loan Servicing Operations Guide
This guide covers post-disbursement operations introduced for Fineract feature parity: staged disbursement, delinquency pause, waivers, top-ups, prepayment schedule recalculation, backdated payments, re-aging, custom fields, maker-checker approvals, and floating interest rates.
Use it alongside the Loan Product Setup Guide, which covers origination-side configuration.
Table of Contents
- Staged Disbursement
- Delinquency Pause / Resume
- Interest and Fee Waivers
- Loan Top-Up
- Prepayment Schedule Recalculation
- Backdated Payments
- Re-Aging
- Custom Fields
- Maker-Checker Approvals
- Floating Interest Rates
Staged Disbursement
Products flagged staged disbursement release the approved amount in ordered tranches instead of one payment.
Setup
- Product Config → Disburse tab → enable Staged Disbursement and define stages (name, percentage or amount, required documents).
- Each stage can carry
required_documents— the release is blocked until those borrower documents are on file.
Releasing a tranche
Loan detail → Manage funding → the stage panel lists all tranches in order.
| UI | API |
|---|---|
| Stage list | GET /api/v1/loans/:id/disbursement-stages |
| Release next stage | POST /api/v1/loans/:id/disbursement-stages/release — body includes stage_id, disbursement method, destination, date, narration |
Each released stage becomes its own disbursement request and flows through the normal verify → process → confirm pipeline. Rejecting a stage disbursement returns the stage to PENDING so it can be released again.
Rules
- Stages release in order; only one tranche may be in-flight at a time.
- Stage 1 activates the loan and runs normal disbursement validation; later stages post against an active loan.
- Deductible fees are taken from the first tranche.
- Interest accrues on drawn principal only — the subledger
PRINCIPALbalance is the accrual basis. - The single-shot
POST /disbursementsendpoint is rejected for staged products; tranches cannot be bypassed.
Delinquency Pause/Resume
Suspend delinquency machinery on a loan during restructuring talks, disaster relief, or disputes.
| UI | API |
|---|---|
| Loan → ⋯ → Pause Delinquency | POST /api/v1/servicing/delinquency/pause/:loan_id { reason } |
| Loan → ⋯ → Resume Delinquency | POST /api/v1/servicing/delinquency/resume/:loan_id |
| History | GET /api/v1/servicing/delinquency/pauses/:loan_id |
While paused:
- Late fee assessment is skipped (both the daily
AssessLateFeesrun and the per-payment fee path). - Escalation/DPD progression excludes the loan.
- IFRS/regulatory stage migration is suspended.
Pause does not stop interest accrual, payments, or staff relief actions (waivers still work). Pause/resume is audit-recorded.
Interest and Fee Waivers
| Action | Endpoint | Behaviour |
|---|---|---|
| Waive accrued interest | POST /api/v1/servicing/delinquency/waive-interest/:loan_id { amount, reason } | Capped at outstanding interest; posts a negative INTEREST_WAIVER subledger entry; audited as INTEREST_WAIVED |
| Waive late fee | POST /api/v1/servicing/delinquency/waive-fee/:fee_id { reason } | Marks the fee WAIVED and reverses it in the subledger |
UI: loan detail → ⋯ menu → Waive Interest (amount + reason).
Loan Top-Up
Increase an active performing loan's principal — the new amount posts as an additional disbursement tranche through the same subledger/GL machinery as staged disbursement, and the unpaid schedule is rebuilt on the new outstanding principal.
| UI | API |
|---|---|
| Loan → ⋯ → Top-Up Loan (amount + reason) | POST /api/v1/loans/:id/top-up |
Requires the loan to be active and in good standing. The response includes the new principal_amount.
Prepayment Schedule Recalculation
When a borrower pays ahead of schedule, the product's prepayment recalc strategy decides what happens to the remaining installments:
| Strategy | Effect |
|---|---|
NONE (default) | Overpayment reduces principal; schedule unchanged |
REDUCE_EMI | Same installment count/dates; lower installment amount |
REDUCE_TERM | Same installment amount; trailing installments dropped |
Set it on Product Config → Payment tab → Prepayment Schedule Recalculation, or PUT /api/v1/products/:id/config/payment with prepayment_recalc_strategy.
Recalculation runs inside the payment transaction: PAID/PARTIAL rows are preserved, unpaid rows are rebuilt on the post-payment principal, and the advertised installment (payment_amount) is updated for REDUCE_EMI.
Backdated Payments
Posting a payment with a past payment_date triggers automatic re-evaluation inside the same transaction:
- Interest accrual catches up from the value date.
- If payments valued on or before that date covered everything due by that date, late fees assessed after it are reversed (waived with reason
BACKDATED_PAYMENT) and the subledger is corrected atomically.
A backdated payoff can therefore flip a loan to PAID_OFF with the wrongful fees removed.
Limitation: this reverses late fees, not a full ledger rebuild — DPD recomputes on the next delinquency run, and interest is not re-accrual-reversed for the backdated window.
Re-Aging
When enabled on the collections policy, a delinquent loan whose amount-past-due reaches zero after a payment is reset to CURRENT classification with a LOAN_REAGED audit event.
Enable per policy: Collections → policy form → Re-age loans on cure, or include reaging_enabled: true in the collections policy payload. Defaults off — existing policies are unaffected.
This is the cure-based variant; it does not implement "N consecutive on-time payments while still overdue".
Custom Fields
Attach arbitrary typed data to any entity — the Fineract datatable equivalent.
GET /api/v1/custom-fields/:entityType/:entityId— list fieldsPUT /api/v1/custom-fields/:entityType/:entityId— create/update a field (body:field_name,field_value,value_type)DELETE /api/v1/custom-fields/:entityType/:entityId/:fieldName— remove a field
| Entity types | LOAN, BORROWER, APPLICATION, PRODUCT, GROUP, COLLATERAL |
|---|---|
| Value types | STRING, NUMBER, BOOLEAN, DATE — validated on write |
UI: loan detail → Details tab → Custom Fields card (staff only). Use for tenant-specific attributes that don't warrant a schema change.
Maker-Checker Approvals
Any configured operation can require a second user to approve before it executes.
For makers
Submit the action as usual (waive interest, top-up, waive fee). If the operation is policy-gated, the response is 202 PENDING_APPROVAL and nothing executes yet — the UI shows "Submitted for approval".
For checkers
Admin → Maker-Checker (/admin/checker):
- Review pending commands with full payloads
- Approve & Execute — runs the operation immediately, attributed to the original maker
- Reject — discards it
- The maker cannot decide their own submission (self-approval is rejected)
| API | Purpose |
|---|---|
GET /api/v1/checker/commands?status=PENDING | Inbox |
POST /api/v1/checker/commands/:id/approve | Approve + execute (loan.approve permission) |
POST /api/v1/checker/commands/:id/reject | Reject |
PUT /api/v1/checker/policies | Toggle per command type (organization.manage) |
Policy-gated command types
WAIVE_INTEREST, WAIVE_LATE_FEE, LOAN_TOP_UP are wired today. DISBURSEMENT_REVERSAL, PAYMENT_REVERSAL, SAVE_PAYMENT_CONFIG, RATE_INDEX_ENTRY are reserved command types. Policies default off — existing behavior is unchanged until you enable one.
Floating Interest Rates
Price a product as index + spread so outstanding loans reprice when the base rate moves.
Setup
- Admin → Rate Indices (
/admin/rate-indices) — create a benchmark (e.g.POLICY_RATE) and post its initial rate. - Product Config → Floating tab — enable floating, select the index, set the spread (percentage points), and choose what happens on repricing:
REDUCE_EMI— same term, installment amount adjustsREDUCE_TERM— same installment, term adjusts
Equivalent API: PUT /api/v1/products/:id/config/floating-rate.
How it works
- At origination the loan snapshots the product's index+spread and stores
index + spreadas its interest rate. Origination fails if the index has no effective rate. - Posting a new index entry (
POST /api/v1/rate-indices/:id/entries) reprices every active loan linked to the index:interest_rateis updated and unpaid installments are rebuilt per the reprice strategy — in one transaction per loan. - Entries effective in the past or future do not trigger mass repricing; the new rate applies from its effective date for accrual.
- The response reports how many loans repriced.
Limitation: repricing is forward-looking — accrual posted between the entry's effective date and its posting date is not re-processed.
Quick Reference
| Capability | Surface |
|---|---|
| Tranche release | Loan → Manage funding → stage panel |
| Pause/resume delinquency | Loan → ⋯ menu |
| Waive interest / top-up | Loan → ⋯ menu |
| Prepayment strategy, schedule shape | Product Config → Payment tab |
| Floating rate | Product Config → Floating tab; Admin → Rate Indices |
| Re-aging | Collections policy form |
| Custom fields | Loan → Details tab → Custom Fields |
| Checker inbox & policies | Admin → Maker-Checker |