> ## Documentation Index
> Fetch the complete documentation index at: https://ormaprotocol.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# GET /api/vaults/:vaultId/broker-history — Conduct Record

> Reconstructs the broker's public transaction history, scores the default ordering against the fair sequence, and returns a reputation grade with findings.

Use this endpoint to examine what a vault manager actually did with their cover pool. The response reconstructs the full default and impairment history from public ledger transactions, computes what the fair declaration order would have paid depositors, and grades the manager's conduct against that benchmark. If two or more distressed loans are currently standing, it also recommends which to declare next to maximise depositor recovery.

## Parameters

<ParamField path="vaultId" type="string" required>
  64-character hex object ID of the `Vault` ledger entry. The first `LoanBroker` associated with the vault is used. Case insensitive.
</ParamField>

This route is cached for 15 seconds per broker — reconstructing the history requires many ledger round-trips.

## Request

```bash theme={null}
curl -s http://localhost:8787/api/vaults/24EAA01AD4CE70D8ABB4ACB4255DC4C216B8AF3B9E7315DB8052BFC1E5810089/broker-history
```

## Response

```json theme={null}
{
  "serverTime": "2026-09-12T22:20:22Z",
  "ledgerIndex": 5263343,
  "loanBrokerId": "8DB104980C31CBE9F196508E7D748E8C31FB783CD4E0A3620AE0B476CBDEA3FA",
  "owner": "rD26gw5goDqU784caePMoA82givcJBjStk",
  "events": [
    {
      "kind": "default",
      "at": "2026-09-12T21:11:02Z",
      "hash": "FB23EC5313F85FA157D56966E0B0B1665068905988D925C70BB0E7C35C3B221B",
      "loanId": "3D830C8049389AD0E7037933D21443635F35077D3A462A2C9783647354A644FE",
      "brokerStateKnown": true,
      "debtBefore": "40000000",
      "debtAfter": "10000000",
      "coverBefore": "10000000",
      "coverAfter": "9600000",
      "coverConsumed": "400000",
      "principal": "30000000",
      "exposure": "30000000"
    },
    {
      "kind": "default",
      "at": "2026-09-12T21:11:10Z",
      "hash": "DE49DF0D6136B96AD28B253CD32100E5715078FD2D0AE6D1DB747AFECB803D1F",
      "loanId": "74402C23FE8E2B30ACAC4A5001AF8D491DFC8A38924125798511618331B452C7",
      "brokerStateKnown": true,
      "debtBefore": "10000000",
      "debtAfter": "0",
      "coverBefore": "9600000",
      "coverAfter": "9500000",
      "coverConsumed": "100000",
      "principal": "10000000",
      "exposure": "10000000"
    }
  ],
  "ordering": {
    "applicable": true,
    "defaultCount": 2,
    "actualCoverPaid": "500000",
    "bestPossible": "700000",
    "worstPossible": "500000",
    "costToDepositors": "200000",
    "spread": "200000",
    "fairness": "0.0000",
    "fairOrder": ["10000000", "30000000"]
  },
  "reputation": {
    "grade": "E",
    "score": 25,
    "observations": {
      "defaults": 2,
      "impairments": 0,
      "defaultsWithoutPriorImpairment": 2,
      "coverWithdrawals": 0,
      "eventsRetained": 3
    },
    "findings": [
      {
        "code": "ORDERING_SELF_SERVING",
        "detail": "Declared losses in an order close to the one that minimises their own first-loss contribution (sequence score 0.0000). The choice cost investors 0.200000 XRP against the fair order."
      },
      {
        "code": "DEFAULT_WITHOUT_IMPAIRMENT",
        "detail": "2 exposures were written off with no prior warning, so the loss was never signalled before it was taken."
      }
    ],
    "caveat": "Reconstructed from the public record only, which is retained for roughly 29 days. Conduct before that window is not visible here."
  },
  "recommendation": {
    "applicable": false,
    "reason": "fewer than two distressed loans",
    "candidates": 0
  }
}
```

## Response Fields

<ResponseField name="loanBrokerId" type="string">
  64-character hex object ID of the `LoanBroker` whose history was reconstructed.
</ResponseField>

<ResponseField name="owner" type="string">
  XRPL address of the vault manager who controls this broker.
</ResponseField>

