> ## 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.

# Panel

> The researcher endpoint — long (id, date, metric, value) observations mixing B3 tickers and CVM fund CNPJs in one call.

<Note>
  **Parameters, response columns and types are generated** from the SQL catalog and
  render under **Endpoints → Panel** in the sidebar. This page carries what a
  schema cannot: the conventions, the nulls that are deliberate, and the traps.
</Note>

### Overview

`panel` returns one row per observation, `(id, date, metric, value)`, so B3 prices and fund fundamentals for the same window come in one request. Pivot locally; there is no server-side `corr`, `rank` or regression.

```sql theme={null}
api.panel(p_ids         TEXT[],
          p_metrics     TEXT[]  DEFAULT ARRAY['close','nav'],
          p_from        DATE    DEFAULT CURRENT_DATE - 365,
          p_to          DATE    DEFAULT NULL,  -- null = clamp fund rows to complete periods
          p_freq        TEXT    DEFAULT 'month',
          p_entity_type TEXT    DEFAULT NULL,  -- keep one fund family
          p_min_nav     NUMERIC DEFAULT NULL,  -- universe mode: latest NAV floor (BRL)
          p_min_months  INT     DEFAULT NULL,  -- universe mode: min observations of the first metric
          p_after       TEXT    DEFAULT NULL)  -- cursor: '' = first page, then the last row's key
```

<Note>
  **The grain is `(id, asset_class, date, metric)`.** 385 CNPJs file under two families in the same month, and the panel returns one row per family. Pivoting on `(id, date, metric)` alone raises on the duplicate or silently averages two vehicles. Pass `p_entity_type`, or keep `asset_class` in your pivot key.
</Note>

<Warning>
  **Over 1,000 rows the panel refuses; it never trims.** A window over one page raises `22023` (HTTP 400): **page with `p_after`**, or narrow the request. See [Paging](#paging).
</Warning>

### Parameters

| Parameter | What to know |
| - | - |
| `p_ids` | Tickers, derivative codnegs and CNPJs, mixed. After stripping non-digits, **exactly 14 digits means CNPJ**; anything else is a B3 code, upper-cased (cash ticker, option series or termo contract is decided by the market segment it prints in). **3 ids anonymously, 50 signed in**; over it raises `22023`. |
| `p_metrics` | Lower-cased and trimmed. **A name not in the Metrics table is silently ignored**, so a typo shows as missing rows, not a `400`. |
| `p_from` | Snapped **down** to the first of the month for fund metrics; as-is for quote metrics. |
| `p_to` | Omitted: fund metrics end at each family's latest **complete** period; quote metrics run to today. Explicit: served verbatim, partial months included. [`coverage`](/api-docs/coverage) reports the bound as `complete_through`. |
| `p_freq` | `day`, `d`, `daily` mean daily; **every other value, including a typo like `week`, falls back to `month`**. |
| `p_entity_type` | `fi`, `fidc`, `fii`, `fip` or `fiagro`; anything else raises `22023`. With `p_ids` empty it selects universe mode. |
| `p_min_nav` | Universe mode only. Latest non-null net assets in the window, in BRL; a filter, not a rank. |
| `p_min_months` | Universe mode only. Minimum non-null observations of the **first** requested metric. |
| `p_after` | `null` is whole-result mode and refuses above one page. `''` is the first page. `'<date>\|<id>\|<metric>\|<asset_class>'` from the last row is the next. A malformed cursor raises `22023`. |

### Universe mode

Leave `p_ids` empty and name a family with `p_entity_type`: the panel selects that family's funds itself, optionally floored by `p_min_nav` and `p_min_months`. Nothing is ranked server-side. **Signed-in callers only** (each page re-scans the family's whole window); `catalog().limits.tiers.<tier>.panel_universe` says which you are.

```json theme={null}
{"p_ids": [], "p_metrics": ["delinquency", "nav"], "p_entity_type": "fidc",
 "p_from": "2025-09-01", "p_min_nav": 10000000, "p_min_months": 12, "p_after": ""}
```

### Metrics

