Skip to content

Transaction Directive ​

Overview ​

The transaction directive records a financial exchange between two or more accounts. It is the fundamental directive for recording economic activity.

Syntax ​

ebnf
transaction = date WHITESPACE txn_flag
              [WHITESPACE txn_strings]
              [WHITESPACE tags_links]*
              (NEWLINE posting)+
              (NEWLINE metadata)*

txn_flag    = "*" | "!" | "txn" | "P" | "#"
txn_strings = string [WHITESPACE string]
posting     = WHITESPACE [posting_flag] account
              [WHITESPACE amount [cost_spec] [price_annotation]]

Components ​

Date ​

The transaction date in ISO 8601 format (YYYY-MM-DD).

Flag ​

Indicates transaction status:

FlagMeaningDescription
*CompleteTransaction verified as correct
!IncompleteNeeds review or correction
txnCompleteKeyword equivalent to *
PPaddingAuto-generated by pad directive
#LinkedUsed by some plugins

Payee and Narration ​

Transactions accept zero, one, or two strings:

beancount
; No strings
2024-01-15 *
  Assets:Cash  -20 USD
  Expenses:Food

; One string (narration only)
2024-01-15 * "Grocery shopping"
  Assets:Cash  -20 USD
  Expenses:Food

; Two strings (payee and narration)
2024-01-15 * "Whole Foods" "Weekly groceries"
  Assets:Cash  -85.50 USD
  Expenses:Groceries

When two strings are provided:

  • First string = payee (who the transaction is with)
  • Second string = narration (description of transaction)

Tags (#tag) and links (^link) appear after the strings:

beancount
2024-01-15 * "Flight to Berlin" #travel #berlin-trip ^invoice-2024-001
  Expenses:Travel:Flights  -450.00 USD
  Liabilities:CreditCard

Postings ​

Each posting transfers an amount to or from an account.

Posting Structure ​

beancount
  [flag] account  [amount] [cost] [price]

Posting Flag ​

Optional flag on individual postings:

beancount
2024-01-15 * "Mixed transaction"
  Assets:Checking   -100 USD    ; no flag
  ! Expenses:Food     50 USD    ; flagged as incomplete
  * Expenses:Coffee   50 USD    ; flagged as complete

Amount ​

A number followed by a currency:

beancount
  Assets:Cash  100.00 USD
  Assets:Cash  -50 EUR
  Assets:Cash  1,234.56 CAD

Amounts support arithmetic expressions:

beancount
  Expenses:Food  (100 / 3) USD
  Expenses:Food  (50 * 1.08) USD  ; with tax

Elided Amounts ​

UNDEFINED: See posting.md for the pending elision rule clarification.

beancount
2024-01-15 * "Deposit"
  Assets:Checking   1000 USD
  Income:Salary                  ; amount computed as -1000 USD

Multiple elided postings for the same currency is always an error:

beancount
; ERROR: Multiple missing amounts for USD
2024-01-15 * "Ambiguous"
  Assets:Checking   100 USD
  Expenses:Food
  Expenses:Coffee

Balancing ​

Transactions MUST balance: the sum of all posting weights MUST equal zero for each currency.

Weight Calculation ​

Posting TypeWeight
Simple amountThe amount
With cost {...}Units × cost per unit
With total cost \{\{...\}\}The total cost
With price @Units × price per unit
With total price @@The total price

Example ​

beancount
2024-01-15 * "Buy stock"
  Assets:Brokerage   10 AAPL {150 USD}  ; weight: 1500 USD
  Assets:Cash       -1500 USD           ; weight: -1500 USD
  ; Sum: 0 USD ✓

Cost Specification ​

Costs track the acquisition price of commodities:

beancount
; Per-unit cost
Assets:Stock  10 AAPL {150.00 USD}

; Total cost
Assets:Stock  10 AAPL \{\{1500.00 USD\}\}

; Cost with date
Assets:Stock  10 AAPL {150.00 USD, 2024-01-15}

; Cost with label
Assets:Stock  10 AAPL {150.00 USD, "lot1"}

; Full specification
Assets:Stock  10 AAPL {150.00 USD, 2024-01-15, "lot1"}

; Merge cost (average all lots)
Assets:Stock  0 AAPL {*}

See costs.md for detailed cost specification documentation.

Price Annotation ​

Prices record exchange rates without affecting balancing:

beancount
; Per-unit price
Assets:EUR  100 EUR @ 1.10 USD

; Total price
Assets:EUR  100 EUR @@ 110 USD

The price annotation does NOT affect the transaction's balance calculation when a cost is also specified.

Metadata ​

Metadata can be attached to transactions and postings:

beancount
2024-01-15 * "Purchase"
  receipt: "scan.pdf"
  category: "groceries"
  Assets:Cash  -50 USD
    vendor-id: "12345"
  Expenses:Food

Transaction-level metadata is indented once; posting-level metadata is indented twice.

Examples ​

Simple Transfer ​

beancount
2024-01-15 * "ATM Withdrawal"
  Assets:Cash        200 USD
  Assets:Checking   -200 USD

Multi-Currency ​

beancount
2024-01-15 * "Currency exchange"
  Assets:EUR   100 EUR @ 1.10 USD
  Assets:USD  -110 USD

Stock Purchase ​

beancount
2024-01-15 * "Buy Apple stock"
  Assets:Brokerage    10 AAPL {185.50 USD}
  Expenses:Commission  9.99 USD
  Assets:Cash

Split Expense ​

beancount
2024-01-15 * "Dinner with friends" #dinner
  Expenses:Food:Restaurant   (75.00 / 3) USD
  Assets:Receivable:Alice    (75.00 / 3) USD
  Assets:Receivable:Bob      (75.00 / 3) USD
  Assets:Cash               -75.00 USD

Validation ​

The following conditions produce validation errors:

ConditionError Type
Transaction does not balanceValidationError
Multiple postings missing amounts for same currencyValidationError
Posting references account not openedValidationError
Posting references account after closeValidationError

Note: See validation/balance.md for rules on empty and single-posting transactions.

Implementation Notes ​

  1. Parse all postings before computing elided amounts
  2. Validate balance after all amounts are known
  3. Store original precision for display
  4. Apply tolerance rules for balance checking