stdin: {"id":1,"jsonrpc":"2.0","method":"initialize","params":{"capabilities":{},"clientInfo":{"name":"toolwitness","version":"s772-v0"},"protocolVersion":"2025-11-25"}} {"jsonrpc":"2.0","method":"notifications/initialized"} {"id":2,"jsonrpc":"2.0","method":"tools/list","params":{}} stdout: {"result":{"protocolVersion":"2025-11-25","capabilities":{"tools":{"listChanged":true},"resources":{"listChanged":true},"prompts":{"listChanged":true}},"serverInfo":{"name":"@ekwo-ai/mcp","version":"0.13.0"},"instructions":"Ekwo OS keeps double-entry books in the user's own Postgres. You act as that user: everything you can see and change is what row level security lets them see and change. Amounts are decimal strings (\"1210.00\"), dates are ISO (2026-06-15), identifiers are uuids.\n\nA first session, in order. (1) list_companies: every other tool takes a company_id from it; an empty list means this user has not been invited to a company yet, and status says who you are acting as. (2) get_company: the financial years and whether each is closed, the lock dates, the journals and the role accounts — a date you book on falls in an open year, after the lock date. (3) list_accounts and the resource ekwo://companies/{companyId}/taxes: a document line names its account and its tax by code, never by rate, because several taxes share a rate; describe_pack says which country pack those codes come from and how far it has been reviewed. (4) search_contacts, then create_contact only if nobody matches, then create_document: a draft with the totals the database computed. Show it to the user. (5) post_document once the user has said yes to that document; record_payment when the money moves.\n\nReading a tax return: vat_return gives the boxes of a period with their names and amounts, summed from what was posted, and the boxes computed from other boxes; a draft is in no box. Name a report_code only where the country files several declarations. It prepares figures and files nothing — the prompt prepare_vat_return walks through checking them against the ledger. The reports beside it are trial_balance, general_ledger, aged_balance, financial_statement (list_statements first) and financial_analysis, the figures a ratio is computed from.\n\nCorrecting: a posted entry is never deleted or edited. A posted invoice is undone by cancel_document — back to draft where its country allows it and nothing has left, by the credit note that names it otherwise, and it says which — and an entry keyed by hand by reverse_entry. A paid document is unmatched first with unreconcile, and only when the user says so. Ask the user before every post, cancel, reversal, payment or lock.\n\nWhen the database refuses, the message starts with a name — period_locked, entry_unbalanced, document_total_mismatch, reversal_date_needed — followed by a sentence saying what to do next. Report it to the user and follow that sentence rather than working around it."},"jsonrpc":"2.0","id":1} {"result":{"tools":[{"name":"list_companies","title":"List companies","description":"The companies of this installation that you are a member of, with your role on each. Start here: every other tool needs a company_id. Returns id, name, country, currency and your role. It does not list companies you were never invited to — those are invisible, not hidden. Next: get_company on the one the user means.","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{}},"annotations":{"readOnlyHint":true,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"get_company","title":"Company settings","description":"Everything needed before booking in a company: its financial years and whether they are closed, its lock dates, its journals, and the accounts that play the receivable, payable, suspense and retained-earnings roles. Read this before creating a document if you do not already know the journals and the lock dates. Next: list_accounts and the ekwo://companies/{companyId}/taxes resource give the codes a document line names.","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"company_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The company to work in. Ask list_companies if unsure."}},"required":["company_id"]},"annotations":{"readOnlyHint":true,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"list_accounts","title":"Chart of accounts","description":"The accounts a company actually works with, filtered by code prefix, by account type, or by a search on the name. Use it to find the income or expense account a document line should carry. By default it returns the working chart — the accounts that carry entries, that the company's settings or an enabled module point at, or that somebody pinned — because a country pack transcribes the whole regulation and a company uses a few dozen of its several hundred accounts; `in_use_from` and `in_use_to` narrow the movements to a period, `include_all` returns the whole chart, and `include_deprecated` returns it with the retired accounts too. This is a reading and not a restriction: any account of the chart that is not deprecated may still be booked on.","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"company_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The company to work in. Ask list_companies if unsure."},"code_prefix":{"description":"Only accounts whose code starts with this, e.g. \"70\".","type":"string","minLength":1},"account_type":{"description":"One of the eighteen account types, e.g. asset_receivable.","type":"string","minLength":1},"search":{"description":"Case-insensitive match on the account name.","type":"string","minLength":1},"in_use_from":{"description":"Narrows the movements to entries on or after this date. References and pinned accounts are not dated and stay in.","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"in_use_to":{"description":"The other end of that period.","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"include_all":{"description":"Return the whole chart instead of the accounts in use. Use it when a search over the working chart found nothing.","type":"boolean"},"include_deprecated":{"description":"Include deprecated accounts. A deprecated account is never in use, so this returns the whole chart.","type":"boolean"},"limit":{"type":"integer","minimum":1,"maximum":2000}},"required":["company_id"]},"annotations":{"readOnlyHint":true,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"search_contacts","title":"Find a contact","description":"Customers, suppliers and other third parties of a company, by name, by type or by VAT number. Use it before creating a document: a document is booked against a contact, and creating a second contact for a customer who already exists splits their account. Nobody matches: create_contact. Found: create_document with its id.","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"company_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The company to work in. Ask list_companies if unsure."},"query":{"description":"Case-insensitive match on the contact name.","type":"string","minLength":1},"contact_type":{"type":"string","enum":["customer","supplier","both","employee","other"]},"vat_number":{"description":"Exact match, e.g. BE0123456749.","type":"string","minLength":1},"limit":{"type":"integer","minimum":1,"maximum":200}},"required":["company_id"]},"annotations":{"readOnlyHint":true,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"list_documents","title":"List documents","description":"Invoices, credit notes and quotes of a company, filtered by type, state, settlement state, contact or date range. `state` is the document (draft, posted, cancelled) and `payment_state` is the settlement (not_paid, partially_paid, paid) — two different questions. Returns headers and totals, not lines; use get_document for those.","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"company_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The company to work in. Ask list_companies if unsure."},"doc_type":{"type":"string","enum":["sale_invoice","sale_credit_note","sale_quote","purchase_invoice","purchase_credit_note","purchase_order"]},"state":{"type":"string","enum":["draft","posted","cancelled"]},"payment_state":{"type":"string","enum":["not_paid","partially_paid","paid","overpaid","reversed"]},"contact_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"from":{"description":"Earliest document date.","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"to":{"description":"Latest document date.","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"unpaid":{"description":"True: posted and still owed — not paid, or partially.","type":"boolean"},"limit":{"type":"integer","minimum":1,"maximum":200}},"required":["company_id"]},"annotations":{"readOnlyHint":true,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"get_document","title":"Read a document","description":"One document with its lines, the account and tax of each line, the legal mentions its country requires on it, that country's payment and e-invoicing rules, and — when it has been posted — the ledger entry it produced with every ledger line. Use it to check what a document will book, what it did book, and what has to be printed on it.","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"document_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["document_id"]},"annotations":{"readOnlyHint":true,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"render_invoice_pdf","title":"The PDF of an invoice","description":"The PDF of a sale invoice or a sale credit note, rendered from the books: the seller with its logo, the buyer, the lines, the tax summary, the totals and what is still due, how to pay, and the legal mentions the country requires — as the views publish them, in the accent colour and on the logo side the company set with update_company_profile. Comes back as a PDF resource (base64) beside a JSON summary: filename, pages, whether the logo was used. factur_x: true embeds the CII XML of a posted document and returns the rules of EN 16931 it breaks. Words of the layout are English unless labels gives them in the document's language. Records nothing, sends nothing: the copy a customer received is not kept here.","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"document_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"A sale invoice or a sale credit note. A draft is rendered titled as a draft, without a number."},"factur_x":{"description":"Embed the CII XML of the document, EN 16931 profile: the PDF becomes a Factur-X PDF/A-3. Only for a posted document; the rules the XML breaks come back in factur_x.violations.","type":"boolean"},"page_size":{"description":"A4 unless Letter is asked for.","type":"string","enum":["A4","Letter"]},"labels":{"description":"The words the layout prints, in the language of the document — invoice, creditNote, dueDate, amountDue, page (\"Page {page} of {pages}\"), units (a map of UN/ECE unit codes)… Every word left out is printed in English.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{"anyOf":[{"type":"string"},{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}}]}}},"required":["document_id"]},"annotations":{"readOnlyHint":true,"openWorldHint":true},"execution":{"taskSupport":"forbidden"}},{"name":"get_preferences","title":"What this user prefers","description":"The signed-in user’s own preferences — which company an interface opens on, the language they read labels in, their timezone and how they like a date and a number written — and the language chain to read labels with: theirs, then the company’s, then the country pack’s. Every one of them may be null, and null means \"take the next answer in the chain\" rather than a default this installation picked.","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"company_id":{"description":"Resolve the language chain against this company. Left out, only what the user themselves chose is returned.","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}}},"annotations":{"readOnlyHint":true,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"list_api_keys","title":"Machine keys of a company","description":"The keys a company has issued to machines, what each one may do, when it was last used and whether it is still live. Only somebody who manages members sees them, and no secret is in here: a key is shown once, when it is issued.","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"company_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The company to work in. Ask list_companies if unsure."},"include_withdrawn":{"description":"Also the ones withdrawn or expired. Default false.","type":"boolean"}},"required":["company_id"]},"annotations":{"readOnlyHint":true,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"list_invitations","title":"Invitations into a company","description":"The people invited into a company and not yet on its books, with the preset and the capabilities each was invited with, and whether the invitation is still pending, expired, accepted or withdrawn. Only somebody who manages members sees them. The token is never in here: it is shown once, when the invitation is issued.","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"company_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The company to work in. Ask list_companies if unsure."},"include_settled":{"description":"Also the ones already accepted or withdrawn. Default false.","type":"boolean"}},"required":["company_id"]},"annotations":{"readOnlyHint":true,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"list_shares","title":"Public links onto documents","description":"The links a company has published onto its own sales documents, with how many times each was opened and when it was last opened. No token is in here: a link is shown once, when it is made. Use it to answer \"did the customer open the invoice?\" and to find the link to withdraw.","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"company_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The company to work in. Ask list_companies if unsure."},"document_id":{"description":"Only the links onto this document. Left out, the whole company.","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"include_withdrawn":{"description":"Also the ones withdrawn or expired. Default false.","type":"boolean"}},"required":["company_id"]},"annotations":{"readOnlyHint":true,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"list_bank_transactions","title":"Bank transactions","description":"Statement lines of a company, pending by default — the ones still waiting to be dealt with. `amount` is signed: positive is money in. A statement line is not a ledger entry; recording a payment is what books it.","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"company_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The company to work in. Ask list_companies if unsure."},"bank_account_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"state":{"description":"Defaults to pending: what still has to be dealt with.","type":"string","enum":["pending","reconciled","ignored","all"]},"from":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"to":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"limit":{"type":"integer","minimum":1,"maximum":200}},"required":["company_id"]},"annotations":{"readOnlyHint":true,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"trial_balance","title":"Trial balance","description":"Opening balance, movements of the period and closing balance for every account, from posted entries only. The debit and credit totals are equal on a healthy ledger; if they are not, say so rather than explaining it away.","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"company_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The company to work in. Ask list_companies if unsure."},"from":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"to":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},"required":["company_id","from","to"]},"annotations":{"readOnlyHint":true,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"general_ledger","title":"General ledger","description":"Every posted line of an account over a period, with the balance carried forward from before it and a running balance. Give account_code for one account; leave it out for all of them, which on a real company is a lot of lines.","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"company_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The company to work in. Ask list_companies if unsure."},"from":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"to":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"account_code":{"description":"The account to detail, by its code, e.g. \"400000\".","type":"string","minLength":1},"account_ids":{"description":"The accounts to detail, by id. Leave both out for every account.","type":"array","items":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}}},"required":["company_id","from","to"]},"annotations":{"readOnlyHint":true,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"aged_balance","title":"Aged balance","description":"What customers still owe (or what is still owed to suppliers), bucketed by how overdue it is. It reads unmatched ledger lines, not invoices, so it ties back to the balance sheet: an invoice counts as settled only once its payment has been matched.","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"company_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The company to work in. Ask list_companies if unsure."},"at":{"description":"The day to age at. Defaults to today.","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"group":{"type":"string","enum":["receivable","payable"]}},"required":["company_id"]},"annotations":{"readOnlyHint":true,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"vat_return","title":"VAT return","description":"The boxes of the VAT return for a period, with their names: the base and tax boxes are summed from what the postings wrote on the ledger lines, the totals are derived from them by the declaration form of the country pack. No country rule lives in this tool, nor in the function behind it. Name a report_code only where a country files several declarations. It prepares figures; it files nothing.","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"company_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The company to work in. Ask list_companies if unsure."},"from":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"to":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"report_code":{"description":"Which declaration form, when the country files more than one (BE-VAT-PERIODIC, FR-CA3). Leave it out and the periodic return of the company country is used.","type":"string"}},"required":["company_id","from","to"]},"annotations":{"readOnlyHint":true,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"ec_sales_list","title":"Recapitulative statement of European Union supplies","description":"Who, in another Member State, was supplied without VAT over a period, and for how much: one line per customer VAT number and per nature — goods, services — read from the treatment of the tax on each sale line, with credit notes deducted. The totals tie back to the European Union boxes of vat_return for the same period. A line that carries an issue cannot be filed as it stands, most often because the customer has no VAT number recorded: say so rather than leaving it out of the answer. Name a report_code to have the period checked against the cadence this company files that statement on — it has one of its own, and it is rarely the cadence of the return. No country rule lives in this tool. It prepares a statement; it files nothing.","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"company_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The company to work in. Ask list_companies if unsure."},"from":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"to":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"report_code":{"description":"Which recapitulative statement form, when the installation carries one and you are filing it. Name it and the period is checked against the cadence this company files that statement on, which is not the cadence of its periodic return in most countries. Leave it out to read the figures without any period being refused.","type":"string"}},"required":["company_id","from","to"]},"annotations":{"readOnlyHint":true,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"portfolio_upcoming_filings","title":"Returns falling due, across your companies","description":"What falls due between two dates in every company you may read the declarations of — the question a firm asks of all the books it keeps, and the one a person asks of the single company they run. \"Portfolio\" is meant as an accounting firm means it — its client portfolio — and is nothing but that: the companies you hold filings.read on, worked out at each call, never a list anybody maintains. Every one of them is in the answer, including a company whose country pack names no deadline, which is listed without a date and says so; a company left out would be indistinguishable from one that was never looked at. No country rule lives in this tool. It reads a calendar; it prepares and files nothing.","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"from":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"First day a return may fall due on. Go back a few days to catch what is already late."},"to":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Last day a return may fall due on."}},"required":["from","to"]},"annotations":{"readOnlyHint":true,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"portfolio_filings_touched_since","title":"Declared periods that moved, across your companies","description":"Which declarations, across your portfolio — every company you may read the declarations of, which for an accounting firm is its clients — had entries posted into their period after they were filed — with the company named, how many entries, and how many of the filed figures now disagree. A period stays open after its return has gone, on purpose; this is what keeps a late entry from going unnoticed. Companies with nothing to report are named too, with how many filed declarations were examined. It reads; whether a corrective is owed is for whoever keeps the books.","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"from":{"description":"Only declarations whose period ends on or after this day.","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"to":{"description":"Only declarations whose period starts on or before this day.","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}}},"annotations":{"readOnlyHint":true,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"list_statements","title":"List financial statements","description":"The schemes this company can be presented on: those of its country and of its chart of accounts, plus the generic framework by account type that fits any chart. Ask this before financial_statement rather than guessing a code.","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"company_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The company to work in. Ask list_companies if unsure."},"at":{"description":"The day to read the schemes in force at. Defaults to today.","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},"required":["company_id"]},"annotations":{"readOnlyHint":true,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"financial_statement","title":"Financial statement","description":"A balance sheet or an income statement for a period, on the scheme the country pack declares — the Belgian abbreviated model, the French liasse — or on the generic framework by account type. Each line is summed from the accounts its rules catch and the totals are derived from the lines; no country rule lives in this tool. It also returns the accounts no line catches: if that list is not empty, say so instead of presenting a statement that does not tie out. It prepares figures; it files nothing.","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"company_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The company to work in. Ask list_companies if unsure."},"statement_code":{"type":"string","minLength":1,"description":"Which scheme, from list_statements (BE-BNB-ABBR-BS, FR-2050, IFRS-SME-BS)."},"from":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"to":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},"required":["company_id","statement_code","from","to"]},"annotations":{"readOnlyHint":true,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"financial_analysis","title":"Financial analysis","description":"The figures an analysis of a company is computed from — revenue, other operating income, purchases, staff costs, depreciation, the financial result, income tax, the net result, equity, total and current assets, cash, trade receivables, current liabilities, trade payables, long-term debt — each with the accounts that make it. The movements are read over the period and the balances at its end; equity includes the result of the years not closed yet. Which accounts make each figure is written in the company's country pack and in no tool: a company whose pack says nothing gets an empty list, and the figures are not to be guessed from account codes. Ratios — a margin, a current ratio, days of sales outstanding — are worked out from these, not stored. It prepares figures; it files nothing.","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"company_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The company to work in. Ask list_companies if unsure."},"from":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"First day of the period the movements are read on: revenue, purchases, the result."},"to":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Last day of the period, and the day the balances are read at: equity, assets, debts, cash."}},"required":["company_id","from","to"]},"annotations":{"readOnlyHint":true,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"generate_fec","title":"Generate the French FEC","description":"The Fichier des Écritures Comptables for a period: the eighteen columns of the arrêté du 29 juillet 2013, as text, with the checks a tax inspector applies first (mandatory fields, one side per line, entries balancing) and the filename the format wants. The file comes back in the answer; writing it to disk is the caller's business.","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"company_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The company to work in. Ask list_companies if unsure."},"from":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"to":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},"required":["company_id","from","to"]},"annotations":{"readOnlyHint":true,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"describe_pack","title":"Where a country pack comes from","description":"The country packs this installation holds, with their version, how much anyone has read them, and the register of texts each was built from — the title, the official publisher, an absolute link and the day somebody opened it, per text. Use it whenever you are asked where a rate, a chart of accounts or a box of the declaration comes from, and before repeating a figure a pack gave you: a community pack has not been read by an accountant, and the status says so. The article behind a single rule is on that rule itself — legal_reference on a tax or on a box — and the register is where that article can be read. It carries no copy of the law: a link that has gone quiet means the register is stale, never that the rule is wrong.","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"country":{"description":"ISO 3166-1 alpha-2, upper case. Left out, every pack this installation holds.","type":"string","minLength":2,"maxLength":2}}},"annotations":{"readOnlyHint":true,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"status","title":"Installation status","description":"The schema version, the instance this is, how this server is connected and as whom, and the companies you can see. Use it first when something does not add up — an empty company list usually means the user was never invited rather than that the books are empty.","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{}},"annotations":{"readOnlyHint":true,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"read_audit_log","title":"Audit trail","description":"Who changed what, and when. Every change to the configuration and reference data of a company — the chart of accounts, the journals, the taxes and the accounts they post to, the bank accounts, the contacts, the products, the financial years, the members and their roles, the country pack version — and every act that changes a state: a document posted or cancelled, an entry posted or reversed, a payment booked, matched or unmatched, a financial year closed or reopened. Filter by table, by natural key, by user, by act, or by date range. The ledger itself is not in here: a posted entry is immutable and is corrected by a reversal, so what is recorded is the act of posting and never the lines. Read-only, and there is no tool that writes it: the trail is append-only and even the operator cannot edit a row.","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"company_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The company to work in. Ask list_companies if unsure."},"table":{"description":"One table of the schema: accounts, journals, taxes, tax_postings, contacts, products, bank_accounts, companies, fiscal_years, company_members, company_packs, api_keys, documents, payments, entries, reconciliations.","type":"string"},"record_key":{"description":"The natural key of one row — an account code, a tax code, an invoice number.","type":"string"},"actor_id":{"description":"Only what this user changed. Their auth.users id.","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"action":{"description":"One act: document_posted, document_cancelled, entry_posted, entry_reversed, payment_posted, payment_reconciled, payment_unreconciled, fiscal_year_closed, fiscal_year_reopened, pack_upgraded.","type":"string"},"operation":{"type":"string","enum":["insert","update","delete"]},"from":{"description":"Earliest date, inclusive.","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"to":{"description":"Latest date, inclusive — the whole of that day.","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"limit":{"type":"integer","minimum":1,"maximum":200}},"required":["company_id"]},"annotations":{"readOnlyHint":true,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"search_products","title":"Find a product","description":"The catalogue of a company: what it sells and buys, with the code, the unit, the price, the account each books to and the tax each carries. Search it before writing a line by hand — a product fills in the text, the price, the account and the tax, and keeps two invoices for the same thing consistent. Retired products are left out unless you ask for them.","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"company_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The company to work in. Ask list_companies if unsure."},"query":{"description":"Matches the code, the name or the description.","type":"string","minLength":1},"kind":{"type":"string","enum":["service","goods"]},"include_inactive":{"description":"Default false: a retired product is hidden.","type":"boolean"},"limit":{"type":"integer","minimum":1,"maximum":200}},"required":["company_id"]},"annotations":{"readOnlyHint":true,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"create_product","title":"Add a product","description":"Adds an item to the catalogue: a code unique in the company, a name, a unit, a price, and optionally the account and the tax a sale or a purchase of it carries. It changes nothing already booked — a product is what a new line is filled in from, never a rule applied to the past. Search first: a second code for the same thing is how a price list stops being one.","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"company_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The company to work in. Ask list_companies if unsure."},"code":{"type":"string","minLength":1,"description":"Your own reference for the item. Unique in the company, and what EN 16931 calls the seller's item identifier (BT-155)."},"name":{"type":"string","minLength":1,"description":"What appears on the invoice line (BT-153)."},"description":{"description":"The longer text under the name (BT-154).","type":"string","minLength":1},"kind":{"description":"Defaults to service. Goods and services are not taxed alike and do not feed the same declaration boxes.","type":"string","enum":["service","goods"]},"unit_code":{"type":"string","minLength":1,"maxLength":3,"description":"UN/ECE recommendation 20: C62 a piece, HUR an hour, DAY a day, MON a month, KGM, LTR, MTR, KWH. Defaults to C62."},"currency_code":{"type":"string","minLength":3,"maxLength":3},"sale_price":{"description":"Net unit price on a sale. A line may still carry another.","type":["string","number"]},"purchase_price":{"type":["string","number"]},"sale_account_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"sale_account_code":{"description":"Income account a sale of this books to.","type":"string","minLength":1},"purchase_account_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"purchase_account_code":{"description":"Expense account a purchase of this books to.","type":"string","minLength":1},"sale_tax_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"sale_tax_code":{"description":"Tax applied when it is sold, by code.","type":"string","minLength":1},"purchase_tax_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"purchase_tax_code":{"type":"string","minLength":1}},"required":["company_id","code","name"]},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"update_product","title":"Change a product","description":"Changes a catalogue row — its name, price, unit, account, tax — or retires it with active: false. Documents already written keep the text, the price and the account they were invoiced with; an invoice is a statement about the day it was raised, and this tool cannot rewrite one. Retiring is the way to withdraw something: deleting is refused while any line still points at it.","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"product_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"company_id":{"description":"Needed with product_code, to say which company the code belongs to.","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"product_code":{"description":"Instead of product_id, with company_id.","type":"string","minLength":1},"code":{"description":"A new reference for it.","type":"string","minLength":1},"name":{"type":"string","minLength":1},"description":{"type":["string","null"]},"kind":{"type":"string","enum":["service","goods"]},"unit_code":{"type":"string","minLength":1,"maxLength":3,"description":"UN/ECE recommendation 20: C62 a piece, HUR an hour, DAY a day, MON a month, KGM, LTR, MTR, KWH. Defaults to C62."},"sale_price":{"type":["string","number","null"]},"purchase_price":{"type":["string","number","null"]},"sale_account_code":{"type":"string","minLength":1},"purchase_account_code":{"type":"string","minLength":1},"sale_tax_code":{"type":"string","minLength":1},"purchase_tax_code":{"type":"string","minLength":1},"active":{"description":"False retires it: searches stop offering it and the lines that already carry it are untouched.","type":"boolean"}}},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"create_contact","title":"Create a contact","description":"Adds a customer, supplier or other third party to a company. Search first: a duplicate contact splits a customer account in two and the aged balance stops making sense. payment_terms_days drives the due date a posted invoice gets when none is given. Next: create_document with the id it returns.","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"company_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The company to work in. Ask list_companies if unsure."},"name":{"type":"string","minLength":1},"contact_type":{"type":"string","enum":["customer","supplier","both","employee","other"]},"vat_number":{"type":"string","minLength":1},"email":{"type":"string","minLength":1},"country":{"description":"ISO country code, e.g. BE.","type":"string","minLength":2,"maxLength":2},"payment_terms_days":{"type":"integer","minimum":0,"maximum":365},"auxiliary_code":{"description":"Sub-ledger code; the French FEC reports it.","type":"string","minLength":1},"address_line1":{"type":"string","minLength":1},"postal_code":{"type":"string","minLength":1},"city":{"type":"string","minLength":1},"client_ref":{"description":"Your own reference for this creation. Calling again with the same one returns what was created the first time (`replayed: true`) instead of creating a second — use it whenever a call might be repeated after a timeout.","type":"string","minLength":1,"maxLength":200}},"required":["company_id","name","contact_type"]},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"create_document","title":"Create a draft invoice","description":"Creates a draft invoice, credit note or quote with its lines, and returns it with the totals the database computed — never with totals you supplied. A line may name a product_code, which fills in its text, price, unit, account and tax; anything the line carries wins over that. With no product and no account_code, the account falls back to the company default and then to its country model. A tax is different: a line with none is booked as a base with no VAT box, which is not the same as 0 %. Nothing is in the ledger yet. Next: show the draft to the user; update_document_lines changes it, and post_document books it once they agree.","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"company_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The company to work in. Ask list_companies if unsure."},"doc_type":{"type":"string","enum":["sale_invoice","sale_credit_note","sale_quote","purchase_invoice","purchase_credit_note","purchase_order"]},"contact_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"document_date":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"due_date":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"accounting_date":{"description":"The date the entry is booked on, when it differs from the document date.","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"number":{"description":"Your own number. Left out, posting takes the entry number.","type":"string","minLength":1},"supplier_reference":{"description":"The supplier's own invoice number, on a purchase.","type":"string","minLength":1},"currency_code":{"type":"string","minLength":3,"maxLength":3},"journal_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"payment_reference":{"type":"string","minLength":1},"client_ref":{"description":"Your own reference for this creation. Calling again with the same one returns what was created the first time (`replayed: true`) instead of creating a second — use it whenever a call might be repeated after a timeout.","type":"string","minLength":1,"maxLength":200},"lines":{"minItems":1,"type":"array","items":{"type":"object","properties":{"name":{"description":"What is billed, as it appears on the invoice. Required unless a product supplies it.","type":"string","minLength":1},"description":{"description":"EN 16931 BT-154, under the name. A product supplies it when the line does not.","type":"string","minLength":1},"quantity":{"description":"Defaults to 1.","type":["string","number"]},"unit_code":{"description":"Unit of measure, UN/ECE rec. 20: C62 a piece, HUR an hour, DAY a day, KGM, LTR, MTR. From the product, then C62.","type":"string","minLength":1,"maxLength":3},"unit_price":{"description":"Price of one unit, excluding tax, as a decimal string. Left out, the product's price; without either, the line is refused.","type":["string","number"]},"discount_percent":{"description":"A percentage off this line, 0 to 99.","type":["string","number"]},"product_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"product_code":{"description":"A catalogue row, by code. It fills in the text, the price, the unit, the account and the tax; anything given on the line wins.","type":"string","minLength":1},"account_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"account_code":{"description":"The income or expense account, by code. Left out: the product, then the company default, then the one its country model names. A company with none of them refuses the line.","type":"string","minLength":1},"tax_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"tax_code":{"description":"The tax, by code, e.g. BE-S-21. Left out, the tax of the product. With no product either, the line books a base with no VAT box, which is not the same as 0 %.","type":"string","minLength":1}}}}},"required":["company_id","doc_type","contact_id","document_date","lines"]},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"update_document_lines","title":"Replace the lines of a draft","description":"Replaces every line of a draft document with the set you give, and returns the document with its recomputed totals. Lines take product_code the same way create_document does. Drafts only: a posted document is never edited; cancel_document undoes it with a credit note.","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"document_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"lines":{"minItems":1,"type":"array","items":{"type":"object","properties":{"name":{"description":"What is billed, as it appears on the invoice. Required unless a product supplies it.","type":"string","minLength":1},"description":{"description":"EN 16931 BT-154, under the name. A product supplies it when the line does not.","type":"string","minLength":1},"quantity":{"description":"Defaults to 1.","type":["string","number"]},"unit_code":{"description":"Unit of measure, UN/ECE rec. 20: C62 a piece, HUR an hour, DAY a day, KGM, LTR, MTR. From the product, then C62.","type":"string","minLength":1,"maxLength":3},"unit_price":{"description":"Price of one unit, excluding tax, as a decimal string. Left out, the product's price; without either, the line is refused.","type":["string","number"]},"discount_percent":{"description":"A percentage off this line, 0 to 99.","type":["string","number"]},"product_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"product_code":{"description":"A catalogue row, by code. It fills in the text, the price, the unit, the account and the tax; anything given on the line wins.","type":"string","minLength":1},"account_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"account_code":{"description":"The income or expense account, by code. Left out: the product, then the company default, then the one its country model names. A company with none of them refuses the line.","type":"string","minLength":1},"tax_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"tax_code":{"description":"The tax, by code, e.g. BE-S-21. Left out, the tax of the product. With no product either, the line books a base with no VAT box, which is not the same as 0 %.","type":"string","minLength":1}}},"description":"The complete new set of lines; what is there now is replaced."}},"required":["document_id","lines"]},"annotations":{"readOnlyHint":false,"destructiveHint":true,"idempotentHint":true,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"post_document","title":"Post a document to the ledger","description":"Books a draft document: base lines, VAT lines from the tax configuration, and the customer or supplier counterpart, numbered and posted. A posted entry is never edited; a mistake is undone by cancel_document, which puts the document back to draft only where its country allows it and nothing has left, and issues a credit note otherwise. Ask the user before calling it. It refuses a locked period, a tax that is not in force, and a header total that disagrees with the lines. Next: get_document shows the entry it wrote, and record_payment books the money when it moves.","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"document_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"dry_run":{"description":"True: the database posts for real and takes it back, and the entry it would have written is returned. Nothing is written; a refusal is the one posting would give.","type":"boolean"}},"required":["document_id"]},"annotations":{"readOnlyHint":false,"destructiveHint":true,"idempotentHint":false,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"cancel_document","title":"Undo a posted invoice","description":"Undoes a posted sale or purchase invoice in one call, the one way its country and its facts allow, and says which in undone_by. 'draft': the country's posted_edit_policy lets a posted document go back to draft and nothing about this one has left — never sent nor on Peppol, not paid, not declared, its period open and, where numbering is gapless, its number the last one drawn; its entry is taken away, its number given back, and it is a draft to correct and post again. 'credit_note' otherwise, with the reason in why: its credit note — the same lines, taxes, accounts, contact, currency and rate — is issued naming it, posted and matched against it, and the invoice is cancelled, payment state reversed; the invoice keeps its number and its entry. Tell the user which it was. A date, or credit_note: true, asks for the credit note outright. Dated on the invoice's booking day unless you give a date; refused by name when that period is locked or closed (reversal_date_needed), and then you ask the user for a date rather than choosing one. Refused for a draft, a credit note, an invoice already cancelled or credited, and one that is paid in part or in full — the payment is unmatched first with unreconcile, and only when the user says so. Ask the user before calling it.","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"document_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The posted sale or purchase invoice to undo."},"date":{"description":"The day a credit note is issued and booked on. Given, it asks for the credit note. Left out: the invoice's own booking day, and refused by name (reversal_date_needed) when that period is no longer open — then ask the user which open date to use; never pick one.","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"credit_note":{"description":"True: undo it with a credit note even where it could go back to draft — the user wants the correction on the record.","type":"boolean"}},"required":["document_id"]},"annotations":{"readOnlyHint":false,"destructiveHint":true,"idempotentHint":false,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"reverse_entry","title":"Reverse a posted entry","description":"Undoes a posted entry in one call: writes its mirror in the same journal — every line on the other side — naming it, posts it under the next number, and matches the two. The original keeps its number and its lines. Dated on the original's day unless you give a date; refused by name when that period is locked or closed (reversal_date_needed), and then you ask the user for a date rather than choosing one. Refused for an entry a document wrote (use cancel_document), the entries of a close (reopen_fiscal_year), an opening, the entry of a payment, a bank transaction, a module or a matching, an entry already reversed or that is itself a reversal, and a matched entry — unmatch it first with unreconcile, and only when the user says so. Ask the user before calling it.","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"entry_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The posted entry to undo. An entry a document wrote is undone with the document, by cancel_document."},"date":{"description":"The day the reversal is booked on. Left out: the original entry's day, and refused by name (reversal_date_needed) when that period is no longer open — then ask the user which open date to use; never pick one.","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},"required":["entry_id"]},"annotations":{"readOnlyHint":false,"destructiveHint":true,"idempotentHint":false,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"record_payment","title":"Record a payment","description":"Records money in or out, books it (bank against the customer or supplier account) and, unless you say otherwise, matches it against that contact's oldest open invoices up to the amount paid. Matching is what makes an invoice count as paid. The entry it produces cannot be unposted, though the matching can be undone with unreconcile.","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"company_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The company to work in. Ask list_companies if unsure."},"direction":{"description":"inbound: a customer paid you. outbound: you paid a supplier. May be left out when document_id is given.","type":"string","enum":["inbound","outbound"]},"amount":{"description":"A positive decimal string; the direction carries the sign.","type":["string","number"]},"payment_date":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"contact_id":{"description":"Who paid or was paid. Needed for the payment to be matched against their invoices.","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"journal_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"journal_code":{"description":"The bank or cash journal, by code, e.g. BNK. Not needed when bank_account_id is given: the account knows its journal.","type":"string","minLength":1},"bank_account_id":{"description":"Which bank account the money moved on. list_bank_accounts says what exists. Given alone, it also names the journal; left out, the default account of the journal is used.","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"reference":{"type":"string","minLength":1},"memo":{"type":"string","minLength":1},"currency_code":{"description":"Left out: the currency the company keeps its books in.","type":"string","minLength":3,"maxLength":3},"exchange_rate":{"description":"Units of the payment currency for one unit of the company currency, as a rate table states it. Only needed when the payment is in another currency; the realised difference against the invoice is booked at matching.","type":["string","number"]},"document_id":{"description":"The posted document this money pays. It names the contact and the direction, read off what is still open on it, and the matching is offered to that document alone rather than to the oldest open items.","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"client_ref":{"description":"Your own reference for this creation. Calling again with the same one returns what was created the first time (`replayed: true`) instead of creating a second — use it whenever a call might be repeated after a timeout.","type":"string","minLength":1,"maxLength":200},"match_open_items":{"description":"Default true: match the payment against the oldest open invoices of that contact, up to the amount paid.","type":"boolean"}},"required":["company_id","amount","payment_date"]},"annotations":{"readOnlyHint":false,"destructiveHint":true,"idempotentHint":false,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"reconcile","title":"Match two ledger lines","description":"Matches a debit line against a credit line on the same reconcilable account, for an amount, defaulting to the smaller of the two open amounts. Use it to settle an invoice against a payment by hand. Matching changes no account and stays possible after a period is locked.","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"line_a":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"A ledger line to match. Either side; the schema works out which is the debit."},"line_b":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The line it settles. Both must be on the same reconcilable account."},"amount":{"description":"Left out: the smaller of the two open amounts.","type":["string","number"]}},"required":["line_a","line_b"]},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"unreconcile","title":"Undo a matching","description":"Removes one matching, putting the residual back on both lines. The entries themselves are untouched. It is what cancel_document and reverse_entry ask for first when what they would undo is matched.","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"reconciliation_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The matching to undo, as returned by reconcile or read from the ledger line."}},"required":["reconciliation_id"]},"annotations":{"readOnlyHint":false,"destructiveHint":true,"idempotentHint":true,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"settle_from_statement","title":"Settle a bank statement line","description":"Books a pending statement line as the payment it is and matches it against the documents or open items named, in one entry: the bank, the customer or supplier account, and the extra lines the money is net of — the fee a payment provider kept from a payout, the charges of a bank, each on the account and with the tax the user names. A payout of 97.00 for an invoice of 100.00 settles the invoice in full with an extra line of 3.00 on a fee account. amounts says how much settles each item; left out, oldest first. The line has to balance to the cent (settlement_unbalanced otherwise, with the difference). Extra lines alone settle a bank charge. One counterparty per line. The entry cannot be unposted. Ask the user before calling it, and for the fee account and its tax.","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"transaction_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The statement line, as list_bank_transactions returns it. It is settled once."},"document_id":{"description":"The posted document the line pays; its open items are what is settled.","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"document_ids":{"description":"Several documents the one line pays, in the order amounts follows.","minItems":1,"type":"array","items":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"line_ids":{"description":"Or the open items themselves, by ledger line.","minItems":1,"type":"array","items":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"amounts":{"description":"How much of the line settles each item — one per line_ids, or one per document — as decimal strings. Left out, the items are settled oldest first, and in full when there are extra_lines. Less than an item has open settles it in part, which is the user's decision, never yours.","minItems":1,"type":"array","items":{"type":["string","number"]}},"extra_lines":{"description":"Lines booked in the same entry beside the settlement: the fee a payment provider kept from a payout, the charges of a bank, a small difference. Money in is the items less these; money out the items plus these; to the cent, or settlement_unbalanced names the difference. Alone, with no document and no line, they settle a bank charge.","type":"array","items":{"type":"object","properties":{"account":{"type":"string","minLength":1,"description":"The account, by code: an expense for a fee or a charge, an income for a surplus. Never a customer or supplier account."},"amount":{"description":"A decimal string. Positive is a charge (debited), negative a credit. With a tax, the tax is inside it.","type":["string","number"]},"tax":{"description":"The tax the charge bears, by code, when the provider or the bank invoices it with one. Ask the user; do not choose.","type":"string","minLength":1},"description":{"type":"string","minLength":1}},"required":["account","amount"],"additionalProperties":false}}},"required":["transaction_id"]},"annotations":{"readOnlyHint":false,"destructiveHint":true,"idempotentHint":false,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"create_bank_account","title":"Add a bank account","description":"Registers a bank account of the company from its identifier — an IBAN, an ABA routing number and an account number, a sort code and an account number, whatever the banks of the company's country use; the pack of the country says which, and it is checked — and wires it to the bank journal and to the ledger account behind it — both of which the country template has already chosen, so neither has to be given. Running it twice with the same identifier returns the one that exists rather than creating a second. Do this once per account: until a company has one, an invoice carries no account to pay into and record_payment can only book on the journal's default account.","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"company_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The company to work in. Ask list_companies if unsure."},"account_identifier":{"description":"What identifies the account at its bank, in the scheme of the company's country: an IBAN, an ABA routing number and an account number, a sort code and an account number, a BSB and an account number, an IFSC and an account number, a CLABE… `list_bank_accounts` and `describe_pack` say which. Separators are ignored and the value is stored in the canonical form of its scheme; it is the natural key of a bank account in a company. Where the country's pack declares no scheme, any account number as the bank wrote it.","type":"string","minLength":1},"iban":{"description":"Deprecated: an alias of account_identifier, accepted only where the country identifies accounts by IBAN.","type":"string","minLength":5},"label":{"description":"What it is called in the books. Defaults to the bank name, then to the identifier.","type":"string","minLength":1},"bic":{"description":"The bank identifier code, where the bank has one.","type":"string","minLength":1},"bank_name":{"type":"string","minLength":1},"currency_code":{"description":"Defaults to the company's own currency.","type":"string","minLength":3,"maxLength":3},"journal_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"journal_code":{"description":"The financial journal it books through. Left out, the bank journal of the company.","type":"string","minLength":1},"account_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"account_code":{"description":"The ledger account behind it. Left out, the journal's default account, which the country template chose.","type":"string","minLength":1}},"required":["company_id"]},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"list_bank_accounts","title":"Bank accounts","description":"The bank accounts of a company, with their identifier and the scheme it is written in, the journal they book through and the ledger account behind each. Read it before recording a payment on a particular account, and to find out whether the company has one at all.","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"company_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The company to work in. Ask list_companies if unsure."},"include_inactive":{"description":"Default false.","type":"boolean"}},"required":["company_id"]},"annotations":{"readOnlyHint":true,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"create_bank_transaction","title":"Add a bank transaction","description":"Records one statement line by hand, for an installation without a bank feed. `amount` is signed: positive is money in. It books nothing — the line waits as pending until a payment is recorded.","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"company_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The company to work in. Ask list_companies if unsure."},"bank_account_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"transaction_date":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"amount":{"description":"Signed: positive is money in, negative is money out.","type":["string","number"]},"description":{"type":"string","minLength":1},"counterpart_name":{"type":"string","minLength":1},"counterpart_iban":{"type":"string","minLength":1},"reference":{"type":"string","minLength":1},"structured_reference":{"description":"A structured communication, e.g. +++000/0000/00000+++ or RF…","type":"string","minLength":1},"statement_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"contact_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"value_date":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},"required":["company_id","bank_account_id","transaction_date","amount"]},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"import_bank_statement","title":"Import a bank statement","description":"Reads a bank statement file and writes its statements and lines. `format` says what the file is — `camt.053` (the ISO 20022 XML statement), `coda` or `cfonb120`, which are the ones this server reads today — and `content` is the file as text. It is never guessed from the content. It books nothing: every line waits as pending, to be settled afterwards. Safe to repeat: the same file imported twice creates nothing the second time, and a statement overlapping an earlier one imports only the new lines. Refused by name, with nothing written: an account the company does not have (create it first with create_bank_account — an import never creates one), a statement whose opening balance plus lines is not its closing balance, a line in another currency. Signalled in `warnings`, not refused: an opening balance that is not the previous closing one, which means a statement is missing.","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"company_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The company to work in. Ask list_companies if unsure."},"format":{"type":"string","enum":["camt.053","coda","cfonb120"],"description":"What the file is. Required, and never guessed from the content: `camt.053` is the ISO 20022 XML statement, `coda` the coded statement of account of 128-character records, `cfonb120` the statement of 120-character records."},"content":{"type":"string","minLength":1,"description":"The file itself, as text (UTF-8)."},"file_name":{"description":"The name the file had, kept on the statement.","type":"string","minLength":1},"storage_path":{"description":"Where the caller stored the file, if it did. With it the file is recorded in attachments, on the statement; this server stores no bytes.","type":"string","minLength":1},"bank_account_id":{"description":"Only for a file of one statement whose account the company identifies otherwise than the file does. Left out, the account is found by the identifier the statement carries, and an unknown one is refused.","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"iban_country":{"description":"Only for `cfonb120`, which identifies an account by a bank code, a branch code and a number, and names no country. With the two letters of the country the account is held in, the statement is matched on the IBAN those make there; left out, on the three joined, as written. Never guessed.","type":"string","minLength":2,"maxLength":2}},"required":["company_id","format","content"]},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"create_company","title":"Create a company","description":"Creates a company on a country pack: its chart of accounts, its journals and its taxes are copied in, its first financial year is opened on the month that country opens one on, and you become its first member. Creating a company is an instance-level act — it needs an instance administrator, and being one is not the same as being on anybody’s books. Ask the user for the country rather than guessing: the wrong answer is a whole chart of accounts.","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"name":{"type":"string","minLength":1},"country":{"type":"string","minLength":2,"maxLength":2,"description":"Which country pack: its chart of accounts, its taxes and its declaration form. list_companies shows what the installation already uses."},"currency_code":{"description":"Left out, the country pack's.","type":"string","minLength":3,"maxLength":3},"language":{"description":"Language the books are kept in — it decides the labels of the chart. Left out, the country pack's.","type":"string","minLength":2,"maxLength":2},"chart_code":{"description":"Which chart, where the country offers several.","type":"string"},"fiscal_year":{"description":"Calendar year the first financial year opens in. Default this year.","type":"integer","minimum":1900,"maximum":2200},"fiscal_year_start":{"description":"First day of it. Left out, the month the country pack opens a year on — and a pack that names none is a refusal, not a January.","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},"required":["name","country"]},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"update_company_profile","title":"Change the company itself","description":"Changes what a company says about itself on its documents: the names it goes by, its address and identifiers, its logo and the colour and logo side of its invoice PDF, its stated capital, its activity code and the bank account customers are asked to pay into. Only the fields you name change. It touches nothing in the ledger, and it needs company.write — the owner preset, not the accountant one.","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"company_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The company to work in. Ask list_companies if unsure."},"name":{"type":"string","minLength":1},"trade_name":{"description":"The name it trades under, if not the statutory one.","type":["string","null"]},"legal_name":{"type":["string","null"]},"legal_form":{"type":["string","null"]},"vat_number":{"type":["string","null"]},"registration_number":{"description":"The number of the commercial register of its country. There is no second column for it.","type":["string","null"]},"address_line1":{"type":["string","null"]},"address_line2":{"type":["string","null"]},"postal_code":{"type":["string","null"]},"city":{"type":["string","null"]},"email":{"type":["string","null"]},"phone":{"type":["string","null"]},"website":{"type":["string","null"]},"logo_url":{"description":"Where the logo is. A URL or a storage path: the core keeps no file.","type":["string","null"]},"share_capital":{"description":"A decimal string. Several legal forms must state it on every document.","type":["string","null"]},"share_capital_currency":{"description":"Left out, the company's own currency.","anyOf":[{"type":"string","minLength":3,"maxLength":3},{"type":"null"}]},"activity_code":{"description":"NACE, APE, SIC — the code itself.","type":["string","null"]},"activity_scheme":{"description":"Which register the code belongs to.","type":["string","null"]},"default_bank_account_id":{"description":"Fills the payee IBAN of a sales document that names none. list_bank_accounts says what exists.","anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"document_template":{"description":"A code the renderer interprets.","type":["string","null"]},"invoice_accent_color":{"description":"The accent colour of its invoice PDF, #rrggbb: the title, the rules and the bands. Null puts back the default.","anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"null"}]},"invoice_logo_position":{"description":"The side of its invoice PDF the logo is printed on. Null puts back the default, left.","anyOf":[{"type":"string","enum":["left","right"]},{"type":"null"}]}},"required":["company_id"]},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"set_preferences","title":"Change what this user prefers","description":"Writes the signed-in user’s own preferences and nobody else’s. Only the fields you name change: leave one out and it is untouched, pass null and it is cleared, which puts that question back to the company and then to the country pack. It changes nothing in the books.","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"preferred_company_id":{"description":"The company to open on.","anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"language":{"description":"Two letters, optionally a region. Labels are read in it first.","type":["string","null"]},"timezone":{"description":"An IANA name.","type":["string","null"]},"date_display_format":{"description":"How this person likes a date written.","type":["string","null"]},"number_display_format":{"description":"How this person likes a number written. Not the pattern a document number is built from, which belongs to the country.","type":["string","null"]},"theme":{"type":["string","null"]}}},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"invite_member","title":"Invite somebody into a company","description":"Invites an address into a company with a preset — viewer reads, client reads and hands pieces over, accountant keeps the books, owner also administers — and any capability granted on top of it. It returns a token once and stores only its hash, so hand the token to the person you invited: they accept it themselves, signed in with that address. It does not send an e-mail, and it does not create an account. Inviting the same address again withdraws the invitation that was pending.","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"company_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The company to work in. Ask list_companies if unsure."},"email":{"type":"string","minLength":3,"description":"The address the invitation is for. Matched when it is accepted."},"role":{"description":"The preset. Default viewer, which reads and changes nothing. client is the person whose company it is, invited by whoever keeps their books: it reads the same, and may also hand a file over (documents.deposit).","type":"string","enum":["owner","accountant","viewer","client"]},"capabilities":{"description":"Capability codes granted on top of the preset, e.g. members.manage. get_company lists what this installation knows.","type":"array","items":{"type":"string"}},"valid_for_days":{"description":"Default 14.","type":"integer","minimum":1,"maximum":365}},"required":["company_id","email"]},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"create_api_key","title":"Issue a key to a machine","description":"Issues a key so a script — a nightly import, a till, a bank feed — can work in one company without a person signing in. It carries an explicit list of capabilities and nothing else, it can never reach another company, and it cannot hold a capability you do not hold yourself — at issuance and at every use: if you lose a capability or leave the company, the key loses it too. The secret comes back once and is stored only as a hash: show it to the user and say it cannot be read back. Prefer this to sharing anybody’s password, and never suggest a service key.","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"company_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The company to work in. Ask list_companies if unsure."},"name":{"type":"string","minLength":1,"description":"What this key is for, in the words an operator will read a year from now."},"capabilities":{"minItems":1,"type":"array","items":{"type":"string"},"description":"Exactly what the machine may do, e.g. [\"bank.write\"]. You cannot put a capability on a key that you do not hold yourself."},"expires_at":{"description":"When it stops working, as a timestamp. Left out, it does not expire on its own.","type":["string","null"]}},"required":["company_id","name","capabilities"]},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"revoke_api_key","title":"Withdraw a machine key","description":"Stops a key working, now and for good. There is no un-withdraw: a secret that has been out of the building is issued again rather than brought back. Whatever the machine was doing with it stops, so say so before calling it.","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"api_key_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["api_key_id"]},"annotations":{"readOnlyHint":false,"destructiveHint":true,"idempotentHint":true,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"revoke_invitation","title":"Withdraw an invitation","description":"Withdraws an invitation that has not been accepted, so its token stops working. An invitation that has already become a membership is refused: a member is taken out with remove_member.","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"invitation_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["invitation_id"]},"annotations":{"readOnlyHint":false,"destructiveHint":true,"idempotentHint":true,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"remove_member","title":"Take somebody out of a company","description":"Removes a member from a company, now: they stop reading and writing its books. Needs members.manage, except to leave a company yourself. The last owner of a company is refused, themself included; make somebody else owner with set_member_role first. Their pending invitations are not touched. Say who is being removed before calling it.","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"company_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The company to work in. Ask list_companies if unsure."},"user_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The member to take out. Your own id leaves the company, which needs no members.manage."}},"required":["company_id","user_id"]},"annotations":{"readOnlyHint":false,"destructiveHint":true,"idempotentHint":false,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"set_member_role","title":"Move a member to another preset","description":"Changes the preset of a member of a company — viewer reads, client reads and hands pieces over, accountant keeps the books, owner also administers. Needs members.manage. The capabilities granted or revoked on that member so far are cleared, and the ones you pass are granted on top of the new preset, the way an invitation writes a new member. The last owner of a company cannot be demoted: promote the successor first.","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"company_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The company to work in. Ask list_companies if unsure."},"user_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"role":{"type":"string","enum":["owner","accountant","viewer","client"],"description":"The new preset. The capabilities granted or revoked on this member so far are cleared."},"capabilities":{"description":"Capability codes granted on top of the new preset, as invite_member takes them. Default none.","type":"array","items":{"type":"string"}}},"required":["company_id","user_id","role"]},"annotations":{"readOnlyHint":false,"destructiveHint":true,"idempotentHint":true,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"share_document","title":"Publish a document behind a link","description":"Publishes a posted sales invoice, credit note or quote behind a link the customer opens without an account and without a password: the token in the url is the whole secret. It returns that token once and stores only its hash, so give the url to the customer and say it cannot be read back. The page shows the document as it was sent and what is still owed on it today, so the link stays worth opening after a payment. A purchase document is refused — it is a third party’s own document — and so is a draft. A link is never edited: to change when it expires, withdraw it and make another.","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"document_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The sales document to publish. A purchase document and a draft are refused."},"expires_at":{"description":"When the link stops answering, as a timestamp. Left out, it answers until it is withdrawn.","type":["string","null"]}},"required":["document_id"]},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":true},"execution":{"taskSupport":"forbidden"}},{"name":"revoke_share","title":"Withdraw a published link","description":"Stops a link working, now and for good. Whoever holds it sees exactly what they would see for a link that never existed. There is no un-withdraw: a secret that has been out of the building is issued again rather than brought back, so say so before calling it.","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"share_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["share_id"]},"annotations":{"readOnlyHint":false,"destructiveHint":true,"idempotentHint":true,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"pin_accounts","title":"Pin accounts to the working chart","description":"Adds accounts to the working chart of a company, so list_accounts offers them whether or not anything has been booked on them. Pass pinned: false to take one back out. Pinning is display and nothing else: an unpinned account may still be booked on, and a pinned one is still hidden once it is deprecated.","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"company_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The company to work in. Ask list_companies if unsure."},"account_codes":{"minItems":1,"type":"array","items":{"type":"string","minLength":1},"description":"Codes in this company's chart. list_accounts with include_all says what exists."},"pinned":{"description":"True pins, false unpins. Defaults to true.","type":"boolean"}},"required":["company_id","account_codes"]},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"lock_period","title":"Lock a period","description":"Moves the accounting lock date, the VAT lock date, or both. After this, nothing can be booked, changed or deleted on or before that date — including corrections you may want later. Only an owner of the company may do it. Always ask the user first, and never lock a period you have just posted into without being told to.","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"company_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The company to work in. Ask list_companies if unsure."},"lock_date":{"description":"Nothing may be booked on or before this date. null lifts the lock.","anyOf":[{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},{"type":"null"}]},"tax_lock_date":{"description":"Additionally freezes anything carrying a VAT box. null lifts it.","anyOf":[{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},{"type":"null"}]}},"required":["company_id"]},"annotations":{"readOnlyHint":false,"destructiveHint":true,"idempotentHint":true,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"import_books","title":"Import books from another system","description":"Takes over the books a user kept elsewhere — a FEC, an XML audit file, an export of journal items, a journal report, a transaction journal, a trial balance, or the export of odoo or xero or quickbooks-online or pennylane or sage-50 or exact-online by name — whole or not at all. Each file is read by the reader of its source; every account of the old chart is matched to one of this company's chart and every old journal to a journal of the company. The codes give a candidate (the same code, the same digits without the padding zeros, or the longest beginning of three digits or more), and what the files say of the old account — its type, its name, the side of its balance — is held against what the chart says the candidate is, never a country: only the same code, not contradicted, is `exact`; anything else is `suggested` with its reason, or `none`. Each old journal is proposed from what its entries touch, never its name — the opening (entries on the first day of a year, balance accounts only), sales, purchases, bank, else the general journal — with its reason under journal_reasons. Call it with dry_run first: it returns the correspondence proposed, the suggestions under mapping.suggested, what is unanswered, and — when everything is answered — what the database would write, rehearsed and rolled back. Show the user every suggested line and its reason first; nothing is posted while one is unconfirmed. Settle each by writing its code under mapping.accounts, or, once the user has read and approved them all, pass accept_suggestions. Every entry is posted through post_entry(); a trial balance becomes the opening entry, on the first day of a year or the day inside it the books were taken over, and the open items beside it (open_items) posted documents that statement matching finds. Imported lines carry no tax and feed no VAT box. The same files twice are refused. The files travel as text, up to 256 KiB in all: a larger export is imported from the terminal with `ekwo import`, which reads it from the disk. Ask the user before the real call.","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"company_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The company to work in. Ask list_companies if unsure."},"source":{"type":"string","enum":["trial-balance","fec","journal-items","journal-report","transaction-journal","xaf","odoo","xero","quickbooks-online","pennylane","sage-50","exact-online"],"description":"What the files are, never guessed from their content: `trial-balance` — a trial balance as CSV — account, debit, credit, or a signed balance — which becomes the opening entry of a year; `fec` — a fichier des écritures comptables, the eighteen-column file of the arrêté of 29 July 2013; `journal-items` — an export of journal items as CSV — one row per line of an entry, with its entry, journal, date, account, partner, debit and credit — optionally with the chart of accounts and the partners exported beside it; `journal-report` — a journal report or a general ledger detail saved as CSV — date, journal number, account code, debit, credit — optionally with the chart of accounts and the contacts exported beside it; `transaction-journal` — a transaction journal saved as CSV — each transaction a run of rows under one date, type and number, with its account, debit and credit — optionally with the list of accounts exported beside it; `xaf` — an XML Audit File Financial (XAF), version 3.2 or 4.0 — the accounts, the parties, the opening balance and every transaction of a year, in one XML file. By the software that wrote them: `odoo` reads the export of the Journal Items of Odoo (Accounting), as CSV, with its chart of accounts and its partners (the same as `journal-items`); `xero` reads the Journal Report or the General Ledger Detail of Xero, saved as CSV, with its chart of accounts and its contacts (the same as `journal-report`); `quickbooks-online` reads the Journal report of QuickBooks Online, exported to Excel and saved as CSV, with its Account # column, and its Account List exported the same way (the same as `transaction-journal`); `pennylane` reads the FEC (fichier des écritures comptables) of Pennylane, exported under Comptabilité > Saisie > Exports: the tab-separated text file inside the ZIP it downloads (the same as `fec`); `sage-50` reads the FEC (fichier des écritures comptables) of Sage 50, exported under Échanges > Exporter des écritures, format FEC (the same as `fec`); `exact-online` reads the XML Audit File (XAF, version 3.2 or 4.0) of Exact Online, exported under Import/Export > Export > Audit file (the same as `xaf`). A bank statement is not books: it goes through import_bank_statement."},"files":{"minItems":1,"type":"array","items":{"type":"object","properties":{"name":{"type":"string","minLength":1,"description":"The name the file had, kept on the record of the import."},"content":{"type":"string","minLength":1,"description":"The file itself, as text (UTF-8)."}},"required":["name","content"]},"description":"The files of one source, in the order given. `journal-items` and `journal-report` take the chart of accounts and the parties beside the lines, and `transaction-journal` the list of accounts, each recognised by its header; the others take one file."},"mapping":{"description":"The correspondence, as a previous call with dry_run returned it and the user completed it. What it answers wins over the proposal.","type":"object","properties":{"accounts":{"description":"Old account code → code of this company's chart.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":["string","null"]}},"journals":{"description":"Old journal → code of a journal of this company, or `@opening` for the entries that are the opening balance. `*` stands for entries the source gives no journal.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":["string","null"]}}}},"dry_run":{"description":"Show what would be written — the correspondence proposed, the entries, the numbers — and write nothing. Always first, and the user reads it before the real call.","type":"boolean"},"open_years":{"description":"Open the fiscal years the entries fall in where the company has none, on the length and first day of its own. Off, such an entry is refused by name.","type":"boolean"},"opening_date":{"description":"For a trial balance: the day it opens on — the first day of a fiscal year, or the day inside it the books were taken over. The file does not say it; an audit file does, and needs none.","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"open_items":{"description":"With an opening: the invoices and credit notes still open on its day, as CSV — type (sale_invoice, sale_credit_note, purchase_invoice, purchase_credit_note), number, contact (the code the balance names the party by), contact name, amount still open, document date and due date as YYYY-MM-DD, payment reference, supplier reference. Each becomes a posted document on the opening journal, found by statement matching like an invoice issued here; the items of a receivable or payable account must add up to its line of the balance.","type":"object","properties":{"name":{"type":"string","minLength":1,"description":"The name the file had, kept on the record of the import."},"content":{"type":"string","minLength":1,"description":"The file itself, as text (UTF-8)."}},"required":["name","content"]},"allow_result_accounts":{"description":"Let an opening balance carry income and expense accounts: books taken over in the middle of a year.","type":"boolean"},"keep_numbers":{"description":"Post each entry under the number it had. Where the country forbids a hole in the sequence it takes the entries.import capability; left out, the journal draws the numbers and the old one is kept as the reference.","type":"boolean"},"date_order":{"description":"For `journal-report` and `transaction-journal`: the order of a date written only in digits, which the file does not say.","type":"string","enum":["dmy","mdy","ymd"]},"accept_suggestions":{"description":"Take every account the proposal only suggested as the answer. Only after the user has read each suggested line and its reason, and said yes to all of them; left out, a suggestion stops the import.","type":"boolean"}},"required":["company_id","source","files"]},"annotations":{"readOnlyHint":false,"destructiveHint":true,"idempotentHint":true,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"opening_balance","title":"Import an opening balance","description":"Turns the trial balance of whatever kept the books before into the opening entry of a fiscal year, on the opening journal, dated on its first day — or on opening_date, the day inside the year the books were taken over. Lines are {account_code, debit, credit}; total debit must equal total credit. Balance-sheet accounts only, unless allow_result_accounts is set, which is for taking books over in the middle of a year. items are the invoices and credit notes still open that day, each posted as a document with its number, payment reference and due date, so a bank statement finds it; the items of an account replace its line and must add up to it. A year holds one opening: a second call is refused rather than added to.","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"company_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The company to work in. Ask list_companies if unsure."},"fiscal_year_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The year the balance opens. The entry is dated on its first day unless opening_date says otherwise."},"opening_date":{"description":"The day the books were taken over, inside that year. Left out, its first day. The balance is what the previous system held at the end of the day before.","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"lines":{"minItems":1,"type":"array","items":{"type":"object","properties":{"account_code":{"type":"string","minLength":1,"description":"Code in this company's chart. list_accounts says what exists; the codes are the pack's, not ours."},"debit":{"description":"A positive decimal string. A line carries a debit or a credit, never both.","type":["string","number"]},"credit":{"type":["string","number"]},"contact_id":{"description":"The customer or supplier behind a receivable or payable line, so the aged balance knows whose it is.","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"label":{"type":"string","minLength":1}},"required":["account_code"]},"description":"The trial balance of the previous system, one entry per row. Total debit must equal total credit."},"allow_result_accounts":{"description":"Default false: an opening balance is made of the balance sheet. Pass true only when taking books over in the middle of a year that has already run.","type":"boolean"},"items":{"description":"The invoices and credit notes still open on the opening day. Each becomes a posted document on the opening journal, with its number, reference and dates, against the suspense account — nothing is booked to revenue or expense again — so statement matching finds it like an invoice issued here. The items of a receivable or payable account replace its line of the balance and must add up to it exactly.","type":"array","items":{"type":"object","properties":{"doc_type":{"type":"string","enum":["sale_invoice","sale_credit_note","purchase_invoice","purchase_credit_note"]},"number":{"type":"string","minLength":1,"description":"The number the document had. Unique among the documents of its type in this company."},"contact_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The customer or supplier who owes it or is owed it."},"amount":{"description":"What is still open of it: a positive decimal string. The type says the side.","type":["string","number"]},"document_date":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"The day it was issued, on or before the opening."},"due_date":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"payment_reference":{"description":"The reference a payment of it quotes — the structured one where the country has them. What statement matching finds it by.","type":"string","minLength":1},"supplier_reference":{"description":"On a purchase, the supplier's own number.","type":"string","minLength":1},"label":{"type":"string","minLength":1}},"required":["doc_type","number","contact_id","amount","document_date"]}}},"required":["company_id","fiscal_year_id","lines"]},"annotations":{"readOnlyHint":false,"destructiveHint":true,"idempotentHint":false,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"close_fiscal_year","title":"Close a fiscal year","description":"Closes a year: the result of the year leaves the income statement the way the country model says — straight to retained earnings, into a current-year result account, or through the appropriation accounts — every income and expense account goes back to zero, and the year stops accepting entries. Refused while the year holds a draft entry, while an earlier year with entries is open, or when a later year is already closed. It never writes what a general meeting decides to do with the result. Always ask the user before calling it.","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"fiscal_year_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The year to close. Every entry in it must be posted."}},"required":["fiscal_year_id"]},"annotations":{"readOnlyHint":false,"destructiveHint":true,"idempotentHint":false,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"reopen_fiscal_year","title":"Re-open a closed fiscal year","description":"Undoes a close that was run too early: the entries it wrote are reversed, never deleted, and the year accepts entries again. Refused once a later year is closed or holds entries of its own, because re-opening changes a result those years stand on. Always ask the user before calling it.","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"fiscal_year_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The closed year to open again."}},"required":["fiscal_year_id"]},"annotations":{"readOnlyHint":false,"destructiveHint":true,"idempotentHint":false,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}}]},"jsonrpc":"2.0","id":2}