> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lerian.studio/llms.txt
> Use this file to discover all available pages before exploring further.

# CADOC 4010 and 4016

> Generate CADOC 4010 and 4016 XML reports for BACEN with Reporter, following the COSIF standard and required regulatory layout.

Reporter lets you generate XML-based reports that follow the official CADOC structure, exactly as required by the Brazilian Central Bank (BACEN).

This guide walks you through the structure and logic used to generate **CADOC 4010** and **CADOC 4016** reports in XML.

<Danger>
  These reports follow the **COSIF** standard and must match the XML structure defined by BACEN. You can adapt the logic to your own data model, but the XML format must be respected.
</Danger>

## What are CADOC 4010 and 4016?

***

The **4010** and **4016** are Analytical Balance Sheet reports used to submit financial reports to the **BACEN** (Central Bank of Brazil).

### What BACEN expects to receive

* Closing balances by COSIF code
* Report base date (reference month)
* Institution's CNPJ (first 8 digits)
* Submission type (`I` = Inclusion, `S` = Replacement)

### Difference between CADOC 4010 and 4016

| Document | Periodicity          | Base Date | Expected Accounts                          |
| -------- | -------------------- | --------- | ------------------------------------------ |
| **4010** | Monthly              | YYYY-MM   | All accounts                               |
| **4016** | Semiannual (Jun/Dec) | YYYY-MM   | Without groups 7 and 8 (Revenues/Expenses) |

The **4016** represents the entity's accounting position after the income statement closing. At this point, Revenue accounts (group 7) and Expense accounts (group 8) have already been closed and their balances transferred to Equity.

### Submission requirements

| Document | Deadline                                                 | STA Code |
| -------- | -------------------------------------------------------- | -------- |
| **4010** | Day 18 of the following month (or the next business day) | ACOS010  |
| **4016** | Last business day of the following month                 | ACOS016  |

<Note>
  The STA code identifies the document type in BACEN’s transmission system. Use `ACOS010` when submitting CADOC 4010 and `ACOS016` when submitting CADOC 4016.
</Note>

## Understanding the data structure

***

### Operation routes

Operation routes work as accounting classifiers. Each route has:

* **Unique identifier (`id`)**: Used internally to relate operations
* **COSIF code (`code`)**: The 10-digit accounting code that will be reported to BACEN

Think of routes as "accounting labels" attached to each operation, indicating which chart of accounts item that movement should be classified under.

### Operations

Operations represent financial movements in the ledger. Each operation contains:

* **Associated account (`account_id`)**: Which account was moved
* **Route (`route`)**: ID of the applied accounting route/classification
* **Balance after operation (`available_balance_after`)**: The account balance immediately after this operation
* **Date and time (`created_at`)**: When the operation occurred

### Relationship between entities

<Frame>
  <img src="https://mintcdn.com/lerian-49cb71fc/AqrijvsB-h8cPNsi/images/en/docs/cadoc-4010-4016-structure.jpg?fit=max&auto=format&n=AqrijvsB-h8cPNsi&q=85&s=5fe2a223282357832afff4df430a803d" alt="" width="3770" height="1657" data-path="images/en/docs/cadoc-4010-4016-structure.jpg" />
</Frame>

<Info>
  The `balance` entity represents the **current** account balance, not the history. For regulatory reports that need balances from a specific period, use the `operation` entity with date filters.
</Info>

## CADOC structure

***

### Base format

The CADOC report **must** be an XML file and **must** follow the structure defined by **BACEN**:

<CodeGroup>
  ```xml XML theme={null}
  <?xml version="1.0" encoding="UTF-8"?>
  <documento codigoDocumento="4010" cnpj="99999999" dataBase="2025-11" tipoRemessa="I">
    <contas>
      <conta codigoConta="1000000009" saldo="99.99" />
      <conta codigoConta="1100000002" saldo="99.99" />
    </contas>
  </documento>
  ```
</CodeGroup>

### Mandatory fields

**`<?xml version="1.0" encoding="UTF-8"?>`**

Always starts the file. It defines the XML version and encoding so the system knows how to read the content.

**`<documento>` tag**

Wraps the entire CADOC structure and includes:

| Field             | Description            | Format               |
| ----------------- | ---------------------- | -------------------- |
| `codigoDocumento` | Fixed identifier       | `"4010"` or `"4016"` |
| `cnpj`            | First 8 digits of CNPJ | Numeric, 8 positions |
| `dataBase`        | Reference month        | YYYY-MM              |
| `tipoRemessa`     | Submission type        | `"I"` or `"S"`       |

<Danger>
  If your first submission was rejected due to errors, you still need to use `"I"` on your next attempt. Only use `"S"` for replacing previously approved data.
</Danger>

**`<contas>` tag**

Groups all account entries for the reporting period.

**`<conta>` tag**

* `codigoConta`: Account code, following COSIF format (10 numeric digits).
* `saldo`: Account balance in decimal format (two decimal places).

## Template construction logic

***

### General structure

The template follows a two-level aggregation logic:

1. **First level**: Iterate through all available operation routes
2. **Second level**: For each route, aggregate the balances of linked operations

