Statements
A statement is a frozen rendering of a frozen snapshot, tied to a repayment due date and corrected only by a replacement that supersedes it.
A statement is the one document the borrower keeps, and once it has gone out it has to keep saying what it said. So each completed statement is a frozen rendering of a frozen data snapshot, produced by the scheduled job at the product’s lead time; there is no public generate operation to fire a second one. Statements are tied to repayment due dates rather than assumed calendar months, because the obligation falls on a due date and a document organized around the calendar would describe a period the borrower was never billed for.
A retry never produces two current statements
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.
Rendering reads only the snapshot
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.
Nothing else is read at render time. A customer address correction made after cutoff cannot change the PDF during a retry—otherwise a failed render followed by a successful one would put two different documents into the world under the same version number, and only one of them would be the statement anybody could produce later.
Where Harbor’s $517.14 comes from
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.
A failed delivery does not prove 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.
Generating the document and delivering it are separate facts, and only the second one is notice. Delivery status and evidence are therefore tracked apart from document completion, and a draw that depends on successful notice can be held—debiting an account after the notice bounced is the failure the ten-day window exists to prevent.
The list row is the metadata
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, because a half-rendered document handed to a borrower is one nobody can take back. There is no separate metadata route: everything a caller needs to identify a version is on the row.
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 a fixed list—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.
Five rules that must hold
- 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.