# Read General Ledger

`POST /accounting/reports/general-ledger`

Group: Accounting › Reports › General Ledger · Operation ID: `readGeneralLedger`

Returns the general ledger for one book and entity over a bounded window: the posted journal entry lines and the lines the ledger derives so the statements tie out. It reports movements only, with no opening, closing or running balance. It is not paginated, so narrow the request until it returns in one response, or it fails with RESULT_TOO_LARGE.

[Open in the interactive reference](https://docs.api.lensing.ai/?op=readGeneralLedger)

## Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `Api-Version` | header | `"v1"` | yes | The API version this request targets, named by its public identifier. Required on every request; omitting it, or naming a version this company does not have, is answered with 400. This document describes version `v1`. |

## Request body

Required, `application/json`: readGeneralLedgerInput.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `bookId` | string | yes | The accounting book to read. Exactly one book per request. An adjustment book automatically includes its base book. See id on GET accounting/books/:id. |
| `entityId` | string | yes | The entity to read. When consolidated is false, this is the posting entity. When true, this is the consolidating parent, and the response covers its whole hierarchy, with each line also carrying preConsolidationEntityId naming the child that posted it. Exactly one entity per request. See id on GET base/entities. |
| `consolidated` | boolean | yes | Whether to return the consolidated ledger for entityId and its hierarchy. When true, amounts are also translated into the parent's currency and elimination and CTA lines appear. When false, this returns the entity's own ledger with no translation, elimination or CTA. |
| `postingDate` | object | no | A window on the posting date, the date a line was booked. Supply exactly one of postingDate or accountingPeriod. Both bounds are inclusive. The window may span at most 366 days. |
| `postingDate.start` | string (date) | yes | The inclusive start of the window. Use format YYYY-MM-DD. |
| `postingDate.end` | string (date) | yes | The inclusive end of the window. Use format YYYY-MM-DD. |
| `accountingPeriod` | object | no | A window on the accounting period, the period a line was booked into. Supply exactly one of postingDate or accountingPeriod. Both bounds are inclusive. The resolved period dates may span at most 366 days. |
| `accountingPeriod.startPeriodId` | string | yes | The first accounting period in the window. See accountingPeriodId on GET accounting/accounting-periods. |
| `accountingPeriod.endPeriodId` | string | yes | The last accounting period in the window, read the same way. |
| `filters` | object | no | Narrows which lines are returned, pushed down into the ledger computation wherever the ledger can express it. Derived amounts stay honest: a filter naming a derived line's offset account, such as CTA, translation elimination or retained earnings, is computed across every line in scope, and a filter that excludes those accounts drops those lines rather than returning a partial figure. Because derived lines carry almost no dimensions, any dimension filter drops nearly every retained-earnings, elimination and CTA line, so the returned lines no longer sum to a balanced ledger and the response carries a RESULT_DOES_NOT_TIE_OUT warning. lineOrigins is applied to the computed result rather than pushed down, as are tags on a dimension the ledger does not index. |
| `filters.accountIds` | array of string | no | Restrict to these accounts. Naming a derived line's offset account returns that line with its amount computed across all accounts. Omitting it drops the line, so a partial CTA is never returned. See id on GET accounting/accounts/:id. |
| `filters.lineOrigins` | array of string, one of `"posted"`, `"retainedEarnings"`, `"elimination"`, `"cta"`, `"ctaElimination"` | no | Restrict to these kinds of line. Omit for all kinds. Pass ['posted'] for posted journal entry lines only, excluding everything the ledger derives. |
| `filters.reportingTags` | array of object | no | Restrict to lines carrying all of these dimension values. This is the one dimension filter: every dimension is filtered here, whether the ledger stores it as a column, such as department, business unit, value center, employee, customer or vendor, or as a tag, such as a custom dimension, team, location or region. Naming two values of the same dimension matches nothing, since a line has one value per dimension. A value that does not exist matches nothing rather than failing. |
| `filters.reportingTags[].dimensionCode` | string | yes | The reporting dimension this filter is for. It determines which model modelId points to. Accepted values: 'department', 'businessUnit', 'team', 'location', 'region', 'employee', 'vendor', 'customer', 'valueCenter', 'custom'. |
| `filters.reportingTags[].modelId` | string | yes | The dimension record this filter points to, on the model that dimensionCode names. |
| `dimensions` | array of string, one of `"accounts"`, `"entities"`, `"periods"`, `"books"`, `"reportingTagDimensions"` | no | Which dimension dictionaries to return in dimensions. Omit for all of them, or pass an empty array for none. This never changes the lines: every id is always present on every line. An unrecognized name fails input validation. |

Example:

```json
{
  "bookId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "entityId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "consolidated": true,
  "postingDate": {
    "start": "2026-01-15",
    "end": "2026-01-15"
  },
  "accountingPeriod": {
    "startPeriodId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "endPeriodId": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
  },
  "filters": {
    "accountIds": [
      "<accountIds>"
    ],
    "lineOrigins": [
      "posted"
    ],
    "reportingTags": [
      {
        "dimensionCode": "<dimensionCode>",
        "modelId": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
      }
    ]
  },
  "dimensions": [
    "accounts"
  ]
}
```

## Response

`200` Success

Under `data` (readGeneralLedgerOutput):

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `lines` | array of object | yes | The ledger's movements, ordered by posting date, then journal entry, then line. The ids on each line resolve in dimensions. A posted line has journalEntryLineId and journalEntryId to reach the underlying record. A derived line is computed per request and has no id of its own. |
| `lines[].lineOrigin` | string, one of `"posted"`, `"retainedEarnings"`, `"elimination"`, `"cta"`, `"ctaElimination"` | yes | What kind of line this is, and the only field always present. 'posted' is a persisted journal entry line. The rest are derived by the ledger. 'elimination', 'cta' and 'ctaElimination' appear only when consolidated is true. |
| `lines[].accountId` | string | yes | The account this line posts to. A derived line lands on the offset account configured for its accounting process, so this is always set. Resolve it in dimensions.accounts. |
| `lines[].entityId` | string | yes | The entity this line belongs to. Resolve it in dimensions.entities. |
| `lines[].postingPeriodId` | string | yes | The accounting period this line is booked into. Resolve it in dimensions.periods. |
| `lines[].postingDate` | string (date) | yes | The posting date. Format YYYY-MM-DD. For a derived line this is the date the ledger assigns it, usually the end of the period it balances. |
| `lines[].bookId` | string | yes | The accounting book this line belongs to. Resolve it in dimensions.books. |
| `lines[].journalEntryLineId` | string | no | The unique identifier for the posted journal entry line. Present only when lineOrigin is 'posted'. |
| `lines[].journalEntryId` | string | no | The journal entry this line belongs to. Present only when lineOrigin is 'posted'. See id on GET accounting/journal-entries/:id. |
| `lines[].journalEntryLineReference` | string | no | A human-readable reference to this line within its journal entry. Present only when lineOrigin is 'posted', and can be absent on some posted lines, as the INCOMPLETE_TRANSACTION_REFERENCES warning reports. |
| `lines[].transactionReference` | string | no | A reference to the business transaction that produced this line. Present only when lineOrigin is 'posted', and can be absent, as INCOMPLETE_TRANSACTION_REFERENCES reports. |
| `lines[].lineType` | string | no | The classification of this line within its journal entry, for example 'standard', 'tax', 'offset' or 'fxRoundingDifference'. A system-assigned value. Absent on a derived line. |
| `lines[].description` | string | no | The line description. |
| `lines[].intercompanyPartnerId` | string | no | The intercompany counterparty for this line. Set on an intercompany line. |
| `lines[].reportingTags` | array of object | no | Every dimension value on this line, one entry each: department, business unit, value center, employee, customer and vendor, alongside any custom dimension. Absent when the line has no dimension, which is normal for a derived line. Resolve each entry in dimensions.reportingTagDimensions. |
| `lines[].reportingTags[].dimensionCode` | string | yes | The reporting dimension this value is for. Possible values: 'department', 'businessUnit', 'team', 'location', 'region', 'employee', 'vendor', 'customer', 'valueCenter', 'custom'. Every custom dimension uses the code 'custom', and dimensions.reportingTagDimensions names which one a value belongs to. |
| `lines[].reportingTags[].modelId` | string | yes | The dimension record this value points to, on the model that dimensionCode names. |
| `lines[].transactionalCurrency` | string | no | The currency the business event happened in. Format ISO 4217, for example 'USD'. Absent on a derived line, which has no transactional amount. |
| `lines[].transactionalDebit` | string (decimal) | no | The debit in the transactional currency. A line has either a debit or a credit, not both. |
| `lines[].transactionalCredit` | string (decimal) | no | The credit in the transactional currency. A line has either a debit or a credit, not both. |
| `lines[].transactionalAmount` | string (decimal) | no | transactionalDebit minus transactionalCredit. Negative for a net credit. To read it in an account's natural direction, with revenue and expense both positive, multiply by the sign that normalBalance implies on the account in dimensions.accounts. |
| `lines[].functionalDebit` | string (decimal) | no | The debit in the posting entity's own currency. The currency is functionalCurrency on the entity in dimensions.entities, since it does not vary per line. |
| `lines[].functionalCredit` | string (decimal) | no | The credit in the posting entity's own currency. |
| `lines[].functionalAmount` | string (decimal) | no | functionalDebit minus functionalCredit. |
| `lines[].functionalExchangeRate` | string (decimal) | no | The rate used to convert the transactional amount into the functional currency. Absent on a derived line, which has no transactional amount. |
| `lines[].consolidatedDebit` | string (decimal) | no | The debit in the consolidating parent's currency. Present only when consolidated is true. The currency is consolidationCurrency at the top of this response, since it is the same for every line. |
| `lines[].consolidatedCredit` | string (decimal) | no | The credit in the consolidating parent's currency. Present only when consolidated is true. |
| `lines[].consolidatedAmount` | string (decimal) | no | consolidatedDebit minus consolidatedCredit. Present only when consolidated is true. |
| `lines[].consolidationExchangeRate` | string (decimal) | no | The rate used to convert the functional amount into the consolidation currency. Which rate this is depends on the account's exchangeRateType in dimensions.accounts. Present only when consolidated is true. |
| `lines[].preConsolidationAccountId` | string | no | The account this line was posted to before consolidation account mapping. Present only when consolidated is true and the account was mapped. Resolve it in dimensions.accounts, which contains both the mapped and the pre-consolidation accounts. |
| `lines[].preConsolidationEntityId` | string | no | The child entity that posted this line, before it rolled into the parent. Present only when consolidated is true. Resolve it in dimensions.entities. |
| `lines[].preConsolidationPostingPeriodId` | string | no | The period this line sat in before it was re-dated into the parent's fiscal calendar. Differs from postingPeriodId when the parent and child keep different calendars. Present only when consolidated is true. Resolve it in dimensions.periods. |
| `dimensions` | object | yes | Display values for the ids on the lines, each appearing once however many lines reference it. A collection is present only when its name was in the dimensions input, which defaults to all of them. Accounts, entities and periods contain both the consolidated and the pre-consolidation records, so every id on every line resolves. |
| `dimensions.accounts` | array of object | no | The accounts referenced by any line, including pre-consolidation source accounts. The field names follow the accounts endpoint, so you can join the two without a mapping table. |
| `dimensions.accounts[].id` | string | yes | The unique identifier for the account. See id on GET accounting/accounts/:id. |
| `dimensions.accounts[].accountNumber` | string | yes | The account number. |
| `dimensions.accounts[].accountName` | string | yes | The name of the account. |
| `dimensions.accounts[].accountType` | string | yes | The top-level classification of the account. Possible values: 'asset', 'liability', 'equity', 'income', 'costOfGoodsSold', 'expense', 'otherIncome', 'otherExpense'. |
| `dimensions.accounts[].accountSubType` | string | no | A finer classification within accountType. Possible values: 'bank', 'accountsReceivable', 'fixedAsset', 'cip', 'prepaidExpenses', 'deferredExpenses', 'otherCurrentAsset', 'otherAsset', 'unbilledReceivable', 'longTermAsset', 'accountsPayable', 'creditCard', 'deferredRevenue', 'otherCurrentLiability', 'longTermLiability', 'equity', 'income', 'costOfGoodsSold', 'expense', 'otherIncome', 'otherExpense', 'otherComprehensiveIncome'. Absent when none is assigned. |
| `dimensions.accounts[].normalBalance` | string, one of `"debit"`, `"credit"` | yes | Whether the account's natural direction is a debit or a credit. Multiply a signed amount by +1 for 'debit' and -1 for 'credit' to read it with revenue and expense both positive. |
| `dimensions.accounts[].exchangeRateType` | string, one of `"current"`, `"average"`, `"historical"` | no | Which rate translates this account's functional amounts into the consolidation currency. |
| `dimensions.entities` | array of object | no | The entities referenced by any line, including pre-consolidation child entities. |
| `dimensions.entities[].id` | string | yes | The unique identifier for the entity. See id on GET base/entities. |
| `dimensions.entities[].entityName` | string | yes | The name of the entity. |
| `dimensions.entities[].functionalCurrency` | string | no | The entity's own currency, the currency of every functional amount on its lines. Format ISO 4217, for example 'USD'. |
| `dimensions.periods` | array of object | no | The accounting periods referenced by any line, including pre-consolidation periods. |
| `dimensions.periods[].id` | string | yes | The unique identifier for the accounting period. See accountingPeriodId on GET accounting/accounting-periods. |
| `dimensions.periods[].periodName` | string | yes | The period name, as its fiscal calendar defines it. |
| `dimensions.periods[].fiscalYear` | string | yes | The fiscal year this period belongs to. |
| `dimensions.periods[].startDate` | string (date) | yes | The first day of the period. Format YYYY-MM-DD. |
| `dimensions.periods[].endDate` | string (date) | yes | The last day of the period. Format YYYY-MM-DD. |
| `dimensions.books` | array of object | no | The books referenced by any line: the requested book, and its base book when an adjustment book was requested. |
| `dimensions.books[].id` | string | yes | The unique identifier for the accounting book. See id on GET accounting/books/:id. |
| `dimensions.books[].name` | string | yes | The name of the book. |
| `dimensions.books[].bookType` | string, one of `"full"`, `"adjustment"` | yes | Whether this book is a full book or an adjustment book. An adjustment book has only the deltas layered over its base book, so read it together with its base and add the two rather than read either alone. |
| `dimensions.books[].accountingStandard` | string | no | The accounting standard this book reports under, by name, for example 'IFRS', 'US GAAP' or a local standard. A tenant defines its own standards, so treat an unrecognized value as data rather than an error. Absent on a book that declares none. |
| `dimensions.reportingTagDimensions` | array of object | no | Every dimension record referenced by a reportingTags entry on any line, named once however many lines reference it. One list for every dimension: department, business unit, value center, employee, customer, vendor, team, location, region and the custom dimensions all resolve here, so adding a dimension adds entries rather than a collection. A record that has since been deactivated is still named, because a posted line legitimately references one. |
| `dimensions.reportingTagDimensions[].dimensionCode` | string | yes | The reporting dimension this record is for, matching the dimensionCode on the lines' reportingTags. Possible values: 'department', 'businessUnit', 'team', 'location', 'region', 'employee', 'vendor', 'customer', 'valueCenter', 'custom'. |
| `dimensions.reportingTagDimensions[].modelId` | string | yes | The dimension record this entry describes, matching the modelId on the lines' reportingTags. The pair (dimensionCode, modelId) is the key. |
| `dimensions.reportingTagDimensions[].code` | string | no | The record's own business code, such as a department number, a customer number or a value center code. Absent for a dimension that keeps no code. |
| `dimensions.reportingTagDimensions[].name` | string | yes | The display name of the dimension record. |
| `dimensions.reportingTagDimensions[].customDimensionId` | string | no | The custom dimension this record belongs to. Present only for a 'custom' value, where several dimensions share one model and are told apart only by this. See id on GET base/custom-dimensions. |
| `consolidationCurrency` | string | no | The consolidating parent's currency, the currency of every consolidated amount in this response. Stated once because it is the same for every line. Format ISO 4217, for example 'USD'. Present only when consolidated is true. |

## Errors

| Code | Status |
| --- | --- |
| `RESULT_TOO_LARGE` | 400 |
| `WINDOW_TOO_LONG` | 400 |
| `DATE_RANGE_REQUIRED` | 400 |
| `AMBIGUOUS_DATE_FILTER` | 400 |
| `ENTITY_NOT_FOUND` | 400 |
| `BOOK_NOT_FOUND` | 400 |
| `PERIOD_NOT_FOUND` | 400 |
| `CONSOLIDATION_ACCOUNTS_NOT_CONFIGURED` | 400 |
| `CONSOLIDATION_ACCOUNT_MAPPING_MISSING` | 400 |
| `CONSOLIDATION_RATES_NOT_CONFIGURED` | 400 |
| `EXCHANGE_RATE_NOT_FOUND` | 400 |

## Statuses

- `400` — Invalid request or business failure. Codes: RESULT_TOO_LARGE, WINDOW_TOO_LONG, DATE_RANGE_REQUIRED, AMBIGUOUS_DATE_FILTER, ENTITY_NOT_FOUND, BOOK_NOT_FOUND, PERIOD_NOT_FOUND, CONSOLIDATION_ACCOUNTS_NOT_CONFIGURED, CONSOLIDATION_ACCOUNT_MAPPING_MISSING, CONSOLIDATION_RATES_NOT_CONFIGURED, EXCHANGE_RATE_NOT_FOUND
- `401` — Missing or invalid access token
- `403` — Not authorized
- `404` — Not found
- `429` — Too many requests
- `500` — Internal server error
