> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lms.bsa.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Record a repayment

> Post a regular installment repayment.

Records a standard repayment against an active loan. The amount is
allocated to interest then principal according to the loan's
processing rules.

Two equivalent forms — prefer the externalId form for partner integrations.

## Path parameters

<ParamField path="loan_external_id" type="string" required>
  The loan's externalId. On the `/v1/loans/{loan_id}/repayments` form,
  this is the numeric LMS id instead.
</ParamField>

## Request body

<ParamField body="transactionAmount" type="number" required>
  Must be greater than 0.
</ParamField>

<ParamField body="transactionDate" type="string">
  Optional **value date** of the payment, in ISO `yyyy-MM-dd`. Books the
  repayment as of the day the money actually moved on your side rather
  than the day you call this API — the reconciliation case where a
  wallet debit succeeds but settling with us is delayed (a failure,
  timeout, or a next-day retry).

  When the value date is **on or before the loan's due date** (the
  customer paid on time) and the loan is carrying an overdue penalty the
  LMS raised while your settle call was in flight, the service
  automatically cancels that penalty before posting the repayment, then
  lets the LMS recompute it against whatever is genuinely still overdue.
  See [Reconciling delayed settlements](/repayments/overview#reconciling-delayed-settlements)
  for the full behaviour.

  Defaults to the current date when omitted. Must be **on or after the
  loan's disbursement date** and **not in the future**. Backdating
  across a later transaction already recorded on the loan may be
  rejected by the ledger.
</ParamField>

<ParamField body="idempotencyKey" type="string">
  Optional dedupe token — typically your **wallet transaction reference**
  for this payment (max 100 characters). If a repayment carrying this key
  has already been recorded on the loan, the original transaction is
  returned unchanged: the retry neither double-posts nor re-runs penalty
  reconciliation. **Strongly recommended on every repayment** so timeouts
  and retries are safe to replay. Use a value unique per payment.
</ParamField>

## Examples

```bash theme={null}
# By loan externalId (recommended)
curl -sf -X POST "$BASE/v1/loans/external/loan-ext-12345/repayments" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "transactionAmount": 11100 }'

# Backdated value date + idempotency key — settle as of the day the
# wallet was debited, safe to retry. Recommended shape for every payment.
curl -sf -X POST "$BASE/v1/loans/external/loan-ext-12345/repayments" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "transactionAmount": 11100, "transactionDate": "2026-06-01", "idempotencyKey": "wallet-txn-abc123" }'

# Same effect, by LMS id
curl -sf -X POST "$BASE/v1/loans/501/repayments" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "transactionAmount": 11100 }'
```

## Response

`200 OK` returns the [repayment object](/repayments/overview) showing
how the amount was allocated.

```json theme={null}
{
  "id": "7821",
  "type": "Repayment",
  "date": "2026-05-25",
  "amount": 11100,
  "principal": 10000,
  "interest": 1100,
  "status": "posted"
}
```

## Errors

| Code                  | When                                                                                                                                                                    |
| --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `not_found`           | No loan with that id or externalId                                                                                                                                      |
| `failed_precondition` | Loan is not in an active state                                                                                                                                          |
| `invalid_argument`    | Missing or non-positive `transactionAmount`; `transactionDate` not ISO `yyyy-MM-dd`, in the future, or before disbursement; `idempotencyKey` longer than 100 characters |
