> ## 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 — Complete Facility Detail

> Returns everything about one facility: vault fields, broker, score with notch trace, every loan, phase info, oracle state, and active alerts.

Use this endpoint when you need the complete picture of a single facility — not just the summary figures from the list, but the full broker state, every individual loan with its payment schedule, the step-by-step scoring trace, the on-chain oracle publication, and any active alerts. This is the route to poll when you have a facility in focus and need to track its trend over time.

## Parameters

<ParamField path="vaultId" type="string" required>
  The 64-character hex object ID of the `Vault` ledger entry. Case insensitive; lowercase is accepted and upper-cased before lookup.
</ParamField>

## Request

```bash theme={null}
curl -s http://localhost:8787/api/vaults/5763707D11EA19D1B5FF04E4EBA4F9336057955CDE65B725D1FF3EF2A96CB0E5
```

## Response

```json theme={null}
{
  "serverTime": "2026-09-12T22:20:22Z",
  "ledgerIndex": 5263343,
  "vault": {
    "vaultId": "5763707D11EA19D1B5FF04E4EBA4F9336057955CDE65B725D1FF3EF2A96CB0E5",
    "label": "Calder Structured Credit III",
    "owner": "r3hE8HanpccSZdgmeHCfYFEkwxFjdDmmvt",
    "pseudoAccount": "rUUomEsKraSfCYppP9nZx7k7aAzEe7CY3B",
    "asset": { "kind": "XRP", "currency": "XRP", "issuer": null, "mptIssuanceId": null },
    "vaultKind": "ClosedEnded",
    "phase": "Investment",
    "grade": "AA",
    "gradeNumeric": 89,
    "trend": "stable",
    "shareMptId": "000000014D667775372D5B78E07FFF294678C7F9CE82AFBC",
    "sharesOutstanding": "51000000",
    "scale": 0,
    "withdrawalPolicy": "FirstComeFirstServe",
    "isPrivate": false,
    "domainId": null,
    "subscriptionAt": "2026-09-12T21:11:47Z",
    "leVersion": "CashBasis",
    "assetsTotal": "51000000",
    "assetsAvailable": "41000000",
    "lossUnrealized": "10000000",
    "navNaive": "1.000000",
    "navCorrect": "0.803922",
    "navDivergenceBps": 1961,
    "redemptionAt": "2026-09-13T15:11:47Z",
    "secondsToRedemption": 60686,
    "explorerUrl": "https://devnet.xrpl.org/accounts/r3hE8HanpccSZdgmeHCfYFEkwxFjdDmmvt"
  },
  "broker": {
    "loanBrokerId": "1C160EFFCA8208DFD8CE9B065A3C3C41CCA80758FBC3099BE27AACFBD1478173",
    "owner": "rGMo2ke9of3GEqJwWAzDmFjrm6SwYowTsB",
    "pseudoAccount": "rUUomEsKraSfCYppP9nZx7k7aAzEe7CY3B",
    "debtTotal": "10000000",
    "debtMaximum": "45000000",
    "coverAvailable": "5000000",
    "coverRateMinimum": 10000,
    "coverRateLiquidation": 10000,
    "managementFeeRate": 1000,
    "coverRequired": "1000000",
    "coverShortfall": "0",
    "maxLiquidatableNow": "100000",
    "strandedCoverFraction": "0.9800"
  },
  "score": {
    "grade": "AA",
    "gradeNumeric": 89,
    "computedAt": "2026-09-12T22:20:21Z",
    "methodVersion": "1.0.0",
    "dimensions": [
      {
        "key": "CONCENT",
        "label": "Concentration",
        "value": "1.0000",
        "unit": "ratio",
        "grade": "D",
        "notches": 0,
        "explain": "Largest loan is 100.0% of broker debt.",
        "worseIsHigher": true
      }
    ],
    "notchTrace": [
      { "from": "AAA", "rule": "anchor on DEADLINE (can claims be met at redemption)", "delta": 0, "to": "AAA" },
      { "from": "AAA", "rule": "single loan >= 75% of broker debt (cover is keyed to total debt, not loan size)", "delta": -1, "to": "AA+" },
      { "from": "AA+", "rule": "liquidatable cover < 5% of the exposure it must absorb", "delta": -1, "to": "AA" }
    ]
  },
  "loans": [
    {
      "loanId": "D6979E3A3FD90234A8BE80FCB37589204C691D0AC1C741C4A780D02D5073F252",
      "borrower": "raxskEENwfnRay2VaQroMoV4XYFUurggL5",
      "status": "impaired",
      "principalOutstanding": "10000000",
      "totalValueOutstanding": "10000039",
      "managementFeeOutstanding": "0",
      "periodicPayment": "3333346.017258355048",
      "interestRate": 100000,
      "lateInterestRate": 20000,
      "paymentInterval": 60,
      "gracePeriod": 60,
      "paymentRemaining": 3,
      "nextPaymentDueAt": "2026-09-12T21:13:10Z",
      "secondsUntilDue": -4031,
      "secondsUntilDefaultable": -3971,
      "shareOfDebtTotal": "1.0000",
      "impairable": false,
      "explorerUrl": "https://devnet.xrpl.org/transactions/D6979E3A3FD90234A8BE80FCB37589204C691D0AC1C741C4A780D02D5073F252"
    }
  ],
  "phaseInfo": {
    "phase": "Investment",
    "canDeposit": false,
    "canWithdraw": false,
    "withdrawBlockedReason": "tecTOO_SOON",
    "nextBoundaryAt": "2026-09-13T15:11:47Z",
    "secondsToNextBoundary": 60686,
    "claimsAtRedemption": "41000000",
    "liquidityAtRedemption": "41100000",
    "projectedShortfall": "0",
    "shortfallPct": "0.00"
  },
  "oracle": {
    "published": true,
    "oracleDocumentId": 3,
    "publisher": "rpVg1ufqoVwHCN814QBqvibYPftMYc2u3B",
    "objectIndex": "03C7B0E151129510F11FF92CCE8FBB3E7AD3C55B25EDA6EB414324E3E995078A",
    "baseAssetHex": "5763707D11EA19D1B5FF04E4EBA4F9336057955C",
    "lastUpdateAt": "2026-09-12T22:20:02Z",
    "ageSeconds": 11,
    "stale": false,
    "dimensionsOnChain": [
      { "key": "CNC", "raw": "2710",  "value": "1.0000",   "scale": 4 },
      { "key": "COV", "raw": "64",    "value": "0.0100",   "scale": 4 },
      { "key": "DDL", "raw": "0",     "value": "0.0000",   "scale": 4 },
      { "key": "HDL", "raw": "22c4",  "value": "0.8900",   "scale": 4 },
      { "key": "LIQ", "raw": "1f67",  "value": "0.8039",   "scale": 4 },
      { "key": "NAV", "raw": "c4452", "value": "0.803922", "scale": 6 }
    ],
    "aggregate": null
  },
  "alerts": [
    {
      "code": "NAV_DIVERGENCE",
      "severity": "high",
      "title": "Reported NAV overstates recoverable value by 19.61%",
      "detail": "AssetsTotal does not net LossUnrealized. Tools reading AssetsTotal alone report par.",
      "sinceAt": null
    },
    {
      "code": "CONCENTRATION_HIGH",
      "severity": "medium",
      "title": "Largest loan is 100% of broker debt",
      "detail": "Cover is keyed to total broker debt, not to the defaulting loan.",
      "sinceAt": null
    }
  ]
}
```

