Skip to content

Progressive Loan Configuration

Apache Fineract supports two loan schedule types: Cumulative and Progressive. Progressive is the modern default for new deployments and is required for any product that needs dynamic interest recalculation, stage-wise disbursements, or BNPL-style workflows.

This guide covers how Progressive loans work and how to configure them via the API.


Cumulative vs Progressive

Cumulative

In a Cumulative loan, the full repayment schedule is calculated upfront from the total committed amount, including any planned future tranches. The schedule is fixed at the point of disbursement and does not change when additional disbursements are made.

  • Simpler to understand and predict
  • Suited for single-disbursement products with fixed terms
  • Does not recalculate when tranches are released

Progressive

In a Progressive loan, the repayment schedule is recalculated from the current period onward every time a new disbursement is made. Each tranche accrues interest only from its own disbursement date.

  • EMI (or principal-per-period) adapts dynamically as new funds are released
  • Suited for BNPL, construction lending, stage-funded business loans, revolving credit
  • Requires isInterestRecalculationEnabled: true

Which should I use?

Use Progressive for any product where disbursements happen in multiple stages or where outstanding balance can change after origination. Use Cumulative only for simple, fully-disbursed-at-once products.


Loan Product Configuration

When creating or updating a loan product, the following fields control the schedule type and processing behaviour.

Required Fields for Progressive

json
{
  "loanScheduleType": "PROGRESSIVE",
  "loanScheduleProcessingType": "HORIZONTAL",
  "transactionProcessingStrategyCode": "advanced-payment-allocation-strategy",
  "isInterestRecalculationEnabled": true
}
FieldValueMeaning
loanScheduleTypePROGRESSIVEEnables progressive schedule recalculation
loanScheduleProcessingTypeHORIZONTALAllocates payments within a period before moving to the next (recommended)
transactionProcessingStrategyCodeadvanced-payment-allocation-strategyRequired for progressive products; enables the payment allocation array
isInterestRecalculationEnabledtrueTriggers recalculation when disbursements, repayments, or charges occur

Interest Recalculation Settings

json
{
  "interestCalculationPeriodType": 0,
  "interestRecalculationCompoundingMethod": 0,
  "rescheduleStrategyMethod": 4,
  "recalculationRestFrequencyType": 2,
  "recalculationRestFrequencyInterval": 1
}
FieldValueMeaning
interestCalculationPeriodType0 (Daily)Daily interest calculation; most accurate for progressive products
interestRecalculationCompoundingMethod0 (None)No compounding on unpaid interest
rescheduleStrategyMethod4 (Adjust last unpaid period)When recalculation occurs, adjusts only the last unpaid installment
recalculationRestFrequencyType2 (Daily)Recalculate the outstanding balance daily
recalculationRestFrequencyInterval1Every 1 day

Payment Allocation

The paymentAllocation array controls how incoming payments are distributed across components. The order in the array defines the priority.

json
{
  "paymentAllocation": [
    {
      "transactionType": "DEFAULT",
      "paymentAllocationOrder": [
        { "paymentAllocationRule": "PAST_DUE_PENALTY", "order": 1 },
        { "paymentAllocationRule": "PAST_DUE_FEE", "order": 2 },
        { "paymentAllocationRule": "PAST_DUE_INTEREST", "order": 3 },
        { "paymentAllocationRule": "PAST_DUE_PRINCIPAL", "order": 4 },
        { "paymentAllocationRule": "DUE_PENALTY", "order": 5 },
        { "paymentAllocationRule": "DUE_FEE", "order": 6 },
        { "paymentAllocationRule": "DUE_INTEREST", "order": 7 },
        { "paymentAllocationRule": "DUE_PRINCIPAL", "order": 8 },
        { "paymentAllocationRule": "IN_ADVANCE_PENALTY", "order": 9 },
        { "paymentAllocationRule": "IN_ADVANCE_FEE", "order": 10 },
        { "paymentAllocationRule": "IN_ADVANCE_INTEREST", "order": 11 },
        { "paymentAllocationRule": "IN_ADVANCE_PRINCIPAL", "order": 12 }
      ],
      "futureInstallmentAllocationRule": "NEXT_INSTALLMENT"
    }
  ]
}

