Skip to main content
A Balance represents the value that a specific account holds in Midaz. It reflects the result of all operations — debits and credits — over time. Each balance belongs to one asset, such as BRL, USD, or BTC.

Multiple balances


A single account can hold several balances. A unique key identifies each one. This lets institutions segment funds without creating multiple accounts for the same customer.
External accounts cannot have multiple balances. Each external account holds exactly one balance.
Typical use cases include:
  • Investment reserves
  • Credit limits
  • Collateral (blocked) funds
  • Day-to-day operational funds
This approach (Figure 1) increases flexibility. It keeps the double-entry model — debit and credit — intact for accounting consistency, traceability, and transparency.
Account with multiple balances

Figure 1. Multiple balances diagram.

If a transaction does not provide a balanceKey, Midaz uses the account’s default balance.

Balance key

A key field identifies each balance uniquely within the account.
  • Maximum length: 100 characters, with no whitespace.
  • Default key: "default". Midaz creates the default balance automatically when the account is created.
  • Uniqueness: Each key must be unique per account. A request to create a balance with a key that already exists on the account returns an error.
  • In transactions: If a transaction does not specify a balanceKey, Midaz uses the balance with key "default".
You set the key at creation time and cannot change it later. Choose descriptive keys like "credit", "collateral", or "savings" to make your balance model self-documenting.

Permission flags

Each balance has two independent permission flags that control whether it can participate in transactions: These flags are per-balance — they apply to one balance, not to the whole account. Both default to true when you do not set them. Common use cases:
  • Freeze a balance: Set both allowSending and allowReceiving to false to prevent any movement.
  • Receive-only balance: Set allowSending to false to block outbound transfers and still accept inflows.
  • Send-only balance: Set allowReceiving to false to prevent new funds from entering this balance.
You can set both flags when you create a balance. You can also update them independently through the Update a Balance endpoint. If an update request omits a flag, its current value stays unchanged.
Midaz reads permission flags during transaction validation. A PATCH that changes only allowSending or allowReceiving does not rewrite an existing Valkey entry, so do not assume the immediately next cache-hit transaction will observe the change. Changes never alter operations already processed.

Usage examples


  • User Wallet (BRL): A digital wallet that shows an available balance of R$500.
    • Use case: Show the balance in a mobile banking app and validate funds before a payment.
  • Settlement Account (USD): A liquidity provider account with a USD balance of $120,000.
    • Use case: Make sure daily treasury operations keep enough buffer for FX settlements.
  • Blocked Balance (BRL): An account balance reserved as collateral.
    • Use case: Prevent the use of funds until a loan closes or the borrower meets the conditions.
A blocked (collateral) balance restricts funds at the balance level. Midaz holds the value in a separate balance and combines it with permission flags to keep the funds unavailable. This differs from a Block transaction, which records a ledger movement with BLOCK-typed operations. A Block transaction flags funds for reasons like a compliance hold. Use a collateral balance for a standing operational restriction. Use a Block transaction when you need an auditable ledger entry.

Balance structure


  • Balance > Account: Each Balance belongs to an Account, which holds and moves value.
  • Balance > Asset: Each Balance uses a specific Asset, such as BRL or BTC.
  • Balance > Ledger: Balances exist within a Ledger, which enables multi-book environments.
  • Balance > Key: Each Balance has a unique key within the account (e.g., default, credit, collateral).
Figure 2 shows an example of the structure.
Balance structure relationships

Figure 2. Balance structure relationships diagram.

A balance is more than just a number. It includes metadata about the state of funds, such as pending operations and effective availability.

Key characteristics


  • Real-time tracking: Midaz updates balances with every confirmed operation.
  • Multiple balances per account: Accounts can hold several balances, each with its own rules.
  • Single source of truth: Balances reflect the net sum of all operations on the account.
  • Query by context: You can list balances within an organization and ledger, retrieve them by account ID or alias, and retrieve an External Account’s balance by asset code. The balance-list endpoints do not filter by a generic asset code or balanceKey.
  • Supports external accounts: You can retrieve balances for internal or external accounts, such as liquidity pools or partners.

Using balances in transactions


The following transaction endpoints accept a balanceKey field to specify which balance to use: If a request does not provide a balanceKey, Midaz uses the account’s default balance.

New fields in responses

  • balanceKey - Appears in transactions and operations to show which balance the transaction used.
  • key - Appears in balances to identify each balance uniquely.
Always use the balanceKey consistently across requests and responses. This avoids mismatches when accounts hold multiple balances.

Cache key changes (Valkey)


Balances in the cache (Valkey) include the balanceKey.

Previous format

New format

The key carries the balance:{transactions}: prefix, and the balance_key is appended to the account alias with a # separator. A tenant namespace can prefix the key further in multi-tenant deployments.
Update direct Valkey readers to construct balance:{transactions}:<org_id>:<ledger_id>:<account_alias>#<balance_key>, including #default for the default balance. Reads using the previous key format miss the current cache entry.

Overdraft


Balances support overdraft — the ability to debit a balance beyond its available funds. When you enable overdraft, Midaz tracks the deficit as overdraftUsed. Midaz also handles the operation split and repayment automatically. Two fields support this feature:
  • direction — For an automatically created default balance, direction is credit for non-external accounts and debit for External Accounts. Additional balances may set direction at creation; it cannot change afterward.
  • settings — Controls overdraft behavior: allowOverdraft, overdraftLimitEnabled, and overdraftLimit.
Midaz reserves the key "overdraft" for the system-managed companion balance that records the liability side. A request to create a balance with this key returns an error.
settings.balanceScope also distinguishes balances by scope. Transactional balances (the default) are user-managed and take part in regular transactions. The system operates internal balances exclusively — like the overdraft companion. User transactions cannot target, modify, or delete them through the public API. For full details on configuration modes, operation splits, automatic repayment, events, and use cases, see Balance Overdraft.

Balance history


Midaz provides point-in-time queries for balances. You can retrieve a balance state at a past timestamp on or after the balance’s creation. If no operation exists before that timestamp, Midaz returns the initial zero state; it returns 404 when the requested timestamp precedes balance creation. This supports auditing, reconciliation, and historical reporting.

How it works

When you query balance history, Midaz returns historical identity and amount fields. It omits allowSending, allowReceiving, deletedAt, and metadata; the current implementation also does not reconstruct historical direction or settings, and returns overdraftUsed as zero. Do not treat it as a full regular-balance response minus permission flags.
Why does history exclude permission flags?allowSending and allowReceiving are mutable operational settings. You can toggle them at any time without a ledger entry. Balance amounts (available, onHold) change only from recorded transactions. Permission flags represent the current operational state of a balance, not a fact about its past.Historical audits and reconciliation care about amounts at a point in time. Whether sending or receiving worked at a given moment does not matter for audit or reconciliation. Mutable permission state in immutable snapshots would add ambiguity without value.

Use cases

  • Regulatory auditing: Prove the exact balance of an account at a specific compliance checkpoint.
  • Reconciliation: Compare balance snapshots across systems at matching timestamps.
  • Dispute resolution: Retrieve the precise account state at the time of a contested transaction.
  • End-of-day reporting: Capture balance positions at market close for treasury operations.
The date parameter is required. It must follow the format yyyy-mm-dd hh:mm:ss (e.g., 2026-01-15 10:30:00). Midaz returns 404 when the requested timestamp precedes balance creation.

Querying balance history

You can query history for a single balance or for all balances of an account:

Managing Balances


You can retrieve your balances through the API. The Midaz ledger engine computes balance amounts from transactions — you cannot set available or onHold directly. You manage the balance records — key, permission flags, and settings — through the endpoints below.
Do you want to trace how a balance formed? Use the Operations API to inspect the ledger history that affected that account.

Next steps


  • Use the Operations API to trace transactions that involve multiple balances.
  • Combine multiple balances with Accounting Routes to create flexible and scalable financial flows.