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

# Transaction Routing

> Validate every Transaction with Transaction Routes and Operation Routes — enforce structure and business rules before recording any movement.

Transaction Routing is Midaz’s two-layer validation system for financial transactions, built from **Transaction Routes** (which define the full transaction pattern) and **Operation Routes** (which validate each individual operation within that pattern). Together, they ensure every transaction is both structurally correct and compliant with your business rules.

* **Transaction Routes** define the complete structure of a transaction — the required sequence of operations and how they fit together to form a valid financial event.
* **Operation Routes** define the rules for each individual operation (or “leg”) of that transaction, including the expected account type or specific account, the accounting annotation, and whether it’s a debit or credit.

When a transaction is submitted, Midaz validates it in two layers: **Transaction Routes** ensure the overall structure matches the predefined pattern, while **Operation Routes** confirm that each component meets account requirements and business rules.

If any part of the transaction fails these checks, it’s rejected before it can be recorded — protecting the integrity of your ledger without limiting its flexibility.

<Note>
  You define the validation patterns through Operation Routes and Transaction Routes. Midaz ensures your transactions comply with these rules before processing.
</Note>

## What is Transaction Routing for?

***

Transaction Routing provides structured control over your financial operations by separating transaction logic from business code. Instead of hardcoding validation rules in your application, you configure reusable patterns that ensure every financial movement follows your organization's requirements.

These entities are dedicated to linking Transactions and Operations from the Midaz ledger to higher-level abstractions that facilitate integration with specialized plugins and external systems, especially for **accounting and treasury** abstractions. The structured annotations and classifications create a standardized vocabulary that other components can understand and leverage.

This approach delivers:

* **Consistency**: All transactions follow predefined structures regardless of where they originate.
* **Flexibility**: Adapt your ledger design to match your business needs without code changes.
* **Integrity**: Automatic validation prevents malformed transactions from affecting your ledger.
* **Maintainability**: Centralized configuration makes it easier to update financial rules as your business evolves.
* **Interoperability**: Business-semantic fields enable seamless integration with accounting plugins and external financial systems.

Whether you're processing simple transfers or complex multi-party transactions, Transaction Routing ensure your financial data remains structured, validated, and reliable at scale while providing the semantic foundation for advanced integrations.

## Working with Transaction Routing

***

To use Transaction Routing, you must complete the initial configuration followed by ongoing transaction execution. Here's your step-by-step process:

### Initial Setup

#### 1. Configure Ledger for transaction route validation

