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

# Accounting Routes

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

Accounting Routes are Midaz's two-layer validation system for financial transactions. **Accounting Routes** define the full transaction pattern. **Operation Routes** validate each operation inside that pattern. Together they keep every transaction structurally correct and compliant with your business rules.

<Note>
  **Naming:** The Lerian Console and product documentation call this concept **Accounting Routes**. In the API and SDKs, the `transactionRoute` resource represents the transaction-level route, with `transaction-route` endpoints. The two terms refer to the same thing.
</Note>

* **Accounting Routes** define the complete structure of a transaction: the required sequence of operations that forms a valid financial event.
* **Operation Routes** define the rules for each operation (or "leg") of that transaction. Each rule sets the expected account type or specific account, the accounting annotation, and the debit or credit side.

When you submit a transaction, Midaz validates it in two layers. The Accounting Routes layer checks that the overall structure matches the predefined pattern. The Operation Routes layer checks that each component meets account requirements and business rules.

If any part of the transaction fails these checks, Midaz rejects it before it records the transaction. This protects the integrity of your ledger and does not limit its flexibility.

<Note>
  You define the validation patterns through Operation Routes and Accounting Routes. Midaz checks that your transactions comply with these rules before it processes them.
</Note>

## What are Accounting Routes for?

***

Accounting Routes provide 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. These patterns make every financial movement follow your organization's requirements.

These entities link Transactions and Operations from the Midaz ledger to higher-level abstractions. These abstractions help you integrate specialized plugins and external systems, especially for **accounting and treasury**. The structured annotations and classifications create a standardized vocabulary that other components can understand and use.

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 let you integrate accounting plugins and external financial systems.

Accounting Routes keep your financial data structured and validated for simple transfers and complex multi-party transactions. They also provide the semantic foundation for advanced integrations.

## Working with Accounting Routes

***

To use Accounting Routes, you complete a one-time setup and then execute transactions. The steps below show the full 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, Midaz rejects an account whose `type` is not a registered Account Type. This gates **account creation**, not transactions — the `account_type` rule on an Operation Route is enforced by `validateRoutes`, independent of this flag.

<Tip>
  Settings changes need no redeployment: you update them at any time through the API. The write invalidates the settings cache, but reads are cached for **5 minutes**, so allow up to that long for a change to be observed by every replica.
</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.

* **code** (deprecated): a legacy external reference kept for backward compatibility. The engine does **not** write it to operations. Instead, it records the resolved rubric's `code` (from `accountingEntries`) as `routeCode` on each operation.

* **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 that receive funds (credit side).
  * `bidirectional` — Applies to both sides of the transaction, as both source and destination.

* **account**: Optional validation rules that set a required account type or a 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**

Attach accounting entries directly to the operation route through the `accountingEntries` field. This field maps each transaction-lifecycle stage to the correct double-entry accounting codes. See [Configure Accounting Entries (Actions)](#4-configure-accounting-entries-actions) below for the full action-type model, the debit/credit requirements, and the validation matrix.

A route with accounting entries configured:

<CodeGroup>
  ```json JSON theme={null}
  {
      "title": "Pix Cash-in - Current Account",
      "description": "Operation route for receiving Pix payments into current account",
      "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"
              }
          },
          "commit": {
              "debit": {
                  "code": "2.1.001",
                  "description": "Pending Obligations"
              },
              "credit": {
                  "code": "3.1.001",
                  "description": "Service Revenue"
              }
          },
          "cancel": {
              "debit": {
                  "code": "2.1.001",
                  "description": "Pending Obligations"
              },
              "credit": {
                  "code": "1.1.002",
                  "description": "Clearing Values"
              }
          }
      },
      "account": {
          "ruleType": "alias",
          "validIf": "@current_account"
      },
      "metadata": {
          "channel": "pix"
      }
  }
  ```
</CodeGroup>

<Note>
  The `operationType` field also supports `bidirectional`. A bidirectional route operates in both directions. Use it for routes that both send and receive, or for operations that you may need to reverse.
</Note>

#### 3. Build Accounting Routes

Complete your setup by combining Operation Routes into Accounting Routes (the `transactionRoute` resource in the API). These define your complete transaction patterns. Each pattern maps how operations work together to form balanced financial events that match your business processes.

<Warning>
  The `operationRoutes` field uses an array of objects with `operationRouteId` rather than a plain array of UUID strings.
</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**. These structured rubrics define how Midaz records debit and credit entries for each transactional event: `direct`, `hold`, `commit`, `cancel`, and `revert`, plus three supplementary keys — `overdraft`, `block`, and `unblock` — that describe accounting impact but are **not** valid transaction-route actions. The engine uses them to resolve which accounts it debits and credits for each action. They also determine the `routeCode` and `routeDescription` annotations on each operation.

The `accounting.validateRoutes` setting in the [Ledger Settings](/en/midaz/ledgers#ledger-settings) controls this behavior. When you enable it, Midaz rejects an operation route that is missing or does not match, and returns `0117 ErrAccountingRouteNotFound`. When you disable it, route resolution is best-effort. A missing rubric leaves `routeCode` empty and does not stop the transaction.

<Note>
  The **[Accounting Entries](/en/midaz/accounting-entries)** page documents the full model in detail. This includes the accounting-entry actions, the debit/credit requirements per operation type, the graceful and strict validation modes, and configuration examples. This section covers only how rubrics attach to Operation Routes.
</Note>

At the route level, you supply accounting entries through the `accountingEntries` block. See **Option C** under [Create Operation Routes](#2-create-operation-routes) above. Each action takes one entry with a `debit` rubric, a `credit` rubric, or both, depending on the route's `operationType`:

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

##### 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 do not match, Midaz rejects the request before it persists the route.

This matrix is critical for integrators. An invalid combination returns error `0166` (field required) or `0162`/`0165` (scenario not allowed for the 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>
  If an entry has neither `debit` nor `credit`, Midaz rejects it, regardless of operation type or action.
</Danger>

**Additional rules:**

* **Reserve group atomicity**: On `source` and `bidirectional` routes, if you define `hold`, you must also define `commit` and `cancel` (and vice versa). These three actions form an atomic group there; you can't configure one without the others. On `destination` routes, `hold` and `cancel` are not allowed (error `0162`), so `commit` can be configured without them; it still requires `direct` per the rule below.
* **Direct is mandatory**: If you define any other action (`hold`, `commit`, `cancel`, `revert`, `overdraft`, `block`, `unblock`), you must also define `direct`. It serves as the baseline entry for the operation route.
* **`overdraft` requires both rubrics** on every `operationType`, including `source` and `destination`.
* **`block` and `unblock` mirror `direct`**: debit on a `source` route, credit on a `destination` route, both on `bidirectional`.
* Any key outside these eight is rejected with error `0053` (Unexpected Fields).

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

### Ongoing Operations

#### 5. Execute Validated Transactions

With your routing configuration in place, you can now submit transactions. In the transaction request, **include the ID of the Accounting Route you created**. Midaz then validates the transaction against your routing patterns. This keeps all financial operations consistent and correct.

For the Accounting Route and Operation Routes configured above, Midaz 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}
  {
      "routeId": "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",
                      "routeId": "0197e6aa-1695-734a-a8c3-8c79e0ad32c2"
                  }
              ]
          },
          "distribute": {
              "to": [
                  {
                      "accountAlias": "@external/BRL",
                      "amount": {
                          "asset": "BRL",
                          "value": "10"
                      },
                      "description": "Fee credit to revenue account",
                      "routeId": "0197e675-37cc-71d7-96c2-f58000f33aa0"
                  }
              ]
          }
      }
  }
  ```
</CodeGroup>

When you submit this transaction, Midaz validates two things. The `@user/wallet_123` account must match the `user_wallet` account type rule. The `@external/BRL` account must match the exact alias. Both checks confirm that the transaction follows your routing patterns.

##### Route fields on operations

When you enable route validation and configure accounting entries, every processed operation includes two extra fields. Midaz populates these fields from the matched rubric:

* **routeCode** — The `code` of the resolved `AccountingRubric` for that operation's action and direction.
* **routeDescription** — The description of the resolved accounting rubric. Midaz populates it alongside `routeCode`.

These fields link each operation to its accounting classification. Downstream systems such as [Reporter](/en/reporter/what-is-reporter) can then produce accurate financial reports without extra lookups.

## Managing Operation and Accounting 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 Accounting Routes** (the `transactionRoute` resource in the API), 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.