### Iterating over routes

The template must iterate through all registered operation routes. For each route:

1. **Check if it has a COSIF code**: Only routes with a filled code generate lines
2. **Filter operations**: Select operations that belong to that route
3. **Calculate the balance**: Aggregate the balances of filtered operations

### Variable naming caution

When building the template, avoid using the same name for the iteration variable and the filter field:

| Approach      | Example                                       | Result          |
| ------------- | --------------------------------------------- | --------------- |
| **Incorrect** | `for route in ... if route == route.id`       | Name conflict   |
| **Correct**   | `for op_route in ... if route == op_route.id` | Works correctly |

## CADOC 4010 template

***

Here's the complete template for generating CADOC 4010 in Reporter:

<CodeGroup>
  ```xml tpl theme={null}
  <?xml version="1.0" encoding="UTF-8"?>
  <documento codigoDocumento="4010" cnpj="{{ midaz_onboarding.organization.0.legal_document|slice:':8' }}" dataBase="{% date_time 'YYYY-MM' %}" tipoRemessa="I">
    <contas>
  {%- for op_route in midaz_transaction.operation_route %}
  {%- if op_route.code %}
      <conta codigoConta="{{ op_route.code }}" saldo="{% sum_by midaz_transaction.operation by "available_balance_after" if route == op_route.id %}" />
  {%- endif %}
  {%- endfor %}
    </contas>
  </documento>
  ```
</CodeGroup>

### Line-by-line explanation

**Line 1 - XML declaration**

Standard XML header with UTF-8 encoding.

**Line 2 - Root element `<documento>`**

* `codigoDocumento="4010"`: Fixed identifier for the Analytical Balance Sheet
* `cnpj`: Extracts the first 8 digits from the organization's legal document
* `dataBase`: Generates the date in YYYY-MM format (reference month)
* `tipoRemessa="I"`: Indicates data inclusion

**Line 4 - Start of `for` loop**

* `op_route`: Variable that receives each route during iteration
* `midaz_transaction.operation_route`: Collection of all operation routes

**Line 5 - `if` condition**

Checks if the route has a filled COSIF code.

**Line 6 - `<conta>` element**

* `codigoConta`: Displays the current route's COSIF code
* `saldo`: Uses the `sum_by` tag to aggregate balances, filtering operations whose route matches the current route's identifier (`op_route.id`)

**Lines 7-8 - Block closing**

Close the condition and loop respectively.

### Tags and filters used

| Element                | Type       | Function                                      |
| ---------------------- | ---------- | --------------------------------------------- |
| `{{ variable }}`       | Expression | Displays a variable's value                   |
| `{% tag %}`            | Tag        | Executes logic (loop, condition, aggregation) |
| `\|slice:':8'`         | Filter     | Cuts the first 8 characters                   |
| `for ... in`           | Tag        | Iterates through a collection                 |
| `if`                   | Tag        | Condition for execution                       |
| `sum_by ... by ... if` | Tag        | Sums values with conditional filter           |
| `date_time`            | Tag        | Generates formatted date                      |

## CADOC 4016 template

***

The CADOC 4016 is the Analytical Balance Sheet, similar to 4010, but with semiannual periodicity and an important restriction: **it must not contain accounts from groups 7 (Revenues) and 8 (Expenses)**.

### Why exclude groups 7 and 8?

The 4016 document represents the entity's accounting position **after the income statement closing**. At this point, Revenue accounts (group 7) and Expense accounts (group 8) have already been closed and their balances transferred to Equity.

### Template example

<CodeGroup>
  ```xml tpl theme={null}
  <?xml version="1.0" encoding="UTF-8"?>
  <documento codigoDocumento="4016" cnpj="{{ midaz_onboarding.organization.0.legal_document|slice:':8' }}" dataBase="{% date_time 'YYYY-MM' %}" tipoRemessa="I">
    <contas>
  {%- for op_route in midaz_transaction.operation_route %}
  {%- if op_route.code and op_route.code|slice:":1" != "7" and op_route.code|slice:":1" != "8" %}
      <conta codigoConta="{{ op_route.code }}" saldo="{% sum_by midaz_transaction.operation by "available_balance_after" if route == op_route.id %}" />
  {%- endif %}
  {%- endfor %}
    </contas>
  </documento>
  ```
</CodeGroup>

### Difference from 4010

The only difference in the template is the additional condition in the `if`:

| Template | Condition                                                                                    |
| -------- | -------------------------------------------------------------------------------------------- |
| **4010** | `if op_route.code`                                                                           |
| **4016** | `if op_route.code and op_route.code\|slice:":1" != "7" and op_route.code\|slice:":1" != "8"` |

### How the exclusion works

The `slice:":1"` filter extracts the first character of the COSIF code:

| COSIF Code | First Digit | Group       | Included in 4016? |
| ---------- | ----------- | ----------- | ----------------- |
| 1000000009 | 1           | Assets      | Yes               |
| 2100000003 | 2           | Liabilities | Yes               |
| 7100000001 | 7           | Revenues    | **No**            |
| 8200000005 | 8           | Expenses    | **No**            |

