Funding & disbursement
Money leaving the lender is approval-gated, released by the system rather than by a caller, and never resubmitted after settlement—and no loan becomes an obligation until its payout posts.
Money leaving the lender is the one operation nobody can undo by asking politely. So funding is an intent rather than an act: approval, rail submission, settlement, and ledger posting happen at different times, and a design that collapsed them would either send a payout before anybody approved it or record a debt the borrower has not yet received. The intent explains where the money is; the ledger explains what the customer owes. Fundings are loan-scoped: every payout lives under /v1/loans/{loanId}/fundings.
A posting failure is not permission to resend
A disbursement requires an approved, inactive loan
The loan must be APPROVED and not yet active, and the amount may not exceed the approved principal. A DISBURSEMENT_HOLD restriction blocks creation outright, which is what makes a hold a stop rather than a warning somebody can decline to read.
curl -X POST "$BASE/v1/loans/7204/fundings" \
-H "Authorization: Bearer $TOKEN" \
-H "LendEasy-Tenant: demo-lender" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: harbor-initial-funding-01" \
-d '{
"amount": "8400.00",
"currency": "USD",
"fundingType": "DISBURSEMENT",
"recipientType": "BORROWER",
"recipientRef": "412",
"instrumentId": 705,
"rail": "ACH",
"reason": "Initial disbursement for approved loan."
}'
{ "fundingId": 5107, "loanRef": "7204", "status": "APPROVAL_REQUIRED" }
Harbor’s $252 prepaid origination fee is a loan charge assessed at disbursement, not a second payout; the posted advance establishes the $8,400 receivable while Maya’s proceeds are $8,148. See Accounting for the balanced entries.
Approval: maker and checker are different people
Every funding starts in APPROVAL_REQUIRED. There is no submit route: once approved, the system releases the payout to the rail itself, leaving no window between the decision and the transfer in which a destination could be edited into something the checker never saw.
POST /v1/loans/7204/fundings/5107/approvetakes no body. The creator can never approve their own funding—a second pair of eyes is only worth having if it belongs to a second person, and this is the last point at which anyone is looking.POST …/rejectrecords a requiredreasonCode.POST …/cancel(reasonCode, optionalcomment) works only before money movement—whileCREATED,VALIDATED,APPROVAL_REQUIRED, orAPPROVED. Cancelling an already-cancelled funding is a no-op.
Approval and rejection return the command receipt, for example { "resourceId": 5107 }; read the funding for its current state with GET /v1/loans/7204/fundings/5107.
Five checks before anything is submitted
A funding recipient is BORROWER or EXTERNAL_PARTY—a merchant, dealer, healthcare provider, school, vendor, or investor. Every one of these is cheap to check now and unrecoverable to discover afterwards, so LendEasy confirms all five before submission:
- the recipient reference resolves to the borrower or an active, verified external party;
- the payment instrument belongs to that recipient and is
ACTIVEwithverificationState: "VERIFIED"; - the requested rail is within the instrument’s capabilities;
- a disbursement does not exceed the approved principal; and
- no restriction blocks money movement.
Juniper’s financed purchase can pay its merchant as an external-party funding while the down payment settles separately. The loan activates only when the financed payout posts.
Accrual starts when the money leaves
The disbursement posts value-dated on release: the accrual start and activation date come from the date funds left the lender’s control, not from createdAt, the approval time, or the moment the rail accepted the request. Pick any of those earlier timestamps and the borrower pays interest for days in which they had nothing to use. Those timestamps all remain on the funding record so the sequence stays auditable, but only the posted value date drives loan calculations.
Treasury wires are recorded, not re-sent
When treasury moves the money—for example a wire—record it instead of creating a rail payout:
POST /v1/loans/7204/fundings/record-external
The body carries amount, currency, fundingType, recipientType, recipientRef, a unique externalRecordRef, and a reason. No instrument or rail is involved and no money moves; the funding enters reconciliation as RECORDED_EXTERNAL.
A refund funding never posts twice
fundingType: "REFUND" moves money out for a ledger effect that already exists—a governed refund command such as credit-balance refund or payout refund creates the balance effect, and the funding pays it. The funding itself does not post a second ledger transaction, so the books can never show a refund twice. A refund funding follows the same approval, submission, and posting path as a disbursement.
Repair the posting, not the payout
Once funds are released, a missing ledger post routes the funding to POSTED_FAILED_REVIEW. What failed there is the bookkeeping, not the transfer: the money has already gone, and sending it again would turn a recording error into a real one. Operators repair or confirm the single posting, and a recovery—if money went to the wrong destination—is a separate governed workflow. Differences between provider events, fundings, and the ledger surface as reconciliation exceptions, which never auto-close a mismatch solely because totals happen to net to zero; two errors that cancel each other out are still two errors, and they rarely cancel twice.