The standard priority order is: overdue penalties first, then overdue fees, overdue interest, overdue principal, then current-period components in the same order, then future components last.

futureInstallmentAllocationRule controls where excess payments are applied when the current installment is fully covered:

  • NEXT_INSTALLMENT - apply to the next upcoming installment
  • LAST_INSTALLMENT - apply to the final installment first (reduces term)
  • REAMORTIZATION - redistribute the excess across all remaining installments

Multi-Disbursement (Tranches)

For stage-funded products:

json
{
  "multiDisburseLoan": true,
  "maxTrancheCount": 5,
  "outstandingLoanBalance": 100000
}
FieldMeaning
multiDisburseLoanEnables multiple disbursement tranches
maxTrancheCountMaximum number of disbursements allowed
outstandingLoanBalanceMaximum total outstanding at any point (credit limit)

Down Payment (Optional)

json
{
  "enableDownPayment": true,
  "disbursedAmountPercentageForDownPayment": 25.0,
  "enableAutoRepaymentForDownPayment": true
}

When enabled, a percentage of each disbursed tranche is automatically applied as a repayment on disbursement day. Useful for BNPL and hire-purchase products.

Charge-off Behaviour

Controls what happens to outstanding interest when a loan is charged off:

json
{
  "chargeOffBehaviour": "ZERO_INTEREST"
}
ValueBehaviour
ZERO_INTERESTStop accruing interest after charge-off
REGULARContinue normal accrual after charge-off
ACCELERATE_MATURITYMove all future installments to be due immediately

Full Product Creation Example

bash
POST /fineract-provider/api/v1/loanproducts
Authorization: Basic <base64>
Fineract-Platform-TenantId: default
Content-Type: application/json
json
{
  "name": "BNPL Progressive Loan",
  "shortName": "BNPL01",
  "currencyCode": "USD",
  "digitsAfterDecimal": 2,
  "principal": 5000,
  "minPrincipal": 100,
  "maxPrincipal": 50000,
  "numberOfRepayments": 12,
  "repaymentEvery": 1,
  "repaymentFrequencyType": 2,
  "interestRatePerPeriod": 1.5,
  "interestRateFrequencyType": 2,
  "amortizationType": 1,
  "interestType": 0,
  "interestCalculationPeriodType": 0,
  "loanScheduleType": "PROGRESSIVE",
  "loanScheduleProcessingType": "HORIZONTAL",
  "transactionProcessingStrategyCode": "advanced-payment-allocation-strategy",
  "isInterestRecalculationEnabled": true,
  "interestRecalculationCompoundingMethod": 0,
  "rescheduleStrategyMethod": 4,
  "recalculationRestFrequencyType": 2,
  "recalculationRestFrequencyInterval": 1,
  "multiDisburseLoan": true,
  "maxTrancheCount": 3,
  "outstandingLoanBalance": 50000,
  "paymentAllocation": [
    {
      "transactionType": "DEFAULT",
      "paymentAllocationOrder": [
        { "paymentAllocationRule": "PAST_DUE_PENALTY", "order": 1 },
        { "paymentAllocationRule": "PAST_DUE_FEE", "order": 2 },
        { "paymentAllocationRule": "PAST_DUE_INTEREST", "order": 3 },
        { "paymentAllocationRule": "PAST_DUE_PRINCIPAL", "order": 4 },
        { "paymentAllocationRule": "DUE_PENALTY", "order": 5 },
        { "paymentAllocationRule": "DUE_FEE", "order": 6 },
        { "paymentAllocationRule": "DUE_INTEREST", "order": 7 },
        { "paymentAllocationRule": "DUE_PRINCIPAL", "order": 8 },
        { "paymentAllocationRule": "IN_ADVANCE_PENALTY", "order": 9 },
        { "paymentAllocationRule": "IN_ADVANCE_FEE", "order": 10 },
        { "paymentAllocationRule": "IN_ADVANCE_INTEREST", "order": 11 },
        { "paymentAllocationRule": "IN_ADVANCE_PRINCIPAL", "order": 12 }
      ],
      "futureInstallmentAllocationRule": "NEXT_INSTALLMENT"
    }
  ],
  "locale": "en",
  "dateFormat": "dd MMMM yyyy",
  "accountingRule": 2
}

