Overview
Three questions before you write a query: does SILO have it, how far back, and how stale can it be. Data inventory is the table-by-table view of the warehouse; this is the view from the API. Every date below is a floor, not a promise about today. The authoritative answer iscoverage() and metric_coverage(), generated from the data — ask them first, and use this page to know what to ask for.
Ask the API what it holds
Note: a stale
landed_at is a pipeline failure. A complete_through that trails today is Brazil’s filing calendar — CVM publishes one to two months in arrears, and that is not an outage.
metric_coverage() goes finer: first and last period carrying a non-null value for every (entity_type, metric) pair, plus how many rows filed it.
How far back
Ingest runs once a day at 06:00 UTC. A slice CVM publishes late is healed on a later run — the daily job re-probes a trailing window and re-fetches any month with no successful ingest.
The B3 BDI ratchet
No deep-history route exists and none is coming: the legacy B3 download API returns HTTP 400 for every BDI table name, and thepesquisapregao archive returns empty zips. run_backfill deliberately offers no lending option.
The failure is silent by default — an over-wide request returns HTTP 200 with the window quietly clamped (2024-01-02 through 2026-09-10 returns 18 sessions). A 200 is not evidence the span you asked for was delivered, which is why every ingest reconciles received sessions against requested ones.
Treat these five as a live feed with a short tail, not as history. If you need a long series, capture it as it publishes. Always read as_of before assuming a window exists.
Three caveats these endpoints publish as columns
short_interest: pct_float is two different metrics
short_interest: pct_float is two different metrics
float_basis says which denominator produced pct_float. index_free_float is B3’s real free float and covers index constituents only; shares_outstanding is a larger denominator and therefore a smaller percentage. Do not rank across the two. pct_float and days_to_cover are null — never 0 — when their denominator is missing.investor_flow is derived and lags T+2
investor_flow is derived and lags T+2
B3 publishes a month-to-date cumulative snapshot; the daily figure is its first difference within a month. Rows whose
flow_basis is unknown_opening_snapshot carry null flows on purpose — reporting the cumulative total as one day’s flow would invent a spike.lending_trades: doador and tomador are brokerages
lending_trades: doador and tomador are brokerages
Not beneficial owners. Around 75% of trades carry the same code on both legs, so a large borrow through a broker is that broker’s client book. Read
short_interest through is_total as well: B3 publishes both the per-market rows and its own Total sum, and adding them double-counts.What is not here
Nothing on this API is interpolated or forward-filled, and exactly one price is adjusted.- Quotes are unadjusted, except
quote_history’sclose_adj.closeand theadjustedflag (falseon every row) are as traded.close_adj, the default field ofquote_history, is continuous across splits, groupings and bonus shares, and a window it cannot adjust is refused with the cause, never served raw.close_total_return, selected inp_fields, adds the cash distributions and is NULL with a reason wherever one cannot be valued. The tape starts on 2019-01-02, andquote_historyrefuses a window that starts before an instrument’s first session.b3_corporate_eventstill carries the events as published. - A null is a null. Never a guessed last close, a zero, or a carried-forward figure. An unknown ticker returns an empty array.
- A regime break is not a trend. FIDC
delinquencystarts in 2013-01 and is on every row only from 2020-11, so a count of reporting funds jumps there.catalog().regime_breakslists them. - No ANBIMA-to-fund mapping exists. ANBIMA rows are industry aggregates carrying no fund id, and CVM’s
classeis a different taxonomy. Joining by name would be an invention.
Next
Your first screen
A working screen of real data in four calls.
Paging without losing rows
Two different cursors, and the trap of confusing them.
Coverage reference
The
coverage() and metric_coverage() endpoints in full.Data inventory
Every table, its grain, and what we deliberately do not ingest.