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

> Map transaction actions to the ledger accounts they debit and credit, and annotate every operation with its accounting classification.

Accounting Entries (also known as **Rubricas**) define the mapping between a transaction action and the ledger entries it generates. They are what the engine uses to resolve which accounts get debited and credited for each action, automatically annotating operations with the correct double-entry accounting codes for every stage of the transaction lifecycle.

## What are Accounting Entries

***

A **rubric** is a mapping that tells the engine which ledger accounts to debit and credit for a given transaction action. Rather than computing accounting classifications by hand for each movement, you register rubrics once and let Midaz resolve them automatically as transactions are processed.

Each rubric carries:

* **`code`** — a unique identifier (the chart of accounts code, e.g., `1.1.1.001`).
* **`description`** — a human-readable label for the entry (e.g., `Customer checking — outbound`).
* A set of **action mappings** — one entry per action type, each with its own debit and/or credit rubric.

When a transaction is processed, the engine resolves the rubric for each operation and records the resulting **`routeCode`** (and **`routeDescription`**) on the operation. This gives you a complete audit trail from transaction → operation → rubric, letting teams trace exactly which accounting rule was applied to each movement.

<Note>
  Rubrics are configured per action on each Operation Route. **Source** routes require the **debit** rubric, **destination** routes require the **credit** rubric, and **bidirectional** routes require **both**.
</Note>

## The 5 action types

***

Each action represents a distinct transactional event. A single rubric can map different debit/credit accounts for each action, so every stage of an operation lands on the right ledger entry.

| Action     | Identifier | Description                                                                                                        |
| :--------- | :--------- | :----------------------------------------------------------------------------------------------------------------- |
| **Direct** | `direct`   | Immediate, single-step debit/credit between two accounts, with no intermediate stages (e.g., a fee or adjustment). |
| **Hold**   | `hold`     | Reserves funds by creating a pending movement (moves value from `available` to `on_hold` on the source account).   |
| **Commit** | `commit`   | Confirms a previously held amount, releasing the `on_hold` value to the destination account.                       |
| **Cancel** | `cancel`   | Cancels/reverses a hold, returning the `on_hold` value to the `available` balance on the source account.           |
| **Revert** | `revert`   | Reverses a completed `direct` transaction by creating a counter-transaction that undoes the original.              |

<Tip>
  Each action can point to different debit/credit account mappings within the same rubric. Map only the actions a route will actually use — but if you enable strict validation (below), make sure every action your transactions emit is covered.
</Tip>

## Configuring Accounting Entries

***

Rubrics are registered via the API as part of your Operation Routes — the `accountingEntries` block on a route defines one entry per action, each with its `debit` and/or `credit` rubric:

<CodeGroup>
  ```json accountingEntries theme={null}
  {
      "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"
              }
          }
      }
  }
  ```
</CodeGroup>

You manage these entries through the Operation Route endpoints — see [Create an Operation Route](/en/reference/midaz/create-an-operation-route) and [Update an Operation Route](/en/reference/midaz/update-an-operation-route). For the full configuration flow, refer to [Transaction Routing](/en/midaz/transaction-routing-entities#4-configure-accounting-entries-actions).

## Validation modes

***

How Midaz reacts when no matching rubric is found depends on the Ledger's accounting settings. There are two distinct gates:

### Default (graceful)

By default, if no rubric is registered for an action, the transaction proceeds normally. The `routeCode` and `routeDescription` fields are simply left empty (nil) for that operation — no error is raised.

### Strict (opt-in)

Set `accounting.validateRoutes` to `true` in the [Ledger Settings](/en/midaz/ledgers#ledger-settings) to enforce that all actions must have a registered rubric. Any operation whose action and direction has no registered mapping is rejected with error `0117 ErrAccountingRouteNotFound`.

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

<Warning>
  With `validateRoutes` enabled, if a route has accounting entries configured but the submitted transaction uses an action that is not registered (for example, a Two-Phase Transaction when only `direct` is mapped), the transaction is denied with `0117 ErrAccountingRouteNotFound`. This prevents mismatches in your accounting reports by ensuring all stages of an operation are mapped before execution.
</Warning>

<Tip>
  Use **strict mode** in production ledgers where every transaction type must be accounted for. The graceful default is convenient while you are still onboarding routes, but in production it can silently leave movements without an accounting classification.
</Tip>

In both modes, when a matching rubric **is** found, the operation is annotated with:

* **routeCode** — the `code` of the resolved `AccountingRubric` for that action and direction.
* **routeDescription** — the description of the resolved accounting rubric, populated alongside `routeCode`.
