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

# FAQ

> Find answers to common questions about Lerian APIs, multi-tenancy, SaaS isolation, pagination, and platform configuration.

## Lerian APIs

***

This section answers frequently asked questions about Lerian's APIs, covering general behavior, configuration, and best practices across all services..

<Accordion title="Is there a maximum number of records per page in API listings? Can I increase this limit?">
  Yes. By default, the maximum number of records per page is **100**. This limit ensures consistent performance and helps manage the volume of data transferred in each request. However, you can increase this value by setting the `MAX_PAGINATION_LIMIT` environment variable in your deployment configuration. Once updated and the application is restarted, the API will accept larger page sizes.

  **Important**: Increasing the page size may affect response times, especially in environments handling large datasets. Always test thoroughly in staging before applying changes in production.
</Accordion>

## Multi-tenancy and SaaS

***

Common questions about data isolation, tenant scoping, and how multi-tenancy works in Lerian deployments.

<AccordionGroup>
  <Accordion title="Is my data isolated from other customers in SaaS?">
    Yes. Every tenant operates on a separate database. The platform resolves your tenant from the JWT on every request and routes it to your isolated database. There is no way to access another tenant's data through the API. Learn more about [multi-tenancy](/en/multi-tenancy).
  </Accordion>

  <Accordion title="Do I need to pass a tenant ID in my API requests?">
    No. Your tenant context is embedded in the JWT access token you receive during authentication. The platform resolves it automatically - you don't need to include any tenant identifier in headers or request bodies.
  </Accordion>

  <Accordion title="Can I have multiple Organizations under a single tenant?">
    Yes. A tenant can contain multiple Organizations, each with its own Ledgers, accounts, and transactions. All of them are scoped to your tenant automatically.
  </Accordion>

  <Accordion title="Is the API different between SaaS and self-hosted deployments?">
    No. The API surface is identical - same endpoints, same payloads, same responses. The only difference is that SaaS requires authentication on every request, and your token automatically scopes all operations to your tenant.
  </Accordion>
</AccordionGroup>

## Midaz

***

Here, you will find the answers to common questions about Organizations, Ledgers, Accounts, Transactions, and more in Midaz.

### Organizations

<AccordionGroup>
  <Accordion title="Do different Organizations communicate with each other?">
    No, each Organization operates independently and does not communicate with others.
  </Accordion>

  <Accordion title="Can I use a single license across multiple Organizations?">
    No, each license is tied to a specific Organization. If you need support for multiple Organizations, you must acquire separate licenses for each. The same rule applies to Plugins.
  </Accordion>

  <Accordion title="Can an Organization have multiple Plugins?">
    Yes, an Organization can have more than one Plugin associated with it.
  </Accordion>

  <Accordion title="Can an Organization have multiple Ledgers?">
    Yes, an Organization can manage multiple Ledgers.
  </Accordion>

  <Accordion title="Can I create transactions between a Parent Organization and a Child Organization?">
    While you can create a **Parent Organization** and a **Child Organization**, each **Organization** maintains its own Ledger, operating independently. Since transactions cannot move value directly between ledgers, you need to orchestrate the transfer with the following steps:

    <Steps>
      <Step>
        Initiate a transaction in the source ledger, transferring the amount from the original account (**source**) to the asset's **external account** (distribute). This removes the value from the original ledger.
      </Step>

      <Step>
        **Create a second transaction** in the destination ledger, where the **source** is now the asset's **external account**, and the amount is allocated to the receiving account (**distribute**).
      </Step>
    </Steps>

    This approach ensures seamless and controlled value transfers between ledgers across different organizations.
  </Accordion>
</AccordionGroup>

### Ledgers

<AccordionGroup>
  <Accordion title="Do different Ledgers communicate with each other?">
    No, Ledgers do not communicate directly. Transfers between Ledgers require orchestration.
  </Accordion>

  <Accordion title="How can I make transactions between Ledgers?">
    You must orchestrate the process and transfer the amount to an External Account. Typically, this involves two steps:

    <Steps>
      <Step>
        Ledger A -> External Account.
      </Step>

      <Step>
        External Account -> Ledger B.
      </Step>
    </Steps>
  </Accordion>

  <Accordion title="Do I need a separate Ledger for each Plugin?">
    No, a single Ledger can support multiple Plugins. For example, a Ledger can handle both Exchange and Pix Plugins simultaneously.
  </Accordion>
