Skip to main content
Every movement of value in the ledger is a transaction made of balanced postings. A posting names an account, an amount in minor units, a direction (debit or credit), and a currency, and a transaction is valid only when its debits equal its credits in every currency it touches. The account ids below (cash, revenue, assets:bank, fees) are illustrative names you choose; the platform attaches no meaning to them.
Amounts below are written as bare numbers for readability. On the wire every monetary value is a JSON string of integer minor units. Parse them with a big-integer type.

A simple credit into one account

The smallest transaction moves value between exactly two accounts. To record 10.00 USD of revenue, you debit cash and credit revenue. The amounts are equal, so the transaction balances. Debits total 1000, credits total 1000. The write is accepted.

A transfer between two accounts

A transfer is the same shape: value leaves one account and lands in another. To move 25.00 USD from cash into assets:bank, credit the source and debit the destination. The two accounts net out against each other and the transaction balances.

A reversal

You never edit a transaction to undo it. You append a reversal, which is a new transaction that posts the inverse of every leg and references the original. Reverse the simple credit above with POST /v1/transactions/{id}/reverse. The reversal’s postings, the inverse of the original: After both transactions, the net effect on cash and revenue is zero. Both remain in history: the reversal links back via reverses, the original gains a reversed_by pointer, and the original’s status moves to archived. Archived means undone, not hidden, so filter on it deliberately when you list transactions.

A partial refund

A refund offsets part of a transaction. POST /v1/transactions/{id}/refund books an inverse for the requested amount, scaling each leg proportionally so the result still balances per currency. Refund 4.00 USD of a 10.00 USD transaction that had a 1.00 USD fee. The refund scales every leg by 400 / 1000, rounds half to even, and puts any leftover minor unit on the largest leg, so the result still balances: Debits total 440, credits total 440. The fee leg is reversed in proportion, so a partial refund never leaves the fee account stranded.

A multi-currency transaction

A single transaction may touch more than one currency. The balance rule applies independently per currency: debits must equal credits within USD and, separately, within EUR. Record an FX leg that takes in 1000 minor units of EUR and pays out 1080 minor units of USD. EUR debits equal EUR credits, and USD debits equal USD credits, so the transaction balances. When a transaction spans currencies, the ledger records an FX snapshot on the transaction (exchange_rate, base_currency, quote_currency) at write time. Downstream reports read that recorded rate for audit and replay rather than recomputing from current market data.

Next steps

Core concepts

The rules behind these shapes, in prose.

Invariants

The guarantees that keep every transaction balanced.

Quickstart

Post your first transaction in four calls.

API reference

Every endpoint, generated from the spec.