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

# What is Fees Engine?

> Fees Engine controls how fees and billing are configured, calculated, and tracked across per-transaction and per-period scenarios.

<Tip>
  **Test the Fee Engine Plugin locally**

  Run Lerian's plugins without deploying to Kubernetes using our [plugins-docker-compose repository](https://github.com/LerianStudio/plugins-docker-compose).

  Keep in mind that these services require a valid license to run. Without it, the application will not start. For license details, check our [License documentation](/en/reference/lerians-license).
</Tip>

## Why use Fees Engine?

***

The **Fees Engine** plugin helps you easily manage complex fee logic. Whether you're applying a flat rate, distributing fees proportionally, or estimating transactions in advance, this plugin is built for flexibility and scale.

Here's what it unlocks:

* **Flexible fee configuration** via fee packages—tailored to account groups or specific ledgers.
* **Multiple calculation methods**: flat fees, percentual rates, and "max between types" logic.
* **Proportional fee distribution** for marketplace flows and multi-account operations.
* **Support for accounting routes** via `transactionRoute`, `routeFrom`, and `routeTo`.
* **Estimation tools** to preview calculations before executing transactions.
* **Fee exemption logic** by account and transaction value ranges.
* **Priority-based application** to control the order in which multiple fees are applied.
* **Accurate deduction mechanics** with `isDeductibleFrom` support.
* **Volume-based billing** via billing packages — charge based on accumulated transaction counts per period (daily or monthly).
* **Maintenance billing** for recurring per-account charges, targeting accounts by segment, portfolio, or explicit list.
* **Free quotas and progressive discounts** to model tiered pricing and volume incentives.
* **Segment-based exemptions** to exempt entire account groups from fee packages without listing individual accounts.

<Tip>
  Fees Engine is a separate plugin. If you'd like to learn more or evaluate it for your use case, [get in touch with our team](https://lerian.studio/contact).
</Tip>

## What are fees?

***

Fees are monetary values charged in exchange for services, products, or access to resources. Their purpose depends on the industry, but the need for clarity and consistency is universal. Below are just a few examples:

### Finance

In the financial sector, fees are applied to cover operational costs and ensure legal compliance.

* **Account maintenance fee**: Keeps accounts operational and covers administrative costs.
* **Transfer fee:** Charged for transactions like TEDs or international transfers.

### Logistics and transportation

In the logistics sector, fees are related to the use of transportation and storage services.

* **Handling fee**: Applied during storage and physical movement of goods.
* **Unloading fee**: Covers unloading operations at delivery points.

### Pharmaceutical and healthcare

In the pharmaceutical sector, fees aim to ensure the quality and regulation of services.

* **Medication registration fee**: Related to regulatory approvals and market entry.
* **Laboratory analysis fee**: Covers testing and quality control costs.

### Agricultural

In the agricultural sector, fees are linked to commercialization and regulatory processes.

* **Sanitary inspection fee**: Ensures health compliance for agricultural exports.
* **Agricultural export fee**: Covers admin and regulatory export costs..

## Fee Packages

***

A **Fee Package** defines how fees are applied to a transaction. It groups one or more fee rules and can be customized by segment, ledger, and accounting routes.

You can create different packages for different products, transaction types, or customer segments, each with its own calculation logic, route configuration, and priority rules.

A package includes required fields and can add optional matching or exemption fields:

* **ledgerId** – The ledger that records the transaction and its fees.
* **transactionRoute** – The main accounting route for the transaction, when route-level matching is used.
* **segmentId** – The product or segment the package applies to, when segment-level matching is used.
* **waivedAccounts** – Accounts that should be exempt from fees, when exemptions are configured.
* **fees** – A map of individual fee rules, each including:
  * **priority** – Defines execution order.
  * **routeFrom** and **routeTo** – Custom accounting routes for the fee.
  * **isDeductibleFrom** – Whether the fee is deducted from the original amount.
  * **referenceAmount** – The base amount used for calculations.

<Note>
  **Fees Engine** requires explicit route configuration for each fee and direction (e.g., debit or credit).
</Note>

### Validation rules

To ensure consistency and prevent configuration errors, Fees Engine enforces the following rules:

* **Fee priority must be unique** within a package.
* Fees with `isDeductibleFrom: true` must use `referenceAmount: originalAmount`.
* Fees with `priority` 1 must also use `referenceAmount: originalAmount`.
* Fields like `organizationId`, `ledgerId`, and `creditAccount` must exist in Midaz and are validated using the [Retrieve an Account by Alias](/en/reference/midaz/retrieve-an-account-by-alias) endpoint.

<Danger>
  Fees Engine validates all packages and transactions according to the latest Midaz standards. Make sure your configuration complies with required rules for fields like `ledgerId`, `creditAccount`, and `referenceAmount`, plus optional matching fields such as `segmentId` when they are configured.
</Danger>

### Choosing the right endpoint: calculate vs. estimate

Fees Engine provides two endpoints to apply fees. They behave differently, depending on how much control and flexibility you need:

#### [Calculate fees for a package](/en/reference/midaz/plugins/fees-engine/calculate-fees)

* Automatically fetches all available packages for the given organization and ledger.
* Picks the best match based on transaction context.
* Applies the corresponding fee rules.
* If **no matching package is found**, **no fees are applied**.

#### [Estimate transaction fees](/en/reference/midaz/plugins/fees-engine/simulate-fees)

* Estimates fees for a **specific** package using its `packageId`.
* Returns calculated fees **only if the transaction matches** the package’s conditions.
* Useful for testing, debugging, or giving users a preview of fees, without writing to the ledger.

<Note>
  Use `calculate` when you want the engine to decide which package to apply. Use `estimate` when you want full control over which package to test.
</Note>

### Segment-based exemptions

Fee packages support exempting individual accounts via `waivedAccounts`. You can also reference a `segmentId` to exempt an entire group of accounts at once.

Use segment-based exemptions when:

* A customer tier (such as premium accounts) is universally exempt from a fee.
* Internal or partner accounts belong to an existing segment in Midaz.
* Maintaining a list of individual account aliases is impractical at scale.

<Tip>
  Segment-based exemptions are resolved at calculation time. When accounts join or leave the segment, the change takes effect on the next fee calculation without requiring a package update.
</Tip>

## Billing Packages

***

**Billing Packages** calculate charges based on accumulated transaction volume over a period — daily or monthly. Unlike fee packages, which apply a charge per individual transaction, billing packages evaluate the total count of qualifying transactions and return payloads for your orchestrator to execute.

Two types are available:

* **Volume** — charges based on the number of transactions matching an event filter in the period.
* **Maintenance** — charges a fixed recurring fee per active account, once per billing period.

<Note>
  Billing packages are a calculation engine, not a billing platform. The engine calculates what should be charged and returns the payloads. Your orchestrator — Flowker, a cron job, or any other caller — executes the actual charges against Midaz.
</Note>

### Volume packages

A volume package counts transactions matching a given `eventFilter` (transaction route + status) within the billing period and applies a charge based on the configured pricing model.

Key fields:

* **eventFilter** — Specifies which transactions to count: `transactionRoute` and `status`.
* **pricingModel** — Either `tiered` (unit price varies by quantity range) or `fixed` (single unit price regardless of volume).
* **tiers** — Quantity ranges (`minQuantity`, `maxQuantity`) and `unitPrice` per unit within each range.
* **freeQuota** — Number of transactions exempt per period. The engine subtracts this count before applying pricing.
* **discountTiers** — Progressive discounts: when total volume meets a threshold, the engine applies the configured discount percentage to the final amount.
* **countMode** — Either `perRoute` (counts all matching transactions as a single total) or `perAccount` (counts per individual account).
* **debitAccountAlias** / **creditAccountAlias** — Accounting routes for the charge.

### Maintenance packages

A maintenance package applies a fixed fee per active account in the billing period, regardless of transaction activity.

Key fields:

* **feeAmount** — Fixed charge per active account.
* **assetCode** — Currency for the charge.
* **maintenanceCreditAccount** — Account that receives the fee revenue.
* **accountTarget** — Defines which accounts to charge. Use exactly one per package:
  * `segmentId` — All accounts in the segment (supports 100k+ accounts).
  * `portfolioId` — All accounts in the portfolio (supports thousands of accounts).
  * `aliases` — Explicit list of account aliases (maximum 100 accounts).

<Warning>
  Each maintenance package supports only one `accountTarget` type. You cannot combine `segmentId`, `portfolioId`, and `aliases` in the same package.
</Warning>

### Managing billing packages

The following endpoints manage billing packages:

* `POST /v1/billing-packages` — Create a billing package.
* `GET /v1/billing-packages` — List all billing packages.
* `GET /v1/billing-packages/:id` — Retrieve a specific billing package.
* `PATCH /v1/billing-packages/:id` — Update a billing package (`label`, `description`, `enable`).
* `DELETE /v1/billing-packages/:id` — Soft-delete a billing package.
* `POST /v1/billing/calculate` — Calculate billing for a period.

## Fee Packages vs. Billing Packages

***

|                       | Fee Packages                                  | Billing Packages                                           |
| --------------------- | --------------------------------------------- | ---------------------------------------------------------- |
| **Trigger**           | Per transaction (synchronous)                 | Per period (monthly or daily)                              |
| **Pricing model**     | Flat, percentual, maxBetweenTypes             | Tiered or fixed by volume                                  |
| **Account exemption** | `waivedAccounts` (individual) or `segmentId`  | `accountTarget`: segment, portfolio, or alias list         |
| **Volume discounts**  | No                                            | Yes (`discountTiers`)                                      |
| **Free quotas**       | No                                            | Yes (`freeQuota` per period)                               |
| **Recurring charges** | No                                            | Yes (maintenance type)                                     |
| **Execution**         | Automatic — engine evaluates each transaction | Caller-triggered — orchestrator calls `/billing/calculate` |
| **Output**            | Transaction with fees applied                 | Calculation payloads for the caller to execute             |

<Note>
  Fee packages and billing packages operate independently. A transaction can trigger a fee package calculation and also be counted toward a billing package in the same period. These are separate, non-conflicting events.
</Note>

## Routing fees

***

Every fee can have:

* A `routeFrom`, which represents the accounting route for the debit (or source).
* A `routeTo`, which represents the accounting route for the credit (or destination).
* A `transactionRoute`, which represents the overall nature of the transaction.

This allows granular tracking of each fee entry in the ledger.

## Deductible fees

***

If a fee is flagged as deductible ( `isDeductibleFrom: true`), the following logic applies:

* The **full value is sent from the source account**.
* The **fee is subtracted from the destination account's received value**.
* The `referenceAmount` used in calculations must be `originalAmount`.

This approach ensures the sender sends the full amount, and the deduction is applied only at the receiving end.

## Soft delete for safe recordkeeping

***

No data gets lost. When a resource is deleted:

* It's marked with a `deletedAt` timestamp. Active records return `deletedAt: null`.
* It's excluded from standard queries, but still stored in the database for audit and historical accuracy.

This ensures full traceability if needed.

## Integrations

***

You can use **Fees Engine** on its own or alongside other components in your stack. It integrates seamlessly with Lerian plugins or your own implementation to apply fees based on your unique business logic.

Popular use cases include:

* Exchange engines
* Lending platforms
* Bill payment systems
* Smart contracts
* Pix (Brazil's instant payment platform)

## Security recommendations

***

**Security is foundational when working with Lerian products and plugins.**\
Before deploying any component into your environment, we strongly recommend reviewing our [**Security Recommendations**](/en/midaz/security-recommendations). Each product—along with its associated plugins—should be implemented in line with security best practices, including:

* Securing network boundaries
* Managing and rotating secrets
* Applying timely patch management
* Enforcing strict role-based access controls (RBAC)

By following these practices, you ensure that Lerian's products and plugins operate securely, integrate seamlessly with your infrastructure, and uphold compliance, data integrity, and user trust across your entire ecosystem.

## Next steps

***

<CardGroup cols={2}>
  <Card title="Explore the Fees Engine API" icon="terminal" href="/en/reference/midaz/plugins/fees-engine/create-package">
    Browse endpoints for fee packages, calculations, and estimations.
  </Card>

  <Card title="Using Fees Engine" icon="rocket" href="/en/midaz/plugins/fees-engine/using-fee-engine">
    Learn how to create fee packages and apply them to transactions.
  </Card>
</CardGroup>
