Access control & maker-checker
Authorize each call through tenant, OAuth scope, exact named permission, resource visibility, sensitivity, case context, and separation of duties—then preserve the decision with the result.
Authentication identifies a client. Authorization decides whether that client may perform this operation on this resource now.
Evaluation layers
valid environment-specific token
∩ tenant isolation
∩ OAuth surface scope
∩ exact endpoint permission
∩ resource / legal-entity visibility
∩ field sensitivity
∩ valid case causation and actor relationship, when required
∩ maker-checker approval
= authorized request
Failure at any layer denies the operation. A broader scope never fills a missing named permission.
Named endpoint permissions
Every operation requires an exact UPPER_SNAKE permission code, displayed on its API page — CREATE_LMS_CUSTOMER, APPLY_LMS_RESTRICTION, READ_LMS_LOAN_SUMMARY, APPROVE_LMS_FUNDING. Read operations alternatively accept the read-superuser permission ALL_FUNCTIONS_READ; no write ever does. Roles aggregate permissions for job functions; integrations receive dedicated least-privilege roles rather than shared administrator credentials.
| Client | Illustrative permissions | Excluded authority |
|---|---|---|
| Borrower portal backend | READ_LMS_CUSTOMER, READ_LMS_LOAN_SUMMARY, CREATE_LMS_PAYMENT |
Product admin, approval, sensitive reads. |
| Servicing workspace | Case/task/interaction permissions, READ_LMS_LOAN_SUMMARY, APPLY_LMS_RESTRICTION |
Direct raw ledger commands. |
| Payment integration | CREATE_LMS_PAYMENT, READ_LMS_PAYMENT, READ_LMS_RECONCILIATION |
Loan modification and customer-document access. |
| Funding approver | READ_LMS_FUNDING, APPROVE_LMS_FUNDING |
Creating and approving the same funding. |
| Reporting pipeline | ALL_FUNCTIONS_READ or named report reads |
Operational mutation. |
Form permissions are derived, not hand-assigned codes from a fixed catalog: publishing a form definition auto-registers READ_LMS_FORM_<KEY>, WRITE_LMS_FORM_<KEY>, and DELETE_LMS_FORM_<KEY> from the form key, so each form’s entries are grantable independently.
External API boundaries
The ordinary client contract exposes normalized customer-facing and lender-integration operations. Three machine-to-machine callbacks are exposed separately in the servicing connector contract; they are not ordinary client operations. Internal orchestration, maintenance, database access, and raw credential/identifier retrieval are not externally reachable endpoints. Ordinary reads are masked; the APIs never return raw payment credentials or vault-tokenized government identifier values outside the audited sensitive routes.
Sensitive reads
Complete identifier values, raw contact values, and vault token references live behind dedicated /sensitive routes that require the ordinary read permission and an additional _SENSITIVE permission — for example READ_LMS_CUSTOMER & READ_LMS_CUSTOMER_SENSITIVE. Every sensitive read is audited, and the response is served with no-store so it is never cached. Search and list endpoints do not reveal hidden content through snippets or counts, and AI work packets receive only the subset their task and policy permit.
Case context and domain authority
When case management is enabled, human servicing mutations — governed commands, restrictions, autopay changes — carry an open case reference in the LendEasy-Case header:
LendEasy-Case: LE-CASE-1001
The platform uses that stable external case reference to validate causation, scope, and the actor’s relationship to the case: owner, active task assignee, or holder of a scoped override. A call without valid case context, or by an actor with none of those relationships, is rejected. Visibility, queue membership, or reservation alone is insufficient.
Case context never grants LMS domain authority. The caller must independently hold the exact permission for the operation. Automation does not send the header; the platform records typed context from the triggering system instead.
Maker-checker
Second-person control is native maker-checker: a flagged governed command parks instead of executing, and a different checker decides through the /v1/makercheckers inbox.
The maker can never be the checker, and the checker must hold the command’s checker permission. The same separation recurs elsewhere in dedicated flows: a funding’s creator cannot approve it, and a reschedule request is applied only when a different user approves it through the reschedule decision route. Approval authorizes execution; it does not guarantee a rail or downstream dependency will accept the result.
Service accounts
Each workload uses a distinct client with owner, environment, purpose, scopes, permissions, rotation policy, network controls where configured, and monitored usage. Human attribution is carried separately from the OAuth client when a backend acts for an authenticated operator.
Audit
Authorization decisions link client, actor, tenant, permission, resource, case context, approval, result, and time. Every governed command execution also writes a governance record — readable per loan or customer via the governance-records routes — capturing the permission code, route, actor class, and case or system context. A 403 is not retriable; change the assigned authority through governed administration.