> ## Documentation Index
> Fetch the complete documentation index at: https://docs.beaconrevenue.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Ledger entry object

> The eight values Beacon publishes about each posted entry in your general ledger — what it was, when it posted, which period it belongs to and which account category it hit.

The ledger-entry object carries eight values about each posted entry in your general ledger, at one row per entry, and two timestamps that accompany every one of them on every door: `as_of` and `computed_at`. **All eight are available through the doors below.**

This is the grain everything in the cost model is built from. A cost pool is a sum of these entries, grouped by the category they hit and the period they posted in — which is why the [chart of accounts object](/data-model/chart-of-accounts) and this one are read together.

<Note>
  The names, types and availability below are fixed. No read interface or MCP tool serves them yet — this page publishes the shape ahead of the doors.
</Note>

On the read interface this object is `ledger_entry` and the collection is [`GET /ledger-entries`](/api-reference).

## Example payload

```json theme={null}
{
  "object": "ledger_entry",
  "id": "gl_88431",
  "as_of": "2026-08-05T06:00:00Z",
  "computed_at": "2026-08-05T06:11:48Z",
  "gl_entry_id": "gl_88431",
  "account_id": "acc_20417",
  "coa_category_id": "412",
  "amount": 18400.00,
  "currency": "EUR",
  "posted_date": "2026-07-29",
  "period_key": "2026-07",
  "cac_component_flag": false
}
```

## Attributes

| Value | Type | Method | What it holds |
| - | - | - | - |
| `as_of` | Timestamp, UTC | System | The moment the value describes. Present on every response and every property. |
| `computed_at` | Timestamp, UTC | System | When Beacon last read or worked the value out. Present on every response and every property. |
| `gl_entry_id` | String | Measured | Your accounting system's own identifier for the posted entry. |
| `account_id` | String | Measured | The customer account this entry is attributed to. **Not available until Beacon has attributed the entry, and that is not a gap in your data** — see below. |
| `coa_category_id` | String | Measured | The chart-of-accounts category the entry posted to. This is the link that gives the entry its cost role. |
| `amount` | Number, in the currency below | Measured | The amount of the entry, signed: **debits positive, credits negative.** So expense and asset postings read positive, and income, liability and equity postings read negative — a revenue category's monthly total is a negative number. That is the convention, not an error. Your accounting system may not present it that way — see below. |
| `currency` | String, ISO 4217 | Measured | The currency the entry was posted in. Present on every entry: an amount without a currency tag is not a figure, and every other place Beacon holds money carries one. |
| `posted_date` | Date | Measured | The date the entry posted, as your ledger recorded it. This is the only evidence of period a ledger line carries, and it is what every reproducible cost figure is anchored to. |
| `period_key` | String, `YYYY-MM` | Measured | The calendar month of the posting date. **Calendar, not your fiscal period** — see below. |
| `cac_component_flag` | Boolean | Measured | Whether this entry counts toward acquisition cost. Beacon works it out from the category's cost role rather than holding it as a separate switch, so the two can never disagree. It cannot be set by hand. |

**`account_id` is not available until an entry is attributed, and that is a property of ledgers rather than of your data.** Until then, reading it returns a refusal saying it has not been worked out yet — never a `null`, because the value does apply to the entry; it simply is not known yet. The example above shows an entry after attribution. A posted general-ledger line does not carry a customer. It carries an amount, a date and an account category — and nothing that says which of your customers it was for. So the cost of serving a particular customer is never read straight off the ledger; it is allocated, using the bases you declare during setup. The field exists because an allocated entry has an account, not because a connector is expected to fill it.

**The period key is a calendar month, deliberately, even if your fiscal year is not.** The reason is comparability: revenue in Beacon is held by calendar month, and a ratio whose top half is fiscal-period cost and whose bottom half is calendar-month revenue is not a ratio of anything. Your own fiscal period is still used — it drives which periods count as closed — but it is kept separate from the key the cost pools group on.

**One consequence worth knowing before you meet it.** If your fiscal year does not start in January, Beacon's monthly cost figures will reconcile to your ledger in total but will not line up period-for-period against your own management accounts, because the period boundaries are different. That is a presentation difference, not a discrepancy.

