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

# Get ETF / index-fund holdings

> Returns an ETF or index fund's current holdings and each position's weight, resolved via a live web search plus a scrape of the fund's public holdings fact sheet (Context.dev /web/search and /web/scrape/markdown) - not an SEC filing feed - see go/service/indexfund.go. Only ticker mode is supported: Financial Datasets' reverse "?holding=AAPL" lookup (funds holding a given security) is not implemented by get_index_fund, so ticker is required regardless of what other query parameters are set (missing ticker answers a real HTTP 400). Pagination is offset/limit (not the cursor scheme this API's other list routes use), applied to the holdings already resolved for this call. If the routable holdings document could not be parsed at all, this server answers HTTP 200 with a bad_request ErrorResponse body ("holdings document not routable for TICKER") rather than fabricating an empty holdings list.



## OpenAPI

````yaml /api-reference/openapi.json get /index-funds
openapi: 3.1.0
info:
  title: Monid Finance API
  version: 1.0.0
  summary: A Financial Datasets-compatible finance REST API backed by Monid providers.
  description: >-
    US equities fundamentals, prices, filings, news, insider trades, and a stock
    screener, generated faithfully from this repository's Go source
    (go/httpapi/rest.go, go/service, go/fd). This server is drop-in compatible
    with the Financial Datasets REST and MCP interface: the same route shapes,
    the same query parameters, and response objects whose field names and field
    order match the Financial Datasets contract, captured 2026-09-04. It is an
    independent, Monid-backed implementation; it is not affiliated with or
    endorsed by Financial Datasets, and no Financial Datasets data or outputs
    are used.


    **Bring your own Monid API key.** Every request carries the caller's own key
    in the `X-API-KEY` header. Usage bills that caller's own Monid wallet; this
    server never stores or logs the key. Get a key at https://monid.ai.


    **Coverage.** All 54 Financial Datasets REST paths are registered. all 54
    return data; most call live Monid providers, and a handful (the static
    catalogs and the accept-universe coverage lists; see each operation's
    description) never call Monid at all. Every registered path answers from a
    live source; there are no not_implemented stubs. /kpi/metrics/sectors
    returns the screener provider's own industry taxonomy and
    /index-funds/tickers the upstream fund universe, both scraped through Monid
    on demand. See docs/compatibility.md for every deliberate deviation and
    docs/openapi-notes.md for how this document was derived.


    **Errors and soft failures.** Every failure — real HTTP error and zero-cost
    soft failure alike — uses the two-key body `{"error": <code>, "message":
    <detail>}`. Some routes answer `not_found` with HTTP 200 rather than a 4xx
    status (see each operation's description).


    **Pagination.** List routes return a wrapped envelope (e.g.
    `{"income_statements": [...], "next_page_url": "..."}`) with opaque,
    server-minted base64url `cursor` tokens. Pages hold 10 records (100 for
    /prices). `next_page_url` is an absolute URL on this deployment's own host,
    present only when more records remain.


    **Ticker coverage lists are accept-universes, not data-coverage claims.**
    The eight `*/tickers` routes (e.g. /company/facts/tickers,
    /kpi/metrics/tickers) all answer from the same ~3,227-ticker US equity
    catalog: the tickers a route will ACCEPT as input, never a promise that
    every one of them has data for that particular dataset - this server has not
    measured per-dataset coverage. Their own `limit` (default 1000, max 5000)
    and `cursor` query parameters page through that shared universe
    independently of every other route's pagination convention above.
  contact:
    url: https://docs.financialdatasets.rip
  license:
    name: MIT
    identifier: MIT
servers:
  - url: https://financialdatasets.rip
    description: Production (Fly.io).
security:
  - ApiKeyAuth: []
tags:
  - name: Financial statements
    description: Income statements, balance sheets, cash flow statements.
  - name: Financial metrics
    description: Historical financial metrics and the live snapshot.
  - name: Earnings
    description: Earnings records composed from SEC filing events.
  - name: Filings
    description: SEC filing index and extracted filing sections.
  - name: Prices
    description: Historical OHLCV prices and the live price snapshot.
  - name: News
    description: Ticker-matched news.
  - name: Insider trades
    description: SEC Form 4 insider trading transactions.
  - name: Screener
    description: Stock screener and its executable filter catalog.
  - name: Company
    description: Company facts.
  - name: KPIs
    description: >-
      KPI-taxonomy metrics, forward guidance, and non-GAAP metrics extracted
      from SEC filings.
  - name: Macroeconomics
    description: Central bank policy interest rates.
  - name: Index funds
    description: ETF / index-fund holdings.
  - name: Institutional holdings
    description: SEC Form 13F institutional-holdings rows.
  - name: Ownership
    description: Insider, beneficial (13D/13G) and activist ownership state.
  - name: Not implemented
    description: >-
      Routes registered for Financial Datasets route parity; always a zero-cost
      not_implemented stub today.
paths:
  /index-funds:
    get:
      tags:
        - Index funds
      summary: Get ETF / index-fund holdings
      description: >-
        Returns an ETF or index fund's current holdings and each position's
        weight, resolved via a live web search plus a scrape of the fund's
        public holdings fact sheet (Context.dev /web/search and
        /web/scrape/markdown) - not an SEC filing feed - see
        go/service/indexfund.go. Only ticker mode is supported: Financial
        Datasets' reverse "?holding=AAPL" lookup (funds holding a given
        security) is not implemented by get_index_fund, so ticker is required
        regardless of what other query parameters are set (missing ticker
        answers a real HTTP 400). Pagination is offset/limit (not the cursor
        scheme this API's other list routes use), applied to the holdings
        already resolved for this call. If the routable holdings document could
        not be parsed at all, this server answers HTTP 200 with a bad_request
        ErrorResponse body ("holdings document not routable for TICKER") rather
        than fabricating an empty holdings list.
      operationId: get_index_fund
      parameters:
        - name: ticker
          in: query
          required: true
          schema:
            type: string
          description: >-
            The fund's ticker symbol (e.g., SPY, QQQ, VTI).
            Uppercase-normalized, 1-20 letters/digits/dots/hyphens.
        - name: as_of
          in: query
          required: false
          schema:
            type: string
            format: date
          description: >-
            Return the fund composition in effect on or before this date
            (YYYY-MM-DD). Without it, this server returns whatever the routable
            fact sheet currently reports. If the routable fact sheet is dated
            after as_of, this server answers HTTP 200 with a not_found
            ErrorResponse body instead of guessing an earlier composition.
        - name: asset_class
          in: query
          required: false
          schema:
            type: string
            enum:
              - equity
              - bond
          description: >-
            Restrict holdings to equity or bond instruments. Omit to return
            every holding the fact sheet lists.
        - name: limit
          in: query
          required: false
          schema:
            type: integer
            minimum: 1
            maximum: 1000
            default: 50
          description: >-
            Number of records to retrieve (default: 50, max: 1000). Maximum
            number of holdings in this page.
        - name: offset
          in: query
          required: false
          schema:
            type: integer
            minimum: 0
            default: 0
          description: >-
            Number of holdings to skip before this page starts, for paging
            through a large holdings list (default 0).
      responses:
        '200':
          description: >-
            Illustrative shape (no captured live sample committed for this
            route); values are structural placeholders, not a claim about real
            reported figures.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/IndexFundHoldingsResponse'
              examples:
                example:
                  value:
                    ticker: SPY
                    fund:
                      name: Example S&P 500 ETF Trust
                      as_of: '2025-08-31'
                      source: public fund holdings fact sheet (markdown)
                      total_holdings: 503
                      returned: 1
                      offset: 0
                    holdings:
                      - ticker: AAPL
                        name: Apple Inc.
                        weight: 7.05
                        market_value: 21000000000
                        shares: 165000000
                        asset_class: equity
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '502':
          $ref: '#/components/responses/BadGateway'
        '504':
          $ref: '#/components/responses/GatewayTimeout'
components:
  schemas:
    IndexFundHoldingsResponse:
      type: object
      title: IndexFundHoldingsResponse
      description: >-
        Unwrapped body for /index-funds (ticker mode only - see this route's
        description). May instead be a two-key ErrorResponse ({"error":
        "bad_request" or "not_found", "message": ...}) when no holdings document
        is routable, or when as_of predates the routable fact sheet.
      properties:
        ticker:
          type: string
          description: The fund ticker, echoed back uppercase-normalized.
        fund:
          $ref: '#/components/schemas/IndexFund'
        holdings:
          type: array
          items:
            $ref: '#/components/schemas/FundHolding'
          description: >-
            Sorted by weight descending (holdings with no weight sort last, by
            ticker-or-name).
      required:
        - ticker
        - fund
        - holdings
    IndexFund:
      type: object
      title: IndexFund
      description: >-
        Fund header for /index-funds: identity, as-of date, and coverage counts
        for the full fund (not just the returned page). Every field is present
        only when this server could source it - see go/service/indexfund.go's
        fund object construction.
      properties:
        name:
          type: string
          description: >-
            Fund name, taken from the matched search result's title. Omitted
            when the routable result had none.
        as_of:
          type: string
          format: date
          description: >-
            Reporting date the holdings fact sheet states for itself. Omitted
            when no as-of date could be parsed from the page.
        source:
          type: string
          enum:
            - public fund holdings fact sheet (markdown)
          description: >-
            Always this literal value: every fund's data comes from the same
            kind of source.
        total_holdings:
          type: integer
          description: >-
            Total holdings this server parsed from the fact sheet, before the
            asset_class filter and offset/limit paging applied.
        returned:
          type: integer
          description: >-
            Number of holdings in this page (after asset_class filtering and
            offset/limit paging).
        offset:
          type: integer
          description: Echoes the request's offset.
      required:
        - source
        - total_holdings
        - returned
        - offset
    FundHolding:
      type: object
      title: FundHolding
      description: >-
        One index-fund/ETF constituent, field order matching go/fd/types.go's
        FundHolding struct declaration. Parsed from a public holdings fact-sheet
        markdown table (go/service/indexfund.go); a field is omitted whenever
        that column was blank or missing from the source table.
      properties:
        ticker:
          type: string
          description: Holding's ticker symbol, when the fact sheet lists one.
        name:
          type: string
          description: Holding's name, when the fact sheet lists one.
        cusip:
          type: string
          description: 9-character CUSIP, when the fact sheet lists one.
        isin:
          type: string
          description: 12-character ISIN, when the fact sheet lists one.
        weight:
          type: number
          description: Percent of fund net assets.
        market_value:
          type: number
          description: Market value of the position, in the fact sheet's stated units.
        shares:
          type: number
          description: Number of shares held.
        asset_class:
          type: string
          enum:
            - equity
            - bond
            - other
          description: >-
            Derived from the row's ticker/name/CUSIP text, not stated directly
            by most fact sheets.
    ErrorResponse:
      type: object
      title: ErrorResponse
      description: >-
        Uniform error/soft-failure body: {"error": <code>, "message": <detail>}.
        Used both for real HTTP error statuses and for 200 OK
        "not_found"/"not_implemented" soft failures that this API never bills
        for.
      properties:
        error:
          type: string
          description: >-
            Machine-readable error code, e.g. bad_request, unauthorized,
            payment_required, rate_limited, upstream_error,
            upstream_schema_changed, upstream_timeout, unsupported,
            invalid_cursor, not_found, not_implemented.
        message:
          type: string
          description: Human-readable detail.
      required:
        - error
        - message
  responses:
    BadRequest:
      description: >-
        400 Bad Request. Validation failed before any paid Monid call was made
        (bad_request), or the request is well-formed but names a capability this
        server deliberately rejects (unsupported), e.g. as_reported=true or a
        non-USD currency.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            bad_request:
              summary: Validation failure
              value:
                error: bad_request
                message: ticker must be 1-20 letters, digits, dots, or hyphens
            unsupported:
              summary: Deliberately rejected capability
              value:
                error: unsupported
                message: >-
                  as_reported is not supported by the Monid-backed server;
                  as_reported=True cannot be answered honestly.
            invalid_cursor:
              summary: Malformed pagination cursor
              value:
                error: invalid_cursor
                message: cursor is not a valid opaque pagination token
    Unauthorized:
      description: >-
        401 Unauthorized. The X-API-KEY header was missing, empty, or contained
        control characters, or (if the operator configured an allowlist) the key
        is not on it. This check runs before any Monid call.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            unauthorized:
              value:
                error: unauthorized
                message: Missing or invalid API key.
    PaymentRequired:
      description: >-
        402 Payment Required. The caller's own Monid wallet could not cover the
        call (Monid returned a blocked/insufficient-funds result).
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            payment_required:
              value:
                error: payment_required
                message: 'Monid run blocked: insufficient wallet balance.'
    TooManyRequests:
      description: >-
        429 Too Many Requests. Per-API-key token-bucket rate limit exceeded
        (default 60/min per key; 10/min for keyless demo traffic, where
        enabled).
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            rate_limited:
              value:
                error: rate_limited
                message: Rate limit exceeded. Retry shortly.
    BadGateway:
      description: >-
        502 Bad Gateway. The upstream Monid provider call failed for a reason
        other than auth/funds/timeout (upstream_error), or its payload no longer
        matches the shape this server parses (upstream_schema_changed).
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            upstream_error:
              summary: Generic upstream failure
              value:
                error: upstream_error
                message: provider returned HTTP 500
            upstream_schema_changed:
              summary: Upstream payload shape drifted
              value:
                error: upstream_schema_changed
                message: provider payload is not valid JSON
    GatewayTimeout:
      description: 504 Gateway Timeout. The upstream Monid provider call timed out.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            upstream_timeout:
              value:
                error: upstream_timeout
                message: provider request timed out
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-API-KEY
      description: >-
        The caller's own Monid API key (get one at
        https://monid.ai?fpr=dhruv-15136b). Passed straight through to Monid on
        every call, so usage bills the caller's own wallet — this is never a
        shared server-side credential, and the server never logs or stores it.
        Missing, empty, or malformed values answer 401 unauthorized before any
        paid call is attempted.

````