Valores numéricos (string)
Todos los valores financieros en Fees Engine deben expresarse como string, usando el tipo numeric. Esto garantiza el manejo de decimales de alta precisión para activos como BRL o BTC, y previene errores de redondeo durante cálculos, divisiones o exenciones.
Importante
- Requerido: Midaz v3.x.x (usa
numeric).
- Incompatible: Midaz v2.x.x (formato obsoleto
amount + scale).
Los clientes que usen Midaz v2.x.x deben actualizar a v3.x.x para garantizar la integración y funcionalidad adecuadas con el Fees Engine.
Ejemplo:
Períodos de facturación
Al activar un cálculo de facturación, especificas la ventana de tiempo a través del campo period. Fees Engine soporta tres formatos:
| Formato | Ejemplo | Ventana |
|---|
| Diario | 2026-03-15 | Inicio de ese día → inicio del día siguiente (UTC) |
| Semanal | 2026-W13 | Lunes 00:00 UTC de la semana ISO → siguiente lunes 00:00 UTC |
| Mensual | 2026-03 | Primer instante del mes → primer instante del mes siguiente (UTC) |
El motor usa el período para contar transacciones que califican (para paquetes de volumen) o cuentas activas (para paquetes de mantenimiento) dentro de esa ventana exacta.
Los períodos semanales siguen ISO 8601. La numeración de semanas va de W01 a W52 (o W53 en años que tienen 53 semanas ISO). La semana siempre comienza el lunes.
Elige la granularidad que coincida con tu ciclo de facturación. Un producto de tarjeta prepago facturado diariamente usaría 2026-03-15; una plataforma SaaS facturada mensualmente usaría 2026-03; un marketplace que liquida semanalmente usaría 2026-W13.
Reglas de cálculo de tarifas
Cada tarifa usa una applicationRule para definir cómo se calcula. Puedes elegir entre tres tipos de reglas:
Puedes combinar diferentes reglas en un solo paquete para ajustarse a tu caso de uso.
Otros campos clave:
isDeductibleFrom: define si la tarifa se deduce del remitente o del receptor.
referenceAmount: ya sea originalAmount o afterFeesAmount.
priority: define el orden de aplicación. La prioridad 1 siempre debe usar originalAmount.
maxBetweenTypes
Aplica el mayor valor entre: una tarifa fija o una basada en porcentaje.
Ejemplo
- Valor de tarifa fija: R$5.
- Tarifa porcentual: 2%.
- Monto de referencia: R$1,000.
tasa = 1000 * 0.02 = R$ 20.00
Dado que R20.00>R5, se aplica la tarifa basada en porcentaje.
flatFee
Aplica un monto de tarifa fijo. El comportamiento depende de isDeductibleFrom.
Ejemplo
- Tarifa fija: R$15.
- Monto de referencia: R$115.
isDeductibleFrom | Fórmula | Tarifa Total |
|---|
false | referenceAmount + fee | R$ 130.00 |
true | referenceAmount - fee | R$ 100.00 |
percentual
Aplica una tarifa como porcentaje del monto de referencia.
Ejemplo
- Valor: 30%.
- Monto de referencia: R$ 389.50.
isDeductibleFrom | Fórmula | Tarifa Total |
|---|
false | referenceAmount * value | R$ 116.85 |
true | referenceAmount - (referenceAmount * value) | R$ 272.65 |
División de tarifas
Cuando una transacción tiene múltiples cuentas de origen, el Fees Engine divide las tarifas proporcionalmente.
Ejemplo
- Monto total: R$4,000.00
- Tarifa fija: R$15.00
- Impuesto: 4%
isDeductibleFrom: false
Porcentaje de participación
Fórmula: (Monto de Cuenta ÷ Monto Total) × 100
| Cuenta | Participación | Monto |
|---|
| @account1 | 25% | R$ 1,000 |
| @account2 | 25% | R$ 1,000 |
| @account3 | 40% | R$ 1,600 |
| @account4 | 10% | R$ 400 |
Distribución de tarifa fija
Fórmula: Tarifa fija × participación %
| Cuenta | Porción de Tarifa | 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 |
Impuesto proporcional
Fórmula: monto de cuenta × impuesto %
| Cuenta | Impuesto | Total c/ Impuesto |
|---|
| @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 |
Monto final por cuenta
Fórmula: principal + tarifa + impuesto
| Cuenta | Tarifa | Impuesto | 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 |
Validaciones
- Total de participaciones = 100%
- División de tarifa coincide con tarifa fija
- División de impuesto = 4%
- Total enviado = R$ 4,175.00
Exenciones de tarifas: reglas y jerarquía
Por monto de transacción
Usa minimumAmount y maximumAmount para definir cuándo deben aplicarse las tarifas.
Por ejemplo: Si el rango es R0–300,unatransaccioˊndeR 301 no activará tarifas.
Por cuenta
El sistema verifica waivedAccounts. Si la fuente está listada, está exenta de tarifas.
Jerarquía: Verificación de rango de valor > luego exención de cuenta
Ejemplo mixto: exenciones de tarifas y división proporcional de tarifas
Veamos un ejemplo de un paquete que incluye cuentas con exenciones de tarifas y requiere dividir las tarifas proporcionalmente.
Escenario
Estamos procesando una transacción de R$ 4,000, que incluye:
- Una tarifa fija de R$ 16.
- Solo algunas cuentas están sujetas a la tarifa fija
- Un impuesto IOF del 6% a deducir.
División en el lado de origen
| Cuenta de Origen | % | Valor Proporcional |
|---|
| @account1 | 15% | R$ 600 |
| @account2 | 35% | R$ 1,400 |
| @account3 | 40% | R$ 1,600 |
| @account4 | 10% | R$ 400 |
Tarifa fija aplicada solo a @account3 y @account4.
Resultado después de Tarifa Administrativa (proporcional)
| Cuenta | Tarifa Admin | Total |
|---|
| @account1 | Exento | R$ 600 |
| @account2 | Exento | R$ 1,400 |
| @account3 | R$ 12.80 | R$ 1,612.80 |
| @account4 | R$ 3.20 | R$ 403.20 |
El valor total de envío aumenta a R$4,016.
Deducción de IOF (destinatario)
| Destinatario | % | Bruto | IOF (6%) | Neto |
|---|
| @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 |
Las tarifas se acreditan a las cuentas definidas en el creditAccount de cada tarifa.
Decimales repetidos
Cuando una división de tarifa resulta en decimales repetidos (por ejemplo, 0.3333…), el Motor de Tarifas ajusta automáticamente el primer o mayor valor por un centavo para garantizar que el total permanezca exacto. Esto evita deriva por redondeo y mantiene tu Ledger consistente.
Cálculos de facturación
Los billing packages usan un modelo de cálculo diferente al de los fee packages. En lugar de evaluar transacciones individuales, agregan datos durante un período de facturación y devuelven payloads de cargo para que tu orquestador los ejecute.
La facturación soporta tres formatos de período: mensual (YYYY-MM), semanal (YYYY-Www, ej., 2026-W13) y diario (YYYY-MM-DD).
Cálculo de facturación por volumen
La facturación por volumen cuenta transacciones que coinciden con un eventFilter (ruta de transacción + estado) dentro del período de facturación, luego aplica precios según el modelo configurado.
El cálculo sigue este orden:
- Contar transacciones que califican en el período.
- Restar el
freeQuota del conteo total.
- Aplicar precios según el
pricingModel (tiered o fixed).
- Aplicar descuentos de
discountTiers si el volumen total alcanza algún umbral.
Precios escalonados
Cada nivel define un rango de cantidad y un precio unitario. El motor aplica el precio correspondiente para cada unidad dentro de cada rango.
Ejemplo: Un billing package para emisión de boletos con tres niveles y una cuota gratuita de 50:
| Rango | Precio unitario |
|---|
| 1–500 | R$ 1.20 |
| 501–2,000 | R$ 0.80 |
| 2,001+ | R$ 0.45 |
Para un cliente que emitió 1,800 boletos en el mes:
- 50 exentos (cuota gratuita)
- 1,750 facturables: 500 × R$ 1.20 + 1,250 × R$ 0.80 = R$ 1,600.00
- Se aplica nivel de descuento (> 1,000 boletos → 5%): −R$ 80.00
- Total: R$ 1,520.00
Precio fijo
Un solo precio unitario se aplica a todas las transacciones facturables independientemente del volumen. La cuota gratuita aún se resta antes del cálculo.
Ejemplo: R$ 0.10 por Pix enviado, sin cuota gratuita:
- 5,000 transacciones Pix × R$ 0.10 = R$ 500.00
Modos de conteo
El campo countMode determina cómo se agrupan las transacciones:
perRoute — Cuenta todas las transacciones coincidentes en la organización como un total único.
perAccount — Cuenta transacciones por cuenta individual y aplica precios de forma independiente a cada una.
Cálculo de facturación de mantenimiento
La facturación de mantenimiento cobra un monto fijo por cuenta activa en el período de facturación. El motor resuelve las cuentas objetivo, filtra por estado activo y genera un único payload de transacción.
El resultado es una transacción N:1:
- Cada cuenta activa aparece como una entrada de débito (
source.from) por el feeAmount configurado.
- La
maintenanceCreditAccount recibe el total completo como una única entrada de crédito (distribute.to).
Las cuentas inactivas, cerradas o suspendidas se excluyen automáticamente.
Ejemplo: Mantenimiento mensual de R$ 9.90 para un segmento con 12,000 cuentas PF activas:
- 12,000 entradas en
source.from, cada una debitada R$ 9.90
- 1 entrada en
distribute.to acreditada R$ 118,800.00
Política de fallo todo-o-nada
Si algún billing package falla durante una llamada a /billing/calculate, toda la operación falla. No se devuelven resultados parciales. La respuesta incluye qué paquete y recurso causó el fallo, para que puedas corregir y re-ejecutar.
Cada resultado de cálculo de facturación incluye metadatos estructurados con todos los parámetros utilizados — modelo de precios, niveles aplicados, cuota gratuita restada, descuentos aplicados y conteos de cuentas. Esto proporciona trazabilidad completa para conciliación y auditoría.