## Response Fields

<ResponseField name="serverTime" type="string">
  ISO 8601 ledger close time for this snapshot.
</ResponseField>

<ResponseField name="ledgerIndex" type="number">
  Ledger sequence number this snapshot was read from.
</ResponseField>

<ResponseField name="vault" type="object">
  All fields from the list row, plus the share token and vault configuration fields.

  <Expandable title="vault fields">
    <ResponseField name="shareMptId" type="string">
      48-character hex MPT issuance ID of the vault's share token. The pointer written into the token's metadata resolves back through `/api/mpt/:mptId/nav`.
    </ResponseField>

    <ResponseField name="sharesOutstanding" type="string">
      Total units of the share token in circulation, in drops.
    </ResponseField>

    <ResponseField name="scale" type="number">
      Decimal precision of the share token. `0` means whole units only.
    </ResponseField>

    <ResponseField name="withdrawalPolicy" type="string">
      Redemption queue policy: `"FirstComeFirstServe"` or `"ProRata"`.
    </ResponseField>

    <ResponseField name="isPrivate" type="boolean">
      Whether `tfVaultPrivate` is set. A private vault with a `DomainID` on the share issuance is gated — deposits require a valid XLS-70 credential.
    </ResponseField>

    <ResponseField name="leVersion" type="string">
      Accounting standard: `"CashBasis"` or `"AccrualBasis"`.
    </ResponseField>

    <ResponseField name="explorerUrl" type="string">
      XRPL Devnet explorer URL for the vault's pseudo-account.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="broker" type="object">
  The first `LoanBroker` associated with this vault.

  <Expandable title="broker fields">
    <ResponseField name="loanBrokerId" type="string">
      64-character hex object ID of the `LoanBroker` ledger entry.
    </ResponseField>

    <ResponseField name="debtTotal" type="string">
      Total outstanding principal across all active loans, in drops.
    </ResponseField>

    <ResponseField name="debtMaximum" type="string">
      Maximum permitted total debt, in drops.
    </ResponseField>

    <ResponseField name="coverAvailable" type="string">
      Posted first-loss cover currently available, in drops.
    </ResponseField>

    <ResponseField name="coverRateMinimum" type="number">
      Minimum cover ratio in units of 10⁻⁵. A value of `10000` equals 0.10 (10%).
    </ResponseField>

    <ResponseField name="coverRateLiquidation" type="number">
      Fraction of cover to liquidate per default, in units of 10⁻⁵. A value of `10000` equals 0.10 (10%).
    </ResponseField>

    <ResponseField name="coverRequired" type="string">
      Minimum cover the broker must maintain given the current `debtTotal`, in drops.
    </ResponseField>

    <ResponseField name="coverShortfall" type="string">
      Amount by which posted cover falls short of `coverRequired`, in drops. `"0"` when cover is sufficient.
    </ResponseField>

    <ResponseField name="maxLiquidatableNow" type="string">
      Maximum cover the protocol can liquidate on the next default, in drops. Equal to `⌈debtTotal × coverRateMinimum × coverRateLiquidation⌉`.
    </ResponseField>

    <ResponseField name="strandedCoverFraction" type="string">
      Fraction of posted cover that cannot be reached at the current book size. `"0.9800"` means 98% of cover is stranded.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="score" type="object">
  The full credit score with per-dimension breakdown and step-by-step notch derivation.

  <Expandable title="score fields">
    <ResponseField name="grade" type="string">
      Composite letter grade: `"AAA"`, `"AA+"`, `"AA"`, `"AA-"`, … down to `"D"`.
    </ResponseField>

    <ResponseField name="gradeNumeric" type="number">
      Integer mapping of the letter grade used for sorting and comparison.
    </ResponseField>

    <ResponseField name="methodVersion" type="string">
      Scoring algorithm version. Breaking changes increment the major version.
    </ResponseField>

    <ResponseField name="dimensions" type="array">
      Six entries: five measured factors (`LIQUIDITY`, `COVER`, `CONCENT`, `RECOG`, `DEADLINE`) and one composite (`HEADLINE`) restated as a row for tabular rendering.

      <Expandable title="dimension fields">
        <ResponseField name="key" type="string">
          Short key: `"LIQUIDITY"`, `"COVER"`, `"CONCENT"`, `"RECOG"`, `"DEADLINE"`, or `"HEADLINE"`.
        </ResponseField>

        <ResponseField name="value" type="string">
          Measured value for this dimension, as a decimal string.
        </ResponseField>

        <ResponseField name="unit" type="string">
          Unit of the measured value: `"ratio"`, `"bps"`, `"seconds"`, etc.
        </ResponseField>

        <ResponseField name="grade" type="string">
          Per-dimension letter grade before notching.
        </ResponseField>

        <ResponseField name="notches" type="number">
          Number of notches this dimension contributed to the composite (negative = downgrade).
        </ResponseField>

        <ResponseField name="explain" type="string">
          Plain-English description of what was measured and why it matters.
        </ResponseField>

        <ResponseField name="worseIsHigher" type="boolean">
          `true` when a higher measured value represents more risk (e.g. concentration ratio).
        </ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="notchTrace" type="array">
      Ordered list of every rule evaluated during scoring. Each entry records the grade before the rule was applied, the rule text, the notch delta (0 or negative), and the grade after. No weights are applied — the trace is the complete derivation.

      <Expandable title="notchTrace entry fields">
        <ResponseField name="from" type="string">
          Grade entering this rule.
        </ResponseField>

        <ResponseField name="rule" type="string">
          Human-readable description of the rule that was evaluated.
        </ResponseField>

        <ResponseField name="delta" type="number">
          Notches applied: `0` means the rule did not fire, negative means a downgrade.
        </ResponseField>

        <ResponseField name="to" type="string">
          Grade exiting this rule.
        </ResponseField>
      </Expandable>
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="loans" type="array">
  Every loan in the broker's book for this facility.

  <Expandable title="loan fields">
    <ResponseField name="loanId" type="string">
      64-character hex object ID of the `Loan` ledger entry.
    </ResponseField>

    <ResponseField name="status" type="string">
      Current loan state: `"current"`, `"overdue"`, `"impaired"`, or `"defaulted"`.
    </ResponseField>

    <ResponseField name="principalOutstanding" type="string">
      Remaining principal in drops.
    </ResponseField>

    <ResponseField name="periodicPayment" type="string">
      Scheduled periodic payment amount in drops. This field can carry up to 18 decimal places — always parse with `decimal.js`, never with `Number()`.
    </ResponseField>

    <ResponseField name="secondsUntilDue" type="number">
      Seconds until the next payment is due. Negative when overdue.
    </ResponseField>

    <ResponseField name="secondsUntilDefaultable" type="number">
      Seconds until the grace period expires and the loan may be defaulted. Negative when the grace period has elapsed.
    </ResponseField>

    <ResponseField name="shareOfDebtTotal" type="string">
      This loan's principal as a fraction of total broker debt.
    </ResponseField>

    <ResponseField name="impairable" type="boolean">
      Whether the manager can call `LoanImpair` on this loan right now. `false` on an already-impaired loan is correct: a loan may only be impaired once.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="phaseInfo" type="object">
  Current phase predicates and redemption-cliff projections.

  <Expandable title="phaseInfo fields">
    <ResponseField name="canDeposit" type="boolean">
      Whether `VaultDeposit` would succeed for this vault right now.
    </ResponseField>

    <ResponseField name="canWithdraw" type="boolean">
      Whether `VaultWithdraw` would succeed right now.
    </ResponseField>

    <ResponseField name="withdrawBlockedReason" type="string">
      The `tec` code that `VaultWithdraw` would return if `canWithdraw` is `false`. For example, `"tecTOO_SOON"` during the Investment phase of a closed-ended vault.
    </ResponseField>

    <ResponseField name="claimsAtRedemption" type="string">
      Total investor claims due at the redemption boundary, in drops.
    </ResponseField>

    <ResponseField name="liquidityAtRedemption" type="string">
      Projected available liquidity at the redemption boundary, in drops.
    </ResponseField>

    <ResponseField name="projectedShortfall" type="string">
      Projected liquidity gap at redemption, in drops. `"0"` when liquidity covers all claims.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="oracle" type="object">
  State of the XLS-47 Oracle object published on-chain for this vault.

  <Expandable title="oracle fields">
    <ResponseField name="published" type="boolean">
      Whether an Oracle object is currently live on the ledger for this vault.
    </ResponseField>

    <ResponseField name="ageSeconds" type="number">
      Seconds since the Oracle object was last updated.
    </ResponseField>

    <ResponseField name="stale" type="boolean">
      `true` if the oracle has not been updated within the expected poll window.
    </ResponseField>

    <ResponseField name="dimensionsOnChain" type="array">
      The six score dimensions as stored in the Oracle's `PriceData` entries.

      <Expandable title="dimensionsOnChain entry fields">
        <ResponseField name="key" type="string">
          Short on-chain key: `"CNC"`, `"COV"`, `"DDL"`, `"HDL"`, `"LIQ"`, `"NAV"`.
        </ResponseField>

        <ResponseField name="raw" type="string">
          Hex-encoded `UInt64` `AssetPrice` value as stored on the ledger. For example, `"c4452"` is the integer 803922.
        </ResponseField>

        <ResponseField name="value" type="string">
          Decoded decimal value: `raw` divided by 10^`scale`.
        </ResponseField>

        <ResponseField name="scale" type="number">
          Decimal scale used for this dimension. Most dimensions use scale 4; `NAV` uses scale 6 for extra precision.
        </ResponseField>
      </Expandable>
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="alerts" type="array">
  Active alerts for this facility, sorted by severity.

  <Expandable title="alert fields">
    <ResponseField name="code" type="string">
      Machine-readable alert code, e.g. `"NAV_DIVERGENCE"`, `"CONCENTRATION_HIGH"`, `"COVER_SHORTFALL"`.
    </ResponseField>

    <ResponseField name="severity" type="string">
      `"high"`, `"medium"`, or `"low"`.
    </ResponseField>

    <ResponseField name="title" type="string">
      Short human-readable summary of the condition.
    </ResponseField>

    <ResponseField name="detail" type="string">
      Longer explanation of why this condition is flagged and what it means.
    </ResponseField>
  </Expandable>
