> ## Documentation Index
> Fetch the complete documentation index at: https://octo-98895abd.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Reading a fundamental

> A listed company's financial statements end to end — and the two conventions that will silently corrupt your numbers.

### Overview

From a ticker to a clean revenue series, stopping at the two places where a reasonable assumption produces a wrong answer that looks right.

<Warning>
  **Read step 3 before you sum anything.** A quarterly filing prints the same account twice under one reference date — once for the quarter, once year-to-date. Nothing about the row shape tells you which is which except `period_months`.
</Warning>

### 1. Resolve the company

```bash theme={null}
curl -s -X POST "$SILO_URL/rpc/lookup" \
  -H "apikey: $SILO_ANON_KEY" -H "Content-Type: application/json" \
  -d '{"p_query": "PETR4"}'
```

Company rows carry their B3 `tickers` from CVM's **published** FCA map. There is no derived ticker-to-CNPJ join anywhere — the mapping is either published or absent.

Both financial endpoints accept a ticker, a CNPJ or a CVM code as `p_id`.

### 2. Start with the summary

`company_financials` is the pre-computed headline: one row per filing.

```bash theme={null}
curl -s -X POST "$SILO_URL/rpc/company_financials" \
  -H "apikey: $SILO_ANON_KEY" -H "Content-Type: application/json" \
  -d '{"p_id": "PETR4", "p_from": "2021-01-01", "p_scope": "con"}'
```

Returns `revenue`, `gross_profit`, `net_income`, `total_assets`, `equity`, `net_margin_pct` and `roe_pct`, alongside `doc_type`, `scope`, `ref_date`, `period_start`, `period_end`, `period_months`, `version`, `setor` and `segmento`.

<Note>
  **Banks file a different chart of accounts — but `3.11` is still net income.** What differs is what each code *means*. For Banco do Brasil (`cd_cvm` 1023, FY2024 consolidated), `3.01` is `Receitas de Intermediação Financeira` rather than `Receita de Venda de Bens e/ou Serviços`, and `3.05` is already `Resultado antes dos Tributos sobre o Lucro` rather than EBIT. Net income is `3.11` just as it is for an industrial filer; `3.09` is profit *before* the statutory profit-sharing on `3.10`, so the two agree only where `3.10` is zero — as it happens to be there.

  `company_financials` resolves `net_income` from the filed net-income label (catalog v36), so it lands on `3.11`, `3.09` or `3.13` depending on the chart, and never substitutes one code for another. If you pull raw accounts in step 3, read the `account_name` filed alongside the code rather than assuming a code carries the same concept across charts, and use `setor` (on every row) as the partition key for any peer median or rank.
</Note>

If the summary answers your question, stop here.

### 3. The raw statements — and `period_months`

```bash theme={null}
curl -s -X POST "$SILO_URL/rpc/financials" \
  -H "apikey: $SILO_ANON_KEY" -H "Content-Type: application/json" \
  -d '{"p_id": "PETR4", "p_statement": "DRE", "p_from": "2024-01-01", "p_scope": "con"}'
```

`p_statement` selects the statement group — `DRE`, `BPA`, `BPP`, and the others as filed. Omit it for all.

An ITR prints each account **twice** under one `ref_date`:

| `ref_date` | `account_code` | `period_start` | `period_end` | `period_months` | `value` |
| - | - | - | - | - | - |
| 2024-09-30 | 3.01 | 2024-07-01 | 2024-09-30 | **3** | Q3 alone |
| 2024-09-30 | 3.01 | 2024-01-01 | 2024-09-30 | **9** | year to date |

The rows differ **only** by their period span, which is why the span is published rather than collapsed — either choice is wrong for somebody.

**Always filter on `period_months` before aggregating.**

```python theme={null}
q   = [r for r in rows if r["period_months"] == 3]   # discrete quarters
ytd = [r for r in rows if r["period_months"] == 9]   # cumulative
```

### 4. Consolidated or individual

`p_scope` is `con` by default; `ind` is the parent company alone. For a group with subsidiaries they are different companies in every meaningful sense.

Do not compare across scopes, and do not switch scope mid-series — a break there looks exactly like a business event.

### 5. Restatements

A re-filed statement is submitted under a higher `versao`. **Only the newest version of each statement is served**, so you never see one quarter twice with two different numbers.

`version` is published anyway, so you can see a restatement happened. In `company_financials`, balance-sheet rows are joined on the *same* document version — a restatement never mixes old assets with new equity.

### 6. Comparatives are excluded

Each filing prints the prior-year figure beside the current one. The API serves only the period the document is **for** (CVM's `ÚLTIMO`), never the comparative (`PENÚLTIMO`). To read an earlier period, pull the earlier document.

### 7. Windows

`financials` **refuses** rather than truncates: a window over 1,000 rows raises `22023`. It offers no cursor on purpose — a statement has tens of rows, so a window that wide is a mistake rather than a walk.

Narrow `p_from`/`p_to`, or pin `p_statement`. A full DRE for one company across five years is comfortable; every statement for five years is not.

**Note**: `coverage()` reports `financials` with a `complete_through` of `null` on purpose — the completeness model describes fund filing cadence and says nothing about companies.

### Putting it on one axis

Once you have a clean series, `panel` aligns it with market data in the same long `(id, date, metric, value)` shape. See [your first screen](/api-docs/guides/first-screen).

### Next

<CardGroup cols={2}>
  <Card title="Financials reference" icon="table-list" href="/api-docs/financials">
    Every column, every statement group.
  </Card>

  <Card title="Paging without losing rows" icon="list-ol" href="/api-docs/guides/pagination">
    What to do when `financials` refuses your window.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.