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

# Get credit scorecard

> Fetch the current credit profile for a customer by externalId.

Returns the customer's current credit grade, score, and pre-approved
loan limit as held by the HaloPesa credit scoring engine. The lookup
key is the **same `externalId`** you set on the customer record — so
once you've created a customer, scoring and lending share one
identifier.

This endpoint is **read-only** — it has no side effects (no SMS, no
database write).

## Path parameters

<ParamField path="external_id" type="string" required>
  The customer's partner-supplied `externalId` (the same value you sent
  on `POST /v1/customers`). 1–128 characters; URL-encode if it contains
  special characters.
</ParamField>

## Example

```bash theme={null}
curl -sf "$BASE/v1/credit-scorecard/partner-key-1779709585" \
  -H "Authorization: Bearer $TOKEN"
```

## Response

`200 OK`

```json theme={null}
{
  "externalId": "partner-key-1779709585",
  "halopesaGrade": "C",
  "finalCreditScore": 500,
  "finalCreditLimit": 5000.0,
  "totalOutstanding": 0.0,
  "totalPaid": 0.0,
  "availableCreditLimit": 5000.0,
  "executionPeriod": "0.01 seconds"
}
```

## Fields

<ResponseField name="externalId" type="string">
  Echoes the queried externalId.
</ResponseField>

<ResponseField name="halopesaGrade" type="string">
  Credit grade band. Common values: `A`, `B`, `C`. Unscored customers
  receive `XX` (see below).
</ResponseField>

<ResponseField name="finalCreditScore" type="integer">
  Numeric credit score on the HaloPesa scale.
</ResponseField>

<ResponseField name="finalCreditLimit" type="number">
  Pre-approved ceiling in TZS as set by the scoring engine. `0` for
  unscored customers. This is the raw upstream value — it doesn't
  account for any current debt.
</ResponseField>

<ResponseField name="totalOutstanding" type="number">
  Sum of `summary.totalOutstanding` across every loan the customer
  holds in the LMS. `0` if the customer has no loans or doesn't exist
  in the LMS yet. This is a best-effort join — if the LMS is
  momentarily unreachable, the field comes back as `0` rather than
  failing the whole scorecard call.
</ResponseField>

<ResponseField name="totalPaid" type="number">
  Sum of `summary.totalRepayment` across every loan the customer
  holds — total amount paid in over the lifetime of the customer's
  loans (principal + interest + fees + penalty). Same best-effort
  semantics as `totalOutstanding`.
</ResponseField>

<ResponseField name="availableCreditLimit" type="number">
  **Computed.** What the customer can borrow *right now*:
  `finalCreditLimit` when `totalOutstanding == 0`, otherwise `0`. The
  binary rule means any active obligation locks the customer out of
  new credit — partial top-ups against existing debt aren't allowed.
</ResponseField>

<ResponseField name="executionPeriod" type="string">
  Upstream processing time. Diagnostic only — partners typically ignore it.
</ResponseField>

## Unscored customers

A customer with no scoring record yet is **not** an error. The upstream
returns `200 OK` with sentinel values so the USSD layer always has
something to render:

```json theme={null}
{
  "externalId": "no-such-customer",
  "halopesaGrade": "XX",
  "finalCreditScore": 100,
  "finalCreditLimit": 0.0,
  "totalOutstanding": 0.0,
  "totalPaid": 0.0,
  "availableCreditLimit": 0.0,
  "executionPeriod": "0.00 seconds"
}
```

Branch on `halopesaGrade == "XX"` to detect "unscored". Use
`availableCreditLimit > 0` to decide whether a new loan can be
offered — that folds in both the scoring result and the LMS debt
state in one check.

## Errors

| Code               | When                                                               |
| ------------------ | ------------------------------------------------------------------ |
| `invalid_argument` | `external_id` path segment is empty                                |
| `unauthenticated`  | Token missing/invalid                                              |
| `internal`         | Upstream credit service unavailable or returned an unhandled error |