| Metric | Id type | Asset class | Grains | Source | Meaning |
| - | - | - | - | - | - |
| `close` | ticker, option, termo | equity, unit, bdr, fund\_quota, cash\_security, derivative | day, month | `b3_cotahist` | Unadjusted close. Cash tickers: the instrument's published BDI board. Monthly = last session of the month. |
| `volume` | ticker, option, termo | equity, unit, bdr, fund\_quota, cash\_security, derivative | day, month | `b3_cotahist` | Session financial volume in BRL. Monthly = the last session's volume, not a sum. |
| `close_unit` | ticker | equity, unit, bdr, fund\_quota, cash\_security | day, month | `b3_cotahist` | `close / quotation_factor`: close per **single** quoted unit. Compares price levels across papers (one quoted per lot reads 1000× its unit price). Not corporate-action adjusted. |
| `close_return` | ticker | equity, unit, bdr, fund\_quota, cash\_security | day, month | `b3_cotahist` | `p_t / p_(t-1) - 1`, with `p_(t-1)` **divided by the share ratio of any split, grouping or bonus** between the two prints (a 1:4 split from 100.00 to 26.00 is +4%, not −74%). Price only, not a total return. **Cash tickers only.** |
| `settlement_rate` | future | derivative | day, month | `b3_price_report` | Futures settlement as a rate, as B3 publishes it: for DI1, % a.a. on 252 business days. Ids are B3 contract codes (`DI1F27`); [`future_curve`](/api-docs/rates) lists a session's. Final (F) settlements only. Nothing is rolled: a contract stops at maturity. The default for a future. |
| `settlement_price` | future | derivative | day, month | `b3_price_report` | Settlement price as published: for DI1 the PU. Final settlements only. |
| `open_interest` | future | derivative | day, month | `b3_price_report` | Open contracts at the session's close. Monthly = the last session's, not a sum. |
| `nav` | cnpj | fi, fidc, fii, fip, fiagro | month | `cvm` | Fund net assets (`vl_patrim_liq`). |
| `quota` | cnpj | fi | month | `cvm` | Unit quota value. Comparable within a subclass only. |
| `delinquency` | cnpj | fidc, fiagro | month | `cvm` | Delinquent portfolio **value**, not a rate; divide by `nav` yourself. |
| `yield` | cnpj | fii | month | `cvm` | Monthly yield percentage as published. |
| `inflows` | cnpj | fi | month | `cvm` | Gross monthly subscriptions. |
| `redemptions` | cnpj | fi | month | `cvm` | Gross monthly redemptions. |
| `quotaholders` | cnpj | fi, fii | month | `cvm` | Number of unit-holders. Not served for fidc, fiagro or fip. |
| `receivables` | cnpj | fidc | month | `cvm` | Receivables portfolio total (tab II `TOTAL`), the denominator for a concentration ratio. See [FIDC concentration](/api-docs/fidc). |
| `sacado_top1` | cnpj | fidc | month | `cvm` | Exposure to the single largest debtor (tab VIII rank 1, as filed). Anonymized in the source. |
| `sacado_top25` | cnpj | fidc | month | `cvm` | Sum of the ranks the fund filed (1..n, n ≤ 25); nothing imputed. Can exceed `receivables` for \~2% of funds, served as filed, never capped. |

A metric asked outside its asset classes (`catalog().applicability`) gives **no rows** for those ids, not nulls or zeros. FIDC `delinquency` starts in 2013-01 and is on every row from 2020-11; before that a fund with no tab VI row is null, not zero (`catalog().regime_breaks`).

<Warning>
  **`freq=day` is quotes only.** No CVM fundamental is daily, so `nav` with `p_freq: "day"` returns the quote rows and nothing else. Mix asset classes at `freq=month`, where the B3 value is the **last real session in the month**. Aligning a monthly NAV to a daily calendar would require filling, and this API does not fill.
</Warning>

### Response fields

| Field | What to know |
| - | - |
| `asset_class` | Cash tickers: the conservative B3 type (`fund_quota` deliberately does not guess ETF versus FII). `derivative` for option and termo codnegs and futures contract codes. Funds: the vehicle's `entity_type`. |
| `date` | At `freq=month` **always the first day of the month**, for every id. This is normalisation: CVM publishes FI/FII/FIAGRO at first-of-month, FIDC at month-**end**, FIP at year-**end**. [`fund_nav`](/api-docs/funds) serves the period as filed. |
| `value` | Nullable for `close` and `volume`; for every other metric a null is **no row at all**. |
| `source` | `b3_cotahist`, `b3_price_report` (futures) or `cvm`. |

