Overview
quotes is the whole cash tape. These endpoints are the same rows split by instrument type, so you can ask for one class without filtering client-side.
The type comes from
vw_b3_instrument_typed, which classifies only from B3’s published TPMERC and ESPECI. Nothing is inferred from a ticker’s shape.
fund_quotas rows carry fund_type — etf | fii | fidc | fiagro — from B3’s published CODBDI (14 → etf, 05/12 → fii, 13 → fiagro), validated against the CVM ETF registry. NULL on boards that carry no family signal, never guessed from the ticker:
equities rows carry share_class (ON | PN | PNA | PNB | PNC | PND) and governance_segment (NM | N1 | N2 | MA | M2 | MB), parsed from ESPECI and cross-checked against the ISIN class code — never inferred from the ticker’s 3/4 suffix:
Lot size is part of the grain
These endpoints carry both lot sizes, withlot derived from tpmerc:
standard—tpmerc010, the round lotodd—tpmerc020/021, the fractional market
(ticker, trade_date, board, term_days, lot) — one column wider than quotes. A query that ignores lot sees what look like duplicate dates.
api.quotes is unchanged — still tpmerc = 010 only. These endpoints are additive.
Columns
Identical toquotes plus lot (and share_class + governance_segment on equities, fund_type on fund_quotas), minus asset_class — the endpoint is the type. Everything is unadjusted.
Price series stay unified
There is deliberately noequity_history or bdr_history. A codneg belongs to exactly one instrument type, so quote_history('PETR4') is already unambiguous — and a typed history would force you to determine the type before you could ask for a price. Split the cross-section; keep whatever is keyed by id.
The same rule is why options and termo do get their own history endpoints: those carry columns the cash shape has no room for.
Empty and error behavior
- No rows matching your filter →
200 []. Never a fabricated price. - A ticker on the wrong endpoint →
200 [].BOVA11is afund_quota, not anequity. Use/quotes, which is untyped, orlookup, which reports the type it resolved. - These views have no built-in cap — always send a
limit.