| name | databolsa-cli |
| description | Retrieve, screen, compare, and analyze financial-market data or the authenticated user's DataBolsa account with the DataBolsa CLI. Use for B3 stocks, FIIs, ETFs, BDRs, funds, Treasury bonds, debentures and private credit, credit ratings, receivables funds (FIDC), structured notes (COE), yield curves, fixed-income benchmarks, indexes, macro, live or historical quotes, dividends, fundamentals, options, offerings, investor flow, fund ownership and insiders, official documents, US assets, crypto, portfolios, suitability, or investment theses. For thesis and portfolio-review tasks, combine account context, market history, primary documents, benchmarks, and explicit risks instead of using a single snapshot. |
| license | Apache-2.0 |
| compatibility | Node.js 18+ and network access. A DATABOLSA_API_KEY is required for the hosted API. |
| metadata | {"version":"3.3.0"} |
DataBolsa CLI
Use the CLI as a thin client to the DataBolsa API. The API contract is the source
of truth, so operation names, options, schemas, and availability can evolve.
Treat returned values as evidence, not investment advice.
What DataBolsa supports
Discover the current operation list at runtime, but expect these surfaces:
- Brazilian equities: profiles, TTM fundamentals, quarterly indicator history,
OHLCV, intraday and delayed live quotes, dividends/JCP, corporate events, VWAP
and trades, insiders, funds that hold an asset, and the monthly ownership flow
that puts fund position changes and insider trades on one timeline.
- FIIs: profiles, indicator snapshots and history, distributions, monthly
reports, and screening by segment and portfolio type.
- Funds, ETFs, BDRs, and indexes: catalogs, profiles, fund holdings and flows,
the fund-of-funds graph in both directions (which funds a fund invests in, and
which funds invest in it), look-through exposure to listed assets, BDR prices,
index levels, and current index composition.
- Fixed income and macro: Tesouro Direto rates and prices, nominal and real
curves, market yield curves by tenor (DI futures plus pre/IPCA+/implied-inflation
reference curves), primary Treasury auctions since 2000, fixed-income benchmark
indexes (IMA-B, IRF-M families, since 2002), Focus expectations,
BCB/IBGE/FRED/World Bank series, macro regime, and macro gears.
- Private credit: the full debenture catalog (issuer, as-filed indexation,
incentivada status, guarantees, maturities) with per-session secondary-market
prices since 2013, a debenture screener (filter by indexer, spread, maturity,
liquidity and institutional demand), fund-level look-through (which funds hold
each debenture, with declared monthly buys/sells and the disclosure-panel size
— never read holder drops without checking
funds_panel_n), over-the-counter
secondary trades by instrument family (CDB, CRI, CRA, LCI, LCA and more), and
quarterly bank-issuer solvency (Basileia ratio, capital, credit portfolio)
behind any CDB rate, and an observed credit-spread curve by tenor bucket
(median as-filed spread of papers that actually traded, with the median
price-vs-par as the repricing gauge). Each debenture also carries its issuer's
link to the CVM registry (issuer_cd_cvm, issuer_primary_ticker,
issuer_categ_reg), and getIssuerProfile resolves a CNPJ into what can be
known about that issuer.
- Credit ratings:
listCreditRatings returns the rating currently in force
per (agency, paper), and listCreditRatingHistory returns every observed
rating action for one ISIN or issuer CNPJ. These are facts read out of
documents filed with public regulators, so every row carries agency,
action_date and download_url — cite the document whenever you state a
rating, and never present it as a DataBolsa rating. Three rules that change
the answer: rating_notch (1 = best) compares only within the same
scale, because a Brazilian issuer is routinely AAA on the national scale
and BB on the global one at the same time; action_date_known: false means
the ordering fell back to the filing date, so the agency's own date is
unknown rather than equal to it; and a missing paper means no rating document
has been read yet, which is not the same as the paper having no rating. When
agencies disagree, report all of them — do not pick one. The optional
declared block is the rating the securitizer itself wrote in its monthly CVM
filing, kept alongside for cross-checking; is_parseable: false there means
not declared in the filing, again never "no rating".
- FIDC (receivables funds):
listFidcs for a monthly cross-section, plus
listFidcHistory, listFidcSeries, listFidcDelinquency and listFidcScr
per class. FIDCs have their own surface rather than appearing in /funds
because their quota is marked to an appraisal and never passes through the
daily filing that feeds ordinary funds. Four things that change the answer:
the key is the class, not the fund, so a multi-class fund has one CNPJ per
class; entity_kind: null marks filings before 2020-11, when the source keyed
on the fund and the grain was different; the two delinquency series never sum,
because in *_with_risk the originator is on the hook and in *_no_risk the
fund eats the loss; and impaired_ratio is a share of the portfolio, and
comes back null with impaired_exceeds_portfolio: true when the declared
impaired amount exceeds the portfolio — the raw components stay in the
response. Senior, mezzanine and subordinated quota series are distinct
instruments and are never consolidated. listFidcScr returns SCR levels
(CMN Resolution 2.682, AA–H) assigned by the institution itself: this is not
an agency rating and is not comparable to brAAA — agency ratings live in
listCreditRatings. declares_scr: false means the class declared no level
at all, which is not the same as declaring zero in a band.
- Structured notes (COE):
listCoes for the over-the-counter register
(issuer, issue size, maturity, lifetime secondary activity) and getCoe for
one instrument, keyed by its B3 instrument code — not the ISIN and not the
commercial campaign name, neither of which the register carries. This is a
separate surface from credit on purpose: a COE is a derivative payoff
wrapped in the issuing bank's credit risk, so the holder carries both, and
reading it as fixed income is the mistake the product's opacity relies on.
Two rules that change the answer. First, this endpoint cannot tell you what a
COE pays: capital protection, underlying, participation and return scenarios
live in the DIE (the essential-information document), which is not public
structured data — indexer, indexer_pct and additional_rate_pct are
register fields, commonly literally SEM REMUNERACAO, and never describe the
investor's return. State plainly that the payoff is not in the data rather
than inferring it from those fields. Second, the secondary-market aggregates
come back null for the overwhelming majority of papers, and that is the fact,
not missing coverage: a COE is normally held to maturity with no exit market.
Use tradedOnly to isolate the ones that ever traded. What the data does
answer well is how much each issuer placed, at what tenor, and how illiquid
the paper actually is. Per-session COE trades live in listOtcQuotes with
family=COE — that is the flow, this is the catalogue.
- Naming, so the surfaces do not get confused: what a Brazilian investor
calls renda fixa is split across three surfaces here, cut by who owes
rather than by payoff shape. Sovereign paper and curves are Bonds
(
listTesouroBonds, getYieldCurve). Private-issuer paper is Credit
(debentures, the OTC families CDB, CRI, CRA, LCI, LCA, and FIDC) — the
contracted return is incidental to the issuer risk. COE is Estruturados, for
the reason above. A portfolio uses a fourth, user-facing axis: asset types
there are renda_fixa (bank and securitized paper such as CDB/LCI/LCA and
CRI/CRA, symbol = the OTC instrument code), debenture (symbol = the trading
code, e.g. ELTN17) and tesouro. Do not assume those labels line up with the
contract's tags. search resolves private-credit codes too: debentures by
trading code and CRI/CRA/LCI/LCA by OTC instrument code, alongside the other
classes.
- Portfolio analytics:
getPortfolioXray (one-call concentration breakdown —
class, sector, fixed-income indexer, currency, top positions, deterministic
flags), getPortfolioLookThrough (effective exposure opening fund
positions through their latest disclosed monthly portfolios, one
fund-of-funds hop, with per-fund coverage) and getPortfolioCosts
(deterministic annual-cost estimate: fund admin fees vs the peer median for
the same CVM classification, Tesouro Direto custody, and the gap of taxable
bank paper contracted below 100% of CDI — each item names the recipient, and
whatever is not observable comes back in not_estimated with the reason).
- Derivatives and primary market: option chains, expiries, option history, and
public offerings.
- Market activity: daily and monthly investor participation by investor type.
- Documents: CVM/IPE company documents and semantic search over official
company and FII documents.
- Market events ledger: point-in-time record of what mattered each day —
structural acts (rate decisions, provisional measures, tariffs, geopolitics),
multi-source press stories and abnormal price days, with sources, threads
(event timelines), semantic search, and historical analogues.
- Global and crypto: US stocks and ETFs, SEC fundamentals and filings, B3
links through BDRs, crypto catalogs, daily BRL candles, and near-live snapshots.
- Authenticated account: consolidated and individual portfolios, ledger,
history, imports, suitability, and saved investment theses.
- Account writes: portfolio and transaction management, reconciliation, and
thesis creation/import/update/publish/export.
If a requested surface is not in --list, inspect the live contract before
concluding it does not exist. Do not invent a fallback operation.
Setup and launcher
The API key identifies the user's account. It must be available only through the
environment. Never ask the user to paste it into chat, print it, or put it in
source control.
export DATABOLSA_API_KEY="db_live_..."
Run without a global install:
npx --yes @databolsa/cli <operation> [arguments]
Or, if the published package is installed globally:
databolsa <operation> [arguments]
Do not translate a newly discovered API operation into guessed shell syntax.
Mandatory discovery
At the start of a market or account research task:
npx --yes @databolsa/cli getHealth --json
npx --yes @databolsa/cli --list
Before using an operation whose arguments have not already been confirmed in the
current task:
npx --yes @databolsa/cli <operation> --help
When the exact request body, response schema, enum, unit, or a newly released
operation matters, query only that operation in the live contract. See
the OpenAPI reference. Do not load the complete contract
into context.
Core research workflow
Use the smallest set of operations that can answer the question, but do not draw
an investment conclusion from a single snapshot.
- Freshness and identity
- Record
data_freshness from getHealth.
- Resolve an ambiguous ticker, title, index, fund, or series with
search or a
catalog operation.
getStock reports whether the code is still traded: active: false means the
ticker was retired by a succession, with successor, renamed_at,
succession_type (rename = 1:1 code change, incorporation = merger) and
succession_ratio (shares of the successor per unit of the old code). The
company.tickers list carries the same fields per class. Never quote a retired
code as a current price: its latest_quote is frozen at the succession date —
read the successor instead, and convert quantities by the ratio.
trading_status reports the issuer's standing as flagged by the exchange:
regular, recuperacao_judicial, recuperacao_extrajudicial, sancionada
or concordataria, with trading_status_since for the current spell. It is
NOT a trading halt — a company under court-supervised reorganization keeps
trading normally. Say so when reporting such a name: valuation multiples on a
distressed issuer mean something different, and the reader deserves the flag.
- Check
sessions_behind before quoting any price. It counts market sessions
between the quote and the latest session: 0 is current, anything higher is
the last known trade of an illiquid or halted paper, frozen. In that case
change_pct comes back null on purpose — there is no variation for today —
so never present a frozen quote as a daily move.
- Current snapshot
- Fetch the profile and current indicators or quote.
- Preserve
reference_date, units, ttm, reasons for nulls, and lineage.
- For historical or backtest reads,
getStockIndicators --at <date> is
point-in-time by publication: it returns the latest statement already FILED
with the regulator on that date (filed_at in the response), and price
reflects the closest trading session on or before the date. When filed_at
is null the cutoff falls back to the accounting period — say so when the
distinction matters. Price-derived indicators (beta, volatilidade,
retorno_12m, volume_medio_2m) have no historical series: under a
historical --at they come back null with an explicit reason instead
of leaking today's value — never present them as values for that date.
free_float comes from the CURRENT registry (no dated series), so it is
null under any --at.
- For structured statement series (revenue, EBITDA, net income, cash, debt,
equity, TTM flows), use
listCompanyStatements <ticker or CVM code> (both
resolve) with from/to
on the accounting period and filed_at per row for point-in-time cuts,
instead of scraping numbers from document text.
- Trajectory
- Fetch indicator, quote, distribution, or macro history over a period suited
to the claim.
- Decide whether the snapshot is routine, peak, trough, or a possible break in
the series before interpreting it.
- Cash and events
- For income claims, inspect payment-level dividends or distributions and
group by a clearly stated date convention.
- Check corporate events when adjusted prices, units, or apparent jumps matter.
- Primary-document context
- Use semantic document search to explain important changes, then retain the
document date, type, protocol/link, and relevant excerpt.
- Search critical facts with multiple formulations. Absence of a search result
is not proof that an event did not happen.
- Comparison and benchmark
- Compare with relevant peers and an alternative compatible in horizon and
risk, such as the appropriate Tesouro curve point.
- Counter-case
- Separate the strongest evidence against the hypothesis, missing variables,
and measurable invalidation triggers from the base interpretation.
Example discovery and read-only calls:
npx --yes @databolsa/cli getStock PETR4 --json
npx --yes @databolsa/cli getStockIndicators PETR4 --json
npx --yes @databolsa/cli getStockIndicatorHistory PETR4 --name roe --from 2021-01-01 --json
npx --yes @databolsa/cli listQuotes PETR4 --from 2026-01-01 --limit 100 --json
npx --yes @databolsa/cli listDividends PETR4 --limit 100 --json
npx --yes @databolsa/cli screenStocks --sector Bancos --sort=-dy_12m --limit 20 --json
These are examples, not a substitute for <operation> --help.
Account-aware tasks
A configured key may belong to the user's personal DataBolsa account. The
following are read-only and do not require confirmation:
- list portfolios and inspect consolidated/detail/history views;
- inspect suitability;
- list portfolio transactions and prior imports;
- list the user's theses and open a thesis detail.
Use account data only when it is relevant to the request. Do not expose exact
portfolio value, quantity, average price, tax information, or other personal
fields in public-facing content unless the user explicitly asks for them. Prefer
weights and rounded aggregates for reports intended to be shared.
For a portfolio review, inspect both the consolidated view and the relevant
portfolio detail. Identify concentration, duplicated risk factors, tiny positions,
unpriced assets, and ledger or corporate-event inconsistencies before discussing
allocation.
getPortfolioDetail responds compact by default: closed positions and the
per-holding monthly series are omitted. Pass include=closed,monthly (composable
with transactions) when the review needs realized history or per-asset monthly
income. Each holding carries valuation telling how it was priced — market
quote, fixed-income accrual, or cost — treat cost-valued positions as unpriced
when discussing performance. Portfolios accept stocks, FIIs, BDRs, ETFs, options,
Tesouro titles, crypto, US assets, private fixed income (renda_fixa),
debentures/CRI/CRA matched to the catalog (debenture), and funds by CNPJ
(fund).
Thesis and report workflow
When asked to create, review, update, or market an investment thesis, do not treat
it as a generic writing task.
- Run
getHealth and record freshness.
- Use
listMyTheses and getThesis to avoid duplicating an existing thesis and
to preserve the user's prior hypothesis, triggers, and writing style.
- If the thesis is personal or portfolio-aware, inspect
getPortfolio, the
relevant detail, and suitability. Keep exact private values out of the public
version by default.
- Build the evidence with the core research workflow: snapshot, history, cash,
events, documents, peers, benchmark, counter-case, and monitoring triggers.
- Separate:
- facts: returned values with dates and sources;
- interpretation: what those facts may imply;
- assumptions: subjective scenario inputs;
- unknowns: missing or conflicting evidence.
- For a public thesis, use a descriptive search-friendly title and subtitle,
mention the covered ticker/topic naturally, and include dated sources and a
clear educational disclaimer. Never claim that DataBolsa or a model increased
returns without a documented baseline and calculation.
- Produce and review the local thesis document before any import or update.
- Import/create as
private first. Publishing, changing visibility, exporting,
reordering, or replacing an existing document is a separate write that requires
explicit confirmation immediately before execution.
- Before publication, remove private sections and explain that the full document
becomes visible according to the selected visibility.
Useful discovery commands:
npx --yes @databolsa/cli listMyTheses --json
npx --yes @databolsa/cli getThesis <id> --json
npx --yes @databolsa/cli createThesis --help
npx --yes @databolsa/cli importThesisFile --help
npx --yes @databolsa/cli publishThesis --help
Two ways to submit the document, and the choice is about where it lives:
createThesis --doc '<json>' passes the report document inline. Structured
options take JSON on the command line, so quote the whole value; an invalid
JSON is reported by the CLI naming the option, before any request is sent.
importThesisFile --file <path> reads the document from a file, which is the
better path for anything large enough to be awkward to quote.
Do not import a draft merely to validate or preview it.
Public offerings
listOfferings unifies regulatory regimes whose vocabularies differ, and reading
it as one flat table produces plausible wrong numbers. Three rules:
- Filter and group by
instrumento or familia, not by tipo_ativo. The source
spells the same instrument several ways depending on the regime, so
instrumento=debenture returns the whole set while a single spelling returns a
fraction of it. tipo_ativo remains the as-filed text and matches only the
spelling asked for.
- Build time series on
data_referencia. Restricted-effort offerings carry no
registration date, so filtering or sorting by data_registro silently drops
them — and they are a large share of the years before 2023. regime_registro
separates registered offerings from exempt ones when that distinction matters.
- Before summing
valor_total, exclude value_is_sentinel and
value_pre_real_currency. It is the REGISTERED amount, not the placed amount,
and the source uses the field freely: filler values and pre-1994 currency both
appear, and a single filler record can dominate a whole year.
For wide scans, fields= projects the response to the columns needed, which keeps
a large page usable.
Documents and semantic search
Use listCompanyDocuments to establish what a company filed and
searchDocuments to locate relevant passages. For a critical claim:
- in
listCompanyDocuments, from/to filter the document's REFERENCE date
(the period it covers), not the filing date: annual statements for year N are
filed in year N+1 and still match a from/to range inside year N. The filing
date is returned as filed_at;
- include the ticker and, when useful, year/category/table filters;
- try 3 to 5 domain-specific formulations;
- distinguish “no matching indexed passage” from “no document exists”;
- inspect the original document link for context before a consequential conclusion;
- compare narrative claims with structured financial data from the same period.
Each searchDocuments result carries a citation with two distinct dates plus
document identity: reference_date is the period the document COVERS;
filed_at is when it was actually FILED/published (often weeks later);
protocol+source identify the exact document at the source;
filed_at_source is "source" when the filing date came from the source and
null when unknown (it is never inferred from reference_date). Quote
filed_at — not reference_date — when the claim is about what was known at a
point in time.
For historical reconstruction ("what was known on date X"), pass
filed_before=<date>: only documents already filed by that date are returned,
and documents with unknown filing date are excluded (the response warnings
notes this). Exact-document filters are also available: protocol (search
inside one document), reference_date/reference_from/reference_to,
filed_after, and doc_type.
npx --yes @databolsa/cli searchDocuments \
--q "resultados 2T22 receita margem bruta" --tickers TASA4 \
--filed_before 2022-11-03 --json
Market events ledger
The events endpoints answer "what was relevant on day X" and "explain this
happening" with sources, not guesses. Each event carries detectors
(official = a primary act such as a Copom decision, provisional measure, or
US tariff; press = multi-outlet coverage; market = an abnormal price move)
and source_refs linking to the underlying evidence.
listMarketEvents --date YYYY-MM-DD for a day's ledger; filter by layer
(estrutural|setorial|corporativa), category, entity (no ticker needed —
political and macro happenings are first-class), ticker, or thread.
getEventThread <slug> for the chronological story of a structural event
(rumor → official act → confirmation → analysis), e.g. a provisional measure
or a Copom meeting.
listMarketAnomalies for days when a tracked series moved N standard deviations
beyond regime (history back decades), each with the explaining event when
matched. An unexplained anomaly means a coverage gap, not "no cause".
For IBOV and IFIX the measure is the LOCAL decoupling (local_zscore), not the
raw move: global factors are subtracted first, so a 5% drop on a day the world
dropped 5% is not a Brazilian event, while a 3% drop while the world rallies is.
Read local_return_pct with factor_model to say what was domestic and what
was imported; zscore stays as the raw figure. Where factor_model is null
(global series, or before the factors existed) the raw move is the measure —
do not describe those as "local".
searchMarketEvents --q "<theme>" for semantic search over the ledger; then
deep-dive by event_id with getMarketEvent and findSimilarMarketEvents
("when did something like this last happen?").
- Events with 2+ detectors are strong; treat single-source
press events as
provisional. Always cite source_refs when a conclusion rests on an event.
Ownership flow: who is buying
listOwnershipFlow <ticker> answers "who has been buying this paper" month by
month, putting the change in fund positions next to insider trading on one
timeline. listOwnershipMovers <ticker> names the individual funds behind that
change, with direction (in, out, all). Four rules decide whether the
answer is real:
- A delta only exists when the disclosure panel is comparable. Funds report
on different calendars, so a naive month-over-month difference reads a drop in
who reported as selling. When the panel is not comparable,
funds_shares_delta
comes back null with the cause in funds_delta_reason. Read the two companion
fields correctly: funds_panel_n is the NUMBER of funds present in both
competencies, while funds_panel_coverage_pct is how much of the universe that
panel covers, as a percentage from 0 to 100 (98.16 means 98.16%, not 0.98%).
Never fill a null delta by subtracting the levels yourself, and never present a
month whose funds_delta_reason is set as flat — it is unknown, not unchanged.
funds_appeared and funds_qty_undisclosed count the funds deliberately cut
from the delta: a fund that merely started disclosing has not bought anything.
- Insider data is company-level, not ticker-level. The same filing repeats on
every ticker of the issuer, so a total that adds up all tickers double counts.
Aggregate only rows where
is_issuer_anchor_ticker is true.
corporate_event_shares is not trading. It isolates share changes that came
from corporate events (splits, bonuses, conversions). It is reported beside
net_shares in listInsiderMoves, and as insider_corporate_event_shares in
the ownership flow. Adding it to the net figure invents buying that never
happened.
- Flow in reais is
funds_value_flow_brl. The change in gross position value
is not flow: it also contains price movement, and the two can carry opposite
signs for the same month.
Months where only insider data exists come back with a null comptc_date.
listFundLookThrough <cnpj> adds a fund's direct position in a listed asset to
what reaches it through the fund shares it holds. Read the result as a FLOOR, not
a total: only part of the underlying portfolios can be opened, and the share that
was is in indirect_coverage_pct. Say "at least" when quoting it.
listInvestedFunds <cnpj> and listFundInvestors <cnpj> walk the fund-of-funds
graph in each direction. Where the weight of a position could not be computed,
weight_reason explains why — report it instead of treating the weight as zero.
npx --yes @databolsa/cli listOwnershipFlow PETR4 --from 2025-01-01 --json
npx --yes @databolsa/cli listOwnershipMovers PETR4 --direction in --json
Screeners, rankings, and comparisons
- Confirm exact filter names, valid sort fields, units, and case sensitivity with
--help.
- State every applied filter, sort, universe, date, and limit.
- Treat a screen as candidate generation, not a recommendation.
- For each shortlisted candidate, inspect history, cash distributions, debt, and
documents before ranking quality.
- Preserve missing fields instead of silently excluding or assigning a score.
Live data and time-sensitive requests
- State the quote delay or snapshot timestamp returned by the operation.
- Distinguish EOD, intraday, and near-live crypto data.
- For “today” or “latest,” verify the date and market session instead of relying on
the conversation date.
- Cross-check material claims against official documents or the underlying
structured data when available.
Output discipline
Add --json whenever output will be filtered, compared, saved, or passed to
another tool. The CLI writes JSON to stdout and errors to stderr.
Every listing and every series answers the same envelope: the items in data, and
in meta the pagination (next_cursor, count) plus the query context (ticker,
session, indicator, reference date). Filter with .data[] regardless of the
operation; single resources answer the object directly, without data.
npx --yes @databolsa/cli screenFiis --segment Logística --json | jq '.data[] | .ticker'
In the final analysis:
- state asset/universe, filters, period, and freshness;
- preserve returned field names and units;
- distinguish market-price date from statement/reference date;
- cite source lineage and official documents for material findings;
- mark calculations and assumptions explicitly;
- keep facts separate from interpretation;
- mention that market data can be delayed or revised;
- do not turn a screen, model output, or scenario into a buy/sell instruction.
Safety for account-changing operations
For any command that can create, update, add, remove, import, publish, reply,
reconcile, reorder, export, or delete:
- Explain the intended effect, target account resource, visibility, and whether
the action is reversible.
- Show the exact command with non-secret arguments. Redact credentials.
- Obtain explicit confirmation immediately before executing it.
- Do not perform a write merely to explore, validate, or test connectivity.
- For uploads, verify the local file path with the user and use the documented
--file <path> option only after confirmation.
- For deletion or reconciliation, call out the destructive or ledger-changing
effect separately.
- One confirmation covers only the displayed operation or clearly enumerated
batch. Ask again if the target, payload, visibility, or command changes.
Read-only market and account operations do not need confirmation.
Troubleshooting
- Key missing or unauthorized: ask the user to configure it in their
environment. Never request the value.
- Unknown command or option: run
--list, inspect the live operation, then
run <operation> --help. Update the published CLI package if the installed
command is older than the live contract.
- HTTP 402: the requested account feature requires another plan. Report the
feature and detail; do not retry as a different write.
- HTTP 429: report the applicable limit and
Retry-After when available.
- Exit code 3 or unavailable endpoint: report that the resource is unavailable;
do not fabricate a fallback result.
- Empty semantic search: vary the query and verify document coverage; do not
convert an empty result into a factual negative.
- Missing value or conflicting source: preserve and explain it. Never silently
substitute a different metric.
getIssuerRisk returns 404: solvency ratios exist only for banks supervised
by the central bank, so a corporate issuer has none by definition, not by gap.
Call getIssuerProfile with the same CNPJ: kind tells you which universe the
issuer belongs to, and a corporate issuer with a cd_cvm has financial
statements and filed documents to read instead. Report the absence as a
different kind of issuer, never as missing data.