</AccordionGroup>

### Assets

<AccordionGroup>
  <Accordion title="Can an Asset be linked to multiple Accounts?">
    No, each Asset is linked to a single Account. However, each Asset will also be linked to an External Account that is automatically created when the Asset is created.
  </Accordion>

  <Accordion title="What types of Assets can I use?">
    Midaz is built for flexibility, supporting a wide range of Assets:

    * *currency*: Traditional fiat currencies like BRL, USD, and EUR.
    * *crypto*: Digital assets such as BTC, ETH, and other cryptocurrencies.
    * *commodities*: Tangible goods like gold, soybean, and oil.
    * *others*: Custom Assets, including loyalty points and tokenized securities.
  </Accordion>
</AccordionGroup>

### Portfolios

<Accordion title="How does a Portfolio work?">
  A **Portfolio** groups accounts that belong to the same entity (**CPF/CNPJ**). For example, if a single CPF has two different `segment_id` values, it will also have two corresponding `account_id` values. To simplify retrieval, a Portfolio is created for that CPF, linking both accounts under a single structure. This ensures easier access and management of related accounts.
</Accordion>

### Accounts

<AccordionGroup>
  <Accordion title="Can an Account be associated with multiple Assets?">
    No, each Account is associated with a single Asset, and this association cannot be changed.
  </Accordion>

  <Accordion title="What is an External Account?">
    An External Account is used to receive funds from outside the Ledger, effectively bringing money into the system.
  </Accordion>

  <Accordion title="How can I create an External Account?">
    Midaz automatically sets up an **External Account** when you create an Asset, ensuring seamless backing for all transactions flowing in and out of the Ledger.
  </Accordion>

  <Accordion title="Can an Account be linked to several Segments?">
    No. Each account (`account_id`) can be linked to only one Segment (`segment_id`).
  </Accordion>

  <Accordion title="Is there a limit to how many Accounts I can create in Midaz?">
    Nope. You can create as many Accounts as your setup needs. No limits, no constraints—just the flexibility to scale your way.
  </Accordion>

  <Accordion title="What is the process for adding funds to an account or performing a cash-in using money coming from outside the Ledger (Midaz) environment?">
    To understand the balance top-up process, let's consider the following points:

    1. In the Midaz Ledger, when an Asset (e.g., BRL) is created, an External Account associated with that asset is also generated.
    2. This External Account acts as a gateway between the Lerian ecosystem and the external world. In other words, it serves as a mirror of the balances held by the institution in its PI account, settlement account, reserve account, or even a traditional bank or payment account holding the actual funds.
    3. To deposit funds into a user account with a specific Asset coming from outside the Midaz Ledger, the process is as follows:
       * Initiate a transaction where the source is the External Account and the destination is the target account(s).
       * As a result, the External Account will be debited by the transferred amount (becoming negative), while the destination account(s) will be credited accordingly, based on the values provided in the transaction payload.
  </Accordion>
</AccordionGroup>

### Transactions

<AccordionGroup>
  <Accordion title="What is the minimum structure of a Transaction?">
    A Transaction must have at least two Operations. For example, transferring R\$ 100 from Account A to Account B consists of:

    * **Operation 1:** Debit R\$ 100 from Account A.
    * **Operation 2:** Credit R\$ 100 to Account B.
  </Accordion>

  <Accordion title="Is it possible to generate a PDF transfer receipt containing the details of a completed transaction?">
    Lerian provides clients with multiple options to access transaction receipts:

    1. **Via APIs** - Retrieve transaction data through our APIs, enabling you to generate a visual receipt in the format of your choice.
    2. **Using the Reporter** - Extract transaction data and create customized visual receipts.
    3. **Through the Console** - Access transaction information directly from the Lerian Console.
  </Accordion>
