LendEasy/DocsLMS + Servicing·v1
Start integrating
GuidesServicing PlaneGoverned operations & action requests

Governed operations & action requests

Execute typed operations at their owning boundary, materialize approval work only when required, and retain the generalized gateway contract as product direction.

The current servicing runtime does not create an action request for every change. The owning operation resolves current facts and policy first. An ALLOWED operation executes immediately; an action request is materialized only for APPROVAL_REQUIRED, deferred, manual, external, or unavailable work.

Current implemented boundary

Work Current path Authority
Servicing-owned change The typed resource endpoint, such as POST /v1/servicing/cases/{caseId}/promises or /restriction-changes. The endpoint’s named permission plus its execution-time policy result.
Direct servicing outcome /responses, /follow-up-tasks, and /payment-support-reviews. Executes directly after current-fact checks; it does not fabricate an action request.
Lending Core command The canonical customer or loan route under /v1, with LendEasy-Case on a human servicing call. The command’s exact LMS permission. The case supplies causation and scope, never authority.
Workflow automation A registered typed case effect. The workflow and effect type are closed contracts; callers cannot submit an arbitrary command, URL, or payload.

The governed operations

Eight case-scoped operations cover the borrower-facing and account-changing work the servicing plane owns. Each is a typed resource under its case, each requires its own permission, and each decides for itself whether to execute or materialize a request:

Operation Route on /v1/servicing/cases/{caseId} Permission
Prepare a customer-authorized payment POST /payment-requests CREATE_SERVICING_PAYMENT_REQUEST
Record an external payment POST /external-payments RECORD_SERVICING_EXTERNAL_PAYMENT
Update contact or consent POST /contact-consent-updates UPDATE_SERVICING_CONTACT_CONSENT
Apply or clear a restriction POST /restriction-changes CHANGE_SERVICING_RESTRICTION
Update a bankruptcy record POST /bankruptcy-updates UPDATE_SERVICING_BANKRUPTCY
Send or log a case response POST /responses SEND_SERVICING_RESPONSE
Create internal follow-up work POST /follow-up-tasks CREATE_SERVICING_FOLLOW_UP_TASK
Create payment-support review work POST /payment-support-reviews REQUEST_SERVICING_PAYMENT_SUPPORT_REVIEW

Every one of them requires a reason. The three that change authoritative state on the strength of evidence — external payments, restriction changes, and bankruptcy updates — also require evidenceIds, so a protective control can never rest on an assertion alone.

curl -X POST "$BASE/v1/servicing/cases/1001/restriction-changes" \
  -H "Authorization: Bearer $TOKEN" \
  -H "LendEasy-Tenant: demo-lender" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: cease-1001-2027-05-05" \
  -d '{
    "customerRef": "123",
    "loanRef": "456",
    "operation": "APPLY",
    "restrictionType": "CEASE_COMMUNICATIONS",
    "effectiveAt": "2027-05-05T18:30:00Z",
    "reason": "Verified written cease request.",
    "evidenceIds": [8801]
  }'

The response is an outcome envelope, not a request receipt:

{
  "outcome": "COMPLETED",
  "restrictionRef": "restriction-41",
  "resourceId": 41
}

Branch on outcome. COMPLETED means the typed operation already executed against the authoritative boundary and the returned reference is real. Where policy instead requires approval, or execution is deferred, manual, external, or unavailable, the same call reports that and returns the materialized action request — which is the only way an action request comes into existence.

Two of these are worth calling out because they look like approvals and are not. /responses, /follow-up-tasks, and /payment-support-reviews create the owning interaction or task directly after current-fact checks. A payment-support review is specialist work, not a request for someone to authorize something.

Applying a protective restriction and relaxing one follow separate action-specific policy. operation: APPLY on a cease request is not the mirror image of clearing it, and the two do not share an approval threshold.

Action-request lifecycle

When an owning operation does materialize a request, the implemented API exposes the case-scoped lifecycle:

Route Purpose Permission
GET /v1/servicing/cases/{caseId}/action-requests List only the requests actually materialized on this case. READ_SERVICING_CASE
GET /v1/servicing/action-requests/{actionRequestId} Read the typed request and its safe lifecycle state. READ_SERVICING_ACTION_REQUEST
POST .../{actionRequestId}/approve Approve with a required decisionNote. APPROVE_SERVICING_ACTION_REQUEST
POST .../{actionRequestId}/reject Reject with a required reason. REJECT_SERVICING_ACTION_REQUEST
POST .../{actionRequestId}/submit Execute the approved inputs. Accepts no request body. SUBMIT_SERVICING_ACTION_REQUEST
POST .../{actionRequestId}/manual-complete Record a manual result, only from MANUAL_EXECUTION_REQUIRED. MANUAL_COMPLETE_SERVICING_ACTION_REQUEST

Both reads return allowedActions computed for the calling actor:

{
  "actionRequestId": 6001,
  "externalActionRef": "LE-ACTION-6001",
  "caseId": 1001,
  "actionType": "AR_002",
  "riskClass": "R2",
  "status": "APPROVAL_REQUIRED",
  "preparedByActorType": "HUMAN",
  "preparedByWorkerId": 4101,
  "approvalRequired": true,
  "approvalPermissionCode": "APPROVE_SERVICING_PROMISE",
  "allowedActions": ["APPROVE", "REJECT"],
  "requestPayload": { "loanRef": "456", "planType": "SINGLE", "promiseDate": "2026-08-01" }
}

