If no
balanceKey is provided, the transaction automatically uses the default balance.Double-entry accounting
The double-entry system operates on a simple yet transformative principle: for every transaction, there are two corresponding entries, a debit and a credit. This framework ensures that all financial activities are recorded holistically, providing a complete and balanced view of your accounts. Each transaction impacts two accounts, maintaining equilibrium in the financial ecosystem:
- Debits reflect the value received or resources consumed.
- Credits indicate the value given or resources provided.
Example
Consider this example: you perform a transaction to transfer R$1000 from one account to another. This process will have two operations:- One operation to debit R$1,000.00 from the source account.
- One operation to credit R$1,000.00 to the destination account.
N:N Transactions (Many-to-Many)
Unlike traditional financial systems that limit transactions to one-to-one or one-to-many relationships, Midaz enables N:N transactions, allowing multiple source and destination accounts within a single transaction.
Examples
- Marketplace payout: multiple sellers (several sources) are paid from a single escrow account, and each seller pays a platform fee.
- Peer-to-peer with fees: one transaction debits the payer and credits both the payee and a fee account.
Atomicity and integrity
Transactions are atomic operations; either all constituent operations succeed, or none do. This ensures that partial financial events do not occur. If any part of a transaction fails validation (say, insufficient funds in one account), the entire transaction will not be applied, preserving ledger integrity.
Transaction source
Transactions in Midaz can be initiated from a single or multiple sources.
The sum of the values in the
source must always equal the value specified right after the send and equal the sum of the values in the distribute.Single source
In a single-source transaction, the specified amount is taken directly from one source account and, optionally, a specific balance.Example
In this example (Figure 1):- BRL 30.00 is taken from
@account1(balancecredit). - 100% is sent to
@destinationAccount1(balanceoperational)

Figure 1. Example of a single source transaction.
Multi-source
In a multi-source transaction, funds are drawn from multiple accounts and/or balances.Example
In this example (Figure 2):- BRL 30.00 will be sent to the destination account (
@destinationAccount1).- BRL 15.00 from
@account1(balancedefault). - BRL 15.00 from
@account2(balanceinvestment).
- BRL 15.00 from
- The destination account will receive 100% of the amount sent.

Figure 2. Example of a multi-source transaction.
Transaction destination
Similar to origins, destinations can be single or multiple.
Single destination
In a single destination transaction, the amount is sent to only one destination account.Example
In this example (Figure 3):- BRL 30.00 is taken from an external account (
@external|BRL). - 100% is sent to the destination account (
@destinationAccount1).

Figure 3. Example of a single destination transaction.
Multi-destination
In multi-destination transactions, the transaction amount is divided among multiple destination accounts. Values can be distributed by shares, fixed amounts, or remaining balance.Example
In this example (Figure 4):- BRL 100 is taken from the source account (
@account1). - 38% of the amount goes to account 2 (
@account2). - 50% goes to account 3 (
@account3). - A fixed BRL 2.00 goes to account 4 (
@account4). - The remaining amount goes to account 5 (
@account5).

Figure 4 Example of a multi-destination transaction.
Multi-source and multi-destination
These complex transactions involve multiple sources and multiple destinations. This is useful for scenarios like a crowdfunding campaign, where contributions are pooled and distributed among multiple recipients.
Example
In this example (Figure 5):- BRL 4,000.00 will be donated, and the amount will be taken from four different accounts.
- 25 % will be taken from account 1 (
@account1). - 25 % will be taken from account 2 (
@account2). - 40 % will be taken from account 3 (
@account3) - 10 % will be taken from account 4 (
@account4).
- 25 % will be taken from account 1 (
- The donations will be distributed to four separate donation accounts, and each will receive a 25% share of the total.

Figure 5. Example of a multi-source and multi-destination transaction.
Transaction flow
When a transaction starts, Midaz validates:
- The accounts involved.
- The specified balances (
balanceKey, ordefaultif not given). - Permissions (
allowSending,allowReceiving). - Sufficient available funds in the selected balance.
APPROVED.
Users should only initiate this type of transaction if they intend to commit it to the ledger immediately.
pending flag to create a Two-Phase Transaction.
Two-Phase Transaction
In this scenario, the transaction is created with status
PENDING. Instead of moving funds right away, Midaz reserves the specified amount in the correct balance (balanceKey, or default if not provided).
- The reserved funds are moved from
availabletoon_hold. - No operations (debits or credits) are yet recorded in the ledger.
- You must explicitly
committo execute the transfer, orcancelto release the funds.

Figure 6. Anti-fraud workflow example
Two-Phase Transaction flow
1. Create a Two-Phase Transaction
- Use the Create a Transaction using JSON endpoint with
"pending": true.
balanceKey), permissions (allowSending, allowReceiving), and available funds. If valid:
- Funds are reserved in the correct balance.
- Transaction status is set to
PENDING. - Metadata is stored, but no debit/credit is yet posted.
2. Commit or cancel the pending transaction
- Commit: Finalizes the transaction. Funds move from on_hold to the destination balance, and debit/credit operations are recorded.
- Use the Commit a Pending Transaction endpoint.
- Status:
APPROVED.
- Cancel: Releases reserved funds back to available in the same balance.
- Use the Cancel a Pending Transaction endpoint.
- Status:
CANCELED.
Past Transactions
Midaz also supports past transactions, enabling institutions to import legacy financial events while preserving historical accuracy.
- Use the optional
createdAtfield to set the original date of the transaction. - Transactions with financial impact recalculate the historical state of balances as if processed on that date.
- Transactions created via the Create a Transaction Annotation validate structure but do not impact balances. They are useful for audits, compliance, and imports where balances must remain unchanged.
Example
When importing legacy data, submit all past transactions before starting live operations. This ensures balances are recalculated consistently across the ledger.
Transactions with no financial impact
Midaz supports creating transactions that are recorded in the ledger but do not affect account balances. These transactions ensure structural integrity while keeping balances unchanged. This feature is useful when you need to:
- Import legacy transactions without altering balances.
- Record auditing or compliance events.
- Add business operations that must be tracked in the ledger but do not require movement of funds.
How does it work?
When a transaction is created without financial impact:- The
balanceandbalanceAfterfields are stored as 0 to preserve double-entry validation. - The
balanceAffected(boolean) field has been introduced in each operation:- true → the operation affects the account balance.
- false → the operation is recorded in the ledger without impacting balances.
Even when no balances are updated, Midaz enforces double-entry rules. This guarantees consistency across all transactions in the ledger.
Example
Related endpoint
- Create a Transaction Annotation — Record a transaction without financial impact in the ledger.
Real-time event publishing
Want to track the status of your transactions as they happen? Midaz supports real-time event publishing via RabbitMQ. Once enabled, every transaction generates an event, such as
APPROVED, PENDING, or CANCELED, that external systems can subscribe to using topic-based routing.
For more information about how to publish and consume transaction events, check out the Event publisher page.
Inflows, outflows, and external accounts
Midaz uses a double-entry ledger system in which all value entering or leaving the system must pass through a special account: the External Account. This account—represented as
@external/{{assetCode}}—acts as the bridge between Midaz and the external financial world (banks, PSPs, payment rails, etc.).
Why does this matter?
When the ledger is first initialized, all accounts—including@external—start with a zero balance. To reflect real-world balances (e.g., institutional funds held externally), you must initiate a transaction that injects funds into Midaz accounts by debiting the external account.
This is the only way to bring funds into Midaz.
Inflows – Adding value into the Ledger
To credit an internal account from outside the ledger:- Source:
@external/{{assetCode}}(e.g.,@external/BRL). - Destination: One or more internal accounts (e.g.,
@organization.main).
| Source | Destination | Amount |
|---|---|---|
| @external/BRL | @accountA | BRL 10,000 |
Outflows – Moving value out of the Ledger
To simulate value leaving the ledger to an external destination:- Source: One or more Midaz accounts.
- Destination:
@external/{{assetCode}}.
| Source | Destination | Amount |
|---|---|---|
| @accountA | @external/BRL | BRL 1,000 |
@accountA and credits the external account. In real life, your system (via SPI or other integrations) will then transfer the funds to the intended recipient.
Behavior and balance rules
@external/{{assetCode}}can have a zero or negative balance, but never positive.- Its balance is always the inverse of the combined balance of all Midaz accounts holding that asset.
- Every inflow increases internal liquidity and reduces the external account balance (i.e., simulates a deposit).
- Every outflow does the reverse.
All value movements between the outside world and the Midaz ledger must go through the external account.Nothing enters or exits the system without a formal transaction, ensuring full traceability, balance integrity, and compliance with double-entry principles.
Transaction Routes
The Transaction Routes API enables structured and validated transaction processing in Midaz. While the Transactions API handles the execution of financial events (debits and credits between accounts), Transaction Routes define templates for how these events should be structured and validated, ensuring consistency and integrity. Think of it as the validation layer that ensures business transactions follow predefined patterns and maintain proper financial structure. For example, a transaction for a fee, a deposit, or a payout may require different account types, validation rules, and structures. Instead of handling validation separately for each transaction, you configure predefined rules that tell Midaz: “When the user submits this type of transaction, validate it against these account requirements and structure patterns.” Each Transaction Route combines multiple Operation Routes, which define the individual components of a transaction, specifying account requirements, directions (source/destination), and validation rules for each “leg” of the financial event.
Why does it matter?
By using Transaction Routes, you:- Ensure consistent transaction structure across your application.
- Make your ledger more maintainable, predictable, and reliable.
- Validate financial events against predefined patterns.
- Enable configuration of transaction templates without code changes.
- Maintain data integrity through structured validation.
Initiating a transaction
There are two main ways to initiate a transaction:
Using DSL
A Domain-Specific Language (DSL) simplifies user interaction by focusing on specific domain concepts, enabling non-developers to perform complex tasks without technical skills. DSLs reduce boilerplate code and embed constraints in their syntax, enforcing business rules and minimizing errors. However, their predefined patterns can limit flexibility, making it harder to create custom parsers or adapt to new requirements. The Transactions DSL in Midaz, called Gold, simplifies transaction processing with an intuitive accounting syntax. It stores transaction information in.gold files, allowing business teams to define transactions easily and fostering collaboration between technical and business workflows.
To use the DSL, follow these steps:
1
Create the
.gold file according to the Transactions DSL structure.2
Submit the file using the Create a Transaction using DSL endpoint.
Using JSON endpoint
JSON endpoints provide a flexible and developer-friendly standard for data interchange, enabling precise control over request structures tailored for custom workflows and specific use cases. Their broad compatibility with various programming languages makes integration and debugging easier. However, this flexibility can result in verbosity and user errors, as developers are required to handle validation manually. For non-developers, the complexity of JSON may present challenges, making it less intuitive than a Domain-Specific Language (DSL) for everyday tasks.- To create a transaction using JSON, use the Create a Transaction using JSON endpoint.
If you need to reserve funds before completing the transfer, set the
pending field to true (Two-Phase Transaction flow).Reverting a transaction
Midaz supports transaction reversal, enabling you to undo approved transactions by creating a mirror transaction that inverts the original debits and credits. This mechanism maintains full audit trails while effectively canceling the financial impact on account balances.
Reversal creates a new transaction that compensates for the original. The original transaction remains in the ledger history for complete traceability.
How does it work?
When you revert a transaction, Midaz automatically:-
Inverts operations:
- CREDIT operations become source operations (
from). - DEBIT operations become destination operations (
to).
- CREDIT operations become source operations (
-
Creates a new transaction with:
- Same amount and asset code.
- Same description and metadata.
- Inverted operations (recipients become senders, senders become recipients).
- Initial status:
CREATED(notPENDING) → then progresses toAPPROVED. parentTransactionIDreferencing the original transaction.
- Processes the reversal through the standard transaction flow, including validation, balance updates, and history recording.
Example
Consider this scenario: Original transaction:- Account A (debit -100) → Account B (credit +100)
- Account B (debit -100) → Account A (credit +100)
- Account A returns to its previous balance (receives back the -100).
- Account B returns to its previous balance (loses the +100).
- Both transactions remain in the ledger history for audit purposes.
- The reversal transaction includes
parentTransactionIDpointing to the original.
Reversal restrictions
Midaz enforces strict rules to maintain ledger integrity. Reversals will fail in the following cases:1. Transaction already has a reversal
- Only one reversal per transaction is allowed.
- Prevents multiple reversals of the same transaction.
2. Transaction is already a reversal
- Cannot revert a transaction that is itself a reversal.
- Prevents creating “reversals of reversals.”
3. Transaction status is not APPROVED
- Only approved transactions can be reverted.
- Transactions with status
PENDING,CREATED, orCANCELEDcannot be reverted.
4. Transaction cannot be reverted
- Occurs when the transaction has no valid operations to invert.
- For example, transactions without standard CREDIT/DEBIT operations.
Only CREDIT and DEBIT operations are considered for reversal. Operations like ON_HOLD and RELEASE are not included in the reversal process.
Use cases
Transaction reversal is essential for various operational scenarios:1. Incorrect payment reversal
A customer paid BRL 500 to the wrong supplier.- Revert the transaction.
- Funds return to the customer’s account.
- Customer can initiate a new payment to the correct supplier.
2. Purchase cancellation
A store processed a BRL 1,000 sale, but the customer cancels the purchase.- Revert the sale transaction.
- Funds return to the customer’s account.
3. Operational error correction
An operator created a transaction with the wrong amount.- Revert the incorrect transaction.
- Create a new transaction with the correct amount.
4. Product return
A customer purchased and paid BRL 200, but returned the product.- Revert the payment transaction.
- Customer receives a refund.
5. Integration failure compensation
A transaction was approved but failed in an external system.- Revert to undo the accounting operation.
- Balances return to their previous state.
Managing transactions
You can manage your Transactions either via API or through the Console.
Via API
- Create a Transaction using DSL (deprecated) — Submit a transaction file using the Midaz DSL.
- Create a Transaction using JSON — Submit a transaction directly using a JSON payload.
- Commit a pending transaction — Finalize a reserved transaction.
- Cancel a pending transaction — Release reserved funds without executing.
- Revert a Transaction — Create a reversal transaction to undo an approved transaction.
- Create an Inflow Transaction — Register incoming funds from external sources into the Ledger.
- Create an Outflow Transaction — Move funds from internal accounts to the external world.
- List Transactions — View all Transactions in your workspace.
- Retrieve a Transaction — Get details of a specific Transaction.
- Update a Transaction — Edit the metadata of an existing Transaction.
- Create a Transaction Annotation — Record a transaction without financial impact in the ledger.

