Create Loan
Create or update (upsert) a loan pushed from an external partner. The loan is keyed on (customer, externalReference). Returns 201 on create, 200 on update.
Overview
Create or update (upsert) a loan pushed from an external partner. The loan is keyed on the combination ofcustomerId and id (your external loan reference). If an active loan with the same external reference already exists for the customer, it is updated in place; otherwise a new loan is created.
This endpoint is designed for collections intake — all loans must be created with servicingStatus: ACTIVE.
Upsert Behavior
POST /loans is an upsert. If you push a loan that already exists (matched on id + customerId among active loans), we update the existing record. Soft-deleted or deactivated (NOT_SERVICING) loans are not matched — a new active loan is created instead.
- New loan: Returns
201 Created - Existing loan updated: Returns
200 OK - Concurrent duplicate: Returns
409 Conflict
Required Fields
| Field | Type | Description |
|---|---|---|
id | string | Your stable loan reference ID. Must be unique per customer among active loans. |
customerId | string | Must match the id used when the customer was pushed via POST /customers. |
amountDue | number | Origination amount due. Must be positive. Immutable after creation — cannot be changed on subsequent upserts. |
dueDate | string | Next scheduled payment date (YYYY-MM-DD). |
servicingStatus | string | Must be ACTIVE on create. On upsert, can be set to NOT_SERVICING to stop servicing. |
totalBalance | number | Current outstanding balance. Must be non-negative. |
originationDate | string | Date the loan was originated (YYYY-MM-DD). Required for cadence policy. |
Validation Rules
Balance fields (non-negative)
All monetary fields must be>= 0 when provided: totalBalance, originalFundedAmount, originalTotalOwed, totalPayoffAmount, payoffAmount, balanceAtTransfer, preTransferPayments, chargeoffAmount.
amountDue must be strictly positive (> 0).
Rate fields
interestRate and apr must be non-negative. Values are stored as decimals where 1.0 = 100%. High-interest loans can have values above 1.0 (e.g. 6.49 = 649% APR).
Chargeoff pairing
chargeoffDate and chargeoffAmount must both be set or both omitted. Setting only one returns a validation error.
Settlement percentages pairing
paymentPlanMinPercentage and paymentPlanMaxPercentage must both be set or both omitted. When set, both must be between 0 and 1, and min <= max. When both are omitted (null), the loan is pay-in-full only (no settlement discount).
Portfolio ID
portfolioId must be a valid UUID when provided. If omitted, defaults to the configured portfolio for your company.
Servicing status
servicingStatus must be ACTIVE on loan creation. To stop servicing on an existing loan, you can either upsert with servicingStatus: NOT_SERVICING (which also updates any other loan fields in the same call) or use the dedicated POST /loans/{id}/cancel-servicing endpoint. Both cancel all scheduled payments and communications.
Schedule creation
A collections schedule is automatically created on new loans based on the specifiedtaskType. The customer must have a valid IANA timezone set. taskType defaults to Collections if not specified.
Request Body
Error Responses
| Status Code | Description |
|---|---|
| 400 | Invalid enum value, servicingStatus not ACTIVE on create, mismatched amountDue on upsert, invalid timezone |
| 404 | Customer with the given customerId not found |
| 409 | Concurrent duplicate — another request created the same loan |
| 422 | Validation error (negative balance/rate, unpaired chargeoff/settlement fields, invalid UUID, missing required field) |
| 500 | Internal server error |
Authorizations
Body
Loan data
Your stable loan reference ID
"LOAN-12345"
External reference of a previously-pushed customer
"CUST-001"
Required. Date the loan was originated.
"2026-04-01"
Required. Current outstanding balance.
x >= 0425
Origination amount due. Must be positive. Immutable after creation.
125
Next payment date (YYYY-MM-DD)
"2026-05-01"
Must be ACTIVE on create. Use cancel-servicing endpoint to stop.
ACTIVE CASH_ADVANCE, PERSONAL_LOAN, INSTALLMENT_LOAN PENDING, APPROVED, FUNDED, WITHDRAWN, REJECTED x >= 0500
x >= 0650
Non-negative decimal where 1.0 = 100% (e.g. 6.49 = 649%)
x >= 00.2999
Non-negative decimal where 1.0 = 100%
x >= 00.355
x >= 0x >= 0x >= 0x >= 0Must be paired with chargeoffAmount
Must be paired with chargeoffDate
x >= 0true
CUSTOMER_OPT_OUT, LEGAL_HOLD, BANKRUPT, INCARCERATED, DECEASED, MILITARY, FRAUD, AGENCY_REQUEST, COMPLAINT, WRONG_NUMBER, OTHER CUSTOMER_OPT_OUT, LEGAL_HOLD, BANKRUPT, INCARCERATED, DECEASED, MILITARY, FRAUD, AGENCY_REQUEST, COMPLAINT, WRONG_NUMBER, OTHER CUSTOMER_OPT_OUT, LEGAL_HOLD, BANKRUPT, INCARCERATED, DECEASED, MILITARY, FRAUD, AGENCY_REQUEST, COMPLAINT, WRONG_NUMBER, OTHER true
x >= 0x >= 0Portfolio UUID for payment processor routing
Min settlement percentage (0-1). Both min+max required together. NULL = pay-in-full.
0 <= x <= 1Max settlement percentage (0-1). Both min+max required together. NULL = pay-in-full.
0 <= x <= 1Schedule task type (e.g. Collections). Defaults to Collections for JustLoans.
"Collections"
Response
Existing loan updated
External loan reference ID
External customer reference ID