Skip to main content
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.
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.

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

DocumentPeriodicityBase DateExpected Accounts
4010MonthlyYYYY-MMAll accounts
4016Semiannual (Jun/Dec)YYYY-MMWithout 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

DocumentDeadlineSTA Code
4010Day 18 of the following month (or the next business day)ACOS010
4016Last business day of the following monthACOS016
The STA code identifies the document type in BACEN’s transmission system. Use ACOS010 when submitting CADOC 4010 and ACOS016 when submitting CADOC 4016.

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

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.

CADOC structure


Base format

The CADOC report must be an XML file and must follow the structure defined by BACEN:
<?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>

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:
FieldDescriptionFormat
codigoDocumentoFixed identifier"4010" or "4016"
cnpjFirst 8 digits of CNPJNumeric, 8 positions
dataBaseReference monthYYYY-MM
tipoRemessaSubmission type"I" or "S"
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.
<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:
ApproachExampleResult
Incorrectfor route in ... if route == route.idName conflict
Correctfor op_route in ... if route == op_route.idWorks correctly

CADOC 4010 template


Here’s the complete template for generating CADOC 4010 in Reporter:
<?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>

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

ElementTypeFunction
{{ variable }}ExpressionDisplays a variable’s value
{% tag %}TagExecutes logic (loop, condition, aggregation)
|slice:':8'FilterCuts the first 8 characters
for ... inTagIterates through a collection
ifTagCondition for execution
sum_by ... by ... ifTagSums values with conditional filter
date_timeTagGenerates 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

<?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>

Difference from 4010

The only difference in the template is the additional condition in the if:
TemplateCondition
4010if op_route.code
4016if 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 CodeFirst DigitGroupIncluded in 4016?
10000000091AssetsYes
21000000032LiabilitiesYes
71000000017RevenuesNo
82000000058ExpensesNo

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:
{
  "templateId": "CADOC_4010_TEMPLATE_ID",
  "filters": {
    "midaz_transaction": {
      "operation": {
        "created_at": {
          "between": ["2025-11-01T00:00:00Z", "2025-11-30T23:59:59Z"]
        }
      }
    }
  }
}

Field explanation

FieldDescription
templateIdIdentifier of the CADOC 4010 template registered in Reporter
filters.midaz_transaction.operationIndicates the filter will be applied to the operations collection
created_at.betweenFilters 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).
Adjust the last day according to the month (28, 29, 30, or 31 days).

Request example for 4016

To generate the CADOC 4016 for the first semester:
{
  "templateId": "CADOC_4016_TEMPLATE_ID",
  "filters": {
    "midaz_transaction": {
      "operation": {
        "created_at": {
          "between": ["2025-01-01T00:00:00Z", "2025-06-30T23:59:59Z"]
        }
      }
    }
  }
}
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

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 %}

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:
AspectCADOC 4111CADOC 4010
DocumentDaily BalancesMonthly Balance Sheet
PeriodicityDailyMonthly
codigoDocumento"4111""4010"
dataBaseYYYY-MMYYYY-MM
Date filter1 day1 month
Expected balanceLast of the dayLast 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


ComponentData SourceUsage in Template
CNPJOrganization (Onboarding)Document header
COSIF CodeOperation Route (Transaction)Account identifier
BalanceOperation (Transaction)Value to be aggregated
Base DateCurrent date functionDocument header
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.