<ResponseField name="events" type="array">
  All default, impairment, and cover-deposit events found in the broker's public transaction history, in chronological order.

  <Expandable title="event fields">
    <ResponseField name="kind" type="string">
      Event type: `"default"`, `"impairment"`, or `"cover_deposit"`.
    </ResponseField>

    <ResponseField name="at" type="string">
      ISO 8601 timestamp of the transaction.
    </ResponseField>

    <ResponseField name="hash" type="string">
      64-character hex transaction hash.
    </ResponseField>

    <ResponseField name="loanId" type="string">
      64-character hex loan object ID. Present on `default` and `impairment` events.
    </ResponseField>

    <ResponseField name="brokerStateKnown" type="boolean">
      Whether the broker's book state before and after this event could be reconstructed. `false` for impairments, because `LoanImpair` does not touch the `LoanBroker` object.
    </ResponseField>

    <ResponseField name="debtBefore" type="string | null">
      Total broker debt before this event, in drops. `null` when `brokerStateKnown` is `false`. See [contract 2](/api/overview#2-absent-means-zero).
    </ResponseField>

    <ResponseField name="debtAfter" type="string | null">
      Total broker debt after this event, in drops. `null` when `brokerStateKnown` is `false`.
    </ResponseField>

    <ResponseField name="coverBefore" type="string | null">
      Cover available before this event, in drops. `null` when `brokerStateKnown` is `false`.
    </ResponseField>

    <ResponseField name="coverAfter" type="string | null">
      Cover available after this event, in drops. `null` when `brokerStateKnown` is `false`.
    </ResponseField>

    <ResponseField name="coverConsumed" type="string">
      Cover liquidated by this event, in drops. Always present; `"0"` for impairments and cover deposits.
    </ResponseField>

    <ResponseField name="principal" type="string">
      Loan principal involved in this event, in drops.
    </ResponseField>

    <ResponseField name="exposure" type="string">
      Total exposure written off, in drops.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="ordering" type="object">
  Analysis of how the manager's declaration order compared to the sequence most beneficial to depositors.

  <Expandable title="ordering fields">
    <ResponseField name="applicable" type="boolean">
      `true` when at least two defaults are present. With only one default, no sequence comparison is possible.
    </ResponseField>

    <ResponseField name="actualCoverPaid" type="string">
      Total cover liquidated in the observed sequence, in drops.
    </ResponseField>

    <ResponseField name="bestPossible" type="string">
      Cover that would have been liquidated in the depositor-best sequence, in drops.
    </ResponseField>

    <ResponseField name="worstPossible" type="string">
      Cover that would have been liquidated in the depositor-worst sequence, in drops.
    </ResponseField>

    <ResponseField name="costToDepositors" type="string">
      `bestPossible - actualCoverPaid`: the cover depositors lost due to the observed ordering, in drops.
    </ResponseField>

    <ResponseField name="spread" type="string">
      `bestPossible - worstPossible`: the maximum possible ordering effect, in drops.
    </ResponseField>

    <ResponseField name="fairness" type="string">
      Normalised fairness score between `"0.0000"` (investor-worst) and `"1.0000"` (investor-best). Defined as `"1.0000"` when `bestPossible` equals `worstPossible`.
    </ResponseField>

    <ResponseField name="fairOrder" type="array">
      The depositor-optimal sequence: principal amounts in the order they should have been declared.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="reputation" type="object">
  Composite reputation grade and supporting findings.

  <Expandable title="reputation fields">
    <ResponseField name="grade" type="string">
      Reputation letter grade from `"A"` (excellent) to `"E"` (poor).
    </ResponseField>

    <ResponseField name="score" type="number">
      Numeric score underlying the grade.
    </ResponseField>

    <ResponseField name="observations" type="object">
      Counts of observed events: `defaults`, `impairments`, `defaultsWithoutPriorImpairment`, `coverWithdrawals`, `eventsRetained`.
    </ResponseField>

    <ResponseField name="findings" type="array">
      Specific conduct issues identified.

      <Expandable title="finding fields">
        <ResponseField name="code" type="string">
          Machine-readable finding code, e.g. `"ORDERING_SELF_SERVING"`, `"DEFAULT_WITHOUT_IMPAIRMENT"`, `"COVER_WITHDRAWAL_AFTER_DISTRESS"`.
        </ResponseField>

        <ResponseField name="detail" type="string">
          Plain-English explanation of the finding, including quantified impact where available.
        </ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="caveat" type="string">
      Statement of the data window limitation. XRPL retains transaction history for approximately 29 days; conduct before that window is not visible.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="recommendation" type="object">
  Forward-looking advice on which distressed loan to declare next.

  <Expandable title="recommendation fields">
    <ResponseField name="applicable" type="boolean">
      `true` only when two or more distressed loans are currently standing.
    </ResponseField>

    <ResponseField name="reason" type="string">
      Explanation of why a recommendation was or was not produced.
    </ResponseField>

    <ResponseField name="candidates" type="number">
      Number of distressed loans currently eligible for declaration.
    </ResponseField>
  </Expandable>
</ResponseField>

<Note>
  The cover liquidated on any one default is `T(p) = min(⌈D × c_min × c_liq⌉, p, C)` where `D` is the broker's **total** book — not the principal of the exposure that defaulted — and `D` decrements as each default lands. Declaring the largest exposure first consumes the least first-loss capital. In the captured example, declaring 30 XRP first then 10 XRP consumed 500 000 drops of cover; the reverse order would have consumed 700 000. The 200 000 drop difference falls on unit holders despite identical total losses.
</Note>

<Note>
  `LoanManage` carries no `LoanBrokerID`, and an impairment does not touch the `LoanBroker` object at all — so a naive filter over `account_tx` silently drops every impairment. The join that recovers them is `Loan.FinalFields.LoanBrokerID` in the same transaction's metadata. Without this join, every unsignalled default looks like the manager was penalised for disclosing; with it, the record is complete.
</Note>