</AccordionGroup>

### Entities

<Accordion title="How can I create an Entity?">
  Currently, the Entity (`entity_id`) is open for external IDs, with no validation enforced by Midaz. This means you can use the IDs that already exist in your database, seamlessly integrating them into your system.
</Accordion>

### Idempotency

<AccordionGroup>
  <Accordion title="What happens if I don't send an idempotency key?">
    Midaz treats the request as new every time. This means retries may result in duplicated operations.
  </Accordion>

  <Accordion title="Can I reuse an idempotency key across endpoints?">
    No. Keys should be scoped to a single operation and endpoint.
  </Accordion>

  <Accordion title="What happens if I change the TTL on a retry?">
    Only the TTL from the first request is used. Changing it later has no effect.
  </Accordion>

  <Accordion title="Will the replayed response always be identical?">
    Yes. Midaz replays the full response, including headers and body, for completed requests.
  </Accordion>

  <Accordion title="What's the default TTL if I don't send X-TTL?">
    The default window is **300 seconds** (5 minutes), but you can customize it up to your allowed limit per endpoint.
  </Accordion>
</AccordionGroup>

### Accounting in Midaz

<Accordion title="How can I reflect my own Chart of Accounts in Midaz?">
  A: Midaz allows you to mirror your organization's official **Chart of Accounts** directly in the platform by configuring two core features:

  * [Account Types](/en/midaz/accounts) - Create the logical categories from your chart (e.g., Assets, Liabilities, Revenue, Expenses) and assign them to accounts in your ledger. When the Account Types feature is enabled, the type field in the Accounts API becomes mandatory and must match one of the values you've registered.
  * [Transaction Routing](/en/midaz/transaction-routing-entities) - Use Operation Routes to validate each "leg" of a transaction (e.g., debit must come from an account type `user_wallet`) and Transaction Routes to define complete transaction patterns that align with your accounting logic.

  By combining Account Types and Transaction Routing, you can enforce your accounting rules at the ledger level - ensuring every transaction is validated and categorized according to your Chart of Accounts, without hardcoding rules in your business logic.
</Accordion>

## Plugins

***

Plugins extend the capabilities of Midaz, enabling seamless integration and process orchestration. Designed to remove complexity, they provide powerful abstractions that let you focus on your business model while ensuring efficiency and scalability.

Explore the most common questions about how plugins work, their deployment, and the options available to enhance your operations.

<AccordionGroup>
  <Accordion title="What are Plugins?">
    Plugins are technologies integrated into the Midaz ledger, designed to simplify process integration and orchestration. They provide abstractions that allow clients to focus on their business model without needing to build or manage essential system logic that falls outside their domain.
  </Accordion>

  <Accordion title="Can plugins be used without Midaz?">
    No. Plugins are designed to operate exclusively with Midaz. They provide specific abstractions and orchestrate transactions based on the ledger's structure, ensuring precise and efficient integration.
  </Accordion>

  <Accordion title="How are plugins distributed?">
    Once contracted, plugins are provided and installed within the client's infrastructure (on-premise model), alongside their Midaz instance. Applications connect according to the specific functionality of each plugin.
  </Accordion>

  <Accordion title="What plugin options does Lerian offer?">
    Lerian provides two types of plugins, categorized by their origin:

    * **Native Plugins:** Developed and fully integrated into the Midaz ledger by Lerian, these plugins ensure complete support and seamless integration with the platform.
    * **Marketplace Plugins:** Created by Lerian's partners to serve specific market niches, these plugins are available in the marketplace. Lerian facilitates their integration into Midaz, but their offering and support are managed directly by the respective partners.
  </Accordion>
</AccordionGroup>

## Plugin Fees

***

Frequently asked questions about the Plugin Fees — the Lerian service responsible for calculating and charging fees on financial transactions.

### General Concepts