Rows are ordered by `date`, `id`, `metric`, `asset_class`.

### Example

<CodeGroup>
  ```bash curl theme={null}
  curl -s -X POST "$SILO_URL/rpc/panel" \
    -H "apikey: $SILO_ANON_KEY" \
    -H "Content-Type: application/json" \
    -d '{
          "p_ids": ["PETR4", "12345678000190"],
          "p_metrics": ["close_return", "delinquency", "nav"],
          "p_from": "2021-01-01",
          "p_to": "2026-06-30",
          "p_freq": "month"
        }'
  ```

  ```python Python theme={null}
  body = {"p_ids": ["PETR4", "12345678000190"], "p_metrics": ["close_return", "delinquency", "nav"],
          "p_from": "2021-01-01", "p_to": "2026-06-30", "p_freq": "month"}
  rows = requests.post(f"{URL}/rpc/panel", headers=H, json=body).json()
  wide = pd.DataFrame(rows).pivot_table(index="date", columns=["id", "metric"], values="value")
  wide.corr(min_periods=12)  # pairwise-complete; do NOT ffill first
  ```
</CodeGroup>

### Paging

Send `p_after: ""` for the first page, then the last row's key `'<date>|<id>|<metric>|<asset_class>'`. A full page always has a next page; a short page is always the last. The SDK does this: `iter_panel(...)` / `panel_all(...)`. `Range` headers and `limit`/`offset` do **not** page an RPC call.

For scale: 3 ids × 2 metrics × 5 years of daily quotes is \~7,500 rows, eight pages.

### Notes

* **Nothing is forward-filled or interpolated.** A month a fund did not file is **absent**. Correlate pairwise-complete.
* **Two shapes of "no data".** `nav`, `quota`, `delinquency`, `yield`, `inflows`, `redemptions`, `quotaholders` and `close_return` never appear with a null `value`; a gap is an absent row. `close` and `volume` are emitted every session and can carry a JSON `null`.
* **`close_return` is adjusted across a share-count event.** Where a split, grouping or bonus (`DESDOBRAMENTO`, `GRUPAMENTO`, `BONIFICACAO` in B3's corporate-event history) lies between the two prints, daily or monthly (monthly: anywhere between the two month-end prints), the previous close is divided by the event's share ratio (1 + factor/100 for a split or bonus, the factor for a grouping) before the return is taken. A close of 100.00 before a 1:4 split is 25.00, so a 26.00 close is +4%, not −74%. An event with an unreadable factor, or published twice with two factors, leaves the row absent. Dividends and JCP still move it, it is not a total return, and an event the nightly sweep has not stored yet is not seen, so treat a jump over \~40% as suspect until you have checked.
* **`close_return` needs a predecessor.** Monthly: only when the preceding row is the immediately preceding calendar month. Daily: against the previous **stored** session, so a session missing from the warehouse makes the return span the gap (check [`coverage`](/api-docs/coverage)). The first observation in a window is always absent, so request more history than you analyze.
* **Windows differ per side.** Quote metrics honor `p_from` exactly; fund metrics start from `date_trunc('month', p_from)` and `p_to` is month-truncated too, so `p_to` of `2026-07-01` still returns all of July for a FIDC filed at `2026-07-31`.
* **Derivatives carry no `close_return`**, and their real grain is wider (COTAHIST keys them on board, termo also on term), so a within-session tie is **cut deterministically** (shortest term wins), not averaged. For the full grain use [`option_history`](/api-docs/options) or [`termo_history`](/api-docs/termo). There is no `underlying` column anywhere.
* **Every cash-market BDI board is accepted**; one row is kept deterministically when a ticker has multiple boards in a session.
* **Statement timeout:** a call that runs too long fails outright rather than returning part of a panel.
* **An empty array means no observation matched**: unknown ids, no filings in the window, a metric that does not apply, or an ignored metric name. Confirm with [`lookup`](/api-docs/lookup) and [`coverage`](/api-docs/coverage).


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