active status, submit the loan details to create and queue it for disbursement.Prerequisite: The merchant's onboarding_statusmust beactivebefore calling this endpoint. Get themerchant_idfrom the Register Personal response. If the status is not yetactive, wait for thekyb.status_updatedwebhook or poll Get Onboarding Status.
| Item | Description |
|---|---|
| Method | POST |
| Path | /v1/loans/submit |
| Auth | OAuth2 Client Credentials (Bearer Token) |
| Content-Type | application/json |
| Header | Type | Required | Description |
|---|---|---|---|
Authorization | String | Yes | Bearer <access_token> |
Request-Id | UUID | Yes | Idempotency key. Use UUID v4. A duplicate Request-Id returns the original loan response without re-creating. |
| Field | Type | Required | Description |
|---|---|---|---|
merchant_id | UUID | Yes | The merchant_id from the registration response. |
loan | Object | Yes | Loan financial details. See below. |
loan)| Field | Type | Required | Description |
|---|---|---|---|
reference_account_number | String | Yes | Your internal reference for this loan. Max 50 characters. Must be unique per lender. |
principal_amount | Number | Yes | Loan principal in IDR (e.g., 5000000). |
interest_amount | Number | Yes | Total interest amount for the full term, in IDR. |
admin_fee_amount | Number | No | Admin fee deducted from the disbursed amount. In IDR. |
reserve_amount | Number | Yes | Reserve/collateral deposit held by QFAST. In IDR. |
term_length | Integer | Yes | Duration of the loan in months. Must equal the number of repayment_schedules. |
penalty_rate | Number | No | Daily late penalty rate as a decimal (e.g., 0.01 = 1%). Range: 0.0–1.0. |
start_date | String | Yes | Loan start date in YYYY-MM-DD format. |
repayment_schedules | Array | Yes | List of scheduled repayment entries. Count must equal term_length. |
| Field | Type | Required | Description |
|---|---|---|---|
principal_amount | Number | Yes | Principal portion due on this schedule entry, in IDR. |
interest_amount | Number | Yes | Interest portion due on this schedule entry, in IDR. |
due_date | String | Yes | Expected payment date in YYYY-MM-DD format. |
daily_amount | Number | Yes | Daily deduction amount from the merchant's revenue, in IDR. |
Validation rule: repayment_schedules.countmust exactly equalterm_length. Mismatches return a422error.
{
"data": {
"loan_id": "019e15a1-c644-705c-9330-fffa62cd44ed",
"reference_account_number": "1234567890",
"status": "pending",
"principal_amount": 5000000,
"interest_amount": 900000,
"admin_fee_amount": 250000,
"reserve_amount": 230533,
"term_unit": "month",
"term_length": 6,
"penalty_rate": "0.0000",
"start_date": "2026-06-01"
}
}| Field | Type | Description |
|---|---|---|
loan_id | UUID | Unique identifier for the loan. Store this — required for operations. |
reference_account_number | String | Your reference number for this loan. |
status | String | Loan status. Initial value: pending. |
principal_amount | Number | Loan principal in IDR. |
interest_amount | Number | Total interest amount in IDR. |
admin_fee_amount | Number | Admin fee in IDR. Deducted from disbursed amount. |
reserve_amount | Number | Reserve amount held by QFAST, in IDR. |
term_unit | String | Loan term unit. Value: month. |
term_length | Integer | Loan duration in months. |
penalty_rate | String | Daily late penalty rate as a string. |
start_date | String | Loan start date in YYYY-MM-DD format. |
disburse_amount = principal_amount - admin_fee_amount{
"error": "invalid_token",
"error_description": "The access token is missing or invalid.",
"code": 401
}{
"error": "merchant_not_found",
"error_description": "Merchant ID [019db2ee-3857-7148-b320-6f6e7c4deedd] does not exist or belongs to a different lender.",
"code": 404
}{
"error": "duplicate_reference",
"error_description": "Reference account number [LND-ACC-2026-0001] already exists.",
"code": 409
}{
"error": "merchant_not_active",
"error_description": "Merchant onboarding_status is not active. Complete KYB first.",
"code": 422
}{
"error": "validation_failed",
"error_description": "repayment_schedules count (2) does not match term_length (3).",
"code": 422
}{
"error": "borrower_has_active_loan",
"error_description": "The borrower already has a PENDING or ACTIVE loan.",
"code": 422
}| HTTP Status | Error | Cause |
|---|---|---|
401 | invalid_token | Missing or invalid access token. |
404 | merchant_not_found | merchant_id does not exist or belongs to a different lender. |
409 | duplicate_reference | reference_account_number already exists for this lender. |
422 | merchant_not_active | Merchant onboarding_status is not active. Complete KYB first. |
422 | validation_failed | Missing required fields, invalid formats, or repayment_schedules count mismatch. |
422 | borrower_has_active_loan | The borrower already has a PENDING or ACTIVE loan. |
loan_submitted webhook to your configured webhook URL — see Onboarding Events.