Record loan payments with component-based allocation, automatic general ledger entries, and duplicate protection through idempotency keys.
Every loan payment in CEF Core is component-based, meaning each payment is broken down into its constituent parts rather than recorded as a single lump sum. This ensures precise tracking of how funds are applied and accurate GL accounting.
Reduces the outstanding loan balance. Recorded via principal_amount.
Covers accrued interest since the last payment. Recorded via interest_amount.
Late fees, origination fees, or other charges. Recorded via fee_amount.
The total payment amount equals the sum of all three components. You may specify zero for any component that does not apply (e.g., a principal-only paydown would set interest_amount: 0 and fee_amount: 0).
Follow these steps to record a payment against an active loan.
principal_amount -- Amount applied to principalinterest_amount -- Amount applied to interestfee_amount -- Amount applied to fees (optional, defaults to 0)payment_date -- Date the payment was receivedpayment_method -- ACH, CHECK, WIRE, or CASHreference_number -- Check number, wire reference, or ACH trace IDPOST /api/v1/loans/:id/payment with an idempotency key.CEF Core supports four payment methods. The method selected affects how the reference number is validated and which cash account receives the funds.
| Method | Reference Number | Notes |
|---|---|---|
ACH | ACH trace number | Electronic transfer via Automated Clearing House. Typically 1-2 business day settlement. |
CHECK | Check number | Physical or electronic check. Record the check number for reconciliation. |
WIRE | Wire reference ID | Bank wire transfer. Same-day settlement for domestic wires. |
CASH | Receipt number | Physical cash deposit. Requires in-person receipt documentation. |
When a payment is recorded, CEF Core automatically generates double-entry journal entries in the General Ledger. No manual GL posting is required.
| Account | Debit | Credit |
|---|---|---|
| Cash (bank account) | Total payment | -- |
| Loans Receivable | -- | Principal portion |
| Interest Income | -- | Interest portion |
| Fee Income | -- | Fee portion |
These entries are posted to the GL via the event outbox pattern, ensuring they are never lost even if the GL service is temporarily unavailable.
Loan payments are money operations, and CEF Core requires an idempotency key for all money operations. This prevents accidental duplicate payments caused by network retries, double-clicks, or system errors.
x-idempotency-key header (typically a UUID) for each payment submission.ops.idempotency_keys table for a matching key.Important: Never reuse an idempotency key for different payment amounts or different loans. Each unique payment intent must have its own key. Keys expire after 24 hours.
| Method | Endpoint | Description |
|---|---|---|
POST | /api/v1/loans/:id/payment | Record a payment (requires x-idempotency-key header) |
GET | /api/v1/loans/:id | View loan detail with payment history |
GET | /api/v1/loans/:id/schedule | View scheduled vs. actual payments |
Pro Tip: The payment endpoint returns the updated loan balance in the response body. Use this to update the UI immediately without making a second GET request.
Learn how amortization schedules determine the expected principal and interest split for each payment period.
Amortization Schedules Guide