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