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.
Reporter lets you generate XML-based reports that follow the official APIX structure, as required by the Brazilian Central Bank (BACEN).
This guide walks you through the structure and logic used to generate the APIX 001 report (Document 1201) in XML.
APIX 001 reports must strictly follow the XSD schema defined by BACEN (version 2.5). Reporter automates the XML generation, but you remain responsible for validating the output and ensuring compliance with regulatory requirements.
What is APIX 001?
The APIX 001 is a monthly regulatory report that Pix participants — direct or indirect — must submit to the Brazilian Central Bank. It consolidates operational statistics for the institution’s Pix ecosystem during a given month.
What BACEN expects to receive
The report covers ten data sections:
| Section | Description |
|---|
| Transacoes | Transaction volumes and values, broken down by detail type and purpose |
| Devolucoes | Refund volumes and values (MED and other reasons) |
| BloqueiosCautelares | Cautionary block counts and values |
| Receitas | Revenue from Pix operations by source and person type |
| TemposTransacoes | Transaction processing time percentiles (P50, P99) |
| TemposDict | DICT operation time percentiles (queries, registrations, portability) |
| ConsultasDict | Total DICT queries in the period |
| Disponibilidade | System availability index (percentage) |
| TempoAutorizacoes | Authorization processing time (P95) |
| Autorizacoes | Pix Automático authorization counts and stock by payer type |
Submission requirements
| Document | Frequency | Deadline | Reference |
|---|
| APIX 001 | Monthly | 15th business day of the following month | Document 1201, XSD version 2.5 |
The root <APIX001> element requires these attributes:
| Attribute | Description | Format |
|---|
DtArquivo | File generation date | YYYY-MM-DD |
Ano | Reference year | YYYY |
Mes | Reference month | 1–12 |
ISPB | Institution’s ISPB code (first 8 digits of CNPJ) | 8 numeric digits |
NomeResp | Responsible person’s name | Text (max 200 chars) |
EmailResp | Responsible person’s email | Valid email |
TelResp | Responsible person’s phone | Text (max 14 chars) |
TipoEnvio | Submission type | I (Inclusion) or S (Replacement) |
Understanding the data structure
Before building the template, it’s important to understand how the Pix plugin data maps to each APIX 001 section.
Pix plugin data sources
The template queries data from the Pix plugin tables registered as Reporter data sources. The main entities used are:
| Data Source | Table | Content |
|---|
payment.transfers | Pix transfers | Transaction records with status, amount, type, and fees |
payment.refunds | Pix refunds | Refund records with status, amount, and reason code |
dict.entries | DICT entries | Pix key registrations |
The Pix plugin does not currently track DICT query events. The dict.entries table stores key registrations, not consultations. For ConsultasDict, source this metric from your infrastructure monitoring or API gateway logs. The template placeholder is included for structural reference only.
| dict.claims | DICT claims | Portability and ownership claims |
The data source prefix (e.g. pix_btg) depends on how you register the Pix plugin in Reporter. Replace it with your actual data source name.
Transfers table structure
| Field | Type | Description |
|---|
id | UUID | Unique transfer identifier |
status | String | Transaction status: COMPLETED, REJECTED, PENDING |
amount | Decimal | Transaction value in BRL |
transfer_type | String | CASHIN (receiving) or CASHOUT (sending) |
destination_person_type | String | NATURAL_PERSON or LEGAL_PERSON |
fee_charge | JSONB | Fee structure (populated only for CASHIN transactions) |
failed_reason | String | Rejection reason code (when status is REJECTED) |
created_at | Timestamp | Creation date and time |
Refunds table structure
| Field | Type | Description |
|---|
id | UUID | Unique refund identifier |
status | String | Refund status: COMPLETED, PENDING |
amount | Decimal | Refund value in BRL |
reason | String | Reason code: FR01, BE08, MD06, SL02 |
created_at | Timestamp | Creation date and time |
Refund reason codes
| Code | Meaning | APIX detail type |
|---|
FR01 | Fraud (MED — Mecanismo Especial de Devolução) | 1 |
BE08 | Bank error | 2 |
MD06 | Customer request | 2 |
SL02 | Creditor-specific service (Pix Saque/Troco) | 2 |
Fee charge structure (JSONB)
The fee_charge field is a JSONB column populated only for CASHIN (receiving) transactions:
{
"applied": true,
"calculationType": "FIXED",
"totalAmount": "1.50",
"netAmount": "98.50",
"fees": [
{
"type": "TRANSACTION_FEE",
"amount": "1.50"
}
]
}
CASHOUT transactions do not have fee charges in the current product model. Revenue from CASHOUT sources should be reported as zero unless your implementation charges fees on outgoing transfers.
Data mapping
Transaction detail types
| Code | Description | Mapping |
|---|
| 5 | Indirect participant (settled via direct participant) | All completed transactions via the settlement partner |
| 6 | Direct participant (own settlement) | Zero for indirect participants |
| 7 | Rejected due to fraud indication | Transactions with status == "REJECTED" filtered by fraud-indication reason (see warning below) |
Detail type 7 should only count rejections due to fraud indication — not all rejected transactions. The current template uses status == "REJECTED" as a simplified filter. In production, cross-reference with dict.infraction_reports (filtering by fraud-related situation_type) or apply specific failed_reason codes. Validate this logic with your engineering team before submitting to BACEN.
Transaction purposes
| Code | Description | Mapping |
|---|
| 1 | Transfer / Purchase | Completed transactions (status == "COMPLETED") |
| 2 | Pix Saque | Zero if not implemented |
| 3 | Pix Troco | Zero if not implemented |
| 4 | Pix Automático | Zero if not implemented |
The report requires exactly 12 transaction entries — one for each combination of 3 detail types × 4 purposes. Entries with no matching data must still be present with zero values.
Revenue sources
| Source | Description | Mapping |
|---|
| 1 | Initiation by legal person (CASHOUT) | fee_charge.totalAmount from CASHOUT + LEGAL_PERSON |
| 2 | Receiving by legal person (CASHIN) | fee_charge.totalAmount from CASHIN + LEGAL_PERSON |
| 3 | Receiving by natural person (CASHIN) | fee_charge.totalAmount from CASHIN + NATURAL_PERSON |
| 4 | Initiation by natural person (CASHOUT) | fee_charge.totalAmount from CASHOUT + NATURAL_PERSON |
Refund detail types
| Code | Description | Mapping |
|---|
| 1 | Fraud refund (MED) | reason == "FR01" |
| 2 | Other reasons | reason != "FR01" (BE08, MD06, SL02) |
Cautionary block detail types
| Code | Description |
|---|
| 1 | Requested |
| 2 | Received |
| 3 | Canceled by requester |
| 4 | Canceled by recipient |
Authorization payer types (Pix Automático)
| Code | Description |
|---|
| 1 | Natural person |
| 2 | Legal person |
Using Reporter
Here is the complete template for generating APIX 001 in Reporter. This example uses pix_btg as the data source prefix — replace it with the name configured in your Reporter data source setup.
<?xml version="1.0" encoding="UTF-8"?>
<APIX001 DtArquivo="{% date_time 'YYYY-MM-dd' %}"
Ano="{{ report_params.year }}"
Mes="{{ report_params.month }}"
ISPB="{{ midaz_onboarding.organization.0.legal_document|slice:':8' }}"
NomeResp="{{ report_params.responsible_name }}"
EmailResp="{{ report_params.responsible_email }}"
TelResp="{{ report_params.responsible_phone }}"
TipoEnvio="I">
<Transacoes>
<!-- Detail 5: Indirect participant — Purpose 1: Transfer/Purchase -->
<Transacao>
<QtdTransacoes>{% count_by pix_btg:payment.transfers if status == "COMPLETED" %}</QtdTransacoes>
<ValorTransacoes>{% sum_by pix_btg:payment.transfers by "amount" if status == "COMPLETED" %}</ValorTransacoes>
<ValorEspecie>0.00</ValorEspecie>
<DetalhamentoTransacoes>5</DetalhamentoTransacoes>
<FinalidadeTransacoes>1</FinalidadeTransacoes>
</Transacao>
<!-- Detail 5 — Purpose 2: Pix Saque -->
<Transacao>
<QtdTransacoes>0</QtdTransacoes>
<ValorTransacoes>0.00</ValorTransacoes>
<ValorEspecie>0.00</ValorEspecie>
<DetalhamentoTransacoes>5</DetalhamentoTransacoes>
<FinalidadeTransacoes>2</FinalidadeTransacoes>
</Transacao>
<!-- Detail 5 — Purpose 3: Pix Troco -->
<Transacao>
<QtdTransacoes>0</QtdTransacoes>
<ValorTransacoes>0.00</ValorTransacoes>
<ValorEspecie>0.00</ValorEspecie>
<DetalhamentoTransacoes>5</DetalhamentoTransacoes>
<FinalidadeTransacoes>3</FinalidadeTransacoes>
</Transacao>
<!-- Detail 5 — Purpose 4: Pix Automático -->
<Transacao>
<QtdTransacoes>0</QtdTransacoes>
<ValorTransacoes>0.00</ValorTransacoes>
<ValorEspecie>0.00</ValorEspecie>
<DetalhamentoTransacoes>5</DetalhamentoTransacoes>
<FinalidadeTransacoes>4</FinalidadeTransacoes>
</Transacao>
<!-- Detail 6: Direct participant (own settlement) -->
<!-- Zero for indirect participants — no transactions settled directly -->
<Transacao>
<QtdTransacoes>0</QtdTransacoes>
<ValorTransacoes>0.00</ValorTransacoes>
<ValorEspecie>0.00</ValorEspecie>
<DetalhamentoTransacoes>6</DetalhamentoTransacoes>
<FinalidadeTransacoes>1</FinalidadeTransacoes>
</Transacao>
<Transacao>
<QtdTransacoes>0</QtdTransacoes>
<ValorTransacoes>0.00</ValorTransacoes>
<ValorEspecie>0.00</ValorEspecie>
<DetalhamentoTransacoes>6</DetalhamentoTransacoes>
<FinalidadeTransacoes>2</FinalidadeTransacoes>
</Transacao>
<Transacao>
<QtdTransacoes>0</QtdTransacoes>
<ValorTransacoes>0.00</ValorTransacoes>
<ValorEspecie>0.00</ValorEspecie>
<DetalhamentoTransacoes>6</DetalhamentoTransacoes>
<FinalidadeTransacoes>3</FinalidadeTransacoes>
</Transacao>
<Transacao>
<QtdTransacoes>0</QtdTransacoes>
<ValorTransacoes>0.00</ValorTransacoes>
<ValorEspecie>0.00</ValorEspecie>
<DetalhamentoTransacoes>6</DetalhamentoTransacoes>
<FinalidadeTransacoes>4</FinalidadeTransacoes>
</Transacao>
<!-- Detail 7: Rejected due to fraud indication -->
<Transacao>
<QtdTransacoes>{% count_by pix_btg:payment.transfers if status == "REJECTED" %}</QtdTransacoes>
<ValorTransacoes>{% sum_by pix_btg:payment.transfers by "amount" if status == "REJECTED" %}</ValorTransacoes>
<ValorEspecie>0.00</ValorEspecie>
<DetalhamentoTransacoes>7</DetalhamentoTransacoes>
<FinalidadeTransacoes>1</FinalidadeTransacoes>
</Transacao>
<Transacao>
<QtdTransacoes>0</QtdTransacoes>
<ValorTransacoes>0.00</ValorTransacoes>
<ValorEspecie>0.00</ValorEspecie>
<DetalhamentoTransacoes>7</DetalhamentoTransacoes>
<FinalidadeTransacoes>2</FinalidadeTransacoes>
</Transacao>
<Transacao>
<QtdTransacoes>0</QtdTransacoes>
<ValorTransacoes>0.00</ValorTransacoes>
<ValorEspecie>0.00</ValorEspecie>
<DetalhamentoTransacoes>7</DetalhamentoTransacoes>
<FinalidadeTransacoes>3</FinalidadeTransacoes>
</Transacao>
<Transacao>
<QtdTransacoes>0</QtdTransacoes>
<ValorTransacoes>0.00</ValorTransacoes>
<ValorEspecie>0.00</ValorEspecie>
<DetalhamentoTransacoes>7</DetalhamentoTransacoes>
<FinalidadeTransacoes>4</FinalidadeTransacoes>
</Transacao>
</Transacoes>
<Devolucoes>
<!-- Detail 1: Fraud refund (MED) — reason FR01 -->
<Devolucao>
<QtdDevolucoes>{% count_by pix_btg:payment.refunds if status == "COMPLETED" and reason == "FR01" %}</QtdDevolucoes>
<ValorDevolucoes>{% sum_by pix_btg:payment.refunds by "amount" if status == "COMPLETED" and reason == "FR01" %}</ValorDevolucoes>
<DetalhamentoDevolucoes>1</DetalhamentoDevolucoes>
</Devolucao>
<!-- Detail 2: Other refund reasons (BE08, MD06, SL02) -->
<Devolucao>
<QtdDevolucoes>{% count_by pix_btg:payment.refunds if status == "COMPLETED" and reason != "FR01" %}</QtdDevolucoes>
<ValorDevolucoes>{% sum_by pix_btg:payment.refunds by "amount" if status == "COMPLETED" and reason != "FR01" %}</ValorDevolucoes>
<DetalhamentoDevolucoes>2</DetalhamentoDevolucoes>
</Devolucao>
</Devolucoes>
<BloqueiosCautelares>
<!-- Cautionary blocks — report zeros when entity is not implemented -->
<BloqueioCautelar>
<QtdeBloqCaut>0</QtdeBloqCaut>
<ValorBloqCaut>0.00</ValorBloqCaut>
<DetalhamentoTransacoesBloqCaut>1</DetalhamentoTransacoesBloqCaut>
</BloqueioCautelar>
<BloqueioCautelar>
<QtdeBloqCaut>0</QtdeBloqCaut>
<ValorBloqCaut>0.00</ValorBloqCaut>
<DetalhamentoTransacoesBloqCaut>2</DetalhamentoTransacoesBloqCaut>
</BloqueioCautelar>
<BloqueioCautelar>
<QtdeBloqCaut>0</QtdeBloqCaut>
<ValorBloqCaut>0.00</ValorBloqCaut>
<DetalhamentoTransacoesBloqCaut>3</DetalhamentoTransacoesBloqCaut>
</BloqueioCautelar>
<BloqueioCautelar>
<QtdeBloqCaut>0</QtdeBloqCaut>
<ValorBloqCaut>0.00</ValorBloqCaut>
<DetalhamentoTransacoesBloqCaut>4</DetalhamentoTransacoesBloqCaut>
</BloqueioCautelar>
</BloqueiosCautelares>
<Receitas>
<!-- Source 1: Initiation by legal person (CASHOUT) -->
<Receita>
<ValorReceita>0.00</ValorReceita>
<FonteReceita>1</FonteReceita>
</Receita>
<!-- Source 2: Receiving by legal person (CASHIN) -->
<Receita>
<ValorReceita>{% sum_by pix_btg:payment.transfers by "fee_charge.totalAmount" if transfer_type == "CASHIN" and destination_person_type == "LEGAL_PERSON" and status == "COMPLETED" %}</ValorReceita>
<FonteReceita>2</FonteReceita>
</Receita>
<!-- Source 3: Receiving by natural person (CASHIN) -->
<Receita>
<ValorReceita>{% sum_by pix_btg:payment.transfers by "fee_charge.totalAmount" if transfer_type == "CASHIN" and destination_person_type == "NATURAL_PERSON" and status == "COMPLETED" %}</ValorReceita>
<FonteReceita>3</FonteReceita>
</Receita>
<!-- Source 4: Initiation by natural person (CASHOUT) -->
<Receita>
<ValorReceita>0.00</ValorReceita>
<FonteReceita>4</FonteReceita>
</Receita>
</Receitas>
<!-- Time metrics — must be sourced from your SPI/infrastructure monitoring -->
<TemposTransacoes
Perc50TempoExpUsuarioLiqSPI="0.00"
Perc99TempoExpUsuarioLiqSPI="0.00"
Perc50TempoExpUsuarioLiqForaSPI="0.00"
Perc99TempoExpUsuarioLiqForaSPI="0.00"
TempoMaxBloqueioCautelar="0.00" />
<TemposDict
Perc99TempoUsuarioConsulta="0.00"
PercTempoEnvioRegistro="0.00"
PercTempoExpUsuarioRegistro="0.00"
PercTempoExpUsuarioExclusao="0.00"
PercTempoNotificacaoPortabilidade="0.00"
PercTempoEnvioPortabilidade="0.00"
PercTempoAberturaMED="0.00" />
<ConsultasDict QtdConsultas="{% count_by pix_btg:dict.entries %}" />
<!--
WARNING: dict.entries stores Pix key registrations, not DICT query events.
Replace with your actual DICT query log data source or populate manually
from infrastructure metrics.
-->
<Disponibilidade IndiceDisponibilidade="0.00" />
<TempoAutorizacoes Perc95TempoAutorizacao="0.00" />
<Autorizacoes>
<!-- Pix Automático — report zeros when not implemented -->
<Autorizacao>
<QtdAutorizacoes>0</QtdAutorizacoes>
<QtdEstoqueAutorizacoes>0</QtdEstoqueAutorizacoes>
<TipoPagador>1</TipoPagador>
</Autorizacao>
<Autorizacao>
<QtdAutorizacoes>0</QtdAutorizacoes>
<QtdEstoqueAutorizacoes>0</QtdEstoqueAutorizacoes>
<TipoPagador>2</TipoPagador>
</Autorizacao>
</Autorizacoes>
</APIX001>
Code breakdown
Root element
<APIX001 DtArquivo="{% date_time 'YYYY-MM-dd' %}"
Ano="{{ report_params.year }}"
Mes="{{ report_params.month }}"
ISPB="{{ midaz_onboarding.organization.0.legal_document|slice:':8' }}"
...
TipoEnvio="I">
DtArquivo: File generation date, dynamically inserted via date_time
Ano and Mes: Reference year and month, passed as report parameters
ISPB: First 8 digits of the institution’s CNPJ, extracted using the slice filter from Midaz onboarding data
TipoEnvio: I for inclusion, S for replacement of previously approved data
Transactions section
The template explicitly declares all 12 required entries (3 detail types × 4 purposes). Dynamic queries are used where data exists:
<!-- Detail 5: Indirect participant — Purpose 1: Transfer/Purchase -->
<Transacao>
<QtdTransacoes>{% count_by pix_btg:payment.transfers if status == "COMPLETED" %}</QtdTransacoes>
<ValorTransacoes>{% sum_by pix_btg:payment.transfers by "amount" if status == "COMPLETED" %}</ValorTransacoes>
<ValorEspecie>0.00</ValorEspecie>
<DetalhamentoTransacoes>5</DetalhamentoTransacoes>
<FinalidadeTransacoes>1</FinalidadeTransacoes>
</Transacao>
count_by counts records matching the filter condition
sum_by ... by "field" sums a specific field across matching records
ValorEspecie is 0.00 for standard transfers (only non-zero for Pix Saque/Troco)
Entries for purposes 2, 3, and 4 (Pix Saque, Troco, Automático) use hardcoded zeros when those features are not implemented. Detail type 6 (direct participant settlement) also uses zeros for indirect participants.
Refunds section
Refunds are split by reason code using the reason field:
<!-- Detail 1: Fraud refund (MED) -->
<Devolucao>
<QtdDevolucoes>{% count_by pix_btg:payment.refunds if status == "COMPLETED" and reason == "FR01" %}</QtdDevolucoes>
<ValorDevolucoes>{% sum_by pix_btg:payment.refunds by "amount" if status == "COMPLETED" and reason == "FR01" %}</ValorDevolucoes>
<DetalhamentoDevolucoes>1</DetalhamentoDevolucoes>
</Devolucao>
<!-- Detail 2: Other reasons (BE08, MD06, SL02) -->
<Devolucao>
<QtdDevolucoes>{% count_by pix_btg:payment.refunds if status == "COMPLETED" and reason != "FR01" %}</QtdDevolucoes>
<ValorDevolucoes>{% sum_by pix_btg:payment.refunds by "amount" if status == "COMPLETED" and reason != "FR01" %}</ValorDevolucoes>
<DetalhamentoDevolucoes>2</DetalhamentoDevolucoes>
</Devolucao>
FR01 maps to BACEN detail type 1 (fraud via MED)
- All other reason codes (
BE08, MD06, SL02) map to detail type 2
Revenue section
Revenue is extracted from the fee_charge.totalAmount JSONB field, filtered by transfer type and person type:
<!-- Source 2: Receiving by legal person (CASHIN) -->
<Receita>
<ValorReceita>{% sum_by pix_btg:payment.transfers by "fee_charge.totalAmount" if transfer_type == "CASHIN" and destination_person_type == "LEGAL_PERSON" and status == "COMPLETED" %}</ValorReceita>
<FonteReceita>2</FonteReceita>
</Receita>
The fee_charge JSONB field uses nested field path syntax (fee_charge.totalAmount). Reporter’s Pongo2 engine navigates the JSON structure to access the nested value.
Time metrics and availability
Time metrics (transaction processing times, DICT operation times) and availability index must be sourced from your infrastructure monitoring system — they are not derived from transactional data. Populate these values from your SPI logs and uptime monitoring.
DICT queries
<ConsultasDict QtdConsultas="{% count_by pix_btg:dict.entries %}" />
This placeholder counts DICT entries (key registrations) as a structural reference. In production, replace dict.entries with your actual DICT query log data source or populate QtdConsultas manually from infrastructure metrics.
Rendered example
<?xml version="1.0" encoding="UTF-8"?>
<APIX001 DtArquivo="2026-04-15"
Ano="2026"
Mes="3"
ISPB="12345678"
NomeResp="João Silva"
EmailResp="joao.silva@institution.com.br"
TelResp="11999998888"
TipoEnvio="I">
<Transacoes>
<Transacao>
<QtdTransacoes>150000</QtdTransacoes>
<ValorTransacoes>75000000.00</ValorTransacoes>
<ValorEspecie>0.00</ValorEspecie>
<DetalhamentoTransacoes>5</DetalhamentoTransacoes>
<FinalidadeTransacoes>1</FinalidadeTransacoes>
</Transacao>
<Transacao>
<QtdTransacoes>0</QtdTransacoes>
<ValorTransacoes>0.00</ValorTransacoes>
<ValorEspecie>0.00</ValorEspecie>
<DetalhamentoTransacoes>5</DetalhamentoTransacoes>
<FinalidadeTransacoes>2</FinalidadeTransacoes>
</Transacao>
<Transacao>
<QtdTransacoes>0</QtdTransacoes>
<ValorTransacoes>0.00</ValorTransacoes>
<ValorEspecie>0.00</ValorEspecie>
<DetalhamentoTransacoes>5</DetalhamentoTransacoes>
<FinalidadeTransacoes>3</FinalidadeTransacoes>
</Transacao>
<Transacao>
<QtdTransacoes>0</QtdTransacoes>
<ValorTransacoes>0.00</ValorTransacoes>
<ValorEspecie>0.00</ValorEspecie>
<DetalhamentoTransacoes>5</DetalhamentoTransacoes>
<FinalidadeTransacoes>4</FinalidadeTransacoes>
</Transacao>
<Transacao>
<QtdTransacoes>0</QtdTransacoes>
<ValorTransacoes>0.00</ValorTransacoes>
<ValorEspecie>0.00</ValorEspecie>
<DetalhamentoTransacoes>6</DetalhamentoTransacoes>
<FinalidadeTransacoes>1</FinalidadeTransacoes>
</Transacao>
<Transacao>
<QtdTransacoes>0</QtdTransacoes>
<ValorTransacoes>0.00</ValorTransacoes>
<ValorEspecie>0.00</ValorEspecie>
<DetalhamentoTransacoes>6</DetalhamentoTransacoes>
<FinalidadeTransacoes>2</FinalidadeTransacoes>
</Transacao>
<Transacao>
<QtdTransacoes>0</QtdTransacoes>
<ValorTransacoes>0.00</ValorTransacoes>
<ValorEspecie>0.00</ValorEspecie>
<DetalhamentoTransacoes>6</DetalhamentoTransacoes>
<FinalidadeTransacoes>3</FinalidadeTransacoes>
</Transacao>
<Transacao>
<QtdTransacoes>0</QtdTransacoes>
<ValorTransacoes>0.00</ValorTransacoes>
<ValorEspecie>0.00</ValorEspecie>
<DetalhamentoTransacoes>6</DetalhamentoTransacoes>
<FinalidadeTransacoes>4</FinalidadeTransacoes>
</Transacao>
<Transacao>
<QtdTransacoes>320</QtdTransacoes>
<ValorTransacoes>160000.00</ValorTransacoes>
<ValorEspecie>0.00</ValorEspecie>
<DetalhamentoTransacoes>7</DetalhamentoTransacoes>
<FinalidadeTransacoes>1</FinalidadeTransacoes>
</Transacao>
<Transacao>
<QtdTransacoes>0</QtdTransacoes>
<ValorTransacoes>0.00</ValorTransacoes>
<ValorEspecie>0.00</ValorEspecie>
<DetalhamentoTransacoes>7</DetalhamentoTransacoes>
<FinalidadeTransacoes>2</FinalidadeTransacoes>
</Transacao>
<Transacao>
<QtdTransacoes>0</QtdTransacoes>
<ValorTransacoes>0.00</ValorTransacoes>
<ValorEspecie>0.00</ValorEspecie>
<DetalhamentoTransacoes>7</DetalhamentoTransacoes>
<FinalidadeTransacoes>3</FinalidadeTransacoes>
</Transacao>
<Transacao>
<QtdTransacoes>0</QtdTransacoes>
<ValorTransacoes>0.00</ValorTransacoes>
<ValorEspecie>0.00</ValorEspecie>
<DetalhamentoTransacoes>7</DetalhamentoTransacoes>
<FinalidadeTransacoes>4</FinalidadeTransacoes>
</Transacao>
</Transacoes>
<Devolucoes>
<Devolucao>
<QtdDevolucoes>45</QtdDevolucoes>
<ValorDevolucoes>22500.00</ValorDevolucoes>
<DetalhamentoDevolucoes>1</DetalhamentoDevolucoes>
</Devolucao>
<Devolucao>
<QtdDevolucoes>230</QtdDevolucoes>
<ValorDevolucoes>115000.00</ValorDevolucoes>
<DetalhamentoDevolucoes>2</DetalhamentoDevolucoes>
</Devolucao>
</Devolucoes>
<BloqueiosCautelares>
<BloqueioCautelar>
<QtdeBloqCaut>0</QtdeBloqCaut>
<ValorBloqCaut>0.00</ValorBloqCaut>
<DetalhamentoTransacoesBloqCaut>1</DetalhamentoTransacoesBloqCaut>
</BloqueioCautelar>
<BloqueioCautelar>
<QtdeBloqCaut>0</QtdeBloqCaut>
<ValorBloqCaut>0.00</ValorBloqCaut>
<DetalhamentoTransacoesBloqCaut>2</DetalhamentoTransacoesBloqCaut>
</BloqueioCautelar>
<BloqueioCautelar>
<QtdeBloqCaut>0</QtdeBloqCaut>
<ValorBloqCaut>0.00</ValorBloqCaut>
<DetalhamentoTransacoesBloqCaut>3</DetalhamentoTransacoesBloqCaut>
</BloqueioCautelar>
<BloqueioCautelar>
<QtdeBloqCaut>0</QtdeBloqCaut>
<ValorBloqCaut>0.00</ValorBloqCaut>
<DetalhamentoTransacoesBloqCaut>4</DetalhamentoTransacoesBloqCaut>
</BloqueioCautelar>
</BloqueiosCautelares>
<Receitas>
<Receita>
<ValorReceita>0.00</ValorReceita>
<FonteReceita>1</FonteReceita>
</Receita>
<Receita>
<ValorReceita>85000.00</ValorReceita>
<FonteReceita>2</FonteReceita>
</Receita>
<Receita>
<ValorReceita>12000.00</ValorReceita>
<FonteReceita>3</FonteReceita>
</Receita>
<Receita>
<ValorReceita>0.00</ValorReceita>
<FonteReceita>4</FonteReceita>
</Receita>
</Receitas>
<TemposTransacoes
Perc50TempoExpUsuarioLiqSPI="1.20"
Perc99TempoExpUsuarioLiqSPI="4.50"
Perc50TempoExpUsuarioLiqForaSPI="2.30"
Perc99TempoExpUsuarioLiqForaSPI="8.10"
TempoMaxBloqueioCautelar="0.00" />
<TemposDict
Perc99TempoUsuarioConsulta="0.80"
PercTempoEnvioRegistro="1.50"
PercTempoExpUsuarioRegistro="2.00"
PercTempoExpUsuarioExclusao="1.80"
PercTempoNotificacaoPortabilidade="3.00"
PercTempoEnvioPortabilidade="2.50"
PercTempoAberturaMED="5.00" />
<ConsultasDict QtdConsultas="500000" />
<Disponibilidade IndiceDisponibilidade="99.85" />
<TempoAutorizacoes Perc95TempoAutorizacao="0.00" />
<Autorizacoes>
<Autorizacao>
<QtdAutorizacoes>0</QtdAutorizacoes>
<QtdEstoqueAutorizacoes>0</QtdEstoqueAutorizacoes>
<TipoPagador>1</TipoPagador>
</Autorizacao>
<Autorizacao>
<QtdAutorizacoes>0</QtdAutorizacoes>
<QtdEstoqueAutorizacoes>0</QtdEstoqueAutorizacoes>
<TipoPagador>2</TipoPagador>
</Autorizacao>
</Autorizacoes>
</APIX001>
Request example with date filter
To generate the APIX 001 for a specific month, send a POST /v1/reports request with the X-Organization-Id header and the following body:
{
"templateId": "APIX_001_TEMPLATE_ID",
"filters": {
"pix_btg": {
"payment.transfers": {
"created_at": {
"between": ["2026-03-01T00:00:00Z", "2026-03-31T23:59:59Z"]
}
},
"payment.refunds": {
"created_at": {
"between": ["2026-03-01T00:00:00Z", "2026-03-31T23:59:59Z"]
}
}
}
}
}
| Field | Description |
|---|
templateId | APIX 001 template identifier registered in Reporter |
filters.pix_btg.payment.transfers | Date filter for the transfers collection |
filters.pix_btg.payment.refunds | Date filter for the refunds collection |
created_at.between | Filters records created within the specified month |
Dates must be in ISO 8601 format with UTC timezone (Z). Make sure to cover the entire reference month — from the first second to the last.
XSD validation rules
Key constraints from the official APIX 001 XSD (version 2.5) that your data must satisfy:
| Field | Constraint |
|---|
| Monetary values | Up to 15 digits total, 2 decimal places, minimum 0 |
| Quantities | Integer, minimum 0, max 999,999,999,999 |
| Time values | Up to 8 digits total, 2 decimal places, 0–999,999 seconds |
| Availability | Percentage, 0.00–100.00 |
| ISPB | Exactly 8 numeric digits |
| Transaction entries | Exactly 12 (3 detail types × 4 purposes) |
| Refund entries | Exactly 2 |
| Cautionary block entries | Exactly 4 |
| Revenue entries | Exactly 4 |
| Authorization entries | Exactly 2 |
BACEN validates both structure and cardinality. If your report has fewer or more entries than expected in any section, the submission will be rejected.
Best practices
Zero-value entries
Even when there are no transactions for a given combination, the entry must still appear in the report with zero values. BACEN requires all 12 transaction entries, all 4 revenue entries, all 4 cautionary block entries, and all 2 authorization entries — regardless of whether data exists.
Replacement submissions
Use TipoEnvio="S" only to replace a previously approved submission. If your first submission was rejected, resubmit with TipoEnvio="I".
Value precision
All monetary values must have exactly 2 decimal places. Use Reporter’s formatting capabilities or ensure your data source provides pre-formatted values.
Time metric sourcing
Transaction time percentiles and DICT operation times must be sourced from your infrastructure monitoring — not from transactional data. These metrics reflect the actual user experience from payment initiation to settlement confirmation. BACEN may audit these values against SPI logs.
JSONB nested fields
Revenue calculations use nested field paths (e.g. fee_charge.totalAmount) to access values inside JSONB columns. Make sure your Reporter version supports nested field parsing in aggregation functions.
Always validate the rendered XML against BACEN’s official XSD before submission. You can download the schema from BACEN’s regulatory documents portal.