## Generating the report with date filter

***

### Request example for 4010

To generate the CADOC 4010 for a specific month, send a `POST /v1/reports` request with the `X-Organization-Id` header and the following body:

<CodeGroup>
  ```json JSON theme={null}
  {
    "templateId": "CADOC_4010_TEMPLATE_ID",
    "filters": {
      "midaz_transaction": {
        "operation": {
          "created_at": {
            "between": ["2025-11-01T00:00:00Z", "2025-11-30T23:59:59Z"]
          }
        }
      }
    }
  }
  ```
</CodeGroup>

### Field explanation

| Field                                 | Description                                                       |
| ------------------------------------- | ----------------------------------------------------------------- |
| `templateId`                          | Identifier of the CADOC 4010 template registered in Reporter      |
| `filters.midaz_transaction.operation` | Indicates the filter will be applied to the operations collection |
| `created_at.between`                  | Filters operations created within the specified interval          |
| `between[0]`                          | First day of the month at 00:00:00 UTC                            |
| `between[1]`                          | Last day of the month at 23:59:59 UTC                             |

**Date format**: ISO 8601 with UTC timezone (`Z`).

<Warning>
  Adjust the last day according to the month (28, 29, 30, or 31 days).
</Warning>

### Request example for 4016

To generate the CADOC 4016 for the first semester:

<CodeGroup>
  ```json JSON theme={null}
  {
    "templateId": "CADOC_4016_TEMPLATE_ID",
    "filters": {
      "midaz_transaction": {
        "operation": {
          "created_at": {
            "between": ["2025-01-01T00:00:00Z", "2025-06-30T23:59:59Z"]
          }
        }
      }
    }
  }
  ```
</CodeGroup>

For the second semester, adjust the dates to July through December.

## Template evolution and balance extraction

***

We are working on evolving our main template to support balance aggregation in compliance with BACEN CADOC 4010/4016, which requires the final balance from the last business day of the month.

While this feature is being developed, we provide an alternative version for extracting these balances using the following template.

### Extraction template

This auxiliary template is designed to correctly calculate balances, ensuring compliance of your reports through the following steps:

1. Group operations by account
2. Sort entries by date and time
3. Select the last record from each account to obtain the final balance
4. Sum final balances by COSIF code

With this option, you can extract the information required for CADOC 4010/4016 and transfer it to the layout format required by BACEN. This template can help if you already have a provider that builds CADOC files.

### Extraction template example

<CodeGroup>
  ```xml tpl theme={null}
  account_id;account_alias;codigo_cosif;created_at;saldo_disponivel
  {%- for op_route in midaz_transaction.operation_route %}
  {%- if op_route.code %}
  {%- for op in filter(midaz_transaction.operation, "route", op_route.id) %}
  {{ op.account_id }};{{ op.account_alias }};{{ op_route.code }};{{ op.created_at }};{{ op.available_balance_after }}
  {%- endfor %}
  {%- endif %}
  {%- endfor %}
  ```
</CodeGroup>

### Extraction output

The template exports all operations in CSV format, containing:

* Account identifier
* Account alias
* COSIF code
* Operation date and time
* Available balance

You can import this CSV into a spreadsheet or your existing reconciliation system to process the final balances.

## Comparison with CADOC 4111

***

CADOC 4010 and CADOC 4111 share the same template structure, with differences only in the parameters:

| Aspect            | CADOC 4111      | CADOC 4010            |
| ----------------- | --------------- | --------------------- |
| Document          | Daily Balances  | Monthly Balance Sheet |
| Periodicity       | Daily           | Monthly               |
| `codigoDocumento` | `"4111"`        | `"4010"`              |
| `dataBase`        | YYYY-MM         | YYYY-MM               |
| Date filter       | 1 day           | 1 month               |
| Expected balance  | Last of the day | Last of the month     |

**Identical template**: The logic for iterating over routes and aggregating balances is the same.

## Best practices for building templates

***

### Variable naming

Use descriptive and unique names for iteration variables, avoiding conflicts with entity field names.

### Field validation

Always check if optional fields have values before using them. Empty fields can generate unwanted lines in the report.

### Date format

BACEN requires dates in YYYY-MM format for 4010. Make sure to configure the format correctly in the template.

### CNPJ handling

The CNPJ must be presented with only the first 8 digits, without formatting (dots, slashes, or dashes).

### COSIF account code

The COSIF chart of accounts is structured with 6 hierarchical levels and a check digit. The `codigoConta` field must have 10 numeric digits, without dots or dashes.

## Component summary

***

| Component  | Data Source                   | Usage in Template      |
| ---------- | ----------------------------- | ---------------------- |
| CNPJ       | Organization (Onboarding)     | Document header        |
| COSIF Code | Operation Route (Transaction) | Account identifier     |
| Balance    | Operation (Transaction)       | Value to be aggregated |
| Base Date  | Current date function         | Document header        |

<Warning>
  Always validate the rendered XML against BACEN's schema before submitting. The structure alone isn't enough — the data must reflect your institution's actual ledger.
</Warning>
