Skip to main content
e-conomic is a read and guardrailed-write connector, called via tools/call over POST /economic/mcp. The connector is connected with a static grant token (see Forbind e-conomic).
Endpoint: https://mcp.consile.ai/economic/mcp. e-conomic is its own named connector with only its own tools. Each tool is exposed as economic__<tool> (e.g. economic__list_customers); the bare names are used here for readability.The connector is multi-instance: each additional e-conomic agreement (portal) the customer adds is served on its own endpoint, e.g. https://mcp.consile.ai/economic-2/mcp, with tools named economic-2__<tool>. Each portal uses only its own agreement’s grant.Besides the connector tools, tools/list on every e-conomic endpoint includes the unprefixed system tool connect_account (no arguments). It returns a link, valid for 10 minutes, that the user opens in the browser to connect (or reconnect) that endpoint’s agreement.

Shared list parameters

The list tools (those returning a collection) accept e-conomic’s pagination, filter and sort parameters:
integer
default:"20"
Rows per page, 1 to 1000.
integer
default:"0"
0-based page index to skip to.
string
e-conomic filter expression, e.g. name$like:*acme* or date$gte:2025-01-01$and:date$lte:2025-12-31.
string
Sort expression, e.g. name (asc) or -date (desc); sortable fields only.
A list result is shaped as { items: [...], pagination: { results, pageSize, skipPages, hasMore } }. The journal tools (list_journals, list_journal_entries) return { items, pagination: { pageSize, skipPages, hasMore } }. There is no total count, and hasMore is true when a full page came back. Their filter and sort accept only the fields listed under Journals.
Not every list tool takes all four. list_accounting_years and list_vat_accounts accept only pagesize / skippages (no filter / sort); list_accounting_periods and list_year_account_totals take a required year plus pagesize / skippages; list_account_entries takes accountNumber, year, pagesize, skippages and filter but not sort. list_journals filters and sorts only on number; list_journal_entries filters and sorts only on the fields listed in its section. The single-resource tools (get_*, download_invoice_pdf) take their own required arguments instead.

Receivables & cash-flow

get_invoice_totals

Accounts-receivable summary in one call: drafts vs booked, booked unpaid (split overdue / not overdue) and paid amounts. Arguments: none.

list_invoices_overdue

Booked invoices past their due date with an outstanding balance. Arguments: shared list parameters.

list_customers

Customers (debtors) with name, currency, balance (outstanding), dueAmount (overdue), payment terms, group and VAT zone. Arguments: shared list parameters (use filter to search).

get_customer

One customer by number, including balance and dueAmount.
integer
required
The customer (debtor) number.

get_customer_outstanding

Per-customer receivables snapshot for dunning: the customer’s balance and dueAmount plus booked-invoice totals split into unpaid and unpaid-overdue. Combine with list_invoices_overdue (filter customer.customerNumber$eq:<n>) for the individual invoices.
integer
required
The customer (debtor) number.
object
customerNumber, name, currency, email, balance, dueAmount.
object
netAmountInBaseCurrency, grossRemainderInBaseCurrency, invoiceCount, minDate, maxDate.
object
Same fields, overdue invoices only.

Invoices

list_booked_invoices

Booked (final, legal) invoices with bookedInvoiceNumber, dates, net/gross/VAT amounts, remainder (outstanding) and customer. Arguments: shared list parameters (filter by date range or customer).

get_booked_invoice

One booked invoice including its line items (description, quantity, prices, VAT).
integer
required
The booked invoice number.

download_invoice_pdf

Download a booked invoice as a PDF, returned base64-encoded in pdfBase64 (drafts have no PDF; book the invoice first). The payload is large. In a plain chat the base64 cannot become a file attachment, so the user downloads the PDF in e-conomic instead. Use the tool from an agent that can decode and save binary data.
integer
required
integer
string
application/pdf.
string
The PDF bytes, base64-encoded.

list_draft_invoices

Draft (unbooked) invoices with no ledger effect yet. Arguments: shared list parameters.

Accounting

list_chart_of_accounts