**A figure read from an open accounting period is marked provisional.** Where your accounting system tells Beacon which periods are closed, entries in a closed period can be relied on as final. Where it does not — and several systems do not expose this at all — you declare the date your books are closed through during setup, and until you do, every accounting-sourced figure is shown as provisional rather than presented as final. The figures are still correct as read; what is withheld is the claim that they will not move.

## Availability

✓ available by default · ⊕ available after an opt-in that states who becomes able to see the value · — not available.

**Nothing on this object is served on any door today, and that is true of all eight rather than of some of them.** The names, types, ceilings and marks below are fixed and will not change when the doors open.

| Value | Read interface | MCP tools | Events | CRM property | Audience ceiling |
| - | - | - | - | - | - |
| `as_of` | ✓ | ✓ | in every event | — | `operational` |
| `computed_at` | ✓ | ✓ | in every event | — | `operational` |
| `gl_entry_id` | ✓ | ✓ | ✓ | — | `operational` |
| `account_id` | ✓ | ✓ | ✓ | — | `operational` |
| `coa_category_id` | ✓ | ✓ | ✓ | — | `operational` |
| `amount` | ✓ | ✓ | ⊕ | — | `operational` |
| `currency` | ✓ | ✓ | ✓ | — | `operational` |
| `posted_date` | ✓ | ✓ | ✓ | — | `operational` |
| `period_key` | ✓ | ✓ | ✓ | — | `operational` |
| `cac_component_flag` | ✓ | ✓ | ✓ | — | `operational` |

**The CRM door is closed on this object, and not by an opt-in.** A ledger entry is not a fact about a customer record, so there is nothing to write it onto. That is a hard limit rather than a setting.

**`amount` is off by default on the events door.** It is the one value here with money in it, and an event is delivered to a destination you name — once it arrives there, the receiving tool governs who reads it and Beacon can no longer record who did. Turning it on takes an opt-in that states who becomes able to see it.

**Every value on this object sits at `operational`**, derived the same way as on the chart-of-accounts object. Beacon's access rules gate money fields to finance and data-governance roles, which reaches `amount`; the roles that gate names sit below leadership level and already read this object at full scope, so the ceiling does not move. That qualification is recorded on the value rather than left out.

## What your accounting system changes

**Two things about this object depend on which accounting system you are on.** Both are stated here rather than left to surface during implementation.

**The sign of the amount is not consistent across accounting systems.** Some deliver a signed number, where debits are positive and credits negative. Others deliver an unsigned number with the direction in a separate field. Others still deliver two columns, a debit and a credit, with one of them zero. Beacon publishes one convention on this object — debits positive, credits negative — and converts on the way in, per system. This is worth knowing because it is the kind of difference that, handled wrongly, produces a cost figure that is wrong *and still balances* — so it is handled once, in a declared and version-pinned step, rather than assumed.

**Not every accounting system exposes its posted general ledger the same way.** Some publish it as a first-class feed of every posting. Others publish only journal entries, which on some platforms means manual journals alone — a small minority of a real ledger, and not a substitute for it. Where the full posted ledger is available, Beacon reads it and nothing else. Where it is not, the fallback is narrower and is declared as such rather than presented as equivalent. **Which of the supported accounting systems fall into which case is being confirmed with the connector providers directly, and will be stated on the [connector catalogue](/connector-catalogue) rather than inferred.**

**Beacon reads the posted ledger and never the documents behind it.** Invoices, bills, payments, expenses and credit notes are all already represented in the posted ledger. Reading both would count the same money twice, so the documents are excluded on that ground, and the entry keeps a reference to the document that produced it so the exclusion can be checked rather than trusted.

## Freshness

| Value | Recomputed | Sealed |
| - | - | - |
| All eight values | On each sync from your accounting system | Inside the locked record of the period the entry's `period_key` names, once that period is locked |

**An entry itself does not change once posted — but a restatement can add one.** Where your accounting system allows a closed period to be reopened and amended, Beacon detects it after the fact by watching the entry's own modification timestamp and by noticing a posting dated outside the period it is labelled with. Detection is not prevention, and the difference is stated plainly: where your system exposes a lock date, Beacon can refuse to seal over a period that is still open; where it does not, a restatement is caught after it happens rather than stopped before it.

## Versioning

The published object is versioned separately from Beacon's internal model. A value is never removed from a published version — it is deprecated, and the removal lands in the next version. A published name is permanent; a rename ships as a redirect.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.