LendEasy/DocsLMS + Servicing·v1
Start integrating
Guides›Overview›Dates & timestamps

Dates & timestamps

A business date and a wall clock answer different questions, and converting one into the other in client code changes what the money means.

The API deliberately uses both calendar dates and timestamps, because they answer different questions: which period the money belongs to, and when something actually happened. Converting one into the other in client code changes the meaning of both — and it changes it quietly. A date that is one day out still parses, still renders, and still passes every test that never checks which period it landed in.

The shape tells you which kind it is

Preserve offsets as supplied. Normalize to UTC for storage if desired, but retain the original customer-local or policy-local context needed for explanation: an offset dropped on the way in cannot be recovered later. The instant survives, but the thing that made it meaningful — the borrower’s evening, the policy’s cutoff — does not, and no amount of arithmetic afterwards puts it back.

Native routes speak a different date dialect

The native loan and accounting routes add two conventions of their own:

  • Requests carry dateFormat and locale alongside every date, and the dates must match that format: { "submittedOnDate": "2026-08-11", "dateFormat": "yyyy-MM-dd", "locale": "en" }.
  • Responses serialize dates as [year, month, day] arrays — a schedule period’s due date arrives as "dueDate": [2026, 9, 12].

LendEasy-owned resources — customers, payments, fundings, statements, the loan summary — use plain ISO strings in both directions and never require dateFormat or locale. Map the array form to a date-only value at your integration boundary. Fed straight into a timestamp constructor it becomes a moment, in a zone nobody chose, and the date-only meaning it arrived with is gone.

Effective date is not posting time

Harbor payment 1 is effective September 12 and posts after ACH settlement on September 15:

{
  "paymentId": 9011,
  "effectiveDate": "2026-09-12",
  "timeline": [
    { "occurredAt": "2026-09-15T14:22:08Z", "source": "LMS", "state": "POSTED", "postedTransactionRef": "30411" }
  ]
}

Allocation, accrual, delinquency, and the next schedule state use the approved effectiveDate — posting is value-dated back to it, and a future effective date posts on that business date. Operational latency and reconciliation use the timeline’s posting instant. The system does not disguise settlement delay by rewriting either field.

This is the distinction that breaks a customer’s tests quietly. A suite that pushes the wall clock forward and waits for an allocation, an accrual, or a delinquency figure to move is watching fields the clock does not drive — all three follow the approved effectiveDate. The test then either waits for something that was never going to happen, or goes green because the only thing it really asserted was that nothing threw. Either way the behaviour it was written to cover was never exercised.

Interest starts at disbursement, not at approval

An expected disbursement date is proposal input. Interest begins from the actual effective disbursement established when the payout settles and posts under product policy. Approval or provider acceptance alone does not establish the loan balance.

A recently observed old fact is still old

Bring-your-own-core facts carry both:

{
  "name": "loan.amountPastDue",
  "value": { "amount": "517.14", "currency": "USD" },
  "asOf": "2027-05-01T10:11:56-07:00",
  "observedAt": "2027-05-01T10:11:57-07:00",
  "freshness": "fresh"
}

asOf measures source truth; observedAt measures integration latency. A recently observed old fact is still old — reading observedAt as freshness makes a stale balance look current every time it is re-fetched, because the fetch is the only thing that moved.

The borrower’s clock decides, never the operator’s

Contact eligibility resolves the customer’s applicable local time from approved facts and records the time zone and rule version. Daylight-saving gaps and repeats are handled by a named scheduling policy. Never compare the operator’s local clock to a customer contact window: a collector working in one time zone and a borrower living three away are inside different days, and the operator’s day is not the one the rule is written about.

Midnight UTC is how a date loses a day

Parse 2026-09-12 into midnight UTC, render it in a negative offset, and it becomes September 11. Treat business dates as date-only values through your stack, whether they arrive as ISO strings or as native [year, month, day] arrays.

A correction leaves the original standing

Backdated financial actions validate permitted effective windows, locked statements, accounting periods, and schedule dependencies. A permitted correction creates explicit reversal/reprocessing records; it does not edit historical timestamps, so the figure somebody acted on last month is still readable beside the correction that superseded it.

Every payoff figure is computed on the read

The loan summary’s payoff block is a projection computed for payoffGoodThroughDate — the current business date when omitted. goodThroughDate identifies the calculation horizon, quotedAt records when it was computed, and validUntil bounds how long the figures may be used. Nothing is stored: if collection will be effective after the good-through date, re-read the summary with a later date rather than appending client-calculated per diem.

Send money on LendEasy-owned resources as decimal strings and business dates as date-only strings; give native routes their decimal numbers and dateFormat + locale. These conventions prevent the most common cross-language rounding and time-zone defects in lending integrations.
Unified search across guides, recipes & the API referenceEsc