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.
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.
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.
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.

