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

# Fees Engine calculations

> Understand how Fees Engine calculates, allocates, and exempts fees with traceable, compliant rules for complex accounting flows.

## Numeric values (string)

***

All financial values in **Fees Engine** must be expressed as a `string`, using the `numeric` type. This ensures high-precision decimal handling for assets like BRL or BTC, and prevents rounding errors during calculations, splits, or exemptions.

<Danger>
  **Important**

  * **Required**: Midaz v3.x.x (uses `numeric`).
  * **Incompatible**: Midaz v2.x.x (deprecated `amount` + `scale` format).

  Clients using Midaz v2.x.x must upgrade to v3.x.x to ensure proper integration and functionality with Fees Engine.
</Danger>

**Example:**

```
"value": "12.50"
```

## Billing periods

***

When triggering a billing calculation, you specify the time window through the `period` field. Fees Engine supports three formats:

| Format  | Example      | Window                                                             |
| ------- | ------------ | ------------------------------------------------------------------ |
| Daily   | `2026-03-15` | Start of that day → start of the next day (UTC)                    |
| Weekly  | `2026-W13`   | Monday 00:00 UTC of the ISO week → following Monday 00:00 UTC      |
| Monthly | `2026-03`    | First instant of the month → first instant of the next month (UTC) |

The engine uses the period to count qualifying transactions (for volume packages) or active accounts (for maintenance packages) within that exact window.