Chart of accounts with live balances. Each row carries accountNumber, name, accountType, balance and debitCredit. Arguments: shared list parameters.

list_year_account_totals

All-account totals for an accounting year (one row per account). Join each row’s accountType to build P&L / balance-sheet lines.
string
required
Accounting year as e-conomic returns it, e.g. "2024".
integer
default:"20"
integer
default:"0"

get_account_year_total

Balance/movement of one account for a full accounting year. Answers “balance of account X in year Y”.
integer
required
Ledger account number, e.g. 1010.
string
required

list_accounting_years

Fiscal years with fromDate / toDate and the year string. Arguments: pagesize / skippages.

list_accounting_periods

Periods of an accounting year (periodNumber, fromDate, toDate). Period numbers are not necessarily 1-12.
string
required
integer
default:"20"
integer
default:"0"

list_account_entries

Posted (booked) general-ledger entries for one account in an accounting year (an account statement). Always scoped by account and year.
integer
required
string
required
integer
default:"20"
integer
default:"0"
string

Journals (kassekladde)

list_journals

The agreement’s journals with number, name, voucher-number settings, default contra accounts and accepted entry types. Use it to find the journalNumber the entry tools need. Arguments: pagesize, skippages, filter, sort. Filter and sort work on number only; match journal names client-side.

list_journal_entries

Unbooked draft entries across all journals. This is where to find entries before correcting or booking them; booked entries are read with list_account_entries. Arguments: pagesize, skippages, filter, sort.
  • filter works only on journalNumber, entryNumber, voucherNumber, date, accountNumber, contraAccountNumber, currency, projectNumber, customerNumber, supplierNumber and entryTypeNumber (2 = customerPayment, 3 = supplierInvoice, 4 = supplierPayment, 5 = financeVoucher, 10 = manualCustomerInvoice). Example: journalNumber$eq:1$and:date$gte:2026-01-01.
  • Text and amount are not filterable. Narrow the query and match those client-side on the returned rows.
  • sort works on entryNumber, entryTypeNumber, voucherNumber or journalNumber.

Products & suppliers

list_products

Products with productNumber, name, salesPrice, costPrice and group. Arguments: shared list parameters.

list_suppliers

Suppliers (creditors) with number, name, currency, payment terms, VAT zone and group, for accounts-payable / spend questions. Arguments: shared list parameters.

Lookups (reference numbers for writes)

Most of these return reference numbers that the write tools take (create_customer, update_customer, create_draft_invoice, update_draft_invoice, create_credit_note), and the connector never auto-selects them. A customer or invoice write takes its VAT zone from list_vat_zones (vatZoneNumber). list_vat_accounts returns the VAT codes that create_journal_entries and update_journal_entries take as vatCode / contraVatCode. Journal entries take accountNumber / contraAccountNumber from list_chart_of_accounts and journalNumber from list_journals. The unitNumber from list_units is optional on invoice lines.

list_vat_accounts

VAT codes with rates (vatCode, name, ratePercentage, account, vatType). Arguments: pagesize / skippages.

list_customer_contacts

Contact persons on one customer (customerContactNumber, name, email, phone, eInvoiceId, notes, emailNotifications). The customer card’s “Deres reference” and “Attention” point at these numbers; pass one to update_customer. Check here before creating a contact to avoid duplicates. Arguments: customerNumber (required) plus the shared list parameters.

list_delivery_locations

Delivery locations on one customer (deliveryLocationNumber, address, postalCode, city, country, termsOfDelivery, barred). Pass a deliveryLocationNumber to update_customer to make it the default delivery address. Arguments: customerNumber (required) plus the shared list parameters.

list_customer_groups

Customer (debtor) groups. customerGroupNumber is required to create a customer. Arguments: shared list parameters.

list_payment_terms

Payment terms. paymentTermsNumber is required for a customer and a draft invoice. Arguments: shared list parameters.

list_vat_zones

VAT zones (domestic / EU / world). vatZoneNumber is required for a customer and for an invoice recipient. Arguments: shared list parameters.

list_layouts

