Skip to content

Search documentation

Search documentation pages, sections, and topics.

On this page

How to post first transaction

A transaction is derived from an event, not chosen from vocabulary. A payment is not "a debit" and a refund is not "a credit": each event changes several accounts, and what each entry does is decided by the account it lands in. Start from what happened, and the entries write themselves.

This page is the short version - the full teaching, with the misconception drills and the derivations, is the guide post your first double-entry ledger transaction. It assumes your accounts already exist. If they do not, how to design your ledger comes first.

Derive the entries from the event

Every posting follows the same pipeline, and debit or credit is the second-to-last step:

text
Real-world event
      ↓
Which economic quantities changed?
      ↓
Which accounts measure them?
      ↓
Did each balance increase or decrease?
      ↓
Debit or credit follows from the account type
      ↓
Total debits must equal total credits

The only table you need on the way: assets and expenses increase on a debit, liabilities, equity and income increase on a credit. Why that is - and not something to memorize - is model normal debit and credit accounts.

Run it on one real event

A guest pays Firecnc $230. The host is owed $200, your service fee is $30. The facts: your Stripe balance goes up $230, your debt to the host goes up $200, your earned income goes up $30. Translate:

yaml
transaction
  description: "Booking 4417 paid"
  entries:
    - account: assets:stripe            debit   USD:230.00
    - account: liabilities:hosts/42     credit  USD:200.00
    - account: income:service-fees      credit  USD:30.00

Debits $230, credits $200 + $30 = $230. Balanced. Note the $200 is a liability, not income - it was never yours, only held by you. Stripe's fee is its own event, a genuine cost:

yaml
transaction
  description: "Stripe processing fee, booking 4417"
  entries:
    - account: expenses:processing-fees  debit   USD:7.00
    - account: assets:stripe             credit  USD:7.00

Paying the host later settles the debt. Nothing is earned or consumed - money just moves:

yaml
transaction
  description: "Payout to host 42"
  entries:
    - account: liabilities:hosts/42     debit   USD:200.00
    - account: assets:stripe            credit  USD:200.00

After all three: Stripe holds $23, the host is owed $0, income shows $30, expenses $7. Profit $23, cash left $23 - the same number, because they were never computed separately.

The check that runs at posting

Ledfra rejects any transaction whose debit and credit totals differ, per currency, at write time. A half-recorded event fails loudly at the API boundary instead of becoming a three-cent discrepancy somebody hunts down in a quarter-end report. The shape of the request is in Transactions, and writes are idempotent, so a retry returns the original transaction instead of double-posting.

Balanced is not the same as correct
Credit the host's $200 to income instead of a liability and the write still succeeds - arithmetic cannot see a filing mistake. The rules that catch that class of error are in how to design your ledger.

Common shapes that trip people up

Every one of these follows the same pipeline. None of them fits "debit means money in", which is why that mnemonic fails:

EventDebitCreditNote
Customer pays an existing invoiceassets:cashassets:receivableNo income - it was earned when invoiced
Customer prepays for future workassets:cashliabilities:deferred-incomeCash without income - you owe the work
The prepaid work is deliveredliabilities:deferred-incomeincome:servicesIncome without cash moving
Loan repaymentliabilities:bank-loanassets:cashBoth sides shrink - nothing is consumed
Vendor refunds an expenseassets:cashexpenses:hostingAn expense account taking a credit

Corrections work the same way: a reversal is a new balanced transaction, never an edit. History is append-only, so the books can always answer what happened and when.

Where to go next

  1. Quickstart - post this transaction against a real ledger, through the app and the API.
  2. How to build a marketplace ledger - the full Firecnc build, from structure to statements.
  3. Guide: Post your first double-entry ledger transaction - the long version, with the derivations and the drills.
  4. What is Ledfra? - where posting fits in the whole model.