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

# portfolio_fees

> Fees per fund, two kinds of number that are never mixed. DISCLOSED (disclosed_*): the fee the fund published, ONE source per fund in this order: the CVM Extrato das Informacoes (cvm_fi_extrato, newest version, one row per fund or class), else the lâmina (cvm_fi_lamina, newest reference month), else cad_fi (cvm_fund_registry taxa_adm / taxa_perfm / inf_taxa_*); disclosed_origin (extrato | lamina | cad_fi), disclosed_source, disclosed_as_of (the filing date), disclosed_age_months and disclosed_age_days say which and how old. Two reading rules on the single administration fee, % a year as filed: a filed 0 is returned as 0 with filed_zero TRUE (read it as not informed, never as a zero cost); a filed value above 5 (or below 0) is NOT returned as the fee: disclosed_taxa_adm is NULL, implausible_filed is TRUE and the value as filed is in taxa_adm_filed_raw. The stored value is never rewritten. A NULL disclosed part is not a zero fee; when the lâmina's classes disclose different fees the single value is NULL and the min / max and disclosed_note say so. An Extrato row that exists is the source, even when its fee is 0 or above 5: it does not fall through to an OLDER source. One exception (v55): when the Extrato filed exactly 0 or above 5, the lâmina's single fee is in (0, 5] and the lâmina is NEWER than the Extrato, the newer lâmina is the source. fee_resolution names the rule: extrato, extrato_lamina_beside (Extrato 0 or above 5, a lâmina fee beside it), extrato_to_check (the same with no lâmina fee), lamina_newer, lamina, cad_fi. The other document's fee is returned as filed whatever the source (lamina_taxa_adm, _min, _max, lamina_n_classes, lamina_age_months; extrato_taxa_adm_filed with extrato_as_of), never rescaled and never a fee to sum; extrato_lamina_ratio is the Extrato over the lâmina when both are above 0, and extrato_scale_factor is 10 or 100 when an Extrato above 5 equals that factor times the lâmina within the two-decimal rounding of both, a flag only. The Extrato's performance fee (extrato_taxa_perfm numeric, extrato_param_taxa_perfm, extrato_calc_taxa_perfm, extrato_inf_taxa_perfm text), entry and exit fees (extrato_existe_* flags, _pr percent and _real reais), custody fee and class note are returned as filed; the row is the class for a CVM 175 fund (no subclass column, a subclass fee is not assumed). lamina_pr_pl_despesa is the declared total expense ratio from the lâmina (with its period and lamina_as_of), whatever the fee source, never added to the administration fee. ESTIMATE (adm_fee_flow, perf_fee_flow and the _pct_annual_est columns): from the balancete accruals (cvm_fi_balancete_resumo): the fee accounts accumulate from each fund's fiscal-year start and are filed negative, so the month's accrual is previous minus current accumulated value (served positive = cost; a negative performance accrual is a reversed provision), annualised x 12 / NAV x 100, NAV = groups 6 + 7 + 8 of the month. In the fiscal-year reset month the accumulated fee falls: fiscal_reset_suspect is TRUE and the estimate is NULL, unless cad_fi DT_INI_EXERC puts the fiscal-year start in that month, in which case the month's accumulated value alone is the accrual. estimate_label says on every row that the estimate is an estimate and why one is missing; it is never presented as the disclosed fee. ETFs (v56): CVM's Extrato, lâmina and cad_fi carry no fee for an ETF, so for a CNPJ in SILO's curated ETF registry etf_ticker names the ticker and etf_site_taxa_adm, etf_site_as_of and etf_site_source give the 'Taxa de administração total' etfsbrasil.com.br prints (etf_market_snapshot, the newest snapshot with a fee, joined by ticker): a third-party site, not a CVM filing, never in disclosed_*, returned as published; etf_site_note says so and why a value is NULL. Since v57 etf_site_nr_cotistas and etf_site_pl (R$) are the 'Número de cotistas' and 'Patrimônio líquido' the same site prints in the SAME snapshot (etf_site_as_of): third-party descriptive facts, never summed, never a fee base. Since v68 (#606 Q36) the filed benchmark, whatever the fee source and as filed, never inferred from a name or a class: benchmark_extrato is the Extrato's PARAM_TAXA_PERFM (the performance fee's index, the Extrato's only benchmark column; dated extrato_as_of), benchmark_lamina the lâmina's INDICE_REFER at lamina_as_of when every class filed the same one, benchmark_lamina_n the count of distinct values filed (0 none, above 1 the classes differ). p_month = the balancete month (NULL = each fund's newest). One row per distinct CNPJ; more than 200 CNPJs RAISES 22023.

