Accounting expenses
Create and inspect paid, reconciled expenses in your workspace accounting records. In live mode, every expense also creates its linked accounting outflow transaction; successful creations fire expense.created.
List expenses
Use exact reference lookups to reconcile external processors safely, or filter by vendor, category, and expense date. Pagination uses the standard limit and offset envelope.
/accounting/expensesaccounting.expenses.readList expenses. Filters: reference, vendor, category, created_at_gte, created_at_lte, limit, offset.
{
"object": "list",
"url": "/v1/accounting/expenses",
"data": [
{
"object": "expense",
"id": "019f...",
"vendor": "Dodo Payments",
"category": "operations",
"amount": "1091.76",
"currency": "NGN",
"exchange_rate": "1.00000000",
"amount_base": "1091.76",
"expense_date": "2026-07-28",
"status": "paid",
"reference": "dodo:pay_example:payment_fees",
"is_reconciled": true,
"chart_account_code": "6000",
"chart_account_name": "Operations Expense"
}
],
"total": 1,
"limit": 25,
"offset": 0,
"has_more": false
}Create an expense
vendor, a positive amount, and a stable reference are required. New live-mode expenses are marked paid and reconciled, assigned to an expense chart account, and mirrored into the accounting transaction ledger as an outflow.
/accounting/expensesaccounting.expenses.writeCreate a paid, reconciled expense. Send an Idempotency-Key header for transport-safe retries.
{
"vendor": "Dodo Payments",
"category": "operations",
"description": "Dodo processor fee for pay_example",
"amount": 1091.76,
"currency": "NGN",
"expense_date": "2026-07-28",
"payment_method": "dodo_balance",
"reference": "dodo:pay_example:payment_fees",
"tax_treatment": "standard_expense",
"tax_rate": 0,
"tax_amount": 0
}{
"object": "expense",
"id": "019f...",
"vendor": "Dodo Payments",
"category": "operations",
"amount": "1091.76",
"currency": "NGN",
"exchange_rate": "1.00000000",
"amount_base": "1091.76",
"expense_date": "2026-07-28",
"payment_method": "dodo_balance",
"status": "paid",
"reference": "dodo:pay_example:payment_fees",
"is_reconciled": true,
"chart_account_code": "6000",
"chart_account_name": "Operations Expense",
"created": true
}References and duplicate protection
Treat reference as the immutable external accounting identifier. Repeating a reference with the same vendor, category, currency, amount, and base amount returns the existing expense with created: false. Reusing it with different accounting values returns HTTP 409 with code reference_conflict. This reference check complements the Idempotency-Key header, so duplicate protection survives a lost client-side state file.
Currency and chart accounts
The workspace currency is the base currency. When the expense currency differs, include a positive exchange_rate; amount_base is calculated as amount × exchange_rate and rounded to two decimals. Pass chart_account_id to use an active expense account in the workspace, or omit it to use Operations Expense (code 6000). Optional tax fields are tax_treatment, tax_rate, and tax_amount.
Test and live parity
The core create/list contract and reference-based duplicate protection are available with mtb_test_ and mtb_live_ keys. Test keys write isolated sandbox expense objects and never modify live accounting tables. Move to production by swapping to a live key carrying accounting.expenses.read and/or accounting.expenses.write.