Modelling Example: Personal Loan
This document shows how to map a personal loan (consumer credit) client onto the platform's Account / Product / Claim model. The client described here ("PrestaFlex") is fictional and, like the BNPL example (see BNPL), is configured with a deliberately rich policy set so the example exercises the mechanisms a real lender might need. A real client will be a subset — the discovery questions at the end tell you which parts apply.
Personal loans differ from BNPL in three ways that matter for modelling:
- Instalments carry interest. Each scheduled payment is part principal, part interest (amortization). The sum of the remaining instalments is therefore more than the debt: it includes interest not yet earned. On acceleration, the enforceable balance is outstanding principal + accrued interest + fees — in most jurisdictions unearned future interest must be rebated, so never model the accelerated claim as "sum of remaining instalments".
- Debt keeps growing after placement. Default interest and collection fees typically continue to accrue while the claim is in collection. The model handles this through claim updates, not through new claims.
- Co-signers and guarantors are common. The schema has two distinct mechanisms for shared liability — choosing between them is a real modelling decision (see below).
Guiding principles
Same as the BNPL example:
- Model what is legally enforceable at placement time. The claim
amountis the collectible debt, not the contract value. - The Receive Instalment Plan is a collections treatment, not the origination schedule.
The loan's amortization schedule is the origination contract; it belongs in
Product.metaas context. The Receive plan is what you offer the debtor to repay the defaulted claim.
Entity mapping
| Loan concept | Platform entity |
|---|---|
| Borrower | Account (one per debtor, groups all their loans) |
| Loan contract | Product (type: "PERSONAL_LOAN", one per loan) |
| Missed scheduled instalment | Claim (one per overdue instalment, pre-acceleration) |
| Accelerated / charged-off balance | Claim (one claim for the enforceable balance) |
| Principal vs interest vs fees | Claim.amount (principal) + Claim.fees[] (named fee entries) |
| Amortization schedule | Product.meta (context data, no business logic) |
| Co-signer on the same claim | Claim.additionalDebtors |
| Same debt on several accounts | Linked claims (set_link_claims → linkGroupId) |
| Negotiated repayment plan | Receive Instalment Plan (collections treatment on the claim) |
Debt composition convention: put the enforceable principal in amount and break out the
rest as named fees entries (Fee is just { name, amount } — the names are a convention you
agree with the client, e.g. accruedInterest, defaultInterest, lateFee,
collectionCosts). totalFees is derived from fees. This keeps the principal/cost split
visible for reporting, settlement negotiations, and jurisdictions that cap collectible costs.
Fictional client: "PrestaFlex"
Assumed policies:
- Unsecured personal loans, €1,000–€20,000, 12–48 monthly instalments, French amortization.
- At the 1st missed instalment, places that instalment in collection (late fee included) while the loan stays active and the borrower keeps paying future instalments to PrestaFlex.
- At the 3rd consecutive missed instalment, accelerates: the loan is terminated and the full outstanding balance (principal + accrued interest, unearned interest rebated) becomes due.
- After acceleration, default interest keeps accruing monthly on the outstanding principal until the claim is resolved.
- Some loans have a co-signer.
Worked example: Carlos's loan
Carlos borrows €5,000 over 24 months at 12% APR, instalment ≈ €235 (figures illustrative). He pays 6 instalments, then stops.
- Account = Carlos.
- Product = the loan:
productReference: "PF-LOAN-2093",type: "PERSONAL_LOAN", withmetaholding principal, APR, term, disbursement date, and (optionally) the amortization schedule.
Phase 1 — early arrears (instalments 7 and 8 overdue)
One claim per missed instalment, grouped by productReference. The instalment amount already
blends principal and interest per the amortization schedule — at this stage that split usually
doesn't matter, so amount is simply the instalment due; the late fee is broken out:
{
"externalClaimRef": "PF-LOAN-2093-INST-07",
"amount": 23500, // cents — the scheduled instalment that fell due
"currency": "EUR",
"dueDate": "2026-05-15",
"externalDueDate": "2026-05-15",
"productReference": "PF-LOAN-2093",
"fees": [{ "name": "lateFee", "amount": 1500 }],
}
// likewise PF-LOAN-2093-INST-08, dueDate 2026-06-15
If Carlos pays one instalment, that claim resolves individually; the loan itself is still serviced by PrestaFlex.
Phase 2 — acceleration (instalment 9 falls due unpaid)
PrestaFlex terminates the loan, credits the open instalment claims, and places one claim for
the enforceable balance. Note the composition: outstanding principal (≈ €3,900 after 6
paid instalments) in amount, accrued interest and fees broken out — not the €4,230 sum of
the 18 remaining instalments, which would include unearned interest:
{
"externalClaimRef": "PF-LOAN-2093-ACCEL",
"amount": 390000, // outstanding principal only
"currency": "EUR",
"dueDate": "2026-07-15", // acceleration date
"externalDueDate": "2026-07-15",
"productReference": "PF-LOAN-2093",
"fees": [
{ "name": "accruedInterest", "amount": 7800 },
{ "name": "lateFee", "amount": 4500 },
],
"relatedClaims": [
{ "type": "REPLACES", "claimReference": "PF-LOAN-2093-INST-07" },
{ "type": "REPLACES", "claimReference": "PF-LOAN-2093-INST-08" },
{ "type": "REPLACES", "claimReference": "PF-LOAN-2093-INST-09" },
],
}
Ongoing accrual — default interest after placement
Each month, PrestaFlex recomputes default interest and pushes the new fee breakdown via
update_claims (providing fees replaces the previous list and recomputes totalFees):
// POST /v1/{clientId}/update_claims — one month later
{
"PF-LOAN-2093-ACCEL": {
"fees": [
{ "name": "accruedInterest", "amount": 7800 },
{ "name": "lateFee", "amount": 4500 },
{ "name": "defaultInterest", "amount": 3900 },
],
},
}
Decide with the client who computes accrual: the platform stores and communicates the debt
but does not run interest formulas — the client (or an integration job) must send the updated
figures. Alternatively debit_claims / credit_claims adjust amounts without replacing the
fee breakdown.
Freezing interest at placement (common for smaller balances) removes this whole section — ask before building the accrual integration.
Phase 3 — collections treatment
On the accelerated claim, the strategy offers Carlos a Receive Instalment Plan (e.g. 18
payments via landing page). As in the BNPL example: the platform internally creates a compound
claim representing the plan (compoundClaimRefs — internal, never sent by the client), missing
a plan payment invalidates the plan and the full claim becomes enforceable again, and a single
plan can span multiple source claims (relevant if the client never accelerates and several
instalment claims are open).
If default interest is still accruing (previous section), agree with the client whether the plan freezes accrual — plans over a moving target are painful; most lenders freeze the balance when a payment agreement is reached.
Workouts executed in the client's core (typed relations)
If PrestaFlex restructures or refinances a defaulted loan in its own core system and places
the result as a new claim, declare the lineage with typed relations instead of meta:
{ "type": "RESTRUCTURES", ... }— same debt re-scheduled by agreement (forbearance; still outstanding risk, tracked for re-default).{ "type": "REFINANCES", ... }— new credit agreement that cures the old debt (counts as recovery). Keeping these two distinct is what stops recovery reporting from conflating "refinanced = recovered" with "restructured = still at risk".{ "type": "REINSTATES", ... }— new claim re-placing debt whose original claim was already resolved (e.g. a settlement breached after closure).
Restructures executed inside the platform keep using the Receive Instalment Plan — no new claim, no relation needed.
Co-signed loans
If Carlos's loan has a co-signer (Ana), there are two modelling options — they are not interchangeable:
additionalDebtors(default choice): one claim, primary debtor Carlos, Ana as additional debtor. One account, one debt, one collections journey. Simple and usually sufficient.- Linked claims (
set_link_claims→linkGroupId): a mirror claim in Carlos's account and in Ana's account, linked so thatamount/totalFees/feesstay synchronized — a payment reflected on one claim propagates to its mirror. Use only when both debtors must be worked as separate accounts with independent journeys (e.g. different strategies, separate communication tracks) over the same debt. This is the legitimate use oflinkGroupId— never use it to group instalments of one loan (see the warning in the BNPL doc).
Multiple loans
A second loan for Carlos is a second Product with its own claims under the same Account; account-level strategy decides whether he is worked as one case.