Skip to main content

Lerian APIs


This section answers frequently asked questions about Lerian’s APIs, covering general behavior, configuration, and best practices across all services..
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.

Multi-tenancy and SaaS


Common questions about data isolation, tenant scoping, and how multi-tenancy works in Lerian deployments.
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.
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.
Yes. A tenant can contain multiple Organizations, each with its own Ledgers, accounts, and transactions. All of them are scoped to your tenant automatically.
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.

Midaz


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

Organizations

No, each Organization operates independently and does not communicate with others.
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.
Yes, an Organization can have more than one Plugin associated with it.
Yes, an Organization can manage multiple Ledgers.
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:
1
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.
2
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).
This approach ensures seamless and controlled value transfers between ledgers across different organizations.

Ledgers

No, Ledgers do not communicate directly. Transfers between Ledgers require orchestration.
You must orchestrate the process and transfer the amount to an External Account. Typically, this involves two steps:
1
Ledger A -> External Account.
2
External Account -> Ledger B.
No, a single Ledger can support multiple Plugins. For example, a Ledger can handle both Exchange and Pix Plugins simultaneously.

Assets

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

Portfolios

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.

Accounts

No, each Account is associated with a single Asset, and this association cannot be changed.
An External Account is used to receive funds from outside the Ledger, effectively bringing money into the system.
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.
No. Each account (account_id) can be linked to only one Segment (segment_id).
Nope. You can create as many Accounts as your setup needs. No limits, no constraints—just the flexibility to scale your way.
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.

Transactions

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

Entities

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.

Idempotency

Midaz treats the request as new every time. This means retries may result in duplicated operations.
No. Keys should be scoped to a single operation and endpoint.
Only the TTL from the first request is used. Changing it later has no effect.
Yes. Midaz replays the full response, including headers and body, for completed requests.
The default window is 300 seconds (5 minutes), but you can customize it up to your allowed limit per endpoint.

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

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

Plugin Fees


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

General Concepts

The Plugin Fees is a Lerian service responsible for calculating and charging fees on financial transactions. Learn more in the Plugin Fees 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.
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.
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>
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.
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.

Fee Packages

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.
Send a POST /v1/packages with the following body. See the Create Package API reference for full details.
{
  "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"
    }
  }
}
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.
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.
If maximumAmount is not defined, the package may apply without an upper limit — check the validation rules for your version.
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").
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.
"waivedAccounts": ["vip-account", "employee-account"]
Any transaction originating from or destined to these accounts will not be charged by this package.
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

Calculation Models

The applicationRule field inside calculationModel defines how the fee is calculated. See Calculation Models for full details. There are three options:
RuleDescription
flatFeeFixed-amount fee
percentualPercentage fee based on the reference amount
maxBetweenTypesCalculates both flat and percentage; applies the greater result
Use exactly 1 calculation of type flat:
"calculationModel": {
  "applicationRule": "flatFee",
  "calculations": [
    { "type": "flat", "value": "5.00" }
  ]
}
This charges a fixed 5.00 regardless of the transaction amount.
Use exactly 1 calculation of type percentage:
"calculationModel": {
  "applicationRule": "percentual",
  "calculations": [
    { "type": "percentage", "value": "2.50" }
  ]
}
This charges 2.5% of the transaction’s reference amount.
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:
"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.
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.

Important Fields

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.
The fee with priority: 1 (the first to be executed) must use originalAmount. This makes sense: there are no prior fees to consider.
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
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.
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.
"creditAccount": "admin-fee-revenue-account"
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.

Billing Packages

These are periodic charge packages, independent of per-transaction fee calculation. See 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.
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.
{
  "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"
}
The last tier must be unbounded (no maxQuantity). There must be no gaps or overlaps between tiers.
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.
{
  "type": "maintenance",
  "feeAmount": "15.00",
  "assetCode": "BRL",
  "maintenanceCreditAccount": "maintenance-revenue-account",
  "accountTarget": {
    "segmentId": "seg_premium_clients"
  }
}
accountTarget must have exactly one of the three fields: segmentId, portfolioId, or aliases (maximum 100 aliases).
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:
"tiers": [
  { "minQuantity": 0, "maxQuantity": 500, "unitPrice": "0.80" },
  { "minQuantity": 501, "maxQuantity": 2000, "unitPrice": "0.60" },
  { "minQuantity": 2001, "unitPrice": "0.40" }
]
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.
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.
It defines how transactions are counted:
  • perRoute: counts transactions by route (e.g., total approved PIX).
  • perAccount: counts transactions per individual account.

Fee Calculation and Estimation

EndpointWhen to use
POST /v1/feesCalculate the actual fee of an ongoing transaction. See the Calculate Fees API reference. The system automatically finds applicable packages based on ledger, segment, route, and amount.
POST /v1/estimatesSimulate 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.
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.
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.
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.
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.

Common Errors

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:
{
  "priority": 1,
  "referenceAmount": "originalAmount"
}
Fees with isDeductibleFrom: true can only use referenceAmount: "originalAmount". Update the field:
{
  "isDeductibleFrom": true,
  "referenceAmount": "originalAmount"
}
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.
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.
Volume billing tiers must cover all ranges without gaps. Check that the minQuantity of each tier is exactly maxQuantity + 1 of the previous tier.
// ❌ 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" }
The last tier in volume billing must have no upper limit (no maxQuantity). This ensures transactions above the highest defined range are still priced.
In maintenance billing, the accountTarget field accepts only one of the three options. Don’t combine fields:
// ❌ Wrong
"accountTarget": {
  "segmentId": "seg_abc",
  "portfolioId": "port_xyz"
}

// ✅ Correct
"accountTarget": {
  "segmentId": "seg_abc"
}
Yes. The aliases field accepts a maximum of 100 aliases per maintenance Billing Package.
The applicationRule: "flatFee" accepts exactly 1 calculation, and it must be of type flat. Do not use percentage with flatFee.
// ✅ Correct
"calculationModel": {
  "applicationRule": "flatFee",
  "calculations": [{ "type": "flat", "value": "10.00" }]
}
Analogous to flatFee, the applicationRule: "percentual" accepts exactly 1 calculation of type percentage.
maxBetweenTypes requires at least 2 calculations to work — it needs values to compare. Provide at least one flat and one percentage.
Diagnostic checklist — see also 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?
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.