Valores numéricos (string)
Todos os valores financeiros no Fees Engine devem ser expressos como string, usando o tipo numeric. Isso garante o manuseio decimal de alta precisão para ativos como BRL ou BTC, e previne erros de arredondamento durante cálculos, divisões ou isenções.
Importante
- Requerido: Midaz v3.x.x (usa
numeric).
- Incompatível: Midaz v2.x.x (formato
amount + scale descontinuado).
Clientes usando Midaz v2.x.x devem atualizar para v3.x.x para garantir integração e funcionalidade adequadas com o Fees Engine.
Exemplo:
Períodos de billing
Ao acionar um cálculo de billing, você especifica a janela de tempo através do campo period. O Fees Engine suporta três formatos:
| Formato | Exemplo | Janela |
|---|
| Diário | 2026-03-15 | Início do dia → início do dia seguinte (UTC) |
| Semanal | 2026-W13 | Segunda-feira 00:00 UTC da semana ISO → segunda-feira seguinte 00:00 UTC |
| Mensal | 2026-03 | Primeiro instante do mês → primeiro instante do mês seguinte (UTC) |
O motor usa o período para contar transações qualificadas (para pacotes de volume) ou contas ativas (para pacotes de manutenção) dentro dessa janela exata.
Períodos semanais seguem a ISO 8601. A numeração das semanas vai de W01 a W52 (ou W53 em anos que possuem 53 semanas ISO). A semana sempre começa na segunda-feira.
Escolha a granularidade que corresponde ao seu ciclo de billing. Um produto de cartão pré-pago cobrado diariamente usaria 2026-03-15; uma plataforma SaaS cobrada mensalmente usaria 2026-03; um marketplace que faz liquidação semanal usaria 2026-W13.
Regras de cálculo de taxas
Cada taxa usa uma applicationRule para definir como é calculada. Você pode escolher entre três tipos de regra:
Você pode combinar diferentes regras em um único pacote para atender ao seu caso de uso.
Outros campos importantes:
isDeductibleFrom: define se a taxa é deduzida do remetente ou do destinatário.
referenceAmount: pode ser originalAmount ou afterFeesAmount.
priority: define a ordem de aplicação. A prioridade 1 deve sempre usar originalAmount.
maxBetweenTypes
Aplica o que for maior: uma taxa fixa ou uma taxa baseada em percentual.
Exemplo
- Valor da taxa fixa: R$5.
- Taxa percentual: 2%.
- Valor de referência: R$1.000.
rate = 1000 * 0.02 = R$ 20,00
Como R$ 20 > R$ 5, a taxa baseada em percentual é aplicada.
flatFee
Aplica um valor fixo de taxa. O comportamento depende do isDeductibleFrom.
Exemplo
- Taxa fixa: R$15.
- Valor de referência: R$115.
isDeductibleFrom | Fórmula | Taxa Total |
|---|
false | referenceAmount + fee | R$ 130,00 |
true | referenceAmount - fee | R$ 100,00 |
percentual
Aplica uma taxa como percentual do valor de referência.
Exemplo
- Valor: 30%.
- Valor de referência: R$ 389,50.
isDeductibleFrom | Fórmula | Taxa Total |
|---|
false | referenceAmount * value | R$ 116,85 |
true | referenceAmount - (referenceAmount * value) | R$ 272,65 |
Divisão de taxas
Quando uma transação tem múltiplas contas de origem, o Fees Engine divide as taxas proporcionalmente.
Exemplo
- Valor total: R$4.000,00
- Taxa fixa: R$15,00
- Imposto: 4%
isDeductibleFrom: false
Participação %
Fórmula: (Valor da Conta ÷ Valor Total) × 100
| Conta | Participação | Valor |
|---|
| @account1 | 25% | R$ 1.000 |
| @account2 | 25% | R$ 1.000 |
| @account3 | 40% | R$ 1.600 |
| @account4 | 10% | R$ 400 |
Distribuição da taxa fixa
Fórmula: taxa fixa × participação %
| Conta | Parcela da Taxa | Total |
|---|
| @account1 | R$ 3,75 | R$ 1.003,75 |
| @account2 | R$ 3,75 | R$ 1.003,75 |
| @account3 | R$ 6,00 | R$ 1.606,00 |
| @account4 | R$ 1,50 | R$ 401,50 |
Imposto proporcional
Fórmula: valor da conta × % do imposto
| Conta | Imposto | Total c/ Imposto |
|---|
| @account1 | R$ 40,00 | R$ 1.040,00 |
| @account2 | R$ 40,00 | R$ 1.040,00 |
| @account3 | R$ 64,00 | R$ 1.664,00 |
| @account4 | R$ 16,00 | R$ 416,00 |
Valor final por conta
Fórmula: principal + taxa + imposto
| Conta | Taxa | Imposto | Total Final |
|---|
| @account1 | R$ 3,75 | R$ 40,00 | R$ 1.043,75 |
| @account2 | R$ 3,75 | R$ 40,00 | R$ 1.043,75 |
| @account3 | R$ 6,00 | R$ 64,00 | R$ 1.670,00 |
| @account4 | R$ 1,50 | R$ 16,00 | R$ 417,50 |
Validações
- Total das participações = 100%
- Divisão da taxa corresponde à taxa fixa
- Divisão do imposto = 4%
- Total enviado = R$ 4.175,00
Isenções de taxas: regras e hierarquia
Por valor da transação
Use minimumAmount e maximumAmount para definir quando as taxas devem ser aplicadas.
Por exemplo: Se a faixa é R$ 0–300, uma transação de R$ 301 não acionará taxas.
Por conta
O sistema verifica waivedAccounts. Se a origem está listada, ela é isenta de taxas.
Hierarquia: Verificação da faixa de valor > depois isenção por conta
Exemplo misto: isenções de taxas e divisão proporcional de taxas
Vamos ver um exemplo de um pacote que inclui contas com isenções de taxas e requer divisão proporcional das taxas.
Cenário
Estamos processando uma transação de R$ 4.000, que inclui:
- Uma taxa fixa de R$ 16.
- Apenas algumas contas estão sujeitas à taxa fixa.
- Um IOF de 6% a ser deduzido.
Divisão no lado da origem
| Conta de Origem | % | Valor Proporcional |
|---|
| @account1 | 15% | R$ 600 |
| @account2 | 35% | R$ 1.400 |
| @account3 | 40% | R$ 1.600 |
| @account4 | 10% | R$ 400 |
Taxa fixa aplicada apenas a @account3 e @account4.
Resultado após Taxa Administrativa (proporcional)
| Conta | Taxa Admin | Total |
|---|
| @account1 | Isenta | R$ 600 |
| @account2 | Isenta | R$ 1.400 |
| @account3 | R$ 12,80 | R$ 1.612,80 |
| @account4 | R$ 3,20 | R$ 403,20 |
O valor total enviado aumenta para R$4.016.
Dedução de IOF (destinatário)
| Destinatário | % | Bruto | IOF (6%) | Líquido |
|---|
| @donation1 | 25% | R$ 1.000 | R$ 60 | R$ 940 |
| @donation2 | 25% | R$ 1.000 | R$ 60 | R$ 940 |
| @donation3 | 25% | R$ 1.000 | R$ 60 | R$ 940 |
| @donation4 | 25% | R$ 1.000 | R$ 60 | R$ 940 |
As taxas são creditadas nas contas definidas no creditAccount de cada taxa.
Dízimas periódicas
Quando uma divisão de taxa resulta em dízimas periódicas (ex.: 0,3333…), o Fees Engine ajusta automaticamente o primeiro ou maior valor em um centavo para garantir que o total permaneça exato. Isso evita desvios de arredondamento e mantém seu ledger consistente.
Cálculos de billing
Os pacotes de billing usam um modelo de cálculo diferente dos pacotes de taxas. Em vez de avaliar transações individuais, eles agregam dados ao longo de um período de billing e retornam payloads de cobrança para seu orquestrador executar.
O billing suporta três formatos de período: mensal (YYYY-MM), semanal (YYYY-Www, ex.: 2026-W13) e diário (YYYY-MM-DD).
Cálculo de billing por volume
O billing por volume conta transações que correspondem a um eventFilter (rota de transação + status) dentro do período de billing e então aplica preços com base no modelo configurado.
O cálculo segue esta ordem:
- Conta as transações qualificadas no período.
- Subtrai o
freeQuota do total contado.
- Aplica preços com base no
pricingModel (tiered ou fixed).
- Aplica descontos dos
discountTiers se o volume total atingir algum limite.
Preço escalonado
Cada faixa define um intervalo de quantidade e um preço unitário. O motor aplica o preço correspondente para cada unidade dentro de cada intervalo.
Exemplo: Um pacote de billing para emissão de boletos com três faixas e uma cota gratuita de 50:
| Faixa | Preço unitário |
|---|
| 1–500 | R$ 1,20 |
| 501–2.000 | R$ 0,80 |
| 2.001+ | R$ 0,45 |
Para um cliente que emitiu 1.800 boletos no mês:
- 50 isentos (cota gratuita)
- 1.750 faturáveis: 500 × R$ 1,20 + 1.250 × R$ 0,80 = R$ 1.600,00
- Faixa de desconto aplicada (> 1.000 boletos → 5%): −R$ 80,00
- Total: R$ 1.520,00
Preço fixo
Um único preço unitário se aplica a todas as transações faturáveis, independentemente do volume. A cota gratuita ainda é subtraída antes do cálculo.
Exemplo: R$ 0,10 por Pix enviado, sem cota gratuita:
- 5.000 transações Pix × R$ 0,10 = R$ 500,00
Modos de contagem
O campo countMode determina como as transações são agrupadas:
perRoute — Conta todas as transações correspondentes na organização como um total único.
perAccount — Conta transações por conta individual e aplica os preços independentemente para cada uma.
Cálculo de billing de manutenção
O billing de manutenção cobra um valor fixo por conta ativa no período de billing. O motor resolve as contas-alvo, filtra pelo status ativo e gera um único payload de transação.
O resultado é uma transação N:1:
- Cada conta ativa aparece como uma entrada de débito (
source.from) pelo valor configurado em feeAmount.
- A
maintenanceCreditAccount recebe o total completo como uma única entrada de crédito (distribute.to).
Contas inativas, encerradas ou suspensas são excluídas automaticamente.
Exemplo: Manutenção mensal de R$ 9,90 para um segmento com 12.000 contas PF ativas:
- 12.000 entradas em
source.from, cada uma debitada em R$ 9,90
- 1 entrada em
distribute.to creditada em R$ 118.800,00
Política de falha tudo-ou-nada
Se qualquer pacote de billing falhar durante uma chamada /billing/calculate, toda a operação falha. Nenhum resultado parcial é retornado. A resposta inclui qual pacote e recurso causou a falha, para que você possa corrigir e re-executar.
Cada resultado de cálculo de billing inclui metadados estruturados com todos os parâmetros utilizados — modelo de preços, faixas aplicadas, cota gratuita subtraída, descontos aplicados e contagem de contas. Isso proporciona rastreabilidade completa para conciliação e auditoria.