Ledger
A real-time, append-only, double-entry ledger per legal entity. It's the source of truth for balances, revenue, tax payable and what your processor owes you.
Every legal entity has one ledger, shared by all its brands. Every payment, invoice, refund, chargeback, credit purchase and tax amount is posted to it as it happens. Balances in Ownrecord come from the ledger, not from your payment processor.
Principles
- Double entry. Every transaction has debits and credits, and they're equal in each currency.
- Append-only. A posted transaction is never changed or deleted. A correction is a new transaction that reverses the original.
- Idempotent. Every posting carries an idempotency key, so posting the same thing twice has no effect.
- Consistent balances. Account balances are updated in the same database transaction that records the entry, so a balance always matches its entries.
- No overdrafts where they make no sense. Accounts such as a customer's prepaid credits can't go below zero; a posting that would overdraw them is refused.
- Exact amounts. Amounts are integers in micros (millionths of the currency's major unit). There are no floating-point numbers anywhere.
Accounts
Accounts are created per entity and per currency, the first time they're needed. They follow the usual five types:
| Type | Examples |
|---|---|
| Asset | Money captured on a processor connection but not yet paid out; your bank account; unpaid invoices. |
| Liability | Customers' prepaid credits; revenue billed in advance but not yet earned; tax collected and owed; expired credits not yet recognised. |
| Revenue | Earned revenue per brand and product; usage revenue; expired credits. |
| Expense | Processor fees; chargeback losses; bad debt; promotional credits; rounding. |
| Equity | Opening balances. |
Revenue, deferred revenue and receivables are kept per brand, so each brand's figures come straight from the ledger. Tax payable is kept per regime and jurisdiction for the whole entity, so one tax return covers every brand. Tax collected during a registration grace period is held in a separate account until you're registered.
Balances and sides
Every account has a normal side: the side that increases it. Assets and expenses increase with debits; liabilities, revenue and equity increase with credits. A balance is stored as an amount on the normal side, so a positive balance sits on that side and a negative one on the other side. The console always shows the amount and the side in words ("€1,500.00 Debit") and marks a balance that sits on the unusual side. In the API, balance.posted and balance.pending are integer micros, signed in the account's normal direction.
Pending transactions (for example an asynchronous bank payment that isn't confirmed yet) move only balance.pending. They count in the posted balance once they're posted, and never if they're voided.
The ledger in the console
Open a legal entity and choose Ledger. Finance, owners, admins and the other entity-wide roles see it; members scoped to one brand don't, because the ledger covers every brand of the entity. Test and live mode each have their own ledger.
- Accounts: the account explorer. Filter by brand (or the entity-wide accounts), type and currency. Each account opens its statement: every transaction with an entry on it, newest first, with what it moved there.
- Transactions: every transaction, newest first. Filter by kind, status, brand, account and effective day (days are in UTC). A transaction shows its entries with debit and credit columns and the totals per currency, what it is about, and who posted it, including the approval request when a second person approved it.
- Trial balance: for each currency, every account with a balance on its debit or credit side, and the debit and credit totals, which must be equal. Each currency shows Balanced or Out of balance with the difference. Pick a day to see the balances at the end of that day (UTC): they are recomputed from the transactions effective up to then. All brands of the entity are included.
Every page names the operation behind it, so you can do the same through the API or an MCP client.
Manual adjustments
A manual adjustment corrects balances by hand, for example to record an opening bank balance or to reclassify an amount booked to the wrong account. It's a transaction of kind adjustment, posted like any other: balanced in every currency, never changed afterwards. To undo one, post the reverse adjustment.
- Who: the finance role, owners and admins, with a sign-in within the last 15 minutes.
- How: two accounts and an amount (debit one, credit the other), or a list of entries that balance in every currency. Accounts are codes from the chart of accounts, such as
opening_balances:EURorbank:ent_…:EUR, in their own currency. - A reason is required. It is stored with the transaction, shown in the ledger and the audit log, and shown to approvers.
- Preview first. The console shows the exact entries from a dry run before anything is posted, then asks you to confirm. Agents should dry-run too (
Ownrecord-Dry-Run: true, ordry_run: trueon MCP). - What can't be adjusted: customers' wallet balances, which move only with their credit grants, so a wallet always equals its remaining credits. An adjustment can open entity-wide accounts, the entity's own bank account and accounts of the entity's brands; accounts that name a processor connection, product or customer must already exist. A customer's credit balance can't go below zero.
- Brand: an adjustment belongs to the brand you choose, or by default to the one brand whose accounts it moves.
- Idempotent: sending the same request again with the same idempotency key posts it once.
Two-person approval above an amount
An owner or admin can require a second person for adjustments in Settings → Approvals: select Create a manual ledger adjustment and set an amount per currency. An adjustment at or below the limit of its currency is posted at once. Above it, in a currency without a limit, or in several currencies at once, nothing is posted: you get an approval request instead (HTTP 202 in the API, a banner in the console). Its diff shows the accounts' balances before and after.
When someone else who may adjust the ledger approves it, the adjustment is posted exactly as you sent it, once, under your name. The transaction's actor carries the approval's ID (approvalId), and the console links the transaction to the approval request.
API and MCP
| Operation | REST | MCP tool |
|---|---|---|
ledger.accounts.list | GET /api/v1/ledger/accounts | ledger_accounts_list |
ledger.accounts.get | GET /api/v1/ledger/accounts/{id} | ledger_accounts_get |
ledger.transactions.list | GET /api/v1/ledger/transactions | ledger_transactions_list |
ledger.transactions.get | GET /api/v1/ledger/transactions/{id} | ledger_transactions_get |
ledger.trial_balance | GET /api/v1/ledger/trial_balance | ledger_trial_balance |
ledger.adjustments.create | POST /api/v1/ledger/adjustments | ledger_adjustments_create |
The ledger belongs to a legal entity: use an entity API key, or an organization key with the Ownrecord-Entity header (entity_id on MCP). Brand keys can't read it.
Why it matters
- Filings reconcile. Each tax report is checked against the tax payable balance for its period. If they differ, the report isn't generated, and you get the list of documents that differ. See Filings.
- Payouts reconcile. The processor clearing account shows what your processor holds for you, so you can match it to your bank statements.
- Audits are simple. Nothing is overwritten, every entry says who or what caused it, and every change can be traced back to its source.