A workspace should render buttons from allowedActions rather than inferring them from status. The list already accounts for the caller’s permissions and for maker-not-approver, so the maker who prepared request 6001 sees an empty approval set on their own request.

Approving checks two authorities, not one: the route permission above and the server-derived action-specific permission named in approvalPermissionCodeAPPROVE_SERVICING_<ACTION>. The caller cannot choose riskClass, approvalPermissionCode, or a generic approval role; all three are derived from the action type. Submit takes no body precisely so that approved inputs stay immutable between approval and execution.

Manual completion is evidence-backed and reachable only from MANUAL_EXECUTION_REQUIRED. outcomeCode, reason, and evidenceIds are all required, with an optional externalResultRef naming the authoritative record outside the platform:

{
  "outcomeCode": "COMPLETED_EXTERNALLY",
  "reason": "The external system completed the change.",
  "evidenceIds": [8801],
  "externalResultRef": "external-result-71"
}
The sections below preserve the broader generalized gateway model as roadmap product direction. They are not a claim that every current operation creates a generic action request.

The generalized lifecycle (roadmap)

Approval binds to an action hash. Editing amount, effective date, recipient, interest handling, or any other material parameter invalidates that approval.

Typed actions, not raw commands

Every request has an actionType from the published catalog and a schema specific to that type. Callers cannot submit arbitrary command names, URLs, or unvalidated payloads.

The catalog includes payments, autopay changes, external-payment records, contact-consent updates, restrictions, re-aging, re-amortization, rescheduling, interest treatment, charges, refunds, recovery payments, write-off, charge-off, fraud flags, SCRA adjustments, contract termination, and closure. See Servicing actions.

Decide, then prepare

There is no preview endpoint on the built-in Lending Core and no preview token. For a schedule-changing or balance-changing action, decide from authoritative reads—GET /v1/loans/{loanId}?associations=repaymentSchedule,transactions and GET /v1/loans/{loanId}/summary—and attach the before/after comparison the decision rests on to the case. Preparation freezes the typed payload and context:

{
  "actionType": "re_amortize",
  "loanRef": "7204",
  "parameters": {
    "interestHandling": "default"
  },
  "context": {
    "caseId": "case_CEDAR_HARDSHIP_4",
    "reasonCode": "temporary_income_reduction"
  }
}

Approval binds to the hash of that frozen request. If material facts change before submission, the execution-time gate fails the request closed and the decision must be remade from fresh reads.

Operational context is mandatory

Every state-changing action links to one of:

  • a case it serves;
  • a controlled administrative exception with approver and expiry; or
  • a named system trigger with policy version.

The context is not a free-form note. It carries structured reason, origin, source interaction or task, evidence references, and actor. This makes the chain traversable from ledger transaction back to decision.

Execution-time gate

Immediately before submission, the gateway re-reads critical facts and reruns policy. Approval from yesterday does not override a bankruptcy restriction received today. Possible outcomes are:

Decision Meaning
ALLOWED Execute under the resolved policy.
ALLOWED_WITH_WARNING Execute and preserve named warnings.
APPROVAL_REQUIRED Stop until the required role approves the frozen action.
BLOCKED A known rule prohibits the action.
UNAVAILABLE_DUE_TO_MISSING_FACTS Required facts are absent or stale; fail closed.

The result stores rule IDs, jurisdictions, effective versions, facts and freshness, and any override—not merely a boolean.

Approval and separation of duties

Approval policy can consider action type, amount, balance effect, customer vulnerability, source worker, and tenant thresholds. Maker and checker must be distinct where dual control applies. A checker sees the same before/after comparison, evidence, warnings, and action hash that execution will use.

AI can prepare and recommend an action within its work packet. It cannot supply human approval, change its own autonomy level, or alter the action after approval.

Idempotent submission and acknowledgement

The gateway derives a stable execution key from tenant, action request, and attempt. The system of record must return the same acknowledgement for a retry.

For the built-in Lending Core, execution is in process rather than a call to a generic actions API: a typed executor resolves the loan’s facts and capabilities, applies the governed native command—case context attached, maker-checker parking respected—and records the case effects and governance record. A bring-your-own-core binding submits the same typed action over its documented HTTP contract.

{
  "actionRequestId": "act_CEDAR_RA_81",
  "status": "completed",
  "result": {
    "coreCommand": "reAmortize",
    "resourceId": 7204,
    "governanceId": 903,
    "effectiveDate": "2027-08-20"
  },
  "requestedHash": "sha256:2a7f…12ce",
  "appliedHash": "sha256:2a7f…12ce"
}

Normalized execution results are COMPLETED, PENDING_EXTERNAL, REJECTED, MANUAL_REQUIRED, FAILED, and CAPABILITY_UNAVAILABLE. Provider-native detail remains available in restricted evidence.

Divergence and manual execution

If the applied amount, date, treatment, or resulting state differs from the approved request, the gateway records both, marks FAILED_ACTION_REVIEW, and opens reconciliation work. It never labels the requested value as applied.

For a MANUAL_REQUIRED binding, an approved specialist records the authoritative reference and applied facts. Manual completion passes the same reconciliation checks; it is not a free-form “done” button.

Undo is a compensating action

Supported undo operations—dedicated commands such as undowriteoff, undo-charge-off, undoReAge, undoReAmortize, and undoContractTermination on the built-in core—create a new action linked to the original. They verify that the target is still reversible and that no later dependent transaction makes undo unsafe. The original action, approval, and evidence remain immutable.

Unified search across guides, recipes & the API referenceEsc