<AccordionGroup>
  <Accordion title="What is the Plugin Fees?">
    The Plugin Fees is a Lerian service responsible for calculating and charging fees on financial transactions. Learn more in the [Plugin Fees overview](/en/midaz/plugins/fees-engine/fees-engine-overview). It operates across three main domains:

    * **Fee Packages (`/v1/packages`):** defines charging rules per transaction (flat fee, percentage, or whichever is greater).
    * **Billing Packages (`/v1/billing-packages`):** defines periodic charges based on transaction volume or account maintenance.
    * **Calculation and Estimation (`/v1/fees` and `/v1/estimates`):** endpoints for calculating fees in real time or simulating before confirming.
  </Accordion>

  <Accordion title="How does the Plugin Fees fit into the Lerian ecosystem?">
    The Plugin Fees is an optional module that integrates with Midaz (Lerian's ledger). It intercepts transactions and, based on configured rules, determines how much should be charged — and from whom. Fee revenue is credited directly to ledger accounts configured by the client.
  </Accordion>

  <Accordion title="What do I need to send in every request to the Plugin Fees?">
    All requests require the `X-Organization-Id` header with your Organization ID in Midaz. This is an organization-scope header specific to Plugin Fees, not a tenant identifier — your tenant context is still resolved automatically from the JWT. When the authentication plugin is active, a Bearer token in the `Authorization` header is also required.

    ```
    X-Organization-Id: <your-organization-id>
    Authorization: Bearer <your-token>
    ```
  </Accordion>

  <Accordion title="What database does the Plugin Fees use for storage?">
    The Plugin Fees uses **MongoDB** as its storage backend. Deletions follow the **soft-delete** pattern — records are not physically removed, only marked with `deletedAt`. This means "deleted" records don't appear in listings but can still be audited.
  </Accordion>

  <Accordion title="What is the minimum Midaz version required to use the Plugin Fees?">
    **Midaz v3.6.0** or higher. The current version of the Plugin Fees depends on Transaction module APIs that are only available from v3.6.0 onwards. Earlier versions of Midaz are not compatible.
  </Accordion>
</AccordionGroup>

### Fee Packages

<AccordionGroup>
  <Accordion title="What is a Fee Package?">
    A Fee Package (`Package`) is a set of charging rules grouped under a `feeGroupLabel`. Each package is linked to an **Organization + Ledger** and optionally to a **Segment**. A package can contain multiple individual fees (`Fee` objects), each with its own calculation logic. Learn more about [Fee Packages](/en/midaz/plugins/fees-engine/using-fee-engine).
  </Accordion>

  <Accordion title="How do I create a Fee Package?">
    Send a `POST /v1/packages` with the following body. See the [Create Package API reference](/en/reference/midaz/plugins/fees-engine/create-package) for full details.

    ```json theme={null}
    {
      "feeGroupLabel": "Digital Account Fees",
      "ledgerId": "ldg_abc123",
      "segmentId": "seg_xyz456",
      "minimumAmount": "100.00",
      "maximumAmount": "50000.00",
      "transactionRoute": "PIX",
      "enable": true,
      "waivedAccounts": ["exempt-account-1", "exempt-account-2"],
      "fees": {
        "admin_fee": {
          "feeLabel": "Administrative Fee",
          "calculationModel": {
            "applicationRule": "percentual",
            "calculations": [
              { "type": "percentage", "value": "1.50" }
            ]
          },
          "referenceAmount": "originalAmount",
          "priority": 1,
          "isDeductibleFrom": true,
          "creditAccount": "fee-revenue-account"
        }
      }
    }
    ```
  </Accordion>

  <Accordion title="Can a package be temporarily disabled?">
    Yes. Set the `enable` field to `false` when creating or updating the package. A disabled package is not considered during fee calculation, even if the transaction context matches its scope.
  </Accordion>

  <Accordion title="How does the package scope work (minimumAmount / maximumAmount)?">
    The package is only applied to transactions whose value falls within the `[minimumAmount, maximumAmount]` range. If the transaction doesn't fit this range, the package is ignored.

    **Example:** A package with `minimumAmount: 100` and `maximumAmount: 5000` will only charge fees on transactions between 100 and 5,000.

    <Note>If `maximumAmount` is not defined, the package may apply without an upper limit — check the validation rules for your version.</Note>
  </Accordion>

  <Accordion title="Can I filter a package by transaction route?">
    Yes. Use the `transactionRoute` field in the package. When set, the package will only be considered for transactions with that specific route (e.g., `"PIX"`, `"TED"`, `"BOLETO"`).
  </Accordion>

  <Accordion title="What are waivedAccounts?">
    These are account aliases that are **exempt** from fees within that package. If the sender or recipient of a transaction is an account listed in `waivedAccounts`, the package fees are not applied to it.

    ```json theme={null}
    "waivedAccounts": ["vip-account", "employee-account"]
    ```

    Any transaction originating from or destined to these accounts will not be charged by this package.
  </Accordion>

  <Accordion title="Do listing endpoints have pagination?">
    Yes. The listing endpoints (`GET /v1/packages`, `GET /v1/billing-packages`) support the `limit` and `page` query parameters for pagination.

    ```
    GET /v1/packages?limit=20&page=2
    ```
  </Accordion>
</AccordionGroup>

### Calculation Models

<AccordionGroup>
  <Accordion title="What calculation models are available?">
    The `applicationRule` field inside `calculationModel` defines how the fee is calculated. See [Calculation Models](/en/midaz/plugins/fees-engine/fee-engine-calculation) for full details. There are three options:

    | Rule              | Description                                                         |
    | ----------------- | ------------------------------------------------------------------- |
    | `flatFee`         | Fixed-amount fee                                                    |
    | `percentual`      | Percentage fee based on the reference amount                        |
    | `maxBetweenTypes` | Calculates both flat and percentage; applies the **greater** result |
  </Accordion>

  <Accordion title="How do I configure a flat fee (flatFee)?">
    Use exactly **1 calculation** of type `flat`:

    ```json theme={null}
    "calculationModel": {
      "applicationRule": "flatFee",
      "calculations": [
        { "type": "flat", "value": "5.00" }
      ]
    }
    ```

    This charges a fixed 5.00 regardless of the transaction amount.
  </Accordion>

  <Accordion title="How do I configure a percentage fee (percentual)?">
    Use exactly **1 calculation** of type `percentage`:

    ```json theme={null}
    "calculationModel": {
      "applicationRule": "percentual",
      "calculations": [
        { "type": "percentage", "value": "2.50" }
      ]
    }
    ```

    This charges 2.5% of the transaction's reference amount.
  </Accordion>

  <Accordion title="How does maxBetweenTypes work?">
    `maxBetweenTypes` requires **2 or more calculations** (combining `flat` and `percentage`). The system calculates both and applies the **greater resulting value**.

    **Example:** Minimum fee of 3.00 or 1% of the value — whichever is greater:

    ```json theme={null}
    "calculationModel": {
      "applicationRule": "maxBetweenTypes",
      "calculations": [
        { "type": "flat", "value": "3.00" },
        { "type": "percentage", "value": "1.00" }
      ]
    }
    ```

    For a 200 transaction: 1% = 2.00 vs. 3.00 flat → charges **3.00**.
    For a 500 transaction: 1% = 5.00 vs. 3.00 flat → charges **5.00**.
  </Accordion>

  <Accordion title="Can I mix multiple percentages in maxBetweenTypes?">
    Yes. You can include any combination of `flat` and `percentage` — the system evaluates all and applies the greatest. However, `flatFee` and `percentual` require exactly 1 calculation; only `maxBetweenTypes` accepts 2 or more.
  </Accordion>
</AccordionGroup>

### Important Fields

<AccordionGroup>
  <Accordion title="What is referenceAmount and how does it affect calculation?">
    The `referenceAmount` defines **which value** the fee is calculated on:

    * `originalAmount`: the original transaction value, **before** any fees are applied.
    * `afterFeesAmount`: the transaction value **after** higher-priority fees have already been applied.

    <Note>The fee with `priority: 1` (the first to be executed) **must** use `originalAmount`. This makes sense: there are no prior fees to consider.</Note>
  </Accordion>

  <Accordion title="What is isDeductibleFrom and when should I use it?">
    When `isDeductibleFrom: true`, the fee is **deducted from the amount sent by the sender**. The recipient receives the amount already discounted, and the sender pays extra to cover the charge.

    When `false`, the fee is charged **separately** (the sender sends the full amount and the fee is debited apart).

    **Constraints:**

    * `isDeductibleFrom: true` requires `referenceAmount: originalAmount`
    * If the type is `percentage`: the value cannot exceed 100
    * If the type is `flat`: the value cannot exceed the package's `minimumAmount`
  </Accordion>

  <Accordion title="How does the priority field work?">
    The `priority` defines the **execution order** of fees within a package. Lower values are executed first.

    * `priority: 1` → executed first (must use `originalAmount`)
    * `priority: 2` → executed after, can use `afterFeesAmount`

    Use priorities to create fee chaining — for example, an administrative fee calculated on the original amount, followed by an IOF fee calculated on the amount after the administrative fee.
  </Accordion>

  <Accordion title="What is creditAccount?">
    It's the alias of the ledger account where the fee revenue will be credited. Each fee can have a different `creditAccount` — useful when different fees need to be accounted for in different cost centers.

    ```json theme={null}
    "creditAccount": "admin-fee-revenue-account"
    ```
  </Accordion>

  <Accordion title="What are routeFrom and routeTo inside a fee?">
    These fields define the routes of the **accounting legs** generated by the fee charge. They are optional and allow tracking the origin and destination of fee movements in the ledger with granularity.
  </Accordion>
</AccordionGroup>

### Billing Packages

<AccordionGroup>
  <Accordion title="What are Billing Packages?">
    These are **periodic** charge packages, independent of per-transaction fee calculation. See [Billing Package examples](/en/midaz/plugins/fees-engine/billing-package-examples) for detailed use cases. There are two types:

    * **`volume`:** charges based on the **number of transactions** in a period, with tiered pricing.
    * **`maintenance`:** charges a **fixed fee per account** in a given scope.
  </Accordion>

  <Accordion title="When should I use volume billing?">
    Use it when you want to charge clients based on the **number of processed transactions** — a common model for payment platforms with volume-based pricing. You define price tiers that apply as volume grows.

    ```json theme={null}
    {
      "type": "volume",
      "eventFilter": {
        "transactionRoute": "PIX",
        "status": "approved"
      },
      "pricingModel": "tiered",
      "tiers": [
        { "minQuantity": 0, "maxQuantity": 1000, "unitPrice": "0.50" },
        { "minQuantity": 1001, "unitPrice": "0.30" }
      ],
      "assetCode": "BRL",
      "debitAccountAlias": "client-account",
      "creditAccountAlias": "volume-revenue-account"
    }
    ```

    <Note>The last tier must be **unbounded** (no `maxQuantity`). There must be no gaps or overlaps between tiers.</Note>
  </Accordion>

  <Accordion title="When should I use maintenance billing?">
    Use it when you want to charge a **fixed periodic fee per account** — for example, a monthly fee per active account. You specify the scope (`segmentId`, `portfolioId`, or `aliases`) and the fee amount.

    ```json theme={null}
    {
      "type": "maintenance",
      "feeAmount": "15.00",
      "assetCode": "BRL",
      "maintenanceCreditAccount": "maintenance-revenue-account",
      "accountTarget": {
        "segmentId": "seg_premium_clients"
      }
    }
    ```

    <Note>`accountTarget` must have exactly **one** of the three fields: `segmentId`, `portfolioId`, or `aliases` (maximum 100 aliases).</Note>
  </Accordion>

  <Accordion title="How do tiers work in volume billing?">
    Tiers define the **unit price per tier** as volume increases. Required rules:

    1. Must be **contiguous** — no gaps between tiers (`minQuantity` of the next = `maxQuantity` of the previous + 1).
    2. Must not **overlap**.
    3. The **last tier must be unbounded** (no `maxQuantity`).

    **Example of correct tiers:**

    ```json theme={null}
    "tiers": [
      { "minQuantity": 0, "maxQuantity": 500, "unitPrice": "0.80" },
      { "minQuantity": 501, "maxQuantity": 2000, "unitPrice": "0.60" },
      { "minQuantity": 2001, "unitPrice": "0.40" }
    ]
    ```
  </Accordion>

  <Accordion title="What is freeQuota?">
    It's a **free allowance** — a number of transactions that are not charged before tiers start to apply. Useful for pricing models with a minimum included volume.

    **Example:** `freeQuota: 100` means the first 100 transactions in the period are not charged.
  </Accordion>

  <Accordion title="What are discountTiers?">
    These are discount tiers applicable to volume billing. They allow reducing the charged amount based on additional criteria, complementing the logic of the main `tiers`.
  </Accordion>

  <Accordion title="What is countMode in volume billing?">
    It defines **how transactions are counted**:

    * `perRoute`: counts transactions by route (e.g., total approved PIX).
    * `perAccount`: counts transactions per individual account.
  </Accordion>
</AccordionGroup>

### Fee Calculation and Estimation

<AccordionGroup>
  <Accordion title="What is the difference between /v1/fees and /v1/estimates?">
    | Endpoint             | When to use                                                                                                                                                                                                                                             |
    | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
    | `POST /v1/fees`      | Calculate the **actual** fee of an ongoing transaction. See the [Calculate Fees API reference](/en/reference/midaz/plugins/fees-engine/calculate-fees). The system automatically finds applicable packages based on ledger, segment, route, and amount. |
    | `POST /v1/estimates` | **Simulate** the fee of a specific package before confirming the transaction. Useful for showing end users the cost before execution. See the [Simulate Fees API reference](/en/reference/midaz/plugins/fees-engine/simulate-fees).                     |
  </Accordion>

  <Accordion title="How does /v1/fees work?">
    The endpoint receives the transaction data and the system **automatically finds** the applicable packages, considering:

    * `ledgerId` — required
    * `segmentId` — optional
    * `transactionRoute` — optional
    * Transaction value — compared with the package's `minimumAmount`/`maximumAmount`

    Fees from all matching packages are calculated and returned.
  </Accordion>

  <Accordion title="How does /v1/estimates work?">
    The `/v1/estimates` endpoint allows you to simulate the fee of a **specific package** (`packageId`), without needing an actual transaction. Ideal for:

    * Displaying the estimated cost to the user before confirming.
    * Testing configurations of newly created packages.
    * Building fee simulators in your product.
  </Accordion>

  <Accordion title="Can I use /v1/estimates in production to show fees to end users?">
    Yes. `/v1/estimates` is a read-only endpoint — it doesn't alter state or register transactions. It's safe to use in UX flows to show the cost before confirmation.
  </Accordion>

  <Accordion title="How do I calculate billing?">
    After configuring Billing Packages, use the endpoint:

    ```
    POST /v1/billing/calculate
    ```

    This endpoint processes the configured rules and generates the charges for the given period. See the [Calculate Billing API reference](/en/reference/midaz/plugins/fees-engine/calculate-billing).
  </Accordion>
</AccordionGroup>

### Common Errors

<AccordionGroup>
  <Accordion title="&#x22;Priority 1 must use originalAmount&#x22; — what does this mean?">
    The fee with `priority: 1` must have `referenceAmount: "originalAmount"`. This is because it's the first fee to be calculated — there are no prior fees to base the calculation on.

    **Fix:**

    ```json theme={null}
    {
      "priority": 1,
      "referenceAmount": "originalAmount"
    }
    ```
  </Accordion>

  <Accordion title="&#x22;isDeductibleFrom requires originalAmount&#x22; — how to fix?">
    Fees with `isDeductibleFrom: true` can only use `referenceAmount: "originalAmount"`. Update the field:

    ```json theme={null}
    {
      "isDeductibleFrom": true,
      "referenceAmount": "originalAmount"
    }
    ```
  </Accordion>

  <Accordion title="&#x22;Flat fee value cannot exceed minimumAmount&#x22; — why?">
    When `isDeductibleFrom: true` and the type is `flat`, the fee value cannot be greater than the package's `minimumAmount`. This prevents scenarios where the fee exceeds the minimum transaction value itself.

    **Example:** If `minimumAmount: 100`, the flat fee cannot exceed 100.
  </Accordion>

  <Accordion title="&#x22;Percentage value cannot exceed 100&#x22; — when does this occur?">
    This error occurs when `isDeductibleFrom: true` and the type is `percentage` with a value above 100. A deductible percentage fee of 100% would zero out the transaction — values above that are invalid.
  </Accordion>

  <Accordion title="&#x22;Tiers must be contiguous&#x22; — how to fix?">
    Volume billing tiers must cover all ranges without gaps. Check that the `minQuantity` of each tier is exactly `maxQuantity + 1` of the previous tier.

    ```json theme={null}
    // ❌ Wrong — gap between 500 and 600
    { "minQuantity": 0, "maxQuantity": 500, "unitPrice": "0.80" },
    { "minQuantity": 600, "unitPrice": "0.40" }

    // ✅ Correct
    { "minQuantity": 0, "maxQuantity": 500, "unitPrice": "0.80" },
    { "minQuantity": 501, "unitPrice": "0.40" }
    ```
  </Accordion>

  <Accordion title="&#x22;Last tier must be unbounded&#x22; — what does this mean?">
    The last tier in volume billing must have **no upper limit** (no `maxQuantity`). This ensures transactions above the highest defined range are still priced.
  </Accordion>

  <Accordion title="&#x22;accountTarget must have exactly one of: segmentId, portfolioId, aliases&#x22;">
    In maintenance billing, the `accountTarget` field accepts only **one** of the three options. Don't combine fields:

    ```json theme={null}
    // ❌ Wrong
    "accountTarget": {
      "segmentId": "seg_abc",
      "portfolioId": "port_xyz"
    }

    // ✅ Correct
    "accountTarget": {
      "segmentId": "seg_abc"
    }
    ```
  </Accordion>

  <Accordion title="Is there a limit on aliases in accountTarget?">
    Yes. The `aliases` field accepts a maximum of **100 aliases** per maintenance Billing Package.
  </Accordion>

  <Accordion title="&#x22;flatFee requires exactly 1 calculation of type flat&#x22;">
    The `applicationRule: "flatFee"` accepts exactly 1 calculation, and it must be of type `flat`. Do not use `percentage` with `flatFee`.

    ```json theme={null}
    // ✅ Correct
    "calculationModel": {
      "applicationRule": "flatFee",
      "calculations": [{ "type": "flat", "value": "10.00" }]
    }
    ```
  </Accordion>

  <Accordion title="&#x22;percentual requires exactly 1 calculation of type percentage&#x22;">
    Analogous to `flatFee`, the `applicationRule: "percentual"` accepts exactly 1 calculation of type `percentage`.
  </Accordion>

  <Accordion title="&#x22;maxBetweenTypes requires 2 or more calculations&#x22;">
    `maxBetweenTypes` requires at least 2 calculations to work — it needs values to compare. Provide at least one `flat` and one `percentage`.
  </Accordion>

  <Accordion title="The package is not being applied to the transaction — what should I check?">
    Diagnostic checklist — see also [Best Practices](/en/midaz/plugins/fees-engine/fees-engine-best-practices):

    * **`enable`:** is the package active (`enable: true`)?
    * **`ledgerId`:** is the package linked to the correct ledger?
    * **`minimumAmount` / `maximumAmount`:** is the transaction value within the range?
    * **`transactionRoute`:** if the package has `transactionRoute`, does the transaction use the same route?
    * **`segmentId`:** if the package is scoped to a segment, does the account belong to it?
    * **`waivedAccounts`:** is the account listed as exempt?
  </Accordion>

  <Accordion title="Can a deleted record be recovered?">
    Technically, records are soft-deleted (marked with `deletedAt`) and are not removed from the database. However, the API does not expose restoration endpoints by default. Contact the Lerian team if you need to recover an accidentally deleted record. For a complete list of error codes, see the [Error Codes reference](/en/reference/midaz/plugins/fees-engine/fee-engine-error-list).
  </Accordion>
</AccordionGroup>