</ResponseField>

***

## Common Misreadings

<Accordion title="oracle.dimensionsOnChain[].raw is hexadecimal">
  `AssetPrice` on an XLS-47 `PriceData` is a `UInt64` serialised as hex. `c4452` is the integer 803922, which at `scale: 6` decodes to `0.803922`. Writing `"100"` into that field means 256, not one hundred. The `value` field gives you the decoded decimal so you do not have to convert it yourself.
</Accordion>

<Accordion title="coverRateMinimum and coverRateLiquidation are scaled by 10⁻⁵">
  Both broker rate fields are expressed in units of 10⁻⁵. A stated value of `10000` represents 0.10 (10%). `maxLiquidatableNow` is derived as `⌈debtTotal × coverRateMinimum × coverRateLiquidation⌉` — which is why the captured example shows `100000` drops against a `coverAvailable` of `"5000000"`: `10000000 × 0.10 × 0.10 = 100000`. `strandedCoverFraction: "0.9800"` means 98% of posted cover cannot be reached at the current book size.
</Accordion>

<Accordion title="canWithdraw: false with withdrawBlockedReason: tecTOO_SOON is not an error">
  `VaultWithdraw` returns `tecTOO_SOON` throughout the entire Investment phase of a closed-ended vault, regardless of how much liquidity the vault holds. It is a phase predicate, not a sign that something is wrong. The API captures and reports this code so you can display a meaningful message ("withdrawals open at redemption") rather than treating it as a failure.
</Accordion>

<Accordion title="impairable: false on an already-impaired loan is correct">
  A loan's `impairable` flag reflects whether `LoanImpair` can be called right now. Once a loan is already in the `"impaired"` state, the flag is `false` — not because the data is wrong, but because a loan may only be impaired once. An impaired loan that has not yet been defaulted remains visible with `impairable: false`.
</Accordion>

<Accordion title="score.dimensions has six entries, not five">
  The scoring model measures five factors (`LIQUIDITY`, `COVER`, `CONCENT`, `RECOG`, `DEADLINE`) and produces one composite grade (`HEADLINE`). `HEADLINE` is restated as a sixth row in the `dimensions` array so a table can render it alongside the five factors. It is an output, not a measured input. The `notchTrace` array contains the complete derivation — no weights are applied anywhere.
</Accordion>
