Servicing actions
A governed catalog of balance, schedule, interest, charge, refund, restriction, and terminal actions—native ledger commands and LendEasy capabilities under one case, maker-checker, and governance-record contract.
Every action in this catalog changes what a borrower owes, and every one of them will be read back later by somebody who was not in the room—an auditor, an examiner, a borrower’s lawyer. That is why none of them is an edit. They arrive in two categories:
- LendEasy-native capabilities have their own APIs with their own lifecycles and approval rules: payments, fundings, autopay, statements, and restrictions.
- Everything the ledger already knows how to do is a governed native command. The command is selected with a
commandquery parameter on the relevant route, and executes immediately unless maker-checker parks it for a second approver.
A human call without a case is rejected
Every human servicing mutation carries a LendEasy-Case header naming an open case when case management is enabled, so no change to a balance can arrive without a reason somebody can go and read. Automation never sends the header; its context is recorded from the triggering system instead, which keeps a scheduled job from wearing a case number and looking, in the record, exactly like a person.
- Caller holds the command’s permissionWAIVEINTERESTPORTION_LOAN
- A human call names an open casecase_CEDAR_HARDSHIP_4
- Maker-checker flag on this commandnot set
curl -X POST "$BASE/v1/loans/7204/transactions?command=waiveinterest" \
-H "Authorization: Bearer $TOKEN" \
-H "LendEasy-Tenant: demo-lender" \
-H "LendEasy-Case: case_CEDAR_HARDSHIP_4" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: cedar-waive-2027-08-20" \
-d '{
"transactionDate": "2027-08-20",
"transactionAmount": 92.75,
"note": "Hardship interest waiver per case plan.",
"dateFormat": "yyyy-MM-dd",
"locale": "en"
}'
Command bodies are native: typically transactionDate, an optional transactionAmount, an optional note, and the dateFormat/locale pair. The response is a short command receipt; read the loan afterward for its current state.
{
"officeId": 1,
"clientId": 412,
"loanId": 7204,
"resourceId": 30514,
"changes": {
"transactionDate": "2027-08-20",
"transactionAmount": 92.75
}
}
There is deliberately no preview endpoint and no preview token. A preview is a promise about a loan that may have changed by the time anyone acts on it, and a token makes that stale promise look authoritative. Decide instead from authoritative reads—GET /v1/loans/{loanId}?associations=repaymentSchedule,transactions and GET /v1/loans/{loanId}/summary—and from the evidence attached to the case, so the facts acted on are the facts that were true.
Maker-checker: the second person
A command flagged for checking does not execute; it parks, and the caller’s response identifies the parked audit entry. A different user holding the command’s checker permission then decides:
curl "$BASE/v1/makercheckers" \
-H "Authorization: Bearer $TOKEN" \
-H "LendEasy-Tenant: demo-lender"
[
{
"id": 118,
"actionName": "WRITEOFF",
"entityName": "LOAN",
"resourceId": 7204,
"maker": "ana.alvarez",
"madeOnDate": "2027-08-20T17:14:09Z",
"commandAsJson": "{\"transactionDate\":\"2027-08-20\"}"
}
]
curl -X POST "$BASE/v1/makercheckers/118?command=approve" \
-H "Authorization: Bearer $TOKEN" \
-H "LendEasy-Tenant: demo-lender"
Approval executes the original command exactly as the maker submitted it; rejection discards it. A checker who could amend the body before approving would be approving their own command, which is the one thing the second person exists to prevent—and the maker can never check their own. Reschedules do not use this inbox: they carry their own request→approve workflow where the approver must differ from the requester.
Every execution names who acted and how
Each record carries the actor, the context, and the route:
curl "$BASE/v1/loans/7204/governance-records" \
-H "Authorization: Bearer $TOKEN" \
-H "LendEasy-Tenant: demo-lender"
{
"items": [
{
"governanceId": 902,
"occurredAt": "2027-08-20T17:14:09Z",
"contextType": "CASE",
"contextRef": "case_CEDAR_HARDSHIP_4",
"permissionCode": "WAIVEINTERESTPORTION_LOAN",
"route": "POST /v1/loans/7204/transactions?command=waiveinterest",
"actorClass": "HUMAN",
"correlationId": "corr_01JZ7M5KX2"
}
]
}
contextType distinguishes DIRECT, CASE, CASE_AUTOMATION, and SYSTEM_TRIGGER executions. A customer-scoped view exists at GET /v1/customers/{customerId}/governance-records.
The loan actions menu offers an action only when the loan is in a state that allows it and the operator holds its permission, so an action somebody cannot complete is never offered in the first place. Each action page names where it sits in that menu.
Twenty-four actions, each with its own page
Each carries its own permission and its own undo.
Schedule and interest
| Action | Mechanism | Undo |
|---|---|---|
| Re-amortize | POST /v1/loans/{loanId}/transactions?command=reAmortize |
command=undoReAmortize |
| Re-age | POST /v1/loans/{loanId}/transactions?command=reAge |
command=undoReAge |
| Reschedule | POST /v1/rescheduleloans + POST /v1/rescheduleloans/{scheduleId}?command=approve|reject |
Corrective reschedule |
| Waive accrued interest | POST /v1/loans/{loanId}/transactions?command=waiveinterest |
— |
| Waive an interest payment | POST /v1/loans/{loanId}/transactions?command=interestPaymentWaiver |
— |
| Pause interest accrual | POST /v1/loans/{loanId}/interest-pauses + PUT|DELETE /v1/loans/{loanId}/interest-pauses/{variationId} |
Update or delete the interval |
| SCRA/MLA protection | Applies the SCRA_MLA_PROTECTED restriction to the account |
Clear the restriction |
Charges
| Action | Mechanism |
|---|---|
| Add a charge | POST /v1/loans/{loanId}/charges |
| Adjust a charge | POST /v1/loans/{loanId}/charges/{loanChargeId}?command=adjustment (or PUT before financial dependencies) |
| Waive a charge | POST /v1/loans/{loanId}/charges/{loanChargeId}?command=waive |
| Refund a charge | POST /v1/loans/{loanId}/transactions?command=chargeRefund |
Payments, credits, and refunds
| Action | Mechanism |
|---|---|
| Reverse a payment | No command—the provider-driven payment return flow |
| Record a recovery payment | POST /v1/loans/{loanId}/transactions?command=recoverypayment |
| Issue a cash refund | POST /v1/loans/{loanId}/transactions?command=refundByCash |
| Issue a goodwill credit | POST /v1/loans/{loanId}/transactions?command=goodwillCredit |
| Record a merchant refund | POST /v1/loans/{loanId}/transactions?command=merchantIssuedRefund |
| Refund a payout | POST /v1/loans/{loanId}/transactions?command=payoutRefund |
| Refund a credit balance | command=creditBalanceRefund, cash out via a REFUND funding |
Accounting, restrictions, and terminal state
| Action | Mechanism | Undo |
|---|---|---|
| Write off a balance | POST /v1/loans/{loanId}/transactions?command=writeoff |
command=undowriteoff |
| Charge off a loan | POST /v1/loans/{loanId}/transactions?command=charge-off |
command=undo-charge-off |
| Flag suspected fraud | PUT /v1/loans/{loanId}?command=markAsFraud |
Same route with fraud: false |
| Apply a servicing restriction | POST /v1/customers/{customerId}/restrictions |
POST …/restrictions/{restrictionId}/clear |
| Terminate a contract | POST /v1/loans/{loanId}?command=contractTermination |
command=undoContractTermination |
| Close a loan | POST /v1/loans/{loanId}/transactions?command=close |
— |
The ledger’s command set also includes foreclosure, but the public product catalog covers unsecured consumer installment lending, BNPL, and merchant advances, not real-property servicing, so it carries no action page. Repayment and disbursement commands are internal-only—money always moves through the payment and funding APIs.
Undo is specific, never generic
There is no generic undo route. Undo exists only where a dedicated command exists: undowriteoff, undo-charge-off, undoReAge, undoReAmortize, and undoContractTermination. Each undo is itself a governed command with its own permission, its own governance record, and its own maker-checker configuration. Anything else is corrected by a new compensating action; nothing deletes history.
Choosing among schedule actions
| Borrower outcome | Choose | Reason |
|---|---|---|
| Keep existing remaining due dates, spread overdue amounts across them | Re-amortize | It preserves the schedule horizon. |
| Set a new first due date, cadence, and number of installments | Re-age | It explicitly constructs a replacement remaining schedule. |
| Change broader contract terms under a request-and-approve workflow | Reschedule | It supports a governed modification proposal with a separate approver. |
| Forgive interest without changing the principal schedule | Interest waiver | It records the forgiven economic component directly. |
A friendlier payment amount is the worst reason to pick one of these. The option that lowers this month’s figure is often the one that extends maturity and costs the borrower more in total, and the borrower will find that out later rather than now. Compare total cost, maturity, disclosures, delinquency treatment, and downstream autopay and statement consequences before executing—the schedule read and loan summary give you the facts, and the case holds the comparison you relied on.