Key field reference:

FieldType codeMeaning
repaymentFrequencyType2Monthly
interestRateFrequencyType2Per month
amortizationType1Equal installments
interestType0Declining balance
accountingRule2Accrual-based accounting

Creating a Progressive Loan Account

Once the product is configured, create a loan account against it:

bash
POST /fineract-provider/api/v1/loans
json
{
  "clientId": 1,
  "productId": 5,
  "principal": 10000,
  "loanTermFrequency": 12,
  "loanTermFrequencyType": 2,
  "numberOfRepayments": 12,
  "repaymentEvery": 1,
  "repaymentFrequencyType": 2,
  "interestRatePerPeriod": 1.5,
  "amortizationType": 1,
  "interestType": 0,
  "interestCalculationPeriodType": 0,
  "transactionProcessingStrategyCode": "advanced-payment-allocation-strategy",
  "loanScheduleType": "PROGRESSIVE",
  "expectedDisbursementDate": "01 March 2025",
  "disbursementData": [
    {
      "expectedDisbursementDate": "01 March 2025",
      "principal": 5000
    },
    {
      "expectedDisbursementDate": "01 June 2025",
      "principal": 5000
    }
  ],
  "dateFormat": "dd MMMM yyyy",
  "locale": "en"
}

The disbursementData array defines the planned tranches. The schedule is initially calculated from the first tranche. When the second tranche is disbursed, Fineract recalculates the remaining installments from that date forward.


How Recalculation Works at Disbursement

When the second tranche (5000 on 01 June 2025) is disbursed:

  1. Outstanding principal increases from remaining balance to remaining balance + 5000
  2. Interest is recalculated from the disbursement date at the new outstanding balance
  3. Remaining installments are recalculated using rescheduleStrategyMethod=4 (adjust last unpaid period)
  4. Previously paid installments are not affected

This means the borrower's EMI changes slightly after each new disbursement, reflecting the actual funds received rather than a fixed upfront commitment.


Interest Refunds

Progressive loans support interest refund on early repayment via supportedInterestRefundTypes:

json
{
  "supportedInterestRefundTypes": ["MERCHANT_ISSUED_REFUND", "PAYOUT_REFUND"]
}

When a merchant refund transaction is posted, Fineract automatically calculates and reverses the proportional interest for the refunded amount.


Verifying the Schedule

After creating and approving a loan, retrieve the repayment schedule to verify it:

bash
GET /fineract-provider/api/v1/loans/{loanId}/repaymentschedule

Each installment in the response shows principalDue, interestDue, feeChargesDue, penaltyChargesDue, and totalDueForPeriod. After a second disbursement, re-fetch the schedule to confirm recalculation has occurred.


Common Mistakes

MistakeSymptomFix
Using CUMULATIVE strategy code with a progressive productSchedule does not recalculateUse advanced-payment-allocation-strategy
isInterestRecalculationEnabled: false on a progressive productNo recalculation on new disbursementsSet to true
recalculationRestFrequencyType not set to Daily (2)Inaccurate interest between recalculation datesSet to 2 (Daily)
Missing paymentAllocation array400 error on product creationInclude the full paymentAllocation array
Not including disbursementData on multi-disburse loan creationOnly one tranche plannedAlways include disbursementData even if dates are estimates