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

# Using Fees Engine

> Use Fees Engine to apply per-transaction fee packages and per-period billing packages aligned with your business rules.

Whether you're applying per-transaction fees or calculating periodic billing charges, Fees Engine offers full control and flexibility. This guide walks you through both workflows: fee packages (per-transaction) and billing packages (per-period).

<Tip>
  Not sure which to use? Fee packages apply charges at transaction time. Billing packages calculate charges over a period (daily or monthly) for your orchestrator to execute. You can use both simultaneously.
</Tip>

## Fee packages: per-transaction workflow

***

Fee packages apply charges synchronously when a transaction is created. Here's how the process works, from configuring fees to seeing the results.

### Step 1 - Create your fee packages

Start by setting up **fee packages** that define how fees are applied. To do so, use the [Create a Package](/en/reference/midaz/plugins/fees-engine/create-package) endpoint. Each package contains a set of fee rules and matching criteria.

You can tailor packages to different segments or ledgers using:

* **transactionRoute** - Identifies the nature of the transaction.
* **segmentId** - Groups customers or product types.
* **ledgerId** - Defines which ledger records the transaction.
* **Minimum** and **maximum** amount - Optional thresholds for fee application.
* **routeFrom** / **routeTo** - Define how each fee moves across accounting flows.

This flexibility lets you apply distinct fees per scenario, from account-based setups to value-based.

**Managing Packages**

The following endpoints are also available for you to manage the packages:

* [List Packages](/en/reference/midaz/plugins/fees-engine/list-packages) - List all packages created.
* [Retrieve a Package](/en/reference/midaz/plugins/fees-engine/retrieve-package) - Retrieve information of a specific package.
* [Update a Package](/en/reference/midaz/plugins/fees-engine/update-package) - Update the information of a specific package.
* [Delete a Package](/en/reference/midaz/plugins/fees-engine/delete-package) - Soft-delete a package.

### (optional) Step 2 - Run an estimation

If you want to preview how a fee package would behave before committing a real transaction, use the [Estimate Transaction Fees](/en/reference/midaz/plugins/fees-engine/simulate-fees) endpoint.

This estimation helps validate:

* Which fee rules will be triggered.
* How the package will behave with the given values.
* Whether any exemptions apply.

### Step 3 - Create a transaction

Once packages are set, trigger the actual transaction using the [create a transaction](/en/reference/midaz/create-a-transaction-using-json) endpoint. Include the appropriate `transactionRoute`, `segmentId`, and `ledgerId` so the engine can evaluate the matching package.

### Step 4 - The Fees Engine kicks in

Fees Engine automatically sends a call to the [Calculate Fees for a Package](/en/reference/midaz/plugins/fees-engine/calculate-fees) endpoint and evaluates whether a package applies based on:

* **transactionRoute**
* **segmentId**
* **ledgerId**
* **Minimum** and **maximum** amount
* **waivedAccounts** (for fee exemptions)

<Note>
  Only one package is selected per transaction.
</Note>

### Step 5 - Check for exemptions

The system checks:

* If the transaction amount is outside the allowed range.
* If the source account is exempt

If either condition is met, no fees are applied and the transaction proceeds normally.

### Step 6 - Fee calculation and application

If a package is applied, Fee Engines:

* Calculates fee values based on the selected `applicationRule`.
* Applies fees proportionally across accounts if needed.
* Uses `isDeductibleFrom` to define if the fee is added or deducted.
* Routes fees to the correct `creditAccount` using the configured `routeFrom` and `routeTo`.
* Returns the full transaction result along with the `packageAppliedID` in the metadata.

### Step 7 - Ledger updates

Once fees are calculated, the **Transactions** component takes over. It processes:

* Debits from source accounts
* Credits to fee destinations
* Fee breakdown per route and account

Every movement is stored in the ledger for full traceability and auditability.

### Step 8 - Review and confirm

After execution, you can:

* Inspect the final transaction and amounts per account.
* Confirm the fee package that was applied.
* Verify all fee movements via metadata and ledger records.

## Why estimate a transaction?

***

Estimations let you preview how a specific fee package behaves, without running a real transaction or writing to the ledger.

Use estimations when:

* You want to test a specific package.
* You're debugging fee rules or thresholds.
* You want to validate exemptions, value ranges, or proportional splits.
* You need a preview before creating a real transaction.
* You're building an interface and want to show estimated fees

Fee Engines provides the [Estimate Transaction Fees](/en/reference/midaz/plugins/fees-engine/simulate-fees) endpoint for this purpose. You only have to pass a `packageId` and the endpoint returns what would happen if **that exact package were applied**.

### What do you get with an estimation?

* A full estimation of the fee rules.
* Which accounts would be charged.
* How the fee would be split.
* No impact on the ledger.

<Tip>
  Use estimations when you're not ready to commit the transaction, or want to give your users a clear fee preview.
</Tip>

## Common errors

***

Fees Engine validates every request to ensure consistency and correct fee logic. Below are the most frequent issues you might run into when creating packages or processing transactions.