**Row cap.** A window producing more than 1000 rows raises SQLSTATE `22023` naming this function. Nothing is trimmed to fit — PostgREST would silently cut the response at 1000 and a cut-short series is indistinguishable from one that simply ends. This function does not page — narrow the window instead.



## OpenAPI

````yaml /openapi.json post /rpc/portfolio_fees
openapi: 3.1.0
info:
  title: SILO Data API
  version: '75'
  summary: >-
    Read-only Brazilian public financial data: CVM filings, BACEN series, B3
    quotes and the B3 BDI group.
  description: >
    Schema `api` over PostgREST. Views are `GET /<view>`; functions are

    `POST /rpc/<function>` with a JSON body.


    **This document is generated** from the live Postgres catalog by

    `scripts/gen_openapi.py` — `pg_get_function_arguments` for the RPC
    signatures,

    `information_schema.columns` for the view columns, and the granted-to-`anon`

    privilege set for which objects exist at all. It is not hand-maintained, and

    `tests/test_openapi_spec.py` fails the build when it drifts from the SQL.


    ### Two different ceilings


    Reading one for the other is the most expensive mistake on this API.


    * **The row cap refuses.** Fifty-nine set-returning functions raise SQLSTATE
      `22023` when the window they were handed would produce more than 1000 rows.
      Nothing is trimmed, and the error says why and how to fix it (the message,
      plus PostgREST's `details` and `hint`). Five of them (`panel`,
      `quote_history`, `fund_nav`, `index_history`, `trade_consolidated_history`)
      take a `p_after` cursor so you can walk the series; the other fifty-four ask you to narrow the window. `fund_nav` paging
      additionally REQUIRES `p_entity_type` — its cursor is a bare period, which
      is unique only within one family, and CNPJs that file under both `fi` and
      `fidc` in the same month would otherwise be ambiguous.
    * **The tier ceiling clamps.** Three other functions (`search_funds`,
      `option_chain`, `option_exercises`) silently lower `p_limit` to a per-tier maximum. No error is raised, so the
      only way to know the result was cut is to know the ceiling. Signing in
      raises it.

    Separately from both, PostgREST's server-wide `db-max-rows = 1000` cuts
    every

    response, on every endpoint, for every tier. On the GET views
    `Content-Range`

    is the signal (`0-999/*`); `Prefer: count=exact` turns the `*` into a total.


    ### Retention


    Most of this warehouse is append-only history. The **B3 BDI group** —

    `short_interest`, `short_interest_by_sector`, `investor_flow`,

    `lending_trades`, `lending_participants` — is not: B3 keeps roughly 21
    business

    days and publishes no archive. A missed session cannot be bought back. See

    Market Coverage.
  license:
    name: See repository
    url: https://github.com/PedroDnT/SILO-BZ
servers:
  - url: https://zcjbtpxuhdekpwcxmepn.supabase.co/rest/v1
    description: Supabase PostgREST, schema `api`
security:
  - apikey: []
tags:
  - name: ANBIMA
  - name: Company events
  - name: Coverage & catalog
  - name: Derivatives
  - name: FIDC
  - name: FNET documents
  - name: Financials
  - name: Funds
  - name: Holdings
  - name: Inflation
  - name: Lookup
  - name: Macro
  - name: Macro expectations
  - name: Other
  - name: Panel
  - name: Portfolio
  - name: Quotes
  - name: Rates
  - name: Research
  - name: Screens
  - name: Securities lending
  - name: Short interest & flows
