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

# Quickstart

> Authenticate, create a customer, and create a loan in under five minutes.

This walks through the common end-to-end flow: authenticate, create a
customer, and create a loan. A single `POST /v1/loans` call returns
an already-active loan — there is no separate approve or disburse
step.

## 1. Obtain a token

The API lives on two hosts:

| Purpose                                                          | Host                         |
| ---------------------------------------------------------------- | ---------------------------- |
| Token issuance, authenticate, authorize                          | `https://auth-api.bsa.ai`    |
| All other endpoints (customers, loans, repayments, credit, etc.) | `https://api-staging.bsa.ai` |

Get a token from the auth host using HTTP Basic with your account
credentials. The service signs with whichever RSA key it currently
considers active — you don't pass a `kid`.

```bash theme={null}
TOKEN=$(curl -sf --user "<email>:<password>" \
  https://auth-api.bsa.ai/v1/auth/token | jq -r .token)
```

The response is `{"token": "<JWT>"}`. Tokens are valid for 365 days —
see [Handling expiry](/concepts/authorization#handling-expiry) for the
three recommended refresh patterns (proactive `exp` check, reactive
401 catch-and-retry, or a scheduled rotation cron).

All examples below assume `TOKEN` is set and `BASE=https://api-staging.bsa.ai`.

## 2. Create a customer

The only field you choose is your own `externalId` — the identifier
that ties the LMS customer record back to your system. Everything else
(office, names, legal form, activation date) is filled in server-side
and the customer is created `Active` immediately.

<CodeGroup>
  ```bash cURL theme={null}
  CUSTOMER_ID=$(curl -sf -X POST "$BASE/v1/customers" \
    -H "Authorization: Bearer $TOKEN" \
    -H "Content-Type: application/json" \
    -d '{"externalId": "ext-ada-001"}' | jq -r .id)
  echo "customerId: $CUSTOMER_ID"
  ```
</CodeGroup>

```json Response theme={null}
{
  "id": "42",
  "accountNo": "000000042",
  "externalId": "ext-ada-001",
  "status": "Active",
  "active": true,
  "officeId": "1",
  "officeName": "Head Office",
  "firstname": "ext-ada-001",
  "lastname": "Customer",
  "displayName": "ext-ada-001 Customer",
  "activationDate": "2026-05-25"
}
```

Note the `id` field — `"42"` as a string. Pass it back exactly as
received. `firstname` mirrors your `externalId` so the customer is
searchable by it; `lastname` is a fixed placeholder LMS requires for
person records.

## 3. Create a loan

Three required fields plus an optional `externalId` — your own
reference for the loan (e.g. a wallet transaction id). `customerId`
carries the **customer's externalId** (the one you chose in step 2),
not the numeric LMS id — you never need to store LMS ids on your side.
Every loan term is inherited from the chosen product. The returned
loan is already `Active`.

<CodeGroup>
  ```bash cURL theme={null}
  LOAN_EXT="loan-ext-$(date +%s)"

  LOAN_ID=$(curl -sf -X POST "$BASE/v1/loans" \
    -H "Authorization: Bearer $TOKEN" \
    -H "Content-Type: application/json" \
    -d "{\"customerId\": \"ext-ada-001\", \"productId\": 1, \"principal\": 5000, \"externalId\": \"$LOAN_EXT\"}" | jq -r .id)
  echo "loanId: $LOAN_ID  loanExternalId: $LOAN_EXT"
  ```
</CodeGroup>

```json Response (abbreviated) theme={null}
{
  "id": "501",
  "externalId": "loan-ext-1779712705",
  "status": "Active",
  "principal": 5000,
  "currencyCode": "TZS",
  "totalOutstanding": 5550,
  "nextDueDate": "2026-06-04",
  "nextDueAmount": 5550,
  "repaymentSchedule": [ /* one period per instalment */ ]
}
```

The response carries the full balance roll-up (`principalOutstanding`,
`interestCharged`, `totalOutstanding`, ...) plus `nextDueDate` /
`nextDueAmount` and the amortisation `repaymentSchedule`. Partners can
render "you owe X, due Y" without a follow-up GET. See
[Create a loan](/loans/create) for the complete field reference.

## 4. Record a repayment

Two equivalent forms — by the LMS numeric id, or by the loan's
`externalId` you set above.

```bash theme={null}
# By LMS id
curl -sf -X POST "$BASE/v1/loans/$LOAN_ID/repayments" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"transactionAmount": 450}'

# Equivalent — by loan externalId
curl -sf -X POST "$BASE/v1/loans/external/$LOAN_EXT/repayments" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"transactionAmount": 450}'
```

Every repayment endpoint (`waive-interest`, `recover`, `refund`,
`credit-balance-refund`, `charge-off`, get/adjust/reverse transaction)
has both forms — see
[Repayments → Identifying the loan](/repayments/overview#identifying-the-loan).

## Next steps

* Browse the full [Customers API](/customers/overview)
* Read [Errors](/concepts/errors) so you can branch on failure codes
* Learn how [pagination](/concepts/pagination) works on list endpoints