Invoice / document layouts. layoutNumber is required for a customer and a draft invoice. Arguments: shared list parameters.

list_units

Units (e.g. hours or pieces) for use on invoice lines. Arguments: shared list parameters.

Support

validate_connection

Connectivity/credential health check: an authenticated request to e-conomic. Use it after connecting and to detect a revoked grant. Arguments: none.

Write safety: guardrail model

The twelve write tools share one confirmation model. Read tools are annotated readOnlyHint: true, destructiveHint: false, openWorldHint: false. Write tools carry readOnlyHint: false, destructiveHint: true and openWorldHint: false; idempotentHint is true on update_customer, update_draft_invoice, update_journal_entries and delete_journal_entry and false on the rest.
  1. Every write is preview-first. A call without confirm: true never changes anything. Tools that change, copy, delete or book an existing record look it up first, so a dry-run can already fail with a read error (e.g. a 404 for a wrong number). Otherwise you get a preview of the exact request and nothing is written.
  2. confirm: true is required to apply, with no exceptions. Re-run the identical call with confirm: true (for book_journal_entries, also pass expectedState). See The confirm argument.
  3. Sales documents are never booked or sent. Invoices and credit notes are created and edited as drafts only. There is no tool that books or sends them.
  4. Journal booking has its own gate. book_journal_entries books only the explicit entry numbers you pass (max 50 per call, never the whole journal), and the confirming call must echo the preview’s expectedState. If any entry changed in between, nothing is booked. Booking is irreversible.
  5. Deletion is limited to one unbooked journal entry per call (delete_journal_entry). Booked entries and booked invoices cannot be edited or deleted; corrections are new entries or a credit note.
  6. Updates change only the fields you pass. update_customer, update_draft_invoice and update_journal_entries keep every field you do not pass. The confirming call applies your changes to the record as it is at that moment.
  7. duplicate_invoice and a reversing create_credit_note create a new draft. The source invoice is only read, never changed, and e-conomic recalculates the amounts on the new draft.
These are safety defaults built into the e-conomic tools. See Handlinger & guardrails for the policy across connectors.

Preview shape

When a write is not confirmed (confirm omitted or false), the tool returns this as a normal (non-error) tool result instead of writing to e-conomic:
string
POST, PUT or DELETE. A DELETE preview (delete_journal_entry) has method and path but no body.
object
Only on book_journal_entries: { expectedState }, which the confirming call sends back as expectedState. Treat the value as an opaque string. This preview also carries its own confirmHint.

Write tools (12 guardrailed)

Write tools change data in e-conomic. Every one is preview-first: without confirm: true you get a preview and nothing is changed. Invoices and credit notes stay drafts. Only book_journal_entries books, and only the journal entries you confirm.

create_customer

Create a new customer (debtor). Requires a name, a currency and the four reference numbers (discover them via the lookup tools).
string
required
Customer (company) name.
string
required
ISO 4217 code, e.g. "DKK".
integer
required
From list_customer_groups.
integer
required
From list_payment_terms.
integer
required
From list_vat_zones.
integer
required
From list_layouts.
integer
Optional; e-conomic auto-assigns one if omitted.
string
Email address (validated as a single email).
string
string
string
string
string
string
CVR / company registration number.
string
string
object
Optional. Created as a delivery location on the new customer and set as its default.
object
Optional. Created on the new customer and set as its “Deres reference”; alsoAttention also sets it as “Attention”.
boolean
Set true to apply; omit for a dry-run preview.
With deliveryAddress or contactPerson the preview lists every planned call in order. If a later step fails, the response states exactly what was already created and with which numbers. Nothing is rolled back. Requires confirmation: always.

update_customer

Update an existing customer. Only the fields you pass are changed; fields you omit are preserved. The currency cannot be changed.
integer
required
The customer to update.
string
string
string
string
string
string
string
string
string
string
integer
integer
integer
integer
integer
”Deres reference”, from list_customer_contacts.
integer
”Attention”, from list_customer_contacts.
integer
Default delivery location, from list_delivery_locations.
integer
”Vores reference” (the responsible employee’s employee number).
boolean
Set true to apply; omit for a dry-run preview.
Requires confirmation: always.

