Statements
Read job-generated due-date statements built from cutoff-based activity windows and immutable fact snapshots, with governed regeneration and PDF download.
LendEasy statements are tied to repayment due dates, not assumed calendar months. Each completed document is a frozen rendering of a frozen data snapshot, generated by the scheduled statement job—there is no public generate operation.
Generation lifecycle
The job runs at the product’s lead time: a loan on a statement-enabled product with statementLeadDays: 10 gets its October 12 statement generated around October 2. Products with statementEnabled: false produce no statements.
Cutoff windows: every posting exactly once
Statement N includes activity in (priorCutoff, currentCutoff]. A transaction posted at the current cutoff belongs to N; one posted one millisecond later belongs to N+1.
For Harbor’s October 12 due date, assume:
| Boundary | Timestamp |
|---|---|
| Prior generation cutoff | September 2, 2026 at 23:59:59 PT |
| Current generation cutoff | October 2, 2026 at 23:59:59 PT |
| Statement due date | October 12, 2026 |
The September 12 payment settled and posted on September 15, so its posted transaction falls inside this window. The statement shows the payment with its September 12 value date and September 15 posting timestamp; it is not pushed backward into a document that had already been generated.
Snapshot contents
Before rendering, LendEasy freezes:
- lender and customer display data, including the selected statement address;
- loan identity, status, and due obligation;
- opening and closing principal, interest, fee, penalty, and credit balances;
- every activity-window transaction with allocation and reversal link;
- active autopay terms and relevant notice data;
- payment instructions and permitted contact channels; and
- the template version, cutoff, and source-fact timestamps.
Rendering reads only this snapshot. A customer address correction made after cutoff cannot change the PDF during a retry.
Harbor statement arithmetic
October due-date statement
opening principal (after origination) $8,400.00
September payment principal allocation −424.39
─────────
closing principal $7,975.61
next scheduled principal 429.08
next scheduled interest 88.06
─────────
amount due October 12 $517.14The scheduled interest shown here follows the regular monthly illustration in the example portfolio. Production statement amounts come from the authoritative schedule snapshot, including exact date and rounding conventions.
Variable autopay notice
When the statement is the notice artifact for a varying preauthorized transfer—every FULL_DUE autopay enrollment—it includes the scheduled debit amount and date plus the required opt-out or range language. Enrollment enforces the lead: statementLeadDays must cover the notice window, since Regulation E § 1005.10(d) generally describes at least 10 days’ advance notice for varying transfers, subject to its range option.
A statement that fails delivery does not prove notice. Delivery status and evidence remain separate from document completion, and a draw that depends on successful notice can be held.
List and download
curl "$BASE/v1/loans/7204/statements" \
-H "Authorization: Bearer $TOKEN" \
-H "LendEasy-Tenant: demo-lender"
{
"items": [
{
"statementId": 7719,
"dueDate": "2026-10-12",
"status": "COMPLETED",
"generationTrigger": "SCHEDULED_JOB",
"templateVersion": "stmt-v1",
"statementVersion": 1,
"createdAt": "2026-10-03T00:10:00Z"
}
]
}
Statements list newest due date first, and superseded versions remain listed. GET /v1/loans/7204/statements/7719/download streams the PDF as an attachment—only COMPLETED statements are downloadable. There is no separate metadata route; the list row is the metadata.
Regeneration, not editing
A completed document is never edited. Correcting a defect creates a replacement:
curl -X POST "$BASE/v1/loans/7204/statements/7719/regenerate" \
-H "Authorization: Bearer $TOKEN" \
-H "LendEasy-Tenant: demo-lender" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: harbor-stmt-7719-regen-01" \
-d '{ "reasonCode": "SOURCE_DATA_CORRECTION", "comment": "Reflects the corrected 2026-09-12 payment allocation." }'
Regeneration applies only to COMPLETED statements and requires a reason code from the closed catalog—SOURCE_DATA_CORRECTION, TEMPLATE_CORRECTION, COMPLIANCE_CORRECTION, OPERATIONAL_RECOVERY, or OTHER (comment required). The replacement carries generationTrigger: "REGENERATION", the recorded regenerationReasonCode, and an incremented statementVersion; the source statement flips to SUPERSEDED only when the replacement completes, so there is never a gap with zero current statements. The original remains retrievable to authorized users.
Statements are also loan documents
Every completed statement is registered as a system document linked to its loan, so it appears in GET /v1/loans/7204/documents alongside uploaded evidence and travels under the same retention and access controls as other loan documents.
Payment receipts are different
A due-date statement describes an account at a cutoff. A payment receipt confirms one posted payment. Receipts are available only after POSTED; a pending debit cannot produce one. If that debit later returns, the receipt remains historical and the return appears in the payment’s timeline.
Operational checks
- Every eligible due date has exactly one current statement.
- Activity-window queries have no gaps or overlaps.
- A
COMPLETEDstatement has a downloadable artifact; a failed render never reports completed. - Delivery evidence references the exact statement version sent.
- Superseded versions and their replacements are both listed, with the regeneration reason on the replacement.