paths:
  /rpc/portfolio_fees:
    post:
      tags:
        - Portfolio
      summary: portfolio_fees
      description: >-
        Fees per fund, two kinds of number that are never mixed. DISCLOSED
        (disclosed_*): the fee the fund published, ONE source per fund in this
        order: the CVM Extrato das Informacoes (cvm_fi_extrato, newest version,
        one row per fund or class), else the lâmina (cvm_fi_lamina, newest
        reference month), else cad_fi (cvm_fund_registry taxa_adm / taxa_perfm /
        inf_taxa_*); disclosed_origin (extrato | lamina | cad_fi),
        disclosed_source, disclosed_as_of (the filing date),
        disclosed_age_months and disclosed_age_days say which and how old. Two
        reading rules on the single administration fee, % a year as filed: a
        filed 0 is returned as 0 with filed_zero TRUE (read it as not informed,
        never as a zero cost); a filed value above 5 (or below 0) is NOT
        returned as the fee: disclosed_taxa_adm is NULL, implausible_filed is
        TRUE and the value as filed is in taxa_adm_filed_raw. The stored value
        is never rewritten. A NULL disclosed part is not a zero fee; when the
        lâmina's classes disclose different fees the single value is NULL and
        the min / max and disclosed_note say so. An Extrato row that exists is
        the source, even when its fee is 0 or above 5: it does not fall through
        to an OLDER source. One exception (v55): when the Extrato filed exactly
        0 or above 5, the lâmina's single fee is in (0, 5] and the lâmina is
        NEWER than the Extrato, the newer lâmina is the source. fee_resolution
        names the rule: extrato, extrato_lamina_beside (Extrato 0 or above 5, a
        lâmina fee beside it), extrato_to_check (the same with no lâmina fee),
        lamina_newer, lamina, cad_fi. The other document's fee is returned as
        filed whatever the source (lamina_taxa_adm, _min, _max,
        lamina_n_classes, lamina_age_months; extrato_taxa_adm_filed with
        extrato_as_of), never rescaled and never a fee to sum;
        extrato_lamina_ratio is the Extrato over the lâmina when both are above
        0, and extrato_scale_factor is 10 or 100 when an Extrato above 5 equals
        that factor times the lâmina within the two-decimal rounding of both, a
        flag only. The Extrato's performance fee (extrato_taxa_perfm numeric,
        extrato_param_taxa_perfm, extrato_calc_taxa_perfm,
        extrato_inf_taxa_perfm text), entry and exit fees (extrato_existe_*
        flags, _pr percent and _real reais), custody fee and class note are
        returned as filed; the row is the class for a CVM 175 fund (no subclass
        column, a subclass fee is not assumed). lamina_pr_pl_despesa is the
        declared total expense ratio from the lâmina (with its period and
        lamina_as_of), whatever the fee source, never added to the
        administration fee. ESTIMATE (adm_fee_flow, perf_fee_flow and the
        _pct_annual_est columns): from the balancete accruals
        (cvm_fi_balancete_resumo): the fee accounts accumulate from each fund's
        fiscal-year start and are filed negative, so the month's accrual is
        previous minus current accumulated value (served positive = cost; a
        negative performance accrual is a reversed provision), annualised x 12 /
        NAV x 100, NAV = groups 6 + 7 + 8 of the month. In the fiscal-year reset
        month the accumulated fee falls: fiscal_reset_suspect is TRUE and the
        estimate is NULL, unless cad_fi DT_INI_EXERC puts the fiscal-year start
        in that month, in which case the month's accumulated value alone is the
        accrual. estimate_label says on every row that the estimate is an
        estimate and why one is missing; it is never presented as the disclosed
        fee. ETFs (v56): CVM's Extrato, lâmina and cad_fi carry no fee for an
        ETF, so for a CNPJ in SILO's curated ETF registry etf_ticker names the
        ticker and etf_site_taxa_adm, etf_site_as_of and etf_site_source give
        the 'Taxa de administração total' etfsbrasil.com.br prints
        (etf_market_snapshot, the newest snapshot with a fee, joined by ticker):
        a third-party site, not a CVM filing, never in disclosed_*, returned as
        published; etf_site_note says so and why a value is NULL. Since v57
        etf_site_nr_cotistas and etf_site_pl (R$) are the 'Número de cotistas'
        and 'Patrimônio líquido' the same site prints in the SAME snapshot
        (etf_site_as_of): third-party descriptive facts, never summed, never a
        fee base. Since v68 (#606 Q36) the filed benchmark, whatever the fee
        source and as filed, never inferred from a name or a class:
        benchmark_extrato is the Extrato's PARAM_TAXA_PERFM (the performance
        fee's index, the Extrato's only benchmark column; dated extrato_as_of),
        benchmark_lamina the lâmina's INDICE_REFER at lamina_as_of when every
        class filed the same one, benchmark_lamina_n the count of distinct
        values filed (0 none, above 1 the classes differ). p_month = the
        balancete month (NULL = each fund's newest). One row per distinct CNPJ;
        more than 200 CNPJs RAISES 22023.


        **Row cap.** A window producing more than 1000 rows raises SQLSTATE
        `22023` naming this function. Nothing is trimmed to fit — PostgREST
        would silently cut the response at 1000 and a cut-short series is
        indistinguishable from one that simply ends. This function does not page
        — narrow the window instead.
      operationId: rpc_portfolio_fees
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                p_cnpjs:
                  type:
                    - array
                    - 'null'
                  items:
                    type:
                      - string
                      - 'null'
                p_month:
                  type:
                    - string
                    - 'null'
                  format: date
                  description: Defaults to `NULL::date`.
                  default: null
              required:
                - p_cnpjs
      responses:
        '200':
          description: >-
            The result set, oldest first. An unknown id is an empty array, not a
            404 and never a guessed value.
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
                  properties:
                    cnpj:
                      type:
                        - string
                        - 'null'
                    fund_name:
                      type:
                        - string
                        - 'null'
                    month:
                      type:
                        - string
                        - 'null'
                      format: date
                    nav:
                      type:
                        - number
                        - 'null'
                    adm_fee_flow:
                      type:
                        - number
                        - 'null'
                    adm_fee_pct_annual_est:
                      type:
                        - number
                        - 'null'
                    perf_fee_flow:
                      type:
                        - number
                        - 'null'
                    perf_fee_pct_annual_est:
                      type:
                        - number
                        - 'null'
                    fiscal_reset_suspect:
                      type:
                        - boolean
                        - 'null'
                    disclosed_taxa_adm:
                      type:
                        - number
                        - 'null'
                    disclosed_taxa_adm_min:
                      type:
                        - number
                        - 'null'
                    disclosed_taxa_adm_max:
                      type:
                        - number
                        - 'null'
                    disclosed_taxa_perfm:
                      type:
                        - string
                        - 'null'
                    disclosed_taxa_adm_info:
                      type:
                        - string
                        - 'null'
                    disclosed_taxa_perfm_info:
                      type:
                        - string
                        - 'null'
                    disclosed_source:
                      type:
                        - string
                        - 'null'
                    disclosed_as_of:
                      type:
                        - string
                        - 'null'
                      format: date
                    disclosed_age_months:
                      type:
                        - integer
                        - 'null'
                      format: int32
                    disclosed_n_classes:
                      type:
                        - integer
                        - 'null'
                      format: int32
                    disclosed_note:
                      type:
                        - string
                        - 'null'
                    estimate_label:
                      type:
                        - string
                        - 'null'
                    disclosed_origin:
                      type:
                        - string
                        - 'null'
                    disclosed_age_days:
                      type:
                        - integer
                        - 'null'
                      format: int32
                    filed_zero:
                      type:
                        - boolean
                        - 'null'
                    implausible_filed:
                      type:
                        - boolean
                        - 'null'
                    taxa_adm_filed_raw:
                      type:
                        - number
                        - 'null'
                    extrato_tp_fundo_classe:
                      type:
                        - string
                        - 'null'
                    extrato_classe_anbima:
                      type:
                        - string
                        - 'null'
                    extrato_class_note:
                      type:
                        - string
                        - 'null'
                    extrato_existe_taxa_perfm:
                      type:
                        - string
                        - 'null'
                    extrato_taxa_perfm:
                      type:
                        - number
                        - 'null'
                    extrato_param_taxa_perfm:
                      type:
                        - string
                        - 'null'
                    extrato_calc_taxa_perfm:
                      type:
                        - string
                        - 'null'
                    extrato_inf_taxa_perfm:
                      type:
                        - string
                        - 'null'
                    extrato_existe_taxa_ingresso:
                      type:
                        - string
                        - 'null'
                    extrato_taxa_ingresso_pr:
                      type:
                        - number
                        - 'null'
                    extrato_taxa_ingresso_real:
                      type:
                        - number
                        - 'null'
                    extrato_existe_taxa_saida:
                      type:
                        - string
                        - 'null'
                    extrato_taxa_saida_pr:
                      type:
                        - number
                        - 'null'
                    extrato_taxa_saida_real:
                      type:
                        - number
                        - 'null'
                    extrato_taxa_custodia_max:
                      type:
                        - number
                        - 'null'
                    lamina_pr_pl_despesa:
                      type:
                        - number
                        - 'null'
                    lamina_dt_ini_despesa:
                      type:
                        - string
                        - 'null'
                      format: date
                    lamina_dt_fim_despesa:
                      type:
                        - string
                        - 'null'
                      format: date
                    lamina_as_of:
                      type:
                        - string
                        - 'null'
                      format: date
                    lamina_expense_note:
                      type:
                        - string
                        - 'null'
                    fee_resolution:
                      type:
                        - string
                        - 'null'
                    lamina_taxa_adm:
                      type:
                        - number
                        - 'null'
                    lamina_taxa_adm_min:
                      type:
                        - number
                        - 'null'
                    lamina_taxa_adm_max:
                      type:
                        - number
                        - 'null'
                    lamina_n_classes:
                      type:
                        - integer
                        - 'null'
                      format: int32
                    lamina_age_months:
                      type:
                        - integer
                        - 'null'
                      format: int32
                    extrato_taxa_adm_filed:
                      type:
                        - number
                        - 'null'
                    extrato_as_of:
                      type:
                        - string
                        - 'null'
                      format: date
                    extrato_lamina_ratio:
                      type:
                        - number
                        - 'null'
                    extrato_scale_factor:
                      type:
                        - integer
                        - 'null'
                      format: int32
                    etf_ticker:
                      type:
                        - string
                        - 'null'
                    etf_site_taxa_adm:
                      type:
                        - number
                        - 'null'
                    etf_site_as_of:
                      type:
                        - string
                        - 'null'
                      format: date
                    etf_site_source:
                      type:
                        - string
                        - 'null'
                    etf_site_note:
                      type:
                        - string
                        - 'null'
                    etf_site_nr_cotistas:
                      type:
                        - integer
                        - 'null'
                      format: int32
                    etf_site_pl:
                      type:
                        - number
                        - 'null'
                    benchmark_extrato:
                      type:
                        - string
                        - 'null'
                    benchmark_lamina:
                      type:
                        - string
                        - 'null'
                    benchmark_lamina_n:
                      type:
                        - integer
                        - 'null'
                      format: int32
        '400':
          description: >-
            Bad request. Contract violations raise SQLSTATE `22023` with a
            message naming the limit or the argument at fault.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: >-
            No usable `apikey`, or a request for a schema outside `api`.
            `Accept-Profile: public` and any `cvm_*` / `b3_cotahist` / `cia_*`
            path answer 401 for every caller, by grant — schema `api` is the
            entire public surface.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: No such endpoint in schema `api`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
components:
  schemas:
    Error:
      type: object
      description: >-
        PostgREST error body. `code` carries the SQLSTATE — `22023` is a
        contract refusal.
      properties:
        code:
          type:
            - string
            - 'null'
          examples:
            - '22023'
        message:
          type:
            - string
            - 'null'
        details:
          type:
            - string
            - 'null'
        hint:
          type:
            - string
            - 'null'
  securitySchemes:
    apikey:
      type: apiKey
      in: header
      name: apikey
      description: >-
        The publishable key (`sb_publishable_…`), on every request. It is NOT a
        JWT — sending it as `Authorization: Bearer` is rejected as an invalid
        JWT. It identifies the project, not you, and maps to the Postgres `anon`
        role.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.