Brazil Public Company Data API for Research Pipelines
You run a research pipeline — equity models, sector screens, or internal dashboards — and need a Brazil public company data API that returns regulatory filings, not just price quotes. Market data vendors cover tickers and prices; they rarely give you programmatic access to CVM PDFs with stable metadata.
apicvm fills the regulatory layer: resolve B3 issuers, list DFP/ITR/FRE documents by year, download originals, and optionally extract page-level text for downstream NLP.
The persona
Typical users:
- Quant researchers building Brazil factor models that need filing timestamps and document access
- Data engineers wiring CVM documents into a warehouse alongside market data
- Fintech teams shipping "view source filing" features for Brazilian equities
Common blocker: CVM open data is bulk CSV/ZIP — great for panels, awkward for "fetch VALE3's latest quarterly filing on demand."
The problem
Research pipelines need repeatable lookups:
- Ticker → company — canonical CNPJ and name
- Company → filings — filter by type (DFP, ITR, FRE) and year
- Filing → file — download the exact PDF your model references
Without an API, each step becomes custom ETL: join open-data tables, hunt PDF URLs, handle portal changes.
Solution: apicvm in your pipeline
Universe (tickers)
→ GET /v1/companies/resolve (batch per ticker)
→ GET /v1/documents?ticker=X&type=DFP|ITR|FRE&year=Y
→ GET /v1/documents/:id/file → object storage
→ (optional) POST /v1/document-text-extractions → NLP features
→ warehouse / feature store
Resolve issuers
export APICVM_KEY='apicvm_...'
export APICVM_URL='https://apicvm.dev'
curl -H "Authorization: Bearer $APICVM_KEY" \
"$APICVM_URL/v1/companies/resolve?query=VALE3&by=ticker"
Store cnpj, name, sector, and tickers[] as dimensions in your warehouse.
List filings for a panel
import os, requests, time
BASE = os.environ["APICVM_URL"]
H = {"Authorization": f"Bearer {os.environ['APICVM_KEY']}"}
TICKERS = ["PETR4", "VALE3", "WEGE3"]
rows = []
for ticker in TICKERS:
for doc_type in ("DFP", "ITR"):
r = requests.get(
f"{BASE}/v1/documents",
headers=H,
params={"ticker": ticker, "type": doc_type, "year": 2024, "perPage": 50},
)
r.raise_for_status()
for doc in r.json()["data"]:
rows.append({
"ticker": ticker,
"type": doc["type"],
"year": doc["year"],
"date_ref": doc["dateRef"],
"document_id": doc["id"],
"name": doc["name"],
})
time.sleep(0.5) # respect rate limits
Respect X-RateLimit-* headers in production schedulers.
Download to object storage
curl -OJ -H "Authorization: Bearer $APICVM_KEY" \
"$APICVM_URL/v1/documents/<document-id>/file"
Store with a deterministic key: s3://research/cvm/{ticker}/{type}/{year}/{document_id}.pdf.
When to combine with open data
Many teams use CVM open data for historical cross-sections (500 companies × 10 years) and apicvm for:
- On-demand filing fetch when a model flags an event
- User-facing "download source" buttons
- Text extraction for NLP features
Current limitations
- apicvm covers the ingested corpus — not guaranteed every B3 company or period.
- No equity prices — pair with a market data provider for quotes.
- No parsed financial line items — PDFs only; parsing is your pipeline's job.
- Rate limits apply per API key — batch jobs need throttling.
- Filings arrive after pipeline ingestion — not real-time CVM publication.
Next steps
Ready to integrate?
Get an API key and start querying Brazilian CVM filings programmatically.