Private Credit

Portfolio holdings for a specific BDC

Holdings for a specific BDC.

NO PAYWALL. The 3-row free teaser + locked / upgrade envelope this docstring described until 2026-09-22 was REMOVED on 2026-06-12 (OWNER QA

  • SF-MONETIZATION-V3, which forbids paywalling EDGAR data); the prose outlived it by three months and is corrected here rather than quietly rewritten. tests/test_routes_bdc_contract.py:: test_bdc_holdings_emits_locked_signal_for_non_plus is the live pin and it guards the REMOVAL -- the handler must not truncate or emit lock metadata. BDCHoldingsResponse still declares locked / lockedTotal / upgrade as Optional, and the client still reads them, as a DEFENSIVE path against an older deploy that does truncate; nothing here writes them.

PAGING (additive, 2026-09-22, OWNER ruling on the external MCP review's oversize-payload row: make the payload FIT rather than truncating it). limit / offset page holdings only; a call declaring NEITHER is byte-for-byte the pre-paging wire, so an installed reader sees nothing new. Out-of-range values are REFUSED by FastAPI (422), never clamped -- the same semantic the MCP seam applies from the schema bounds. The slice is data.bdc_query.page_holding_rows, twin of the search_bdc_borrower pager.

get/api/bdc/holdings

Request

  • Base URL: https://www.oxfordledge.com (the document declares no server; this is the origin it was published from)
  • URL: https://www.oxfordledge.com/api/bdc/holdings
  • Auth: none declared

Query parameters

tickerstring
limitinteger nullable

Max holdings rows to return. Omit for every row (the store's 5000-row backstop). Pages the row list only -- every filing-level total stays computed over the whole book.

offsetinteger nullable

Rows to skip before the page (default 0). Past the end returns an empty page with page.total intact.

Response

Successful Response

bdcTickerstring required
bdcNamestring nullable
dataSourcestring nullable
fetchedAtstring nullable
filingDatestring nullable
filingTypestring nullable
periodEndstring nullable
totalHoldingsinteger nullable

REGISTRY count of parsed positions -- the population totalFairValue / byLienPosition / portfolioStructure cover. NOT len(holdings): the served list drops non-identity borrower cells (see holdingsReturned / nonBorrowerRowsExcluded).

holdingsReturnedinteger nullable

len(holdings) as served: totalHoldings minus the rows the non-identity borrower filter dropped.

nonBorrowerRowsExcludedinteger nullable

Rows read from the store but NOT served because their borrower cell carries no issuer identity (SOI section labels, bare legal suffixes, security-description text). Their fair value is still inside totalFairValue and the portfolio percentages.

excludedRowsFairValuenumber nullable

Sum of fairValue over the excluded rows: sum(holdings[].fairValue) + this == parsedRowSumFairValue (or totalFairValue on a parsed-rows basis).

totalParAmountnumber nullable
totalFairValuenumber nullable
weightedAvgPricenumber nullable
byLienPositionobject nullable
topIndustriesobject[] nullable
portfolioStructureobject nullable
lockedboolean nullable
locked_totalinteger nullable

Changes

No recorded changes to this operation across all 1 revision of this API.