Skip to main content
Money events, such as a disbursement, a repayment, or an interest accrual, reach the . Lender’s accounting layer is how they get there. A product declares its posting rules once. From then on, each of those events books automatically and traceably.

Accounting profiles and posting rules


An accounting profile binds a product version to the ledger. It defines the posting rules: the legs that fire for each kind of financial event. It also defines the ledger organization and ledger the resulting transactions book into. You create a profile per product: POST /api/v1/loan-products/{id}/accounting-profiles Lender validates the posting rules when you create the profile. A product therefore cannot go live with legs that would not balance.

Posting intents and the relay


Lender does not call the ledger inline. When a financial event happens, Lender persists a durable posting intent. That write happens in the same database transaction that changes domain state. A relay then posts the balanced transaction to Midaz asynchronously. These properties make bookings reliable:
  • The intent commits with the state change: both land in one database transaction, through a transactional outbox.
  • Idempotent: each posting carries a deterministic key, so retries collapse to one ledger transaction.
  • Fails closed: if routing cannot resolve a non-empty ledger target, Lender refuses the post and does not write it to the wrong place.
Lender in the platform describes the full path.

Accrual runs


An accrual run recognizes interest and the other time-based amounts. One run closes the last civil month that had fully ended before its business date, for every loan it selects. It also produces the postings for that month. POST /api/v1/accrual-runs starts a run. Lender selects the candidate loan accounts itself, recognizes interest per account, and writes one posting intent per recognition.
Recognition is idempotent per loan account, per accounting month, and per amount kind. A run started twice for the same month recognizes interest once.

Retrying a run


A recognition is durable the moment the run commits. The ledger booking is not. When a posting never arrives, retry the run instead of starting a new one. POST /api/v1/accrual-runs/{id}/retry names the items to re-send, and takes the same X-Idempotency header the run itself takes. It is a second attempt on the same run, so Lender records no second run. Lender rebuilds the posting behind every named item the ledger has not acknowledged, and enqueues it under the deterministic key the original run used. The relay delivers it, and the ledger treats a duplicate as a duplicate rather than as a second booking. Lender leaves alone the items the ledger already acknowledged. The answer names, item by item, what it could not re-send. It also names why: the posting had already been delivered, it was quarantined, the contract behind it is gone, or the product is misconfigured.
A retry refuses with LENDER-0405 when the posting it rebuilds differs from the one already enqueued under that key. The product’s accounting profile changed after the run, so re-sending would book the month against legs nobody chose for it. Reconcile the enqueued posting first, because repeating the request reproduces the same refusal.

Journal references


Each accrual run records a journal reference, the run’s own accounting identifier. The reference record also stores the correlation id that Lender derived for the run. The journal reference id identifies one run exactly. A read by correlation id returns the most recent run that shares that mode, business date, and product scope. A run emits one posting per loan account, per accounting month, per amount kind. Lender therefore records the tie back to the ledger per posting, not per run. Once the ledger acknowledges a posting, Lender stores a receipt under that posting’s own key. A read by that key answers with the ledger transaction that booked it. A run-level reference carries no ledger transaction of its own: it names the run, and the receipts name the bookings.

Next steps


Jurisdictions

See how the active jurisdiction shapes disclosures and endpoints.

Brazil regulatory pack

Layer CET, IOF, and PDD staging on top of the accounting model.