| Code     | Title                                           | Message                                                                                                                                             |
| :------- | :---------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------- |
| FEE-0002 | Missing fields in request                       | Your request is missing one or more required fields. Please refer to the documentation to ensure all necessary fields are included in your request. |
| FEE-0012 | Entity not found                                | No entity was found for the given ID. Please make sure to use the correct ID for the entity you are trying to manage.                               |
| FEE-0013 | Invalid fee priority                            | The priority field in fees is invalid. Field can not be repeated.                                                                                   |
| FEE-0015 | minimumAmount greater than maximumAmount        | minimumAmount value is greater than maximumAmount.                                                                                                  |
| FEE-0022 | Failed to calculate fee                         | Error to make the calculation of a fee about a transaction.                                                                                         |
| FEE-0024 | originalAmount is required when priority is one | For Priority equals to one, referenceAmount must be 'originalAmount' for fee.                                                                       |
| FEE-0025 | Failed to apply rule: flatFee or percentual     | applicationRule flatFee or percentual must have exactly 1 calculation for Fee.                                                                      |
| FEE-0035 | Package amount range overlap                    | The maximumAmount and minimumAmount of the new package overlap with the amount range of an existing package.                                        |

<Note>
  Want the full list of error codes? You'll find it in the [Fees Engine error list](/en/reference/midaz/plugins/fees-engine/fee-engine-error-list) page in the [API reference](/en/reference/introduction).
</Note>

## Billing packages: per-period workflow

***

Billing packages calculate charges based on accumulated transaction volume or per-account maintenance over a billing period. Unlike fee packages, billing is caller-triggered — your orchestrator decides when to calculate and executes the resulting charges.

### Step 1 — Create billing packages

Set up billing packages that define your periodic charge rules. Each package is either **volume** or **maintenance** type.

**Volume package example** — charge per Pix sent with tiered pricing:

```json theme={null}
POST /v1/billing-packages
Headers:
  X-Organization-Id: org_01HZ...

Body:
{
  "label": "Pix Send Monthly Billing",
  "description": "Monthly volume billing for Pix transactions",
  "ledgerId": "ldg_01HZ...",
  "type": "volume",
  "enable": true,
  "eventFilter": {
    "transactionRoute": "pix-send",
    "status": "APPROVED"
  },
  "pricingModel": "tiered",
  "tiers": [
    { "minQuantity": 1, "maxQuantity": 100, "unitPrice": "0.50" },
    { "minQuantity": 101, "maxQuantity": 500, "unitPrice": "0.35" },
    { "minQuantity": 501, "maxQuantity": null, "unitPrice": "0.20" }
  ],
  "freeQuota": 10,
  "discountTiers": [
    { "minQuantity": 200, "discountPercentage": "5.00" },
    { "minQuantity": 400, "discountPercentage": "10.00" }
  ],
  "countMode": "perAccount",
  "assetCode": "BRL",
  "debitAccountAlias": "client-wallet",
  "creditAccountAlias": "fees-revenue"
}
```

**Maintenance package example** — monthly fee per active PF account:

```json theme={null}
POST /v1/billing-packages
Headers:
  X-Organization-Id: org_01HZ...

Body:
{
  "label": "PF Account Maintenance",
  "description": "Monthly maintenance fee for active PF accounts",
  "ledgerId": "ldg_01HZ...",
  "type": "maintenance",
  "enable": true,
  "feeAmount": "9.90",
  "assetCode": "BRL",
  "maintenanceCreditAccount": "fees-maintenance-pf",
  "accountTarget": {
    "segmentId": "seg_pf_01HZ..."
  }
}
```

### Step 2 — Trigger billing calculation

Call `POST /v1/billing/calculate` with the ledger ID and billing period. The engine evaluates all active billing packages matching the criteria.

```json theme={null}
POST /v1/billing/calculate

Body:
{
  "ledgerId": "ldg_01HZ...",
  "period": "2026-03",
  "type": "volume"
}
```

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

The `type` field is optional. Use `"volume"` or `"maintenance"` to restrict the calculation to one type. Omit it to calculate both types in a single call.

### Step 3 — Receive calculation results

The engine returns an array of results, each containing a `transactionPayload` ready to be sent to Midaz.

Each result includes:

* The billing package that generated it.
* The calculated amounts with full breakdown (tiers applied, discounts, free quota subtracted).
* A transaction payload with `source.from` (debit entries) and `distribute.to` (credit entries).
* Structured audit metadata for traceability.

### Step 4 — Execute charges

Send each `transactionPayload` to Midaz via `POST /transactions/json` to create the actual billing transactions. This step is your orchestrator's responsibility — Flowker, a cron job, or any other system.

<Note>
  The billing engine calculates and returns results. It does not create transactions in Midaz. Your orchestrator controls when and how charges are executed.
</Note>

### Step 5 — Review and reconcile

After executing the charges:

* Verify the created transactions in Midaz match the billing calculation results.
* Use the audit metadata in each result for reconciliation.
* The billing calculation is stateless — you can re-run it for the same period to verify results.

### Managing billing packages

Use these endpoints to manage existing billing packages:

* `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` only).
* `DELETE /v1/billing-packages/:id` — Soft-delete a billing package.

<Warning>
  Billing calculation follows an all-or-nothing policy. If any package fails during calculation, the entire operation fails and no partial results are returned. Fix the failing package and re-execute.
</Warning>
