Resolve Brazilian Companies by Ticker, CNPJ, or Name
Every CVM filings workflow starts with one question: which company is this? A Brazil company lookup API should resolve PETR4, a CNPJ, or a partial legal name into stable metadata before you list documents. apicvm exposes GET /v1/companies/resolve for exactly that — the first step in the recommended filings flow.
This guide covers resolution modes, ambiguity handling, and how resolve connects to document listing.
The problem
Brazilian issuers appear under multiple identifiers:
- Tickers —
ITUB4,BBAS3(B3-listed symbols) - CNPJ — 14-digit corporate tax ID (with or without formatting)
- Legal names — "ITAÚ UNIBANCO HOLDING S.A." or partial matches
CVM open-data dumps are CNPJ-centric. Product code is ticker-centric. Without a resolve step, you maintain your own mapping tables or guess which company a filter returns.
How resolve works
GET /v1/companies/resolve finds one company per request.
| Parameter | Required | Description |
|---|---|---|
query |
Yes | Ticker, CNPJ, or name |
by |
No | auto (default), ticker, cnpj, or name |
Resolution order (by=auto)
- Ticker (case-insensitive)
- CNPJ (formatted or digits only)
- Exact name (case-insensitive)
- Partial name match
Force a mode when you know the identifier type: by=ticker, by=cnpj, or by=name.
Response shape
Success (200) returns a company object:
| Field | Type | Example | |
|---|---|---|---|
id |
integer | Internal company ID | |
name |
string | Legal name | |
cnpj |
string | Digits only | |
sector |
string \ | null | Industry sector |
tickers |
array | { id, idCompany, ticker, tickerClass } |
Use id for companyId filters on GET /v1/documents, or pass ticker/cnpj directly in document queries.
Example: resolve by ticker
export APICVM_KEY='apicvm_...'
export APICVM_URL='https://apicvm.dev'
curl -H "Authorization: Bearer $APICVM_KEY" \
"$APICVM_URL/v1/companies/resolve?query=PETR4&by=ticker"
Example: resolve by CNPJ
CNPJ works with or without punctuation:
curl -H "Authorization: Bearer $APICVM_KEY" \
"$APICVM_URL/v1/companies/resolve?query=60872504000123&by=cnpj"
Returns Itaú Unibanco Holding (ITUB4).
Example: Python with error handling
import os, requests
BASE = os.environ["APICVM_URL"]
H = {"Authorization": f"Bearer {os.environ['APICVM_KEY']}"}
def resolve(query: str, by: str = "auto") -> dict:
r = requests.get(
f"{BASE}/v1/companies/resolve",
headers=H,
params={"query": query, "by": by},
)
if r.status_code == 409:
candidates = r.json()["error"]["details"]["candidates"]
raise ValueError(f"Ambiguous: {len(candidates)} matches")
r.raise_for_status()
return r.json()
company = resolve("BBAS3", by="ticker")
print(company["name"], company["cnpj"])
Handling ambiguity (409)
When multiple companies match, the API returns 409 AMBIGUOUS_RESULT with details.candidates[]. It never silently picks one.
Common fixes:
- Use
by=tickerorby=cnpjfor unambiguous identifiers - Narrow a name query ("BANCO DO BRASIL" vs "BANCO")
- Present candidates to the user and retry with a specific CNPJ
After resolve: list documents
Once you have the company, list filings:
curl -H "Authorization: Bearer $APICVM_KEY" \
"$APICVM_URL/v1/documents?ticker=PETR4&type=DFP&year=2024&perPage=20"
Alternatively, filter by companyId from the resolve response.
List companies (browse mode)
To search or paginate the full universe, use GET /v1/companies with filters like search, ticker, cnpj, name, and status=ACTIVE. Resolve is for point lookups; list is for discovery.
Current limitations
- Resolve returns companies in the ingested corpus — not every B3-listed symbol may be present yet.
- Partial name matches can trigger ambiguity; prefer ticker or CNPJ in automated pipelines.
- Resolve does not return filing counts or document metadata — follow with
GET /v1/documents.
Next steps
Ready to integrate?
Get an API key and start querying Brazilian CVM filings programmatically.