Finance
Space MCP tools in the Finance scope (finance). Reach these with a wks_live_ key over space-mcp or space-api.
Tools in the finance scope, callable over space-mcp (tools/call) or space-api (REST) with a wks_live_* key that grants finance.
add_bill
Scope: finance:write
Record a bill the space owes a supplier. Give the invoice (url, asset_id, data base64 + file_name + mime_type, or its text) and it is read — vendor, number, amount, issue and due dates, category — or give the fields yourself (anything you give wins over what is read). The books watch it: when the payment leaves the bank it is matched, the bill is marked paid and the payment takes the bill's category. Its owner is reminded before it is due.
| Parameter | Type | Required | Description |
|---|---|---|---|
url | string | ||
asset_id | string | ||
data | string | ||
file_name | string | ||
mime_type | string | ||
text | string | ||
vendor_name | string | ||
bill_number | string | ||
amount | number | ||
currency | string | ISO code, default USD | |
issue_date | string | yyyy-mm-dd | |
due_date | string | yyyy-mm-dd | |
category_id | string | an expense category from list_finance_categories | |
note | string |
add_receipt
Scope: finance:write
Keep a receipt or invoice in the space's books: pass a link (url), a file already in the space's Assets (asset_id), the file as base64 (data + file_name + mime_type), or the receipt's text. It is read (merchant, total, date, tax, category) and attached to its bank transaction when one clearly matches — otherwise it waits and is tried again whenever the books update. Photos, PDFs and receipt emails.
| Parameter | Type | Required | Description |
|---|---|---|---|
url | string | ||
asset_id | string | ||
data | string | base64 of the file | |
file_name | string | ||
mime_type | string | ||
text | string | The receipt's text, when there is no file (e.g. a receipt email you read). | |
title | string | ||
note | string |
attach_receipt
Scope: finance:write
Attach a receipt to a bank transaction (bank_transaction_id from get_receipt's candidates or list_finance_transactions), or pass an empty bank_transaction_id to detach it. When the transaction has no category or only an unsure guess, the receipt's category takes its place.
| Parameter | Type | Required | Description |
|---|---|---|---|
receipt_id | string | yes | |
bank_transaction_id | string | The transaction to attach it to; empty to detach. |
close_month
Scope: finance:write
Close a month in the books (default last month): nothing more can be posted into it, and a bank transaction that arrives later is posted on the first open day. Always asks the owner first. Run get_month_end before and tell the owner what is still to do.
| Parameter | Type | Required | Description |
|---|---|---|---|
month | string | yyyy-mm | |
note | string |
confirm_finance_transactions
Scope: finance:write
Say the books sorted these transactions right: they stop waiting to be checked. Pass bank_transaction_ids, or all: true for every one waiting. If a guess is wrong, don't confirm it — set the right category with set_finance_category (that also teaches the books for that merchant).
| Parameter | Type | Required | Description |
|---|---|---|---|
bank_transaction_ids | string[] | ||
all | boolean |
delete_bill
Scope: finance:write
Delete a bill and its file (prefer update_bill status void to keep a trace).
| Parameter | Type | Required | Description |
|---|---|---|---|
bill_id | string | yes |
delete_finance_category
Scope: finance:write
Delete a category. Pass move_to_category_id to move its transactions, splits, rules and bills there first (else they become uncategorized). The defaults can't be deleted — rename them instead.
| Parameter | Type | Required | Description |
|---|---|---|---|
category_id | string | yes | |
move_to_category_id | string |
delete_finance_rule
Scope: finance:write
Delete a categorization rule (what it already sorted keeps its category).
| Parameter | Type | Required | Description |
|---|---|---|---|
rule_id | string | yes |
delete_receipt
Scope: finance:write
Delete a receipt and its file (e.g. a duplicate, or something that was not a receipt).
| Parameter | Type | Required | Description |
|---|---|---|---|
receipt_id | string | yes |
delete_recurring_entry
Scope: finance:write
Delete a recurring journal entry (recurring_id). What it already posted stays; proposals still waiting stay in Pending.
| Parameter | Type | Required | Description |
|---|---|---|---|
recurring_id | string | yes |
export_books_for_accountant
Scope: finance:read
Make the accountant pack for a period: one zip with the trial balance, P&L, balance sheet, general ledger, bank transactions, receipts, bills and tax — answers a download link (7 days). To send it, email the link (e.g. send_agent_mail).
| Parameter | Type | Required | Description |
|---|---|---|---|
start_date | string | yes | yyyy-mm-dd |
end_date | string | yes | yyyy-mm-dd |
get_account_ledger
Scope: finance:read
One account's history (the general ledger an accountant asks for): its balance before the period, every line in the period with a running balance, and its balance after. account_id or code; default period = this year to today.
| Parameter | Type | Required | Description |
|---|---|---|---|
account_id | string | ||
code | string | ||
start_date | string | yyyy-mm-dd | |
end_date | string | yyyy-mm-dd |
get_bill
Scope: finance:read
One bill in full: vendor, number, amount, dates, category, whether and how it was paid, a link to the bill file (1 hour), and — while open — the bank payments that could be it.
| Parameter | Type | Required | Description |
|---|---|---|---|
bill_id | string | yes |
get_exchange_rate
Scope: finance:read
An exchange rate (European Central Bank reference rates; euro-pegged currencies such as XOF by their peg) between two currencies on a date (default today), and an amount converted when given.
| Parameter | Type | Required | Description |
|---|---|---|---|
from | string | yes | |
to | string | yes | |
date | string | ||
amount | number |
get_finance_cashflow
Scope: finance:read
Daily cashflow for the space: inflow, outflow and net per day.
| Parameter | Type | Required | Description |
|---|---|---|---|
start_date | string | ||
end_date | string |
get_finance_pnl
Scope: finance:read
Monthly profit and loss for the space, broken down by category: income, expense and net per month.
| Parameter | Type | Required | Description |
|---|---|---|---|
start_date | string | ||
end_date | string |
get_finance_recurring
Scope: finance:read
Recurring streams detected from the space's transaction history: subscriptions, regular income and standing payments, each with interval, average amount, next predicted date and a confidence score where 1 is perfectly regular.
| Parameter | Type | Required | Description |
|---|---|---|---|
min_occurrences | number | ||
lookback_days | number |
get_finance_settings
Scope: finance:read
The space's Finance settings: its home currency (the books' currency), whether it is registered for VAT / sales tax and what it calls it, its tax rates, and which categories carry a rate.
get_finance_top_merchants
Scope: finance:read
Merchants ranked by spend for the space over a period.
| Parameter | Type | Required | Description |
|---|---|---|---|
start_date | string | ||
end_date | string | ||
limit | number |
get_ledger_balance_sheet
Scope: finance:read
Balance sheet from the posted ledger as of a date: assets, liabilities and equity (net income folded in as Current Period Earnings). Returns balances — if false the books are broken and you must say so plainly rather than reporting the figures as fact. Amounts in CENTS.
| Parameter | Type | Required | Description |
|---|---|---|---|
as_of | string | yyyy-mm-dd; defaults to all activity to date |
get_ledger_profit_and_loss
Scope: finance:read
Profit & Loss from the POSTED LEDGER (double-entry journal lines), split into income, cost of goods sold and operating expenses, with gross profit and net income. Prefer this over get_finance_pnl for anything the user would call 'the books', 'my P&L', 'how did we do' or anything they might file from — get_finance_pnl only sums bank rows by category and is not accounting. All amounts are in CENTS.
| Parameter | Type | Required | Description |
|---|---|---|---|
start_date | string | yyyy-mm-dd | |
end_date | string | yyyy-mm-dd | |
class_id | string | One class (project, client, location…) from list_finance_classes, or "none" for lines with no class; omit for the whole space. |
get_ledger_trial_balance
Scope: finance:read
Trial balance: every account with its debit and credit totals, plus balances (do total debits equal total credits). This is the health check for the books — run it first if any statement looks wrong, and never present figures from books that do not balance. Amounts in CENTS.
| Parameter | Type | Required | Description |
|---|---|---|---|
as_of | string | yyyy-mm-dd |
get_money_owed
Scope: finance:read
Who owes what: invoices customers have not paid (by how late — not due, 1–30, 31–60, 61–90, 90+ days), invoices marked paid still waiting for their deposit, and the bills the space owes, with totals. Works on either basis; on accrual these are the receivable and payable on the balance sheet.
get_month_end
Scope: finance:read
The month-end checklist for one month (default: last month): what is uncategorized, waiting to be checked, still pending at the bank, proposed entries waiting for approval, receipts not attached, and for each bank account the books' balance at month end and its statement check. Ends with ready_to_close and still_to_do (sentences). Run this before closing a month or when asked 'are the books ready?'.
| Parameter | Type | Required | Description |
|---|---|---|---|
month | string | yyyy-mm (e.g. 2026-08); default last month |
get_receipt
Scope: finance:read
One receipt in full: what was read, a link to the file (valid 1 hour), and — when it is not attached yet — the bank transactions it could belong to, best first.
| Parameter | Type | Required | Description |
|---|---|---|---|
receipt_id | string | yes |
get_receipts_address
Scope: finance:read
The space's receipts email address: anything forwarded or sent to it is filed as a receipt (each photo/PDF attachment, or the email itself when it has none). Give it to people who want their receipts in the books.
get_tax_report
Scope: finance:read
The space's VAT / sales tax for a period (default last quarter): tax collected on sales, tax paid on purchases (reclaimable), net to pay, and what was already paid to the tax office — in the books' currency. Only a space registered for the tax splits it out.
| Parameter | Type | Required | Description |
|---|---|---|---|
period | this_month | last_month | this_quarter | last_quarter | this_year | last_year | default last_quarter | |
start_date | string | ||
end_date | string |
list_bank_accounts
Scope: finance:read
List bank accounts linked to the space (read-only).
list_bank_transactions
Scope: finance:read
List recent bank transactions for the space (read-only).
| Parameter | Type | Required | Description |
|---|---|---|---|
limit | number |
list_bills
Scope: finance:read
Bills the space owes suppliers (default: the open ones), soonest due first, with the totals owed, overdue and due this week. status: open | paid | void | overdue | all.
| Parameter | Type | Required | Description |
|---|---|---|---|
status | open | paid | void | overdue | all | ||
limit | number | ||
offset | number |
list_commerce_payouts
Scope: finance:read
Wakato Commerce payouts to the bank (one deposit carries many sales, minus Wakato's fee): amount, arrival day, and the bank deposit it was matched to (unmatched: only those still waiting). A matched deposit is booked as a transfer out of 'Wakato Commerce balance', never as income.
| Parameter | Type | Required | Description |
|---|---|---|---|
unmatched | boolean | ||
limit | number |
list_finance_categories
Scope: finance:read
List the space's finance categories (its chart of accounts), with kind (income/expense) and colour.
list_finance_classes
Scope: finance:read
The space's classes — what the books are tracked by: projects, clients, locations, departments, funds.
list_finance_rules
Scope: finance:read
The space's categorization rules, first match (lowest priority number) wins: match_type merchant_exact | merchant_contains | name_contains, the pattern, the category and class it sets.
list_finance_transactions
Scope: finance:read
List categorised bank transactions for the space, with the user's categories, notes and exclusions applied. Use this rather than list_bank_transactions when the question involves categories, spending by type, or anything the Finance tab shows.
| Parameter | Type | Required | Description |
|---|---|---|---|
start_date | string | ||
end_date | string | ||
category_id | string | ||
search | string | ||
to_check | boolean | Only the ones the books were unsure how to sort (needs_review) — posted with a best guess, waiting for a person. | |
uncategorized | boolean | Only transactions with no category. | |
include_excluded | boolean | ||
limit | number | ||
offset | number |
list_journal_entries
Scope: finance:read
Journal entries with their debit and credit lines. Reversed entries are hidden unless include_reversed is true; a reversed entry always has a matching mirror entry beside it and the two net to zero, so read them as a pair rather than as two separate events. Amounts in CENTS.
| Parameter | Type | Required | Description |
|---|---|---|---|
start_date | string | ||
end_date | string | ||
include_reversed | boolean | ||
limit | number |
list_ledger_accounts
Scope: finance:read
The space's chart of accounts: code, name, type (asset/liability/equity/income/expense), subtype and normal balance. Accounts with subtype 'suspense_expense' (9000) or 'suspense_income' (9010) hold money that posted but was never categorised — a balance there is a to-do list, not an error. Use these ids when proposing a journal entry.
| Parameter | Type | Required | Description |
|---|---|---|---|
type | asset | liability | equity | income | expense | ||
include_inactive | boolean |
list_pending_ledger_entries
Scope: finance:read
Entries you proposed and what happened to them: pending (awaiting the owner), approved (posted — posted_entry_id is the live entry), rejected (with the owner's note), or failed. Check here before re-proposing something, so you do not queue the same entry twice.
| Parameter | Type | Required | Description |
|---|---|---|---|
status | pending | approved | rejected | failed |
list_receipts
Scope: finance:read
List the space's receipts (photos, PDFs, receipt emails) with what was read from each — merchant, total, currency, date, tax, suggested category — and the bank transaction it is attached to. unmatched: only the ones not attached yet.
| Parameter | Type | Required | Description |
|---|---|---|---|
unmatched | boolean | ||
bank_transaction_id | string | ||
limit | number | ||
offset | number |
list_recurring_entries
Scope: finance:read
The space's recurring journal entries — entries that come back on a schedule with no bank line behind them (depreciation, a prepaid expense spread over months, loan interest, an accrual): name, amount, frequency, next date, how many are left, and whether each occurrence is proposed for approval or posted by itself.
match_commerce_payout
Scope: finance:write
Say which bank deposit brought a Wakato Commerce payout (bank_transaction_id from list_finance_transactions — money in), or null to unlink. The books match most by themselves; use this when two deposits looked the same.
| Parameter | Type | Required | Description |
|---|---|---|---|
payout_id | string | yes | |
bank_transaction_id | string,null |
match_invoice_deposit
Scope: finance:write
Say which bank deposit paid an invoice that was marked paid (bank_transaction_id — money in), or null to unlink. On accrual that deposit then settles what the customer owed instead of counting as new income.
| Parameter | Type | Required | Description |
|---|---|---|---|
invoice_id | string | yes | |
bank_transaction_id | string,null |
pay_bill
Scope: finance:write
Mark a bill paid: with bank_transaction_id (from get_bill's candidates) when you know its payment — the payment takes the bill's category — or without it when it was paid another way (cash, another account), with paid_at yyyy-mm-dd. undo: true opens it again. This does NOT move money — it records what happened.
| Parameter | Type | Required | Description |
|---|---|---|---|
bill_id | string | yes | |
bank_transaction_id | string | ||
paid_at | string | ||
undo | boolean |
post_ledger
Scope: finance:write
Post the space's categorised bank transactions into the ledger. Safe to run any time: unchanged transactions are skipped, and a transaction whose category changed is reversed and re-posted rather than edited. Run this before reporting on the books if transactions were recently categorised. Reports per-transaction failures — if ok is false, say so instead of reporting the run as clean.
| Parameter | Type | Required | Description |
|---|---|---|---|
since | string | yyyy-mm-dd; only consider transactions on or after this date | |
limit | number |
propose_journal_entry
Scope: finance:write
Propose a manual journal entry for the OWNER TO APPROVE. This does NOT post anything — it queues the entry for review in Space Finance → Books. Never tell the user the entry is in the books after calling this; say it is waiting for their approval. Lines must balance (total debits = total credits), need at least two lines, and each line is either a debit or a credit, never both. Amounts in CENTS (2500 = $25.00). Identify accounts by gl_account_id from list_ledger_accounts, or by account_code. Always give a rationale — an entry the owner cannot understand should be rejected.
| Parameter | Type | Required | Description |
|---|---|---|---|
entry_date | string | yes | yyyy-mm-dd |
memo | string | What this entry is for, in the owner's language | |
rationale | string | Why you believe this entry is correct — shown to the approver | |
lines | object[] | yes | At least two lines; total debit_cents must equal total credit_cents |
propose_void_entry
Scope: finance:write
Propose reversing a posted journal entry, for the OWNER TO APPROVE. The original stays live until they approve. Entries are never edited or deleted — a correction is always a reversal plus a new entry, which is what keeps the audit trail honest. Explain in reason what was wrong.
| Parameter | Type | Required | Description |
|---|---|---|---|
entry_id | string | yes | |
reason | string | ||
rationale | string |
record_statement_balance
Scope: finance:write
Check the books against a bank statement: give the bank account, the statement's end date and its ending balance exactly as printed (for a credit card, the amount owed). Answers the books' balance on that date and the difference. The FIRST statement of an account can set the books' starting balance from it (set_starting_balance: true) — the books began at the first imported transaction, so until then they cannot match; ask the owner before setting it on an account that already has one.
| Parameter | Type | Required | Description |
|---|---|---|---|
bank_account_id | string | yes | |
statement_date | string | yes | yyyy-mm-dd, the statement's end date |
balance | number | yes | |
set_starting_balance | boolean | ||
note | string |
refresh_bank
Scope: finance:write
Ask the bank for anything new now (the books then sort and post it within minutes, or call update_books). Answers what each connected account is doing.
reopen_month
Scope: finance:write
Reopen a closed month so it can be corrected. Needs a reason (kept with the books). Always asks the owner first.
| Parameter | Type | Required | Description |
|---|---|---|---|
month | string | yes | yyyy-mm |
reason | string | yes |
save_finance_category
Scope: finance:write
Create a category (name + kind income | expense | transfer — its ledger account is made with it) or change one (category_id: name, color). A default category keeps its kind.
| Parameter | Type | Required | Description |
|---|---|---|---|
category_id | string | ||
name | string | ||
kind | income | expense | transfer | ||
color | string |
save_finance_class
Scope: finance:write
Create a class (name + kind project | client | location | department | fund | other) or change one (class_id: name, kind, active false to retire).
| Parameter | Type | Required | Description |
|---|---|---|---|
class_id | string | ||
name | string | ||
kind | project | client | location | department | fund | other | ||
active | boolean |
save_finance_rule
Scope: finance:write
Create a rule (category_id + pattern, match_type default merchant_contains, optional class_id, priority) or change one (rule_id). apply_to_existing (default true) re-sorts the transactions it matches that have no category or only the AI's guess — never a person's own pick.
| Parameter | Type | Required | Description |
|---|---|---|---|
rule_id | string | ||
category_id | string | ||
class_id | string | ||
match_type | merchant_exact | merchant_contains | name_contains | ||
pattern | string | ||
priority | number | ||
enabled | boolean | ||
apply_to_existing | boolean |
save_ledger_account
Scope: finance:write
Add an account to the chart of accounts (code, name, type asset | liability | equity | income | expense — e.g. a loan, equipment, a deposit) or change one (account_id: name, code, description, active false to retire — only at a zero balance; built-in accounts keep their code).
| Parameter | Type | Required | Description |
|---|---|---|---|
account_id | string | ||
code | string | ||
name | string | ||
type | asset | liability | equity | income | expense | ||
description | string | ||
parent_id | string | ||
active | boolean |
save_recurring_entry
Scope: finance:write
Set up a recurring journal entry (or change one: recurring_id). Each occurrence is PROPOSED for the owner to approve in Books → Pending — an agent cannot make one post by itself. name, lines: [{ account_id | account_code, debit | credit (in money, e.g. 250.00) — or debit_cents | credit_cents, memo?, class_id? }] — balanced, at least two, frequency weekly|monthly|quarterly|yearly, start_date (yyyy-mm-dd, the first time), day_of_month (31 = last day), end_date or occurrences (e.g. 36 for three years of depreciation), active: false pauses it. Accounts from list_ledger_accounts.
| Parameter | Type | Required | Description |
|---|---|---|---|
recurring_id | string | ||
name | string | ||
lines | object[] | ||
frequency | weekly | monthly | quarterly | yearly | ||
start_date | string | ||
day_of_month | number | ||
end_date | string | ||
occurrences | number | ||
active | boolean |
save_tax_rate
Scope: finance:write
Create a tax rate (name + rate in percent, e.g. 'VAT 20%', 20) or change one (tax_rate_id). active: false retires it.
| Parameter | Type | Required | Description |
|---|---|---|---|
tax_rate_id | string | ||
name | string | yes | |
rate | number | yes | |
active | boolean |
set_category_tax
Scope: finance:write
Give a category a tax rate (its transactions are tax-inclusive: the books split the tax out — reclaimable on money out, owed on money in), or an empty tax_rate_id to clear it.
| Parameter | Type | Required | Description |
|---|---|---|---|
category_id | string | yes | |
tax_rate_id | string |
set_finance_category
Scope: finance:write
Categorise a bank transaction, or add a note, mark it reviewed, or exclude it from reports. Pass category_id null to clear the category.
| Parameter | Type | Required | Description |
|---|---|---|---|
bank_transaction_id | string | yes | |
category_id | string | ||
note | string | ||
is_reviewed | boolean | ||
is_excluded | boolean |
set_finance_settings
Scope: finance:write
Change the space's Finance settings: base_currency (a three-letter code — only before anything is posted), vat_registered (true splits tax out of taxed categories from now on), tax_label (VAT, GST, Sales tax…), basis (cash = income and expenses when money moves; accrual = when invoiced or billed, with what customers owe and what the space owes on the balance sheet — the open months are re-posted, closed months stay). Ask the owner before registering for tax, changing the currency or the basis.
| Parameter | Type | Required | Description |
|---|---|---|---|
base_currency | string | ||
vat_registered | boolean | ||
tax_label | string | ||
basis | cash | accrual |
set_transaction_class
Scope: finance:write
Put a bank transaction in a class (project, client, location…) — its lines in the books carry it; an empty class_id takes it out. For part of a transaction, split it instead.
| Parameter | Type | Required | Description |
|---|---|---|---|
bank_transaction_id | string | yes | |
class_id | string |
set_transaction_splits
Scope: finance:write
Split one bank transaction across categories (and classes): splits = [{ category_id, amount, class_id?, note? }] that add up to the transaction exactly (amounts positive, in its own currency). At least two parts; an empty list removes the split. Use a receipt's line items when it has them.
| Parameter | Type | Required | Description |
|---|---|---|---|
bank_transaction_id | string | yes | |
splits | object[] | yes |
update_bill
Scope: finance:write
Correct a bill (any field), or void it (status: void — it was a duplicate or was cancelled), or open it again (status: open).
| Parameter | Type | Required | Description |
|---|---|---|---|
bill_id | string | yes | |
status | void | open | ||
vendor_name | string | ||
bill_number | string | ||
amount | number | ||
currency | string | ISO code, default USD | |
issue_date | string | yyyy-mm-dd | |
due_date | string | yyyy-mm-dd | |
category_id | string | an expense category from list_finance_categories | |
note | string |
update_books
Scope: finance:write
Bring the space's books up to date now: sort uncategorized bank transactions (the space's rules, what it learned from past picks, then AI — unsure guesses are flagged to_check), post every settled transaction, and reverse entries whose bank transaction was cancelled. The books already do this on their own every few minutes; call it before reporting on the books if something just changed. Reports problems — if ok is false, say so.
| Parameter | Type | Required | Description |
|---|---|---|---|
categorize | boolean | Sort uncategorized transactions first (default true). | |
use_ai | boolean | Ask AI about merchants no rule or past pick covers (default true; a small charge to the space). |
update_receipt
Scope: finance:write
Correct what was read from a receipt (merchant, total, currency, receipt_date, tax, category_id, note) — it is matched again — or reread: true to read the file again.
| Parameter | Type | Required | Description |
|---|---|---|---|
receipt_id | string | yes | |
merchant | string | ||
total | number | ||
currency | string | ||
receipt_date | string | ||
tax | number | ||
category_id | string | ||
note | string | ||
reread | boolean |