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 the CADOC 4111 report 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 is CADOC 4111?


The CADOC 4111 is a regulatory document required by the Brazilian Central Bank (BACEN) that reports daily balances of accounting accounts grouped by COSIF code (Chart of Accounts for Institutions of the National Financial System).

What BACEN expects to receive

  • Consolidated balances by COSIF code
  • Report base date
  • Institution’s CNPJ (first 8 digits)
  • Submission type (I = Inclusion, S = Replacement)

Submission requirements

DocumentDeadlineSTA Code
4111Day following the reference date (or next business day)ACOS011
The STA code identifies the document type in BACEN’s transmission system. Use ACOS011 when submitting CADOC 4111.

Understanding the data structure


Before building the template, it’s essential to understand how data is organized in the Midaz ledger.

Operation routes

Operation routes function 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
When an operation is recorded in Midaz, it’s associated with a route. This route carries the corresponding COSIF code.
Think of routes as “accounting labels” attached to each operation, indicating which chart of accounts category that movement should be classified under.

Operations

Operations represent financial movements in the ledger. Each operation contains:
  • Associated account (account_id): Which account was affected
  • 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
The balance after operation field represents the accumulated account balance at that moment, not the value of the operation itself.

Relationship between routes and operations

Each route can have multiple operations linked to it throughout the day.

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="4111" cnpj="99999999" dataBase="2025-11" tipoRemessa="I">
  <contas>
    <conta codigoConta="1000000009" saldoDia="99.99" />
    <conta codigoConta="1100000002" saldoDia="99.99" />
  </contas>
</documento>

Mandatory fields

These fields are required and must be included: <?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"4111"
cnpjFirst 8 digits of CNPJNumeric, 8 positions
dataBaseReference dateYYYY-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: COSIF code from the operation route (10 numeric digits)
  • saldoDia: Consolidated balance in decimal format (two decimal places)

Template construction logic


General structure

The template follows an aggregation logic at two levels:
  1. First level: Iterate through all available operation routes
  2. Second level: For each route, sum the balances of linked operations

Document header

The XML header must contain:
  • Document code: Fixed identifier 4111
  • CNPJ: Extracted from organization data, limited to first 8 digits
  • Base date: Report generation date in YYYY-MM format
  • Submission type: I for inclusion
Organization data is obtained from the Midaz onboarding data source, specifically from the organization entity.

Iterating over routes

The template must iterate through all registered operation routes. For each route:
  1. Check for COSIF code: Only routes with a valid COSIF code should generate lines in the report
  2. Filter operations: Select only operations belonging to that specific route
  3. Calculate balance: Sum the balances of filtered operations
Not all routes have a COSIF code filled in. Routes without a code are used for internal controls and should not appear in the regulatory report.

Filtering operations by route

The association between operations and routes is made through the route identifier. The template uses this identifier to:
  1. Access a specific route
  2. Find all operations that reference this route
  3. Process only these operations in the aggregation
When building the template, avoid using the same name for the iteration variable and the filter field, as this can cause conflicts in template interpretation.

Summing balances

For each set of operations from a route, the template sums the available balances. The field used is the available balance after each operation. The aggregation function iterates through all operations that meet the filter criteria (same route) and accumulates the balance field values.

Using Reporter


Here’s the complete template for generating CADOC 4111 in Reporter:
<?xml version="1.0" encoding="UTF-8"?>
<documento codigoDocumento="4111" 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 }}" saldoDia="{% sum_by midaz_transaction.operation by "available_balance_after" if route == op_route.id %}" />
{%- endif %}
{%- endfor %}
  </contas>
</documento>

Code breakdown


Line 1 - XML declaration

<?xml version="1.0" encoding="UTF-8"?>
Standard XML header with UTF-8 encoding.

Line 2 - Root element <documento>

<documento codigoDocumento="4111" cnpj="{{ midaz_onboarding.organization.0.legal_document|slice:":8" }}" dataBase="{% date_time "YYYY-MM" %}" tipoRemessa="I">
  • codigoDocumento="4111": Fixed document type identifier
  • cnpj: Accesses the organization’s legal document and extracts the first 8 characters using the slice filter
  • dataBase: Generates the current date in BACEN’s required format using the date_time tag
  • tipoRemessa="I": Indicates data inclusion

Line 4 - Start of for loop

{%- for op_route in midaz_transaction.operation_route %}
  • op_route: Variable that receives each route during iteration (name chosen to avoid conflict with the route field in operations)
  • midaz_transaction.operation_route: Collection of all operation routes

Line 5 - if condition

{%- if op_route.code %}
Checks if the route has a COSIF code filled in. Routes without a code are ignored.

Line 6 - <conta> element

<conta codigoConta="{{ op_route.code }}" saldoDia="{% sum_by midaz_transaction.operation by "available_balance_after" if route == op_route.id %}" />
  • codigoConta: Displays the current route’s COSIF code
  • saldoDia: Uses the sum_by tag to sum balances, filtering only operations whose route matches the current route identifier (op_route.id)

Lines 7-8 - Closing blocks

{%- endif %}
{%- endfor %}
Close the condition and loop respectively.

Tags and filters reference

ElementTypeFunction
{{ variable }}ExpressionDisplays a variable’s value
{% tag %}TagExecutes logic (loop, condition, aggregation)
|slice:":8"FilterExtracts the first 8 characters
for ... inTagIterates through a collection
ifTagExecution condition
sum_by ... by ... ifTagSums values with conditional filter
date_timeTagGenerates formatted date

Date filter considerations


Request example with date filter

To generate CADOC 4111 for a specific day, send a POST /v1/reports request with the X-Organization-Id header and the following body:
{
  "templateId": "CADOC_4111_TEMPLATE_ID",
  "filters": {
    "midaz_transaction": {
      "operation": {
        "created_at": {
          "between": ["2025-11-11T00:00:00Z", "2025-11-11T23:59:59Z"]
        }
      }
    }
  }
}

Field explanation

FieldDescription
templateIdCADOC 4111 template identifier 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]Start date and time (midnight of desired day)
between[1]End date and time (last second of desired day)
Dates must be in ISO 8601 format with UTC timezone (Z).

Template evolution and balance extraction


We are working on evolving our main template to support balance aggregation in compliance with BACEN CADOC 4111, which requires the final balance from the last business day. 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 4111 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.

Best practices for template construction


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. 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).

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.