# Ledger tools

> MCP tools for Ledger: ledger_accounts_get, ledger_accounts_list, ledger_adjustments_create, ledger_transactions_get, ledger_transactions_list, ledger_trial_balance.

- `ledger_accounts_get`: Get a ledger account
- `ledger_accounts_list`: List ledger accounts
- `ledger_adjustments_create`: Create a manual ledger adjustment
- `ledger_transactions_get`: Get a ledger transaction
- `ledger_transactions_list`: List ledger transactions
- `ledger_trial_balance`: Get the trial balance

## `ledger_accounts_get`

**Get a ledger account.** Operation [`ledger.accounts.get`](https://ownrecord.io/docs/reference/ledger-accounts-get.md) · Legal entity level · permission `ledger:read` · risk tier `read` · since M2

Returns one account of the legal entity's ledger by its ID (`acct_…`): code, type, normal side, currency and
balance (integer micros, signed in the account's normal direction), plus its newest transactions
(`recentTransactions`, up to 10). For the full statement, list transactions with
`accountId` (`recentTransactions.url`). An account of another entity or mode is `resource_not_found`.

Annotations: `readOnlyHint: true` · `destructiveHint: false` · `idempotentHint: true` · `openWorldHint: false`

### Arguments

| Argument    | Type          | Required | Description                                                                                                                                       |
| ----------- | ------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`        | ID (`acct_…`) | yes      | –                                                                                                                                                 |
| `entity_id` | ID (`ent_…`)  | no       | The legal entity to act on (ent\_…), inside your API key's reach. Needed with an organization key; entity and brand keys act on their own entity. |

- **Legal entity:** pass `entity_id` with an organization key; entity and brand keys act on their own entity.
- **Read-only:** changes nothing; `idempotency_key` is ignored.

### Errors

- [`resource_not_found`](https://ownrecord.io/docs/reference/errors.md#resource_not_found): No account with this ID is in this entity's ledger in this mode.
- [`scope_required`](https://ownrecord.io/docs/reference/errors.md#scope_required): The request names no legal entity (an org key without `Ownrecord-Entity`).
- [`permission_denied`](https://ownrecord.io/docs/reference/errors.md#permission_denied): You can't see this entity's ledger (brand-scoped members never can).

### Example

**The entity's EUR bank account**

Arguments:

```json
{
  "id": "acct_01m4tx5nj8emwbyf7y9vcf47xc",
  "entity_id": "ent_01jbx4m3v8e9t0s6k2c5n7q1wy"
}
```

Result `output`:

```json
{
  "id": "acct_01m4tx5nj8emwbyf7y9vcf47xc",
  "object": "ledger_account",
  "entityId": "ent_01m4tx5nj8emwbyf7y9vcf47x2",
  "livemode": true,
  "brandId": null,
  "code": "bank:ent_01m4tx5nj8emwbyf7y9vcf47x2:EUR",
  "kind": "bank",
  "type": "asset",
  "currency": "EUR",
  "normalSide": "debit",
  "noNegative": false,
  "balance": {
    "posted": "1500000000",
    "pending": "0"
  },
  "createdAt": "2026-10-13T12:00:00.000Z",
  "updatedAt": "2026-10-14T09:30:00.000Z",
  "recentTransactions": {
    "object": "list",
    "data": [
      {
        "id": "txn_01m4tx5nj8emwbyf7y9vcf47xg",
        "object": "ledger_transaction",
        "entityId": "ent_01m4tx5nj8emwbyf7y9vcf47x2",
        "livemode": true,
        "brandId": null,
        "kind": "adjustment",
        "status": "posted",
        "entries": [
          {
            "accountId": "acct_01m4tx5nj8emwbyf7y9vcf47xc",
            "accountCode": "bank:ent_01m4tx5nj8emwbyf7y9vcf47x2:EUR",
            "side": "debit",
            "amount": "1500000000",
            "currency": "EUR"
          },
          {
            "accountId": "acct_01m4tx5nj8emwbyf7y9vcf47xd",
            "accountCode": "opening_balances:EUR",
            "side": "credit",
            "amount": "1500000000",
            "currency": "EUR"
          }
        ],
        "totals": [
          {
            "currency": "EUR",
            "debits": "1500000000",
            "credits": "1500000000"
          }
        ],
        "effectiveAt": "2026-10-14T09:30:00.000Z",
        "postedAt": "2026-10-14T09:30:00.000Z",
        "voidedAt": null,
        "reversalOf": null,
        "links": {},
        "memo": "Opening bank balance from the 2026-09-30 statement",
        "actor": {
          "type": "user",
          "id": "usr_01m4tx5nj8emwbyf7y9vcf47xa",
          "via": "console",
          "approvalId": "apr_01m4tx5nj8emwbyf7y9vcf47xj",
          "onBehalfOfUserId": null,
          "clientId": null,
          "supportGrantId": null
        },
        "createdAt": "2026-10-14T09:30:00.000Z"
      }
    ],
    "has_more": false,
    "url": "/api/v1/ledger/transactions?accountId=acct_01m4tx5nj8emwbyf7y9vcf47xc"
  }
}
```

## `ledger_accounts_list`

**List ledger accounts.** Operation [`ledger.accounts.list`](https://ownrecord.io/docs/reference/ledger-accounts-list.md) · Legal entity level · permission `ledger:read` · risk tier `read` · since M2

Lists the accounts of the legal entity's ledger in the mode of the request, newest first: the account
explorer. One ledger serves all brands of the entity (spec §11.2); accounts are opened the first time a
posting uses them, one per account code and currency.

Each account shows its `balance` in integer micros, signed in the account's normal direction: a positive
balance is on the `normalSide` (debit for assets and expenses, credit for liabilities, revenue and equity),
a negative one on the other side. `posted` counts posted entries; `pending` counts entries of pending
transactions.

Filter by `brandId` (a brand's revenue, deferred revenue and receivables accounts and its customers'
accounts; `none` for the entity-wide accounts), `currency` and `type`. Paginate with `limit` (1–100, default 10) and `starting_after` (the `next_cursor` of the previous page).

Annotations: `readOnlyHint: true` · `destructiveHint: false` · `idempotentHint: true` · `openWorldHint: false`

### Arguments

| Argument         | Type                                                        | Required | Description                                                                                                                                       |
| ---------------- | ----------------------------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `brandId`        | ID (`brd_…`) or `none`                                      | no       | A brand's accounts (`brd_…`), or `none` for the entity-wide accounts.                                                                             |
| `currency`       | string                                                      | no       | Accounts in this currency.                                                                                                                        |
| `type`           | one of `asset`, `liability`, `revenue`, `expense`, `equity` | no       | Accounts of this type.                                                                                                                            |
| `limit`          | integer                                                     | no       | Page size, 1 to 100 (default 10). (1–100)                                                                                                         |
| `starting_after` | ID (`acct_…`)                                               | no       | The `next_cursor` of the previous page.                                                                                                           |
| `entity_id`      | ID (`ent_…`)                                                | no       | The legal entity to act on (ent\_…), inside your API key's reach. Needed with an organization key; entity and brand keys act on their own entity. |

- **Legal entity:** pass `entity_id` with an organization key; entity and brand keys act on their own entity.
- **Read-only:** changes nothing; `idempotency_key` is ignored.

### Errors

- [`validation_failed`](https://ownrecord.io/docs/reference/errors.md#validation_failed): A filter or pagination value is invalid.
- [`scope_required`](https://ownrecord.io/docs/reference/errors.md#scope_required): The request names no legal entity (an org key without `Ownrecord-Entity`).
- [`permission_denied`](https://ownrecord.io/docs/reference/errors.md#permission_denied): You can't see this entity's ledger (brand-scoped members never can).

### Examples

**The entity's EUR accounts**

Arguments:

```json
{
  "currency": "EUR",
  "entity_id": "ent_01jbx4m3v8e9t0s6k2c5n7q1wy"
}
```

Result `output`:

```json
{
  "object": "list",
  "data": [
    {
      "id": "acct_01m4tx5nj8emwbyf7y9vcf47xd",
      "object": "ledger_account",
      "entityId": "ent_01m4tx5nj8emwbyf7y9vcf47x2",
      "livemode": true,
      "brandId": null,
      "code": "opening_balances:EUR",
      "kind": "opening_balances",
      "type": "equity",
      "currency": "EUR",
      "normalSide": "credit",
      "noNegative": false,
      "balance": {
        "posted": "1500000000",
        "pending": "0"
      },
      "createdAt": "2026-10-13T12:00:00.000Z",
      "updatedAt": "2026-10-14T09:30:00.000Z"
    },
    {
      "id": "acct_01m4tx5nj8emwbyf7y9vcf47xc",
      "object": "ledger_account",
      "entityId": "ent_01m4tx5nj8emwbyf7y9vcf47x2",
      "livemode": true,
      "brandId": null,
      "code": "bank:ent_01m4tx5nj8emwbyf7y9vcf47x2:EUR",
      "kind": "bank",
      "type": "asset",
      "currency": "EUR",
      "normalSide": "debit",
      "noNegative": false,
      "balance": {
        "posted": "1500000000",
        "pending": "0"
      },
      "createdAt": "2026-10-13T12:00:00.000Z",
      "updatedAt": "2026-10-14T09:30:00.000Z"
    }
  ],
  "has_more": false,
  "next_cursor": null
}
```

**Entity-wide equity accounts, one per page**

Arguments:

```json
{
  "brandId": "none",
  "type": "equity",
  "limit": 1,
  "entity_id": "ent_01jbx4m3v8e9t0s6k2c5n7q1wy"
}
```

Result `output`:

```json
{
  "object": "list",
  "data": [
    {
      "id": "acct_01m4tx5nj8emwbyf7y9vcf47xd",
      "object": "ledger_account",
      "entityId": "ent_01m4tx5nj8emwbyf7y9vcf47x2",
      "livemode": true,
      "brandId": null,
      "code": "opening_balances:EUR",
      "kind": "opening_balances",
      "type": "equity",
      "currency": "EUR",
      "normalSide": "credit",
      "noNegative": false,
      "balance": {
        "posted": "1500000000",
        "pending": "0"
      },
      "createdAt": "2026-10-13T12:00:00.000Z",
      "updatedAt": "2026-10-14T09:30:00.000Z"
    }
  ],
  "has_more": true,
  "next_cursor": "acct_01m4tx5nj8emwbyf7y9vcf47xd"
}
```

## `ledger_adjustments_create`

**Create a manual ledger adjustment.** Operation [`ledger.adjustments.create`](https://ownrecord.io/docs/reference/ledger-adjustments-create.md) · Legal entity level · permission `ledger:adjust` · risk tier `financial` · since M2

Posts a manual adjustment to the legal entity's ledger: a transaction of kind `adjustment` that corrects
balances, e.g. to record an opening bank balance. Posted transactions are never changed; to undo an
adjustment, post the reverse one.

Send either two accounts and an amount (`debitAccount`, `creditAccount`, `amount` as
`{ "amount": "<integer micros>", "currency": "EUR" }`), or `entries` (2–50, each
`{ account, side, amount, currency }`) that balance in every currency. Every adjustment needs a `memo`: the
reason, shown in the ledger, the audit log and to approvers.

- Customer wallet accounts can't be adjusted (credit grants move them).
- Accounts are codes from the chart of accounts, in the entry's currency. An adjustment may open
  entity-wide, bank (this entity's) and brand accounts (of this entity's brands); accounts that name a
  processor connection, product or customer must already exist.
- `brandId` makes the transaction the brand's (default: the one brand whose accounts it moves).

Financial tier: the finance role (or an owner or admin) with a sign-in in the last 15 minutes. If the
organization's approval policy lists this operation, a call above the limit of its currency (or in several
currencies) answers `approval_required`: it runs once a second person approves it, as you sent it. Dry-run
it first (`Ownrecord-Dry-Run: true`, `dry_run: true`) to see the entries it would post.

Annotations: `readOnlyHint: false` · `destructiveHint: false` · `idempotentHint: true` · `openWorldHint: false`

### Arguments

| Argument          | Type            | Required | Description                                                                                                                                                                                              |
| ----------------- | --------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `debitAccount`    | string          | no       | Two-account form: the account code to debit, e.g. `bank:ent_…:EUR`. (1–200 characters)                                                                                                                   |
| `creditAccount`   | string          | no       | Two-account form: the account code to credit, e.g. `opening_balances:EUR`. (1–200 characters)                                                                                                            |
| `amount`          | object          | no       | Two-account form: the amount, integer micros as a string, and its currency.                                                                                                                              |
| `entries`         | array of object | no       | Entries form: 2 to 50 entries that balance in every currency. (2–50 items)                                                                                                                               |
| `brandId`         | ID (`brd_…`)    | no       | The brand the adjustment belongs to. Default: the one brand whose accounts it moves.                                                                                                                     |
| `memo`            | string          | yes      | The reason: shown in the ledger, the audit log and to approvers. (1–500 characters)                                                                                                                      |
| `entity_id`       | ID (`ent_…`)    | no       | The legal entity to act on (ent\_…), inside your API key's reach. Needed with an organization key; entity and brand keys act on their own entity.                                                        |
| `idempotency_key` | string          | no       | A unique string for this change. Retrying with the same key and arguments never acts twice. When left out, the server generates one and returns it in the result's `idempotency_key`. (1–255 characters) |
| `dry_run`         | boolean         | no       | true: check permissions and rules and compute the result, then roll everything back. Nothing is saved. (default `false`)                                                                                 |

- **Legal entity:** pass `entity_id` with an organization key; entity and brand keys act on their own entity.
- **Idempotency:** the result returns the `idempotency_key` used, yours or one the server generated. Retry with it: a call with the same key and arguments never acts twice (keys are kept for 24 hours).
- **Dry run:** supported. `dry_run: true` checks permissions and rules and computes the result, then rolls everything back.

### Errors

- [`validation_failed`](https://ownrecord.io/docs/reference/errors.md#validation_failed): A field is missing or malformed, an entry's currency isn't its account's, both input forms were sent, or an account can't be used here (`details.issues`).
- [`ledger_unbalanced`](https://ownrecord.io/docs/reference/errors.md#ledger_unbalanced): Debits and credits differ in a currency (`details.imbalances`).
- [`ledger_account_not_adjustable`](https://ownrecord.io/docs/reference/errors.md#ledger_account_not_adjustable): An entry posts to a customer wallet account.
- [`insufficient_funds`](https://ownrecord.io/docs/reference/errors.md#insufficient_funds): The adjustment would take a customer's credit balance below zero.
- [`resource_not_found`](https://ownrecord.io/docs/reference/errors.md#resource_not_found): `brandId` isn't a brand of this legal entity.
- [`idempotency_key_reused`](https://ownrecord.io/docs/reference/errors.md#idempotency_key_reused): The idempotency key was used before for another adjustment.
- [`approval_required`](https://ownrecord.io/docs/reference/errors.md#approval_required): The approval policy needs a second person for this amount; nothing was posted yet.
- [`approval_rejected`](https://ownrecord.io/docs/reference/errors.md#approval_rejected): The same request was sent again after it was rejected.
- [`approval_expired`](https://ownrecord.io/docs/reference/errors.md#approval_expired): The same request was sent again after its approval request expired.
- [`stale_approval`](https://ownrecord.io/docs/reference/errors.md#stale_approval): The approved request could no longer run as requested.
- [`fresh_auth_required`](https://ownrecord.io/docs/reference/errors.md#fresh_auth_required): Your last sign-in is older than 15 minutes.
- [`livemode_not_allowed`](https://ownrecord.io/docs/reference/errors.md#livemode_not_allowed): You have no live-mode access, so you can't adjust the live ledger.
- [`scope_required`](https://ownrecord.io/docs/reference/errors.md#scope_required): The request names no legal entity (an org key without `Ownrecord-Entity`).
- [`permission_denied`](https://ownrecord.io/docs/reference/errors.md#permission_denied): You can't adjust this entity's ledger (finance, owners and admins can).
- [`version_conflict`](https://ownrecord.io/docs/reference/errors.md#version_conflict): Another posting changed the same accounts at the same moment; retry.

### Examples

**Record an opening bank balance**

Two accounts and an amount: debit the bank account, credit opening balances.

Arguments:

```json
{
  "debitAccount": "bank:ent_01m4tx5nj8emwbyf7y9vcf47x2:EUR",
  "creditAccount": "opening_balances:EUR",
  "amount": {
    "amount": "1500000000",
    "currency": "EUR"
  },
  "memo": "Opening bank balance from the 2026-09-30 statement",
  "entity_id": "ent_01jbx4m3v8e9t0s6k2c5n7q1wy",
  "idempotency_key": "8d0c5f8e-4b7a-4e43-9b0f-2f6a0c1d9e21"
}
```

Result `output`:

```json
{
  "id": "txn_01m4tx5nj8emwbyf7y9vcf47xg",
  "object": "ledger_transaction",
  "entityId": "ent_01m4tx5nj8emwbyf7y9vcf47x2",
  "livemode": true,
  "brandId": null,
  "kind": "adjustment",
  "status": "posted",
  "entries": [
    {
      "accountId": "acct_01m4tx5nj8emwbyf7y9vcf47xc",
      "accountCode": "bank:ent_01m4tx5nj8emwbyf7y9vcf47x2:EUR",
      "side": "debit",
      "amount": "1500000000",
      "currency": "EUR"
    },
    {
      "accountId": "acct_01m4tx5nj8emwbyf7y9vcf47xd",
      "accountCode": "opening_balances:EUR",
      "side": "credit",
      "amount": "1500000000",
      "currency": "EUR"
    }
  ],
  "totals": [
    {
      "currency": "EUR",
      "debits": "1500000000",
      "credits": "1500000000"
    }
  ],
  "effectiveAt": "2026-10-14T09:30:00.000Z",
  "postedAt": "2026-10-14T09:30:00.000Z",
  "voidedAt": null,
  "reversalOf": null,
  "links": {},
  "memo": "Opening bank balance from the 2026-09-30 statement",
  "actor": {
    "type": "user",
    "id": "usr_01m4tx5nj8emwbyf7y9vcf47xa",
    "via": "console",
    "approvalId": "apr_01m4tx5nj8emwbyf7y9vcf47xj",
    "onBehalfOfUserId": null,
    "clientId": null,
    "supportGrantId": null
  },
  "createdAt": "2026-10-14T09:30:00.000Z"
}
```

**Move usage revenue of one brand, with entries**

Arguments:

```json
{
  "entries": [
    {
      "account": "revenue:brd_01m4tx5nj8emwbyf7y9vcf47x4:usage:api.calls:EUR",
      "side": "debit",
      "amount": "2500000",
      "currency": "EUR"
    },
    {
      "account": "rounding:EUR",
      "side": "credit",
      "amount": "2500000",
      "currency": "EUR"
    }
  ],
  "memo": "Reclassify a rounding difference booked as usage revenue",
  "entity_id": "ent_01jbx4m3v8e9t0s6k2c5n7q1wy",
  "idempotency_key": "8d0c5f8e-4b7a-4e43-9b0f-2f6a0c1d9e21"
}
```

Result `output`:

```json
{
  "id": "txn_01m4tx5nj8emwbyf7y9vcf47xh",
  "object": "ledger_transaction",
  "entityId": "ent_01m4tx5nj8emwbyf7y9vcf47x2",
  "livemode": true,
  "brandId": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
  "kind": "adjustment",
  "status": "posted",
  "entries": [
    {
      "accountId": "acct_01m4tx5nj8emwbyf7y9vcf47xe",
      "accountCode": "revenue:brd_01m4tx5nj8emwbyf7y9vcf47x4:usage:api.calls:EUR",
      "side": "debit",
      "amount": "2500000",
      "currency": "EUR"
    },
    {
      "accountId": "acct_01m4tx5nj8emwbyf7y9vcf47xf",
      "accountCode": "rounding:EUR",
      "side": "credit",
      "amount": "2500000",
      "currency": "EUR"
    }
  ],
  "totals": [
    {
      "currency": "EUR",
      "debits": "2500000",
      "credits": "2500000"
    }
  ],
  "effectiveAt": "2026-10-14T09:30:00.000Z",
  "postedAt": "2026-10-14T09:30:00.000Z",
  "voidedAt": null,
  "reversalOf": null,
  "links": {},
  "memo": "Reclassify a rounding difference booked as usage revenue",
  "actor": {
    "type": "user",
    "id": "usr_01m4tx5nj8emwbyf7y9vcf47xa",
    "via": "api",
    "approvalId": null,
    "onBehalfOfUserId": null,
    "clientId": null,
    "supportGrantId": null
  },
  "createdAt": "2026-10-14T09:30:00.000Z"
}
```

## `ledger_transactions_get`

**Get a ledger transaction.** Operation [`ledger.transactions.get`](https://ownrecord.io/docs/reference/ledger-transactions-get.md) · Legal entity level · permission `ledger:read` · risk tier `read` · since M2

Returns one transaction of the legal entity's ledger by its ID (`txn_…`): its `kind` and `status`, the
debit and credit `entries` with their account codes (integer micros), the totals per currency, the business
date (`effectiveAt`), the objects it is about (`links`), the `memo`, and the `actor` who posted it
(`actor.approvalId` names the approval request when a second person approved it). A transaction of another
entity or mode is `resource_not_found`.

Annotations: `readOnlyHint: true` · `destructiveHint: false` · `idempotentHint: true` · `openWorldHint: false`

### Arguments

| Argument    | Type         | Required | Description                                                                                                                                       |
| ----------- | ------------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`        | ID (`txn_…`) | yes      | –                                                                                                                                                 |
| `entity_id` | ID (`ent_…`) | no       | The legal entity to act on (ent\_…), inside your API key's reach. Needed with an organization key; entity and brand keys act on their own entity. |

- **Legal entity:** pass `entity_id` with an organization key; entity and brand keys act on their own entity.
- **Read-only:** changes nothing; `idempotency_key` is ignored.

### Errors

- [`resource_not_found`](https://ownrecord.io/docs/reference/errors.md#resource_not_found): No transaction with this ID is in this entity's ledger in this mode.
- [`scope_required`](https://ownrecord.io/docs/reference/errors.md#scope_required): The request names no legal entity (an org key without `Ownrecord-Entity`).
- [`permission_denied`](https://ownrecord.io/docs/reference/errors.md#permission_denied): You can't see this entity's ledger (brand-scoped members never can).

### Example

**An approved manual adjustment**

Arguments:

```json
{
  "id": "txn_01m4tx5nj8emwbyf7y9vcf47xg",
  "entity_id": "ent_01jbx4m3v8e9t0s6k2c5n7q1wy"
}
```

Result `output`:

```json
{
  "id": "txn_01m4tx5nj8emwbyf7y9vcf47xg",
  "object": "ledger_transaction",
  "entityId": "ent_01m4tx5nj8emwbyf7y9vcf47x2",
  "livemode": true,
  "brandId": null,
  "kind": "adjustment",
  "status": "posted",
  "entries": [
    {
      "accountId": "acct_01m4tx5nj8emwbyf7y9vcf47xc",
      "accountCode": "bank:ent_01m4tx5nj8emwbyf7y9vcf47x2:EUR",
      "side": "debit",
      "amount": "1500000000",
      "currency": "EUR"
    },
    {
      "accountId": "acct_01m4tx5nj8emwbyf7y9vcf47xd",
      "accountCode": "opening_balances:EUR",
      "side": "credit",
      "amount": "1500000000",
      "currency": "EUR"
    }
  ],
  "totals": [
    {
      "currency": "EUR",
      "debits": "1500000000",
      "credits": "1500000000"
    }
  ],
  "effectiveAt": "2026-10-14T09:30:00.000Z",
  "postedAt": "2026-10-14T09:30:00.000Z",
  "voidedAt": null,
  "reversalOf": null,
  "links": {},
  "memo": "Opening bank balance from the 2026-09-30 statement",
  "actor": {
    "type": "user",
    "id": "usr_01m4tx5nj8emwbyf7y9vcf47xa",
    "via": "console",
    "approvalId": "apr_01m4tx5nj8emwbyf7y9vcf47xj",
    "onBehalfOfUserId": null,
    "clientId": null,
    "supportGrantId": null
  },
  "createdAt": "2026-10-14T09:30:00.000Z"
}
```

## `ledger_transactions_list`

**List ledger transactions.** Operation [`ledger.transactions.list`](https://ownrecord.io/docs/reference/ledger-transactions-list.md) · Legal entity level · permission `ledger:read` · risk tier `read` · since M2

Lists the transactions of the legal entity's ledger in the mode of the request, newest first. Every
transaction has balanced debit and credit `entries` (integer micros) on the entity's accounts, its `kind`
and `status`, the `actor` who posted it (with `approvalId` when a second person approved it) and the objects
it is about (`links`). Posted transactions are never changed: corrections are reversals (`reversalOf`).

Filters: `accountId` (an account statement), `kind` (one or several), `status`, `brandId` (or `none`), and
`effectiveFrom` / `effectiveTo`, whole days in UTC (`YYYY-MM-DD`, both included). Paginate with `limit`
(1–100, default 10) and `starting_after` (the `next_cursor` of the previous page). With a date filter, one
call reads at most 1,000 transactions, so a page can hold fewer
than `limit` items while `has_more` is true: keep paging with `next_cursor`.

Annotations: `readOnlyHint: true` · `destructiveHint: false` · `idempotentHint: true` · `openWorldHint: false`

### Arguments

| Argument         | Type                                                                                                        | Required | Description                                                                                                                                       |
| ---------------- | ----------------------------------------------------------------------------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `accountId`      | ID (`acct_…`)                                                                                               | no       | Transactions with an entry on this account: its statement.                                                                                        |
| `kind`           | one of 19 values, e.g. `topup`, `sale`, `grant` or array of one of 19 values, e.g. `topup`, `sale`, `grant` | no       | One kind, or several.                                                                                                                             |
| `status`         | one of `pending`, `posted`, `voided`                                                                        | no       | `pending`, `posted` or `voided`.                                                                                                                  |
| `brandId`        | ID (`brd_…`) or `none`                                                                                      | no       | A brand's transactions (`brd_…`), or `none` for those of no brand.                                                                                |
| `effectiveFrom`  | string                                                                                                      | no       | Effective on or after this day (`YYYY-MM-DD`, UTC).                                                                                               |
| `effectiveTo`    | string                                                                                                      | no       | Effective on or before this day (`YYYY-MM-DD`, UTC).                                                                                              |
| `limit`          | integer                                                                                                     | no       | Page size, 1 to 100 (default 10). (1–100)                                                                                                         |
| `starting_after` | ID (`txn_…`)                                                                                                | no       | The `next_cursor` of the previous page.                                                                                                           |
| `entity_id`      | ID (`ent_…`)                                                                                                | no       | The legal entity to act on (ent\_…), inside your API key's reach. Needed with an organization key; entity and brand keys act on their own entity. |

- **Legal entity:** pass `entity_id` with an organization key; entity and brand keys act on their own entity.
- **Read-only:** changes nothing; `idempotency_key` is ignored.

### Errors

- [`validation_failed`](https://ownrecord.io/docs/reference/errors.md#validation_failed): A filter or pagination value is invalid, or `effectiveFrom` is after `effectiveTo`.
- [`scope_required`](https://ownrecord.io/docs/reference/errors.md#scope_required): The request names no legal entity (an org key without `Ownrecord-Entity`).
- [`permission_denied`](https://ownrecord.io/docs/reference/errors.md#permission_denied): You can't see this entity's ledger (brand-scoped members never can).

### Examples

**Manual adjustments in October 2026**

Arguments:

```json
{
  "kind": "adjustment",
  "effectiveFrom": "2026-10-01",
  "effectiveTo": "2026-10-31",
  "entity_id": "ent_01jbx4m3v8e9t0s6k2c5n7q1wy"
}
```

Result `output`:

```json
{
  "object": "list",
  "data": [
    {
      "id": "txn_01m4tx5nj8emwbyf7y9vcf47xg",
      "object": "ledger_transaction",
      "entityId": "ent_01m4tx5nj8emwbyf7y9vcf47x2",
      "livemode": true,
      "brandId": null,
      "kind": "adjustment",
      "status": "posted",
      "entries": [
        {
          "accountId": "acct_01m4tx5nj8emwbyf7y9vcf47xc",
          "accountCode": "bank:ent_01m4tx5nj8emwbyf7y9vcf47x2:EUR",
          "side": "debit",
          "amount": "1500000000",
          "currency": "EUR"
        },
        {
          "accountId": "acct_01m4tx5nj8emwbyf7y9vcf47xd",
          "accountCode": "opening_balances:EUR",
          "side": "credit",
          "amount": "1500000000",
          "currency": "EUR"
        }
      ],
      "totals": [
        {
          "currency": "EUR",
          "debits": "1500000000",
          "credits": "1500000000"
        }
      ],
      "effectiveAt": "2026-10-14T09:30:00.000Z",
      "postedAt": "2026-10-14T09:30:00.000Z",
      "voidedAt": null,
      "reversalOf": null,
      "links": {},
      "memo": "Opening bank balance from the 2026-09-30 statement",
      "actor": {
        "type": "user",
        "id": "usr_01m4tx5nj8emwbyf7y9vcf47xa",
        "via": "console",
        "approvalId": "apr_01m4tx5nj8emwbyf7y9vcf47xj",
        "onBehalfOfUserId": null,
        "clientId": null,
        "supportGrantId": null
      },
      "createdAt": "2026-10-14T09:30:00.000Z"
    }
  ],
  "has_more": false,
  "next_cursor": null
}
```

**The statement of one account, one per page**

Arguments:

```json
{
  "accountId": "acct_01m4tx5nj8emwbyf7y9vcf47xc",
  "limit": 1,
  "entity_id": "ent_01jbx4m3v8e9t0s6k2c5n7q1wy"
}
```

Result `output`:

```json
{
  "object": "list",
  "data": [
    {
      "id": "txn_01m4tx5nj8emwbyf7y9vcf47xg",
      "object": "ledger_transaction",
      "entityId": "ent_01m4tx5nj8emwbyf7y9vcf47x2",
      "livemode": true,
      "brandId": null,
      "kind": "adjustment",
      "status": "posted",
      "entries": [
        {
          "accountId": "acct_01m4tx5nj8emwbyf7y9vcf47xc",
          "accountCode": "bank:ent_01m4tx5nj8emwbyf7y9vcf47x2:EUR",
          "side": "debit",
          "amount": "1500000000",
          "currency": "EUR"
        },
        {
          "accountId": "acct_01m4tx5nj8emwbyf7y9vcf47xd",
          "accountCode": "opening_balances:EUR",
          "side": "credit",
          "amount": "1500000000",
          "currency": "EUR"
        }
      ],
      "totals": [
        {
          "currency": "EUR",
          "debits": "1500000000",
          "credits": "1500000000"
        }
      ],
      "effectiveAt": "2026-10-14T09:30:00.000Z",
      "postedAt": "2026-10-14T09:30:00.000Z",
      "voidedAt": null,
      "reversalOf": null,
      "links": {},
      "memo": "Opening bank balance from the 2026-09-30 statement",
      "actor": {
        "type": "user",
        "id": "usr_01m4tx5nj8emwbyf7y9vcf47xa",
        "via": "console",
        "approvalId": "apr_01m4tx5nj8emwbyf7y9vcf47xj",
        "onBehalfOfUserId": null,
        "clientId": null,
        "supportGrantId": null
      },
      "createdAt": "2026-10-14T09:30:00.000Z"
    }
  ],
  "has_more": true,
  "next_cursor": "txn_01m4tx5nj8emwbyf7y9vcf47xg"
}
```

## `ledger_trial_balance`

**Get the trial balance.** Operation [`ledger.trial_balance`](https://ownrecord.io/docs/reference/ledger-trial-balance.md) · Legal entity level · permission `ledger:read` · risk tier `read` · since M2

Returns the trial balance of the legal entity's ledger in the mode of the request: for each currency, every
account with a non-zero posted balance, its balance on the debit or the credit side (integer micros), and the
debit and credit totals. The totals of a currency must be equal (`balanced`); `difference` is debits minus
credits. All brands of the entity are included.

Without `asOf`, the balances are the accounts' current posted balances. With `asOf` (`YYYY-MM-DD`), they are
recomputed from the posted transactions effective up to the end of that day (UTC). Pending and voided
transactions never count. Filter with `currency`.

Annotations: `readOnlyHint: true` · `destructiveHint: false` · `idempotentHint: true` · `openWorldHint: false`

### Arguments

| Argument    | Type         | Required | Description                                                                                                                                       |
| ----------- | ------------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `asOf`      | string       | no       | Balances at the end of this day (`YYYY-MM-DD`, UTC). Leave it out for the balances now.                                                           |
| `currency`  | string       | no       | One currency only.                                                                                                                                |
| `entity_id` | ID (`ent_…`) | no       | The legal entity to act on (ent\_…), inside your API key's reach. Needed with an organization key; entity and brand keys act on their own entity. |

- **Legal entity:** pass `entity_id` with an organization key; entity and brand keys act on their own entity.
- **Read-only:** changes nothing; `idempotency_key` is ignored.

### Errors

- [`validation_failed`](https://ownrecord.io/docs/reference/errors.md#validation_failed): `asOf` isn't a date such as 2026-09-30, or `currency` isn't a currency code.
- [`scope_required`](https://ownrecord.io/docs/reference/errors.md#scope_required): The request names no legal entity (an org key without `Ownrecord-Entity`).
- [`permission_denied`](https://ownrecord.io/docs/reference/errors.md#permission_denied): You can't see this entity's ledger (brand-scoped members never can).

### Examples

**The trial balance now**

Arguments:

```json
{
  "entity_id": "ent_01jbx4m3v8e9t0s6k2c5n7q1wy"
}
```

Result `output`:

```json
{
  "object": "ledger_trial_balance",
  "entityId": "ent_01m4tx5nj8emwbyf7y9vcf47x2",
  "livemode": true,
  "asOf": null,
  "balanced": true,
  "currencies": [
    {
      "currency": "EUR",
      "accounts": [
        {
          "accountId": "acct_01m4tx5nj8emwbyf7y9vcf47xc",
          "code": "bank:ent_01m4tx5nj8emwbyf7y9vcf47x2:EUR",
          "type": "asset",
          "normalSide": "debit",
          "brandId": null,
          "balance": "1500000000",
          "debit": "1500000000",
          "credit": "0"
        },
        {
          "accountId": "acct_01m4tx5nj8emwbyf7y9vcf47xd",
          "code": "opening_balances:EUR",
          "type": "equity",
          "normalSide": "credit",
          "brandId": null,
          "balance": "1500000000",
          "debit": "0",
          "credit": "1500000000"
        }
      ],
      "totals": {
        "debit": "1500000000",
        "credit": "1500000000"
      },
      "difference": "0",
      "balanced": true
    }
  ]
}
```

**EUR balances at the end of September 2026**

Arguments:

```json
{
  "asOf": "2026-09-30",
  "currency": "EUR",
  "entity_id": "ent_01jbx4m3v8e9t0s6k2c5n7q1wy"
}
```

Result `output`:

```json
{
  "object": "ledger_trial_balance",
  "entityId": "ent_01m4tx5nj8emwbyf7y9vcf47x2",
  "livemode": true,
  "asOf": "2026-09-30",
  "balanced": true,
  "currencies": [
    {
      "currency": "EUR",
      "accounts": [
        {
          "accountId": "acct_01m4tx5nj8emwbyf7y9vcf47xc",
          "code": "bank:ent_01m4tx5nj8emwbyf7y9vcf47x2:EUR",
          "type": "asset",
          "normalSide": "debit",
          "brandId": null,
          "balance": "1500000000",
          "debit": "1500000000",
          "credit": "0"
        },
        {
          "accountId": "acct_01m4tx5nj8emwbyf7y9vcf47xd",
          "code": "opening_balances:EUR",
          "type": "equity",
          "normalSide": "credit",
          "brandId": null,
          "balance": "1500000000",
          "debit": "0",
          "credit": "1500000000"
        }
      ],
      "totals": {
        "debit": "1500000000",
        "credit": "1500000000"
      },
      "difference": "0",
      "balanced": true
    }
  ]
}
```