<Tip>
  Weekly periods follow [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601#Week_dates). Week numbering ranges from `W01` to `W52` (or `W53` in years that have 53 ISO weeks). The week always starts on Monday.
</Tip>

Choose the granularity that matches your billing cycle. A prepaid card product billed daily would use `2026-03-15`; a SaaS platform billed monthly would use `2026-03`; a marketplace that settles weekly would use `2026-W13`.

## Fee calculation rules

***

Each fee uses an `applicationRule` to define how it's calculated. You can choose from three rule types:

* [maxBetweenTypes](#maxbetweentypes)
* [flatFee](#flatfee)
* [percentual](#percentual)

You can combine different rules in a single package to match your use case.

Other key fields:

* `isDeductibleFrom`: defines if the fee is deducted from the sender or the receiver.
* `referenceAmount`: either `originalAmount` or `afterFeesAmount`.
* `priority`: defines the order of application. Priority 1 must always use `originalAmount`.

### maxBetweenTypes

Applies whichever is greater: a flat or percentage-based fee.

**Example**

* Flat fee value: R\$5.
* Percentual fee: 2%.
* Reference amount: R\$1,000.

```
rate = 1000 * 0.02 = R$ 20.00
```

Since **R 5**, the percentage-based fee is applied.

### flatFee

Applies a fixed fee amount. Behavior depends on `isDeductibleFrom`.

**Example**

* Flat fee: R\$15.
* Reference amount: R\$115.

| `isDeductibleFrom` | Formula                 | Total Fee  |
| :----------------- | :---------------------- | :--------- |
| `false`            | `referenceAmount + fee` | R\$ 130.00 |
| `true`             | `referenceAmount - fee` | R\$ 100.00 |

### percentual

Applies a fee as a percentage of the reference amount.

**Example**

* Value: 30%.
* Reference amount: R\$ 389.50.

| `isDeductibleFrom` | Formula                                       | Total Fee  |
| :----------------- | :-------------------------------------------- | :--------- |
| `false`            | `referenceAmount * value`                     | R\$ 116.85 |
| `true`             | `referenceAmount - (referenceAmount * value)` | R\$ 272.65 |

## Fee splitting

***

When a transaction has multiple source accounts, Fees Engine splits fees proportionally.

### Example

* Total amount: R\$4,000.00
* Fixed fee: R\$15.00
* Tax: 4%
* `isDeductibleFrom: false`

### Participation %

> **Formula**: (Account Amount ÷ Total Amount) × 100

| Account   | Share | Amount    |
| :-------- | :---- | :-------- |
| @account1 | 25%   | R\$ 1,000 |
| @account2 | 25%   | R\$ 1,000 |
| @account3 | 40%   | R\$ 1,600 |
| @account4 | 10%   | R\$ 400   |

### Fixed fee distribution

> **Formula**: `fixed Fee × participation %`

| Account   | Fee Share | 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   |

### Proportional tax

> **Formula**: `account amount × tax %`

| Account   | Tax       | Total w/ Tax |
| :-------- | :-------- | :----------- |
| @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   |

### Final amount per account

> **Formula**: `principal + fee + tax`

| Account   | Fee      | Tax       | Final Total  |
| :-------- | :------- | :-------- | :----------- |
| @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   |

#### Validations

* Total shares = 100%
* Fee split matches flat fee
* Tax split = 4%
* Total sent = R\$ 4,175.00

## Fee exemptions: rules & hierarchy

***

### By transaction amount

Use `minimumAmount` and `maximumAmount` to define when **fees should apply**.

> For example: If the range is R$ 0–300, a transaction of R$ 301 won’t trigger fees.

### By account

The system checks `waivedAccounts`. If the source is listed, it’s exempt from fees.

<Tip>
  **Hierarchy:** Value range check > then account exemption
</Tip>

## Mixed example: fee exemptions and proportional fee splitting

***

Let’s look at an example of a package that includes accounts with fee exemptions and requires splitting fees proportionally.

### Scenario

We’re processing a transaction of **R\$ 4,000**, which includes:

* A **fixed fee** of **R\$ 16**.
* Only some accounts are subject to the fixed fee
* An **IOF tax** of **6%** to be deducted.

#### Split on the source side

| Source Account | %   | Proportional Value |
| :------------- | --- | :----------------- |
| @account1      | 15% | R\$ 600            |
| @account2      | 35% | R\$ 1,400          |
| @account3      | 40% | R\$ 1,600          |
| @account4      | 10% | R\$ 400            |

Fixed fee applied only to `@account3` and `@account4`.

#### Result after Admin Fee (proportional)

| Account   | Admin Fee | Total        |
| :-------- | :-------- | :----------- |
| @account1 | Exempt    | R\$ 600      |
| @account2 | Exempt    | R\$ 1,400    |
| @account3 | R\$ 12.80 | R\$ 1,612.80 |
| @account4 | R\$ 3.20  | R\$ 403.20   |

Total send value increases to **R\$4,016**.

#### IOF deduction (recipient)

| Recipient  | %   | Gross     | IOF (6%) | Net     |
| :--------- | --- | :-------- | :------- | :------ |
| @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 |

<Danger>
  Fees are credited to the accounts defined in each fee’s `creditAccount`.
</Danger>

## Repeating decimals

***

When a fee split results in repeating decimals (e.g., 0.3333...), Fees Engine automatically adjusts the first or largest value by a cent to ensure the total remains exact. This avoids rounding drift and keeps your ledger consistent.

## Billing calculations

***

Billing packages use a different calculation model than fee packages. Instead of evaluating individual transactions, they aggregate data over a billing period and return charge payloads for your orchestrator to execute.

Billing supports three period formats: monthly (`YYYY-MM`), weekly (`YYYY-Www`, e.g., `2026-W13`), and daily (`YYYY-MM-DD`).

### Volume billing calculation

Volume billing counts transactions matching an `eventFilter` (transaction route + status) within the billing period, then applies pricing based on the configured model.

The calculation follows this order:

1. **Count** qualifying transactions in the period.
2. **Subtract** the `freeQuota` from the total count.
3. **Apply pricing** based on the `pricingModel` (`tiered` or `fixed`).
4. **Apply discounts** from `discountTiers` if the total volume meets any threshold.

#### Tiered pricing

Each tier defines a quantity range and a unit price. The engine applies the corresponding price for each unit within each range.

**Example**: A billing package for boleto issuance with three tiers and a free quota of 50:

| Range     | Unit price |
| --------- | ---------- |
| 1–500     | R\$ 1.20   |
| 501–2,000 | R\$ 0.80   |
| 2,001+    | R\$ 0.45   |

For a client that issued 1,800 boletos in the month:

* 50 exempt (free quota)
* 1,750 billable: 500 × R\$ 1.20 + 1,250 × R\$ 0.80 = R\$ 1,600.00
* Discount tier applies (> 1,000 boletos → 5%): −R\$ 80.00
* **Total: R\$ 1,520.00**

#### Fixed pricing

A single unit price applies to all billable transactions regardless of volume. The free quota is still subtracted before calculation.

**Example**: R\$ 0.10 per Pix sent, no free quota:

* 5,000 Pix transactions × R\$ 0.10 = R\$ 500.00

#### Count modes

The `countMode` field determines how transactions are grouped:

* **`perRoute`** — Counts all matching transactions across the organization as a single total.
* **`perAccount`** — Counts transactions per individual account and applies pricing independently to each.

### Maintenance billing calculation

Maintenance billing charges a fixed amount per active account in the billing period. The engine resolves the target accounts, filters for active status, and generates a single transaction payload.

The result is a N:1 transaction:

* Each active account appears as a debit entry (`source.from`) for the configured `feeAmount`.
* The `maintenanceCreditAccount` receives the full total as a single credit entry (`distribute.to`).

Inactive, closed, or suspended accounts are excluded automatically.

**Example**: Monthly maintenance of R\$ 9.90 for a segment with 12,000 active PF accounts:

* 12,000 entries in `source.from`, each debited R\$ 9.90
* 1 entry in `distribute.to` credited R\$ 118,800.00

### All-or-nothing failure policy

If any billing package fails during a `/billing/calculate` call, the entire operation fails. No partial results are returned. The response includes which package and resource caused the failure, so you can fix and re-execute.

### Audit metadata

Each billing calculation result includes structured metadata with all parameters used — pricing model, tiers applied, free quota subtracted, discounts applied, and account counts. This provides complete traceability for reconciliation and audit.