create_customer_contact

Add a contact person to an existing customer.
integer
required
The customer.
string
required
Contact name.
string
string
string
string
E-invoicing id (EAN/GLN), if any.
boolean
Also set as “Deres reference” in the same confirmation.
boolean
Also set as “Attention” in the same confirmation.
boolean
Set true to apply; omit for a dry-run preview.
Not idempotent: a second call creates a second contact. Requires confirmation: always.

create_delivery_location

Add a delivery address to an existing customer.
integer
required
The customer.
string
required
string
required
string
required
string
string
Terms of delivery.
boolean
Also make it the customer’s default delivery location in the same confirmation.
boolean
Set true to apply; omit for a dry-run preview.
Not idempotent: a second call creates a second location. Requires confirmation: always.

create_draft_invoice

Create a draft (unbooked) invoice with no ledger effect. No tool books it; the customer books it in e-conomic.
integer
required
The customer to invoice.
string
required
ISO 4217 code.
integer
required
From list_payment_terms.
integer
required
From list_layouts.
string
required
Invoice recipient name.
integer
required
Recipient VAT zone (from list_vat_zones).
object[]
required
At least one line. Each: productNumber (string, from list_products), quantity (greater than 0), unitNetPrice, description?, unitNumber? (from list_units), discountPercentage? (0-100).
string
Invoice date YYYY-MM-DD (defaults to today).
string
Due date YYYY-MM-DD (required if the payment terms type is dueDate).
string
string
string
boolean
Set true to apply; omit for a dry-run preview.
Requires confirmation: always. On confirm, e-conomic returns the new draftInvoiceNumber and the calculated net/gross/VAT amounts.

update_draft_invoice

Update an existing draft invoice. Only the fields you pass are changed. Lines are kept unless you pass replaceLines. Booked invoices cannot be edited (use create_credit_note). If the draft would end up with no lines, the call fails with a message asking for replaceLines.
integer
required
The draft invoice to update.
string
YYYY-MM-DD.
string
YYYY-MM-DD.
integer
Re-target the draft to a different customer.
integer
integer
string
integer
string
string
string
object[]
If set, replaces the draft’s lines entirely with these (same line shape as create_draft_invoice).
boolean
Set true to apply; omit for a dry-run preview.
Requires confirmation: always.

duplicate_invoice

Create a new draft invoice by copying an existing booked or draft invoice, then optionally overriding the customer, dates, notes or replacing the lines. e-conomic recalculates the amounts on the copy. The copy keeps the source invoice’s date and dueDate unless you pass date / dueDate; pass today’s date to avoid backdating the new draft. If the source has no copyable lines, the call fails with a message asking for replaceLines.
string
required
booked or draft: where to copy from.
integer
required
The bookedInvoiceNumber or draftInvoiceNumber to copy from.
integer
Re-target the copy to a different customer.
string
Override the invoice date (YYYY-MM-DD).
string
Override the due date (YYYY-MM-DD).
string
string
string
object[]
If set, replaces the copied lines entirely with these (same line shape as create_draft_invoice).
boolean
Set true to apply; omit for a dry-run preview.
Requires confirmation: always.

create_credit_note

Create a draft credit note: an invoice whose lines have negative quantities. The result is always unbooked.
string
required
booked or draft reverses that invoice and requires invoiceNumber. scratch builds the note from lines.
integer
Invoice to reverse (source booked / draft).
object[]
At least one line. Required for scratch; when reversing, it replaces the copied lines (e.g. for a partial credit). Each line: productNumber, quantity (positive; the tool negates it), unitNetPrice (0 or more), description?, unitNumber?, discountPercentage? (0-100).
integer
Required for scratch; overrides the customer when reversing.
string
Required for scratch.
integer
Required for scratch.
integer
Required for scratch.
string
Required for scratch.
integer
Required for scratch.
string
YYYY-MM-DD. Defaults to today, also when reversing (the source invoice’s date is not copied).
string
string
string
boolean
Set true to apply; omit for a dry-run preview.
Rules:
  • Reversing negates every copied line.
  • A source that already has negative lines (a credit note) is refused.
  • Every resulting line must be negative with a non-negative unit price, or nothing is created.
  • A scratch call missing a required field fails with a message naming the missing fields (Credit note from scratch requires: …).
