> ## 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.

# Roll back a loan

> Tear down a loan whose wallet disbursement failed — one call instead of three.

Removes a loan that should never have existed — the exception flow for
a failed wallet disbursement. One call performs the full teardown
internally (`undo-disbursal` → `undo-approval` → `delete`) and returns
a single response, so your exception handler doesn't need to chain
three synchronous requests.

The three individual endpoints remain available; rollback is the
consolidated form built on top of them.

## Resumable by design

Each teardown step is durable in the LMS the moment it succeeds. If a
step fails (or your call times out mid-sequence), the loan is left at
a well-defined interim state — and **calling rollback again resumes
from that state** instead of failing on steps that already ran:

| Loan status when called                                        | Steps performed                                                  |
| -------------------------------------------------------------- | ---------------------------------------------------------------- |
| `Active`                                                       | undo-disbursal → undo-approval → delete                          |
| `Approved`                                                     | undo-approval → delete                                           |
| `Submitted and pending approval`                               | delete                                                           |
| `Closed (obligations met)`, `Closed (written off)`, `Overpaid` | rejected with `409 aborted` — settled loans can't be rolled back |

So the partner-side recovery logic collapses to: *call rollback until
you get `200`*. There is no partial-failure state you need to
disambiguate yourself — but if you want to inspect anyway,
`GET /v1/loans/external/{loan_external_id}` reports the interim status
dynamically after every step (`Active` → `Approved` →
`Submitted and pending approval` → `404` once deleted).

<Warning>
  A loan with **recorded repayments** is rejected with `409 aborted`.
  Rollback assumes the loan should never have existed; once a customer
  has paid against it, that premise no longer holds and erasing the
  payment must be an explicit decision. Reverse the repayment(s) first,
  then roll back.
</Warning>

## Path parameters

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

## Request body

<ParamField body="note" type="string">
  Optional. Reason for the rollback — recorded against both undo steps
  in the LMS audit log.
</ParamField>

The body is optional; POST with no body is valid.

## Examples

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

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

## Response

`200 OK` with the steps that ran on this call. A rollback resumed from
an interim state reports only the remaining steps it executed.

```json theme={null}
{
  "rolledBack": true,
  "stepsPerformed": ["undo-disbursal", "undo-approval", "delete"]
}
```

After a successful rollback the loan no longer appears in queries —
`GET /v1/loans/external/{loan_external_id}` returns `404`. The LMS
retains the full activity history (creation, approval, disbursal,
every reversal, deletion) in its audit log.

## Errors

| Code        | When                                                                                                                                                                     |
| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `not_found` | No loan with that id or externalId (including a loan already fully rolled back)                                                                                          |
| `aborted`   | Loan is settled (`Closed` / `Overpaid`), or has recorded repayments — rollback is not applicable in either case                                                          |
| other       | A teardown step failed mid-sequence. The message names the step that halted and the steps already completed; completed steps are durable — call rollback again to resume |
