What is Accounts Payable? A Beancount-Friendly Guide for Tracking Vendor Bills in Plain Text
Accounts payable (AP) is the money your business owes to its suppliers for goods or services you’ve already received but haven't paid for yet. In the world of accounting, AP is classified as a current liability on your balance sheet—an amount typically due within the next year, and often within 30 to 60 days.
This concept is central to accrual accounting, where you record the expense and the corresponding liability the moment a bill arrives, not when you actually send the cash. This guide will show you how to manage the entire AP workflow cleanly and efficiently using the plain-text accounting tool, Beancount.
Quick Summary
Before we dive into the details, let's cover the essentials:
- Accounts Payable (AP) represents your short-term debts to vendors. You'll find it under the
Liabilities
section of your balance sheet. - Accrual vs. Cash: AP is a concept that exists only if you keep your books on an accrual basis. Beancount fully supports accrual workflows, and its web interface, Fava, will display your liabilities correctly.
- AP vs. AR: It's simple: Payables are what you owe, while Receivables (AR) are what others owe you.
Where AP Lives in Beancount (and Fava)
To start tracking AP, you first need to declare an account for it in your ledger. A standard convention is:
Liabilities:AccountsPayable
You can optionally create subaccounts for major vendors (e.g., Liabilities:AccountsPayable:ForestPaintSupply
).
In Fava, this account will appear on your Balance Sheet under Liabilities
. You can click on it to drill down and see a list of all open and paid items, giving you a clear view of your obligations. You can even see this in action in Fava's public example ledger, which includes a Liabilities:AccountsPayable
account.
Beancount Building Blocks You’ll Use
A robust AP workflow in Beancount relies on a few core features:
- Accounts: You'll primarily use your
Liabilities:AccountsPayable
account, a cash account likeAssets:Bank:Checking
, and your various expense accounts (e.g.,Expenses:Supplies
). - Metadata: You can attach key-value data to any transaction. For AP, you'll use metadata like
invoice:
,due:
,terms:
, anddocument:
. Fava even recognizes thedocument:
key and will automatically create a clickable link to the attached file if you configure a documents folder. - Tags & Links: Use
#tags
(like#ap
) for easy filtering and^links
(like^INV-10455
) to programmatically tie a bill and its subsequent payment together. This creates a clear, auditable trail. - Queries (BQL): Beancount's SQL-like query language (BQL) allows you to run powerful reports, like listing all open payables sorted by due date, directly from the command line with
bean-query
or on Fava's "Query" page.
Core AP Workflow in Beancount
Managing AP in your ledger involves two or three key steps: recording the bill, paying it, and sometimes handling partial payments or discounts.
1) Record the Vendor Bill (This Creates the Liability)
First, you book the expense and create the payable when the invoice arrives.
; Optionally set your documents folder in your main Beancount file:
option "documents" "documents"
2025-08-05 * "Forest Paint Supply" "Paint order INV-10455" ^INV-10455 #ap
invoice: "INV-10455"
due: "2025-09-04"
terms: "2/10, n/30"
document: "invoices/2025-08-05-forest-paint-INV-10455.pdf"
Expenses:Supplies:Paint 500.00 USD
Liabilities:AccountsPayable -500.00 USD
This single entry accomplishes two critical things:
- It immediately recognizes the $500 expense in the correct period (August).
- It creates a corresponding $500 liability, showing that you owe money to Forest Paint Supply.
The ^INV-10455
link is a unique identifier that lets you attach the same link to the payment later, keeping the bill and payment transactions logically connected.
2) Pay the Bill (This Clears the Liability)
When you pay the invoice, you create a transaction that moves money from your bank account to clear the liability.
a) Standard Payment (No Discount):
2025-09-01 * "Forest Paint Supply" "Payment INV-10455" ^INV-10455
Liabilities:AccountsPayable 500.00 USD
Assets:Bank:Checking -500.00 USD
This entry reduces your AP balance by $500 and your checking account balance by the same amount. The liability is now cleared.
b) Early-Payment Discount (e.g., "2/10, n/30"):
If the terms are "2/10, n/30", you can take a 2% discount if you pay within 10 days. For our 10 discount. Here are two acceptable ways to record it—just pick one method and be consistent.
; Option 1: Record the discount as other income (a contra-expense effect)
2025-08-12 * "Forest Paint Supply" "Early payment discount INV-10455" ^INV-10455
Liabilities:AccountsPayable 500.00 USD
Assets:Bank:Checking -490.00 USD
Income:Discounts:Payables -10.00 USD
; Option 2: Reduce the original expense directly
2025-08-12 * "Forest Paint Supply" "Early payment discount INV-10455" ^INV-10455
Liabilities:AccountsPayable 500.00 USD
Assets:Bank:Checking -490.00 USD
Expenses:Supplies:Paint -10.00 USD
In both cases, you clear the full 490 you actually paid, and account for the $10 benefit.
3) Handling Partial Payments
Beancount's linking feature makes tracking partial payments simple and clean.
; Invoice for $1,200
2025-08-10 * "Acme Parts" "INV-9001" ^INV-9001
invoice: "INV-9001"
due: "2025-09-09"
Expenses:Parts 1200.00 USD
Liabilities:AccountsPayable -1200.00 USD
; First payment of $400
2025-08-20 * "Acme Parts" "Payment INV-9001 (1/3)" ^INV-9001
Liabilities:AccountsPayable 400.00 USD
Assets:Bank:Checking -400.00 USD
; Final payment of $800
2025-09-05 * "Acme Parts" "Payment INV-9001 (final)" ^INV-9001
Liabilities:AccountsPayable 800.00 USD
Assets:Bank:Checking -800.00 USD
By using the ^INV-9001
link on all three transactions, you can easily filter your journal to see the complete history of this specific bill and its associated payments.
Helpful Queries (BQL)
You can run these queries in Fava’s “Query” tab or from the command line with bean-query
.
Tip: The
any_meta()
function is incredibly useful for pulling metadata fields likeinvoice:
anddocument:
into your query results.
Open AP by Vendor (Balance View):
This query sums up the current outstanding balance you owe to each supplier.
SELECT payee, COST(SUM(position)) AS amount
WHERE account ~ "^Liabilities:AccountsPayable"
GROUP BY payee
ORDER BY payee;
Open AP by Invoice + Due Date:
Get a tidy list of every open bill, sorted by its due date, to help you prioritize payments.
SELECT payee,
any_meta('invoice') AS invoice,
any_meta('due') AS due,
COST(SUM(position)) AS amount
WHERE account ~ "^Liabilities:AccountsPayable"
GROUP BY payee, invoice, due
ORDER BY due, payee;
List Bills with Attached PDFs:
This query finds all your bills and shows the path to the linked document.
SELECT date, payee, any_meta('invoice') AS invoice, any_meta('document') AS file
WHERE account ~ "^Liabilities:AccountsPayable"
ORDER BY date DESC;
Where to See AP in Fava
- Balance Sheet: Navigate to
Balance Sheet
→Liabilities
→AccountsPayable
to see the total balance and drill down into the transaction details. - Journal: Filter the journal by
account:Liabilities:AccountsPayable
or a specific link like^INV-xxxx
to see a bill's complete lifecycle. - Documents Sidebar: If you use the
document:
metadata and set theoption "documents"
directive, you'll see a list of linked documents in the sidebar.
AP Aging, Turnover, and Cash-Flow Awareness
- Aging Schedule: This report groups your open invoices by how long they’ve been outstanding (e.g., 1–30 days, 31–60 days, 60+ days). In Beancount, the most practical approach is to run the "Open AP by Invoice + Due Date" query above, export the results as a CSV, and bucket them in a spreadsheet or a small Python script.
- AP Turnover Ratio: This is a quick health check on how fast you pay your vendors. The formula is
Total Supplier Purchases ÷ Average AP
. A related metric, Days Payable Outstanding (DPO), is roughly365 ÷ Turnover Ratio
. - If You Can’t Pay on Time: AP is meant for short-term debt. If a vendor agrees to formal, longer-term repayment, you should reclassify the debt out of AP and into a note payable.
2025-10-01 * "Helix Industries" "Convert overdue AP to 12-month note" ^INV-1110
Liabilities:AccountsPayable 2000.00 USD
Liabilities:NotesPayable -2000.00 USD
Best Practices for AP in a Plain-Text Ledger
- Go Paperless: Store invoice PDFs in your
documents
folder and link them with thedocument:
metadata key. - Use Links Consistently: Put the unique invoice number in a
^link
on both the bill and all associated payment entries. - Keep Metadata Tidy: Consistently using
invoice:
,due:
, andterms:
improves search, queries, and financial reviews. - Accrual All the Way: If you want useful AP reporting, commit to keeping your books on an accrual basis. Beancount and Fava handle this beautifully.
Copy-Paste Starter: Vendor Bill + Payment
; ---- Bill ----
2025-08-05 * "Forest Paint Supply" "Paint order INV-10455" ^INV-10455 #ap
invoice: "INV-10455"
due: "2025-09-04"
document: "invoices/2025-08-05-forest-paint-INV-10455.pdf"
Expenses:Supplies:Paint 500.00 USD
Liabilities:AccountsPayable -500.00 USD
; ---- Payment (no discount) ----
2025-09-01 * "Forest Paint Supply" "Payment INV-10455" ^INV-10455
Liabilities:AccountsPayable 500.00 USD
Assets:Bank:Checking -500.00 USD
This guide is for educational purposes and does not constitute tax, legal, or financial advice.