To activate transaction route validation for a specific Ledger, enable the validation settings through the [Ledger Settings API](/en/midaz/ledgers#ledger-settings). This controls whether transactions in that Ledger must comply with your configured routes.

<CodeGroup>
  ```json PATCH /v1/organizations/{org_id}/ledgers/{ledger_id}/settings theme={null}
  {
    "accounting": {
      "validateRoutes": true,
      "validateAccountType": true
    }
  }
  ```
</CodeGroup>

* **`validateRoutes`**: When enabled, every transaction must reference a valid transaction route.
* **`validateAccountType`**: When enabled, account types are validated against operation route rules.

<Tip>
  Settings changes take effect immediately — no redeployment required. You can update them at any time via the API.
</Tip>

#### 2. Create Operation Routes

Create Operation Routes that define validation rules and behavior for individual transaction components.

**Key fields:**

* **title**: Brief label that identifies the operation route.

* **description**: Optional detailed explanation.

* **metadata**: Key-value pairs for business context and custom categorization.

* **operationType**: The accounting direction for this route — `source`, `destination`, or `bidirectional`.
  * `source` — Identifies accounts where funds originate (debit side).
  * `destination` — Identifies accounts where funds are sent (credit side).
  * `bidirectional` — Applies to both sides of the transaction, acting as both source and destination.

* **account**: Optional validation rules specifying required account type or specific account.
  * **ruleType**: Type of account validation rule (`account_type`, `alias`).
  * **validIf**: The expected value that must match for validation to pass.

* **accountingEntries**: Optional accounting entries for each action type. See [Accounting Entries](#4-configure-accounting-entries-actions) below.

Configure account rules based on your needs:

**Option A: No Account Rule**

If you don't need account validation for the operation route, omit the account object:

<CodeGroup>
  ```json JSON theme={null}
   {
      "title": "Fee Collection",
      "description": "Operation route for collecting service fees from user transactions",
      "metadata": {
          "businessUnit": "payments",
          "category": "revenue"
      },
      "operationType": "source"
  }
  ```
</CodeGroup>

**Option B: Account Validation Rule**

If you need account validation for the operation, configure account rules based on your ledger setup:

* **Target Specific Account**

Validate against a specific account using its alias.

<CodeGroup>
  ```json JSON theme={null}
  {
      "title": "Fee Revenue Collection",
      "description": "Operation route for crediting collected fees to revenue account",
      "metadata": {
          "businessUnit": "payments",
          "category": "revenue"
      },
      "operationType": "destination",
      "account": {
          "ruleType": "alias",
          "validIf": "@external/BRL"
      }
  }
  ```
</CodeGroup>

* **Target Account Type**

Validate against specific account types.

<CodeGroup>
  ```json JSON theme={null}
  {
      "title": "User Cashout Fee",
      "description": "Operation route for collecting fees from user cashout transactions",
      "metadata": {
          "businessUnit": "payments",
          "category": "fee"
      },
      "operationType": "source",
      "account": {
          "ruleType": "account_type",
          "validIf": ["user_wallet", "asset"]
      }
  }
  ```
</CodeGroup>

**Option C: With Accounting Entries**

Each stage of a transaction lifecycle — execution, settlement, cancellation, reversal — may require its own accounting annotations. The `accountingEntries` field maps each stage to the correct double-entry accounting codes automatically.

Configure accounting entries for each action type:

<CodeGroup>
  ```json JSON theme={null}
  {
      "title": "PIX Cash-in - Current Account",
      "description": "Operation route for receiving PIX payments into current account",
      "code": "PIX-CASHIN-001",
      "operationType": "source",
      "accountingEntries": {
          "direct": {
              "debit": {
                  "code": "1.1.001",
                  "description": "Cash - Available funds"
              },
              "credit": {
                  "code": "3.1.001",
                  "description": "Service Revenue"
              }
          },
          "hold": {
              "debit": {
                  "code": "1.1.002",
                  "description": "Clearing Values"
              },
              "credit": {
                  "code": "2.1.001",
                  "description": "Pending Obligations"
              }
          }
      },
      "account": {
          "ruleType": "alias",
          "validIf": "@current_account"
      },
      "metadata": {
          "channel": "pix"
      }
  }
  ```
</CodeGroup>

Each action type (`direct`, `hold`, `commit`, `cancel`, `revert`) maps to a double-entry accounting pair — allowing your ledger to automatically annotate operations with the correct accounting codes based on the transaction lifecycle stage.

<Note>
  The `operationType` field now also supports `bidirectional`, which allows the route to operate in both directions — useful for routes that handle both sending and receiving, or for operations that may need to be reversed.
</Note>

#### Accounting entries validation matrix

Not every combination of `operationType` and action is valid. Midaz enforces a strict validation matrix when you create or update an Operation Route — if the rules aren't met, the request is rejected before persisting.

Understanding this matrix is critical for integrators: sending an invalid combination returns error `0166` (field required) or `0162`/`0165` (scenario not allowed for direction).

**source**

| Action   | Debit    | Credit   | Notes                                                   |
| :------- | :------- | :------- | :------------------------------------------------------ |
| `direct` | Required | Optional | Standard one-step transaction at origin                 |
| `hold`   | Required | Required | Reserves funds — moves available → on\_hold             |
| `commit` | Required | Optional | Finalizes a two-phase transaction                       |
| `cancel` | Required | Required | Releases reserved funds — moves on\_hold → available    |
| `revert` | —        | —        | Not allowed (error `0165`). Use `bidirectional` instead |

**destination**

| Action   | Debit    | Credit   | Notes                                                   |
| :------- | :------- | :------- | :------------------------------------------------------ |
| `direct` | Optional | Required | Standard one-step transaction at destination            |
| `hold`   | —        | —        | Not allowed (error `0162`)                              |
| `commit` | Optional | Required | Finalizes a two-phase transaction                       |
| `cancel` | —        | —        | Not allowed (error `0162`)                              |
| `revert` | —        | —        | Not allowed (error `0165`). Use `bidirectional` instead |

**bidirectional**

| Action   | Debit    | Credit   | Notes                               |
| :------- | :------- | :------- | :---------------------------------- |
| `direct` | Required | Required | Both sides of the double entry      |
| `hold`   | Required | Required | Both sides of the double entry      |
| `commit` | Required | Required | Both sides of the double entry      |
| `cancel` | Required | Required | Both sides of the double entry      |
| `revert` | Required | Required | Only direction that supports revert |

<Danger>
  An entry with neither `debit` nor `credit` is always rejected, regardless of operation type or action.
</Danger>

**Additional rules:**

* **Reserve group atomicity**: If you define `hold`, you must also define `commit` and `cancel` (and vice versa). These three actions form an atomic group — you can't configure one without the others.
* **Direct is mandatory**: If any other action (`hold`, `commit`, `cancel`, `revert`) is defined, `direct` must also be present. It serves as the baseline entry for the operation route.

<Tip>
  When designing your operation routes, start with the `direct` action and add `hold`/`commit`/`cancel` only if you need two-phase transaction support. Add `revert` only on `bidirectional` routes.
</Tip>

#### 3. Build Transaction Routes

Complete your setup by combining Operation Routes into Transaction Routes. These define your complete transaction patterns, mapping how different operations work together to form balanced financial events that match your business processes.

<Warning>
  The `operationRoutes` field now uses an array of objects with `operationRouteId` instead of a plain array of UUID strings. If you have existing integrations, update them to use the new format.
</Warning>

<CodeGroup>
  ```json JSON theme={null}
  {
      "title": "Fee Transaction",
      "description": "Complete transaction for collecting fees from user cashout operations",
      "metadata": {
          "transactionType": "cashout_fee",
          "businessFlow": "withdrawal_processing"
      },
      "operationRoutes": [
          {
              "operationRouteId": "0197e6aa-1695-734a-a8c3-8c79e0ad32c2"
          },
          {
              "operationRouteId": "0197e675-37cc-71d7-96c2-f58000f33aa0"
          }
      ]
  }
  ```
</CodeGroup>

#### 4. Configure Accounting Entries (Actions)

Each Operation Route can include **Accounting Entries** — structured rubrics that define how debit and credit entries are recorded for each type of transactional event. When a Ledger is configured to validate routes, only events with registered entries are allowed. This ensures consistency in your accounting reports.

##### Action types

Each action represents a transactional event. You configure accounting entries per action on each Operation Route:

| Action                    | Identifier | Description                                                                                                                                               |
| :------------------------ | :--------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Direct Transaction**    | `direct`   | Standard one-step transaction between two accounts, with no intermediate stages.                                                                          |
| **Hold (Value Reserve)**  | `hold`     | First step of a Two-Phase Transaction: moves value from the `available` balance to `on_hold` on the source account.                                       |
| **Commit (Confirmation)** | `commit`   | Confirms a pending Two-Phase Transaction, transferring the `on_hold` value from the source account to the `available` balance on the destination account. |
| **Cancel**                | `cancel`   | Cancels a pending Two-Phase Transaction, returning the `on_hold` value to the `available` balance on the source account.                                  |
| **Revert**                | `revert`   | Creates a reverse transaction that undoes the original operation.                                                                                         |

##### Accounting entry structure

Each action entry contains a **debit** and/or **credit** rubric, depending on the operation type:

* **Source** routes require the **debit** rubric.
* **Destination** routes require the **credit** rubric.
* **Bidirectional** routes require **both** debit and credit rubrics.

Each rubric has:

* **code** — The chart of accounts code (e.g., `1.1.1.001`).
* **description** — A human-readable description of the entry (e.g., `Customer checking — outbound`).

<CodeGroup>
  ```json JSON theme={null}
  {
      "title": "Pix Transfer",
      "description": "Bidirectional route for Pix transfers between checking accounts",
      "operationType": "bidirectional",
      "account": {
          "ruleType": "account_type",
          "validIf": ["checking"]
      },
      "accountingEntries": {
          "direct": {
              "debit": {
                  "code": "1.1.1.001",
                  "description": "Customer checking — outbound"
              },
              "credit": {
                  "code": "1.1.1.002",
                  "description": "Customer checking — inbound"
              }
          },
          "hold": {
              "debit": {
                  "code": "1.1.1.001",
                  "description": "Customer checking — reserve"
              },
              "credit": {
                  "code": "2.1.1.001",
                  "description": "Pending settlement — hold"
              }
          },
          "commit": {
              "debit": {
                  "code": "2.1.1.001",
                  "description": "Pending settlement — release"
              },
              "credit": {
                  "code": "1.1.1.002",
                  "description": "Customer checking — settled"
              }
          }
      }
  }
  ```
</CodeGroup>

##### Validation behavior

When route validation is enabled for a Ledger and accounting entries are configured:

* **Only events with registered entries are allowed.** If a client registers only the `direct` action on a route, any attempt to execute a Two-Phase Transaction (which requires `hold`) will be automatically rejected.
* Successful operations will have the rubric details recorded in the `routeCode` and `routeDescription` fields on each operation.

<Warning>
  If a route has accounting entries configured but the submitted transaction uses an action that is not registered, the transaction will be denied. This prevents mismatches in your accounting reports by ensuring all stages of an operation are properly mapped before execution.
</Warning>

<Accordion title="Practical example: missing action rejection">
  **Scenario:** A client creates an Operation Route with only the `direct` action configured.

  If that client attempts a Two-Phase Transaction (by sending `pending: true`), the transaction is automatically rejected because there is no `hold` entry registered.

  This ensures that your accounting reports remain consistent — all stages of an operation must be mapped before they can be executed.
</Accordion>

### Ongoing Operations

#### 5. Execute Validated Transactions

With your routing configuration in place, **you can now submit transactions with confidence by including the ID of the previously created Transaction Route in your transaction request**. Midaz will automatically validate the transaction against your defined routing patterns, ensuring consistency and integrity across all financial operations.

For the previously configured Transaction Route and Operation Routes examples, the system composes the following validation structure:

<CodeGroup>
  ```bash text theme={null}
  Transaction Route: "Fee Transaction" (ID: 5656daa5-5b2a-4637-955f-e43bafceaf5d)

  ├── Operation Route 1: "User Cashout Fee" (ID: 0197e6aa-1695-734a-a8c3-8c79e0ad32c2)
  │   ├── Type: source
  │   ├── Account Rule: account_type ["user\_wallet", "asset"]
  │   └── Validates: source operations in transactions
  └── Operation Route 2: "Fee Revenue Collection" (ID: 0197e675-37cc-71d7-96c2-f58000f33aa0)
      ├── Type: destination
      ├── Account Rule: alias "@external/BRL"
      └── Validates: destination operations in transactions
  ```
</CodeGroup>

For route properties on Midaz transactions, an appropriate payload request:

<CodeGroup>
  ```json JSON expandable theme={null}
  {
      "route": "5656daa5-5b2a-4637-955f-e43bafceaf5d",
      "description": "Cashout fee collection transaction",
      "send": {
          "asset": "BRL",
          "value": "10",
          "source": {
              "from": [
                  {
                      "accountAlias": "@user/wallet_123",
                      "amount": {
                          "asset": "BRL",
                          "value": "10"
                      },
                      "description": "Fee debit from user wallet",
                      "route": "0197e6aa-1695-734a-a8c3-8c79e0ad32c2"
                  }
              ]
          },
          "distribute": {
              "to": [
                  {
                      "accountAlias": "@external/BRL",
                      "amount": {
                          "asset": "BRL",
                          "value": "10"
                      },
                      "description": "Fee credit to revenue account",
                      "route": "0197e675-37cc-71d7-96c2-f58000f33aa0"
                  }
              ]
          }
      }
  }
  ```
</CodeGroup>

When this transaction is submitted, Midaz validates that the `@user/wallet_123` account matches the `user_wallet` account type rule, and `@external/BRL` matches the exact alias requirement, ensuring the transaction follows your configured routing patterns.

##### Route fields on operations

When route validation is enabled and accounting entries are configured, every successfully processed operation will include two additional fields populated from the matched rubric:

* **routeCode** — The chart of accounts code from the matching accounting entry rubric.
* **routeDescription** — The description from the matching accounting entry rubric.

These fields provide a direct link between each operation and its accounting classification, enabling downstream systems (such as [Reporter](/en/reporter/what-is-reporter)) to produce accurate financial reports without additional lookups.

## Managing Operation and Transaction Routes

***

To **configure your Operation Routes**, use the following endpoints:

* [Create an Operation Route](/en/reference/midaz/create-an-operation-route) — Define a new accounting rule for your operations.
* [List Operation Routes](/en/reference/midaz/list-operation-routes) — View all configured Operation Routes.
* [Retrieve an Operation Route](/en/reference/midaz/retrieve-an-operation-route) — Get detailed information on a specific Operation Route.
* [Update an Operation Route](/en/reference/midaz/update-an-operation-route) — Modify existing accounting rules.
* [Delete an Operation Route](/en/reference/midaz/delete-an-operation-route) — Remove an outdated or unused Operation Route.

To **configure your Transaction Routes**, use the following endpoints:

* [Create a Transaction Route](/en/reference/midaz/create-transaction-route) — Define new routing logic to connect transactions to accounting operations.
* [List Transaction Routes](/en/reference/midaz/list-transaction-routes) — View all configured Transaction Routes.
* [Retrieve a Transaction Route](/en/reference/midaz/retrieve-a-transaction-route) — Get details of a specific Transaction Route.
* [Update a Transaction Route](/en/reference/midaz/update-a-transaction-route) — Modify existing routing criteria.
* [Delete a Transaction Route](/en/reference/midaz/delete-a-transaction-route) — Remove routes that are no longer applicable.