Requires confirmation: always.

create_journal_entries

Create unbooked draft entries in a journal. Nothing is booked.
integer
required
From list_journals.
object[]
required
1-50 entries. Each entry:
  • required: type (financeVoucher, customerPayment, supplierInvoice, supplierPayment or manualCustomerInvoice), date (YYYY-MM-DD), amount (signed: positive = debit, negative = credit), currency (ISO 4217)
  • optional: accountNumber, contraAccountNumber, vatCode, contraVatCode, text (max 250 characters), customerNumber, supplierNumber, customerInvoiceNumber, supplierInvoiceNumber (string), dueDate, voucherNumber (omit to use the journal’s next number)
boolean
Set true to apply; omit for a dry-run preview.
The preview summarises the count per type and the totals per currency. Returns { created }. Requires confirmation: always.

update_journal_entries

Update unbooked draft entries. Only the fields you pass are changed. Booked entries cannot be changed; post a counter-entry instead.
object[]
required
1-50 patches: entryNumber plus the fields to change (same fields as create_journal_entries, all optional).
boolean
Set true to apply; omit for a dry-run preview.
Returns { updated: [entryNumber, ...] }. See rule 6 above. Requires confirmation: always.

delete_journal_entry

Delete one unbooked draft entry. The entry is fetched first and described in the preview (type, amount, currency, date, text). A wrong or already booked number fails in the preview call. Booked entries cannot be deleted.
integer
required
The draft entry to delete.
boolean
Set true to apply; omit for a dry-run preview.
Returns { deleted }. Requires confirmation: always.

book_journal_entries

Book draft entries to the ledger. This is irreversible: booked entries cannot be edited or deleted, only countered with new entries.
integer
required
The journal the entries belong to.
integer[]
required
1-50 exact draft entry numbers (duplicates are ignored).
string
Copy preview.state.expectedState from the preview. Required together with confirm: true.
boolean
Set true to book; omit for a dry-run preview.
Flow:
  1. Call without confirm. Every number must be a draft entry in that journal; otherwise the call fails naming the numbers (Not draft entries in journal N: … This call booked nothing.). The preview lists each entry (number, type, amount, currency, date, text) with per-currency totals and returns preview.state.expectedState.
  2. Re-run with confirm: true and expectedState. Without expectedState the call is refused. If any entry changed since the preview, it fails with Entries changed since the preview: … This call booked nothing.
Returns { booked, journalNumber }. If a booking call times out or fails without a clear answer, check list_account_entries before retrying, because the entries may already be booked. Requires confirmation: always, plus expectedState.

Access levels (per user)

An account administrator chooses one of two access levels for e-conomic per user, on the portal’s Team page, or picks the exact tools under Tilpasset (custom). All levels cost the same. Uniconta has the same levels (see the Uniconta reference). Under Read only:
  • tools/list on every e-conomic endpoint omits the 12 write tools (connect_account is still listed).
  • A direct tools/call to a write tool returns a tool result with isError: true explaining that the tool is not enabled for the user. Nothing is sent to e-conomic.
  • The initialize result carries instructions telling the model the session can only read.
The level applies to all of the user’s e-conomic portals and is enforced by Consile per user; colleagues on Full access keep their write tools. Clients that cache tools/list should start a new session after a level change; a cached write tool is refused when called. A user who holds no seat on e-conomic still sees the tool list, but every tools/call is refused with a seat message (see Errors).

Errors and timeouts

Tool failures come back as a normal tool result with isError: true and one text block. Most failures carry an explanatory message: A write that fails with a timeout or an unavailable error may still have been applied in e-conomic, so check there before repeating it. See Errors & limits for the protocol-level errors and rate limits shared by all connectors.

Code examples