> ## Documentation Index
> Fetch the complete documentation index at: https://docs.consile.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# API reference: Uniconta

> The 19 read-only tools in the Uniconta connector: shared parameters (row cap, server-side paging and projection), debtors, creditors, general ledger, inventory, the query/aggregate escape-hatches and the opt-in recently-added data layer.

All Uniconta tools are **read-only** and are called via `tools/call` over
`POST /uniconta/mcp`. The connector is connected with an **API key**: a dedicated
Uniconta **Server-Login User** (username + password) plus a **Company ID**, with no
OAuth. See [Forbind Uniconta](/connect/forbind-uniconta).

<Info>
  Endpoint: `https://mcp.consile.ai/uniconta/mcp`. Uniconta is its own named
  connector with only its own tools. The transport namespaces each tool as
  `uniconta__<tool>` (e.g. `uniconta__get_account_balance`); your AI assistant
  invokes these for you, so the names below are the bare tool names.
</Info>

<Note>
  This connector is **read-only by construction**: every read is the uniform
  `POST /Query/Get/{Entity}` request plus the company list, and the client never
  calls a create/update/delete or posting endpoint. Uniconta is one of our
  read-only data connectors. Your AI can read your figures but can never change,
  create or delete anything, so there are no confirm-gated tools.
</Note>

## Shared parameters

Most **list** tools accept a row cap; several support search, exact-account and
date-range filtering; and the high-volume reads (`list_inventory_items`, `query`)
add server-side sorting, paging and connector-side projection.

<ParamField path="limit" type="integer" default="50">
  Max rows to return. The connector's own input schema caps this at `1000`
  (client-side).
</ParamField>

<ParamField path="search" type="string">
  Name search. Wildcards are added automatically (`acme` becomes `*acme*`); pass your
  own `*` to control matching. Available on the debtor, creditor, G/L-account and
  inventory list tools.
</ParamField>

<ParamField path="account" type="string">
  Exact account number to filter on (debtor, creditor or G/L account, depending on
  the tool).
</ParamField>

<ParamField path="fromDate / toDate" type="string (YYYY-MM-DD)">
  Inclusive date range, e.g. `"2025-01-01"` / `"2025-12-31"`. Available on the
  invoice, transaction and posting list tools.
</ParamField>

<ParamField path="offset" type="integer">
  Rows to skip SERVER-side before the page is returned (maps to Uniconta's `Skip`).
  Use with `limit` and follow the result's `nextOffset` to page. Available on
  `list_inventory_items`, `list_inventory_transactions` and `query`.
</ParamField>

<ParamField path="fields" type="string[]">
  Return ONLY these properties per row (connector-side projection that trims the
  payload on wide entities). Available on `list_inventory_items` and `query`. Custom
  fields only exist on the `…ClientUser` entity variants.
</ParamField>

### Result shape

A plain list result is `{ entity, count, total, items: [...] }`, where `total` is
the full row count before the `limit` cap and `count` is the number of rows
returned. When a tool runs a **server-side sort or page** it fetches only one page,
so the full count is unknown: `total` is omitted and the result carries
`truncated: true` on a full page. `offset` and `nextOffset` are added only when the
request itself passed an `offset`; a sort-only read (no `offset`) returns
`truncated: true` on a full page without any cursor. A `fields` projection that names
a property present in no returned row echoes it in `unknownFields`.

***

## Companies

### list\_companies

List the Uniconta companies the connected Server-Login User can access
(`CompanyId`, name, CVR/registration number, country). **Arguments:** none. Returns
`{ count, companies: [...] }`.

***

## Debtors (customers)

### list\_debtors

List debtors (customers) with account, name, address, currency, balance
(`CurBalance`), overdue and credit limit.
<ParamField path="search" type="string">Name search (wildcards added automatically).</ParamField>
<ParamField path="account" type="string">Exact debtor account number.</ParamField>
<ParamField path="cvr" type="string">CVR / registration number (`CompanyRegNo`).</ParamField>

<ParamField path="limit" type="integer" default="50" />

### list\_debtor\_open\_items

Open (unpaid) debtor items (accounts-receivable / aging view): account, voucher,
invoice, due date and `AmountOpen` (outstanding).
<ParamField path="account" type="string">Exact debtor account number.</ParamField>

<ParamField path="limit" type="integer" default="50" />

### list\_debtor\_invoices

Issued customer invoices (debitorfakturaer): `InvoiceNumber`, account, dates,
net/VAT/total amounts and `Paid` flag.
<ParamField path="account" type="string">Exact debtor account number.</ParamField>
<ParamField path="fromDate" type="string (YYYY-MM-DD)">From date; pairs with `toDate` as a range.</ParamField>

<ParamField path="toDate" type="string (YYYY-MM-DD)" />

<ParamField path="limit" type="integer" default="50" />

### list\_debtor\_orders

Sales orders (salgsordrer): `OrderNumber`, account, name, amounts and status.
<ParamField path="account" type="string">Exact debtor account number.</ParamField>

<ParamField path="limit" type="integer" default="50" />

### list\_debtor\_transactions

A debtor's posted ledger movements (debitorposteringer): date, voucher, invoice,
amount and text. Read from the central `GLTransClient` table filtered on `DCAccount`.
For the unpaid/overdue view with due dates and outstanding amounts use
`list_debtor_open_items` instead.
<ParamField path="account" type="string">Exact debtor account number (matched on `DCAccount`).</ParamField>

<ParamField path="fromDate" type="string (YYYY-MM-DD)" />

<ParamField path="toDate" type="string (YYYY-MM-DD)" />

<ParamField path="limit" type="integer" default="50" />

***

## Creditors (suppliers)

### list\_creditors

Creditors (suppliers) for accounts-payable / spend questions: account, name,
currency, balance, overdue and payment method.
<ParamField path="search" type="string">Name search (wildcards added automatically).</ParamField>
<ParamField path="account" type="string">Exact creditor account number.</ParamField>

<ParamField path="limit" type="integer" default="50" />

### list\_creditor\_open\_items

Open (unpaid) creditor items (accounts-payable view): account, voucher, due
date and outstanding amount.
<ParamField path="account" type="string">Exact creditor account number.</ParamField>

<ParamField path="limit" type="integer" default="50" />

### list\_creditor\_transactions

A creditor's posted ledger movements (kreditorposteringer): date, voucher, invoice,
amount and text. Read from the central `GLTransClient` table filtered on `DCAccount`.
For the unpaid/overdue view use `list_creditor_open_items` instead.
<ParamField path="account" type="string">Exact creditor account number (matched on `DCAccount`).</ParamField>

<ParamField path="fromDate" type="string (YYYY-MM-DD)" />

<ParamField path="toDate" type="string (YYYY-MM-DD)" />

<ParamField path="limit" type="integer" default="50" />

***

## Finance / general ledger

### list\_gl\_accounts

The chart of accounts (kontoplan): `Account`, `Name`, `AccountType`, `Balance` and
this-year / last-year figures.
<ParamField path="search" type="string">Account name search (wildcards added automatically).</ParamField>
<ParamField path="account" type="string">Exact G/L account number.</ParamField>

<ParamField path="limit" type="integer" default="50" />

### get\_account\_balance

Read **one** G/L account's balance and this-year figures by account number: the
direct "balance of account X" answer. Returns the single matching account row, or
`null` if no account matches.
<ParamField path="account" type="string" required>G/L account number, e.g. `"1010"`.</ParamField>

### list\_gl\_transactions

General-ledger postings (finansposteringer): date, account, voucher, text, amount,
VAT and transaction type.
<ParamField path="account" type="string">Exact G/L account number.</ParamField>

<ParamField path="fromDate" type="string (YYYY-MM-DD)" />

<ParamField path="toDate" type="string (YYYY-MM-DD)" />

<ParamField path="limit" type="integer" default="50" />

### list\_vat\_codes

VAT / moms codes with rates (`Vat`, `Name`, `Rate`, `Account`, `VatType`), needed
to interpret VAT on invoices and postings.

<ParamField path="limit" type="integer" default="50" />

***

## Inventory (products)

### list\_inventory\_items

Products / inventory items (varer): `Item`, `Name`, prices (sales/cost/purchase),
unit, group, EAN and quantity on stock. Optionally sort server-side (fetches only the
top-N, not the whole catalogue), page with `offset`, trim wide rows with `fields`, and
set `includeCustomFields` to read the `InvItemClientUser` variant so the company's own
custom/user-defined fields come along. Uniconta stores no creation date on items, so
"newest created product" is not answerable here (use `list_recently_added_items`).
<ParamField path="search" type="string">Product name search (wildcards added automatically).</ParamField>
<ParamField path="item" type="string">Exact item number.</ParamField>
<ParamField path="group" type="string">Exact product group code.</ParamField>

<ParamField path="includeCustomFields" type="boolean" default="false">
  Read the `InvItemClientUser` entity variant so the company's custom/user-defined
  item fields are included in each row (they are absent on the base entity).
</ParamField>

<ParamField path="sortBy" type="enum">
  One of `item`, `name`, `sales_price`, `cost_price`, `quantity`, `last_movement`.
  Sorts server-side and returns only the top-N (per `limit`). Uniconta has no item
  creation date, so `last_movement` is the date of the last stock movement.
</ParamField>

<ParamField path="sortDescending" type="boolean" default="true">
  `true` = highest/newest first (default); `false` = ascending.
</ParamField>

<ParamField path="limit" type="integer" default="50" />

<ParamField path="offset" type="integer">Server-side paging (follow `nextOffset`).</ParamField>
<ParamField path="fields" type="string[]">Return only these properties per row.</ParamField>

### list\_product\_groups

Inventory product groups (`Group`, `Name`) used to categorise items.

<ParamField path="limit" type="integer" default="50" />

### list\_inventory\_transactions

Inventory postings / stock movements (lagerposteringer) from `InvTransClient`: `Item`,
`ItemName`, `Date`, `Qty` (NEGATIVE on a sale), `DCAccount` (the debtor/creditor on
the line), `AccountName`, `InvoiceNumber`, `NetAmount` and `MovementType`. This is how
you read the actual sales lines for an item (qty \< 0) with their invoice date and
customer. To count units sold in a product group, first get the item numbers via
`list_inventory_items` (`group=…`), then call this filtered to those items plus the
date range and sum the negative `Qty`.

<ParamField path="item" type="string">
  Item number (exact). Multiple via Uniconta list syntax, e.g. `"1001;1002;1003"`.
</ParamField>

<ParamField path="account" type="string">Debtor/creditor account on the line (`DCAccount`).</ParamField>

<ParamField path="fromDate" type="string (YYYY-MM-DD)" />

<ParamField path="toDate" type="string (YYYY-MM-DD)" />

<ParamField path="limit" type="integer" default="50" />

<ParamField path="offset" type="integer">Server-side paging (follow `nextOffset`).</ParamField>

***

## Advanced

### query

The read-only escape-hatch: fetch rows for **any** Uniconta Query entity with raw
filters. Use it for entities not covered by a dedicated tool (e.g. `"ProjectClient"`).
Read-only by construction: it only ever issues `POST /Query/Get/{entity}`, never a
write. Optionally sort server-side via `orderBy` (returns only the top-N per `limit`),
page with `offset`, and trim wide rows with `fields`. Custom/user-defined fields are
only returned, and only filterable, on the `…ClientUser` entity variants (e.g.
`InvItemClientUser`); on the base entity a filter on a custom field is silently ignored.
For per-group totals across a whole table, prefer `aggregate`.

<ParamField path="entity" type="string" required>
  Uniconta entity / table name, e.g. `"DebtorClient"`, `"GLTransClient"`. Use the
  `…ClientUser` variant (e.g. `"InvItemClientUser"`) to include custom fields.
</ParamField>

<ParamField path="filters" type="array" default="[]">
  Uniconta query filters; empty means all rows. Each filter is
  `{ "PropertyName": string, "FilterValue": string }`. `FilterValue` can be exact,
  a wildcard (`*abc*`), a range (`a..b`) or a list (`a;b;c`).
</ParamField>

<ParamField path="orderBy" type="string">Property to sort by server-side, e.g. `"Item"` or `"Date"`.</ParamField>
<ParamField path="descending" type="boolean" default="true">When `orderBy` is set: `true` = descending (default), `false` = ascending.</ParamField>

<ParamField path="limit" type="integer" default="50" />

<ParamField path="offset" type="integer">Server-side paging (follow `nextOffset`).</ParamField>
<ParamField path="fields" type="string[]">Return only these properties per row.</ParamField>

### aggregate

Group and sum **any** Uniconta Query entity inside the connector. It pages through all
matching rows server-side (1000 rows/page, up to 50 pages, roughly 50,000 rows) and
returns ONLY the per-group totals, e.g. contribution margin per product group across a
17k-item catalogue in one call. Uniconta has no server-side aggregation, so this is the
sanctioned way past the per-call row limit. Pure pass-through: rows are folded into the
running totals and discarded, nothing is stored. It rejects groupings over 1000 groups,
and if the result says `truncated: true` you should narrow the filters or date range
rather than retry.

<ParamField path="entity" type="string" required>
  Uniconta Query entity, e.g. `"InvTransClient"` or `"InvItemClientUser"` (the
  `…ClientUser` variant is required for custom/user-defined fields).
</ParamField>

<ParamField path="filters" type="array" default="[]">Filters applied BEFORE aggregating; empty means all rows.</ParamField>
<ParamField path="groupBy" type="string[]" default="[]">Properties to group by (max 3), e.g. `["Group"]`. Empty means one grand-total row.</ParamField>

<ParamField path="sum" type="string[]" default="[]">
  Numeric properties to sum per group (max 10). Unparseable values are skipped and
  counted in the result's `nonNumeric` tally (never summed as 0).
</ParamField>

<ParamField path="dateField" type="string" default="Date">Property the `fromDate`/`toDate` range filters on.</ParamField>

<ParamField path="fromDate" type="string (YYYY-MM-DD)" />

<ParamField path="toDate" type="string (YYYY-MM-DD)" />

<ParamField path="orderBy" type="string">Stable sort key while paging, recommended on large tables so `Skip`-based pages do not overlap or miss rows.</ParamField>

Returns `{ entity, groupCount, rowsScanned, pages, truncated, groups: [{ key, count, sums }] }`. `nonNumeric` is included only when it is non-empty, and there is no `groupBy` key in the result.

***

## Opt-in data layer

### list\_recently\_added\_items

List the inventory items Consile saw appear **most recently** (newest first). Uniconta
stores no item creation date, so this is backed by Consile's **opt-in** data layer
`uniconta.first_seen`, which the tenant must enable in the portal (**Konto, Datalag**).
Timestamps are "first seen by Consile after opt-in", not Uniconta creation dates, so
items that existed before opt-in share the initial baseline. With the data layer not
enabled the tool returns a structured `data_layer_not_enabled` hint (never data) so
your AI can point you to the portal toggle.
<ParamField path="since" type="string (ISO)">Only items first seen on/after this date, e.g. `"2026-01-01"`.</ParamField>

<ParamField path="limit" type="integer" default="50" />

***

## Code examples

<CodeGroup>
  ```json Request: get_account_balance theme={null}
  {
    "name": "uniconta__get_account_balance",
    "arguments": { "account": "1010" }
  }
  ```

  ```json Request: list_debtor_open_items theme={null}
  {
    "name": "uniconta__list_debtor_open_items",
    "arguments": { "account": "10100", "limit": 100 }
  }
  ```

  ```json Request: aggregate (contribution margin per group) theme={null}
  {
    "name": "uniconta__aggregate",
    "arguments": {
      "entity": "InvTransClient",
      "groupBy": ["Item"],
      "sum": ["Qty", "NetAmount"],
      "fromDate": "2026-01-01",
      "toDate": "2026-12-31"
    }
  }
  ```

  ```json Request: query (escape-hatch) theme={null}
  {
    "name": "uniconta__query",
    "arguments": {
      "entity": "GLTransClient",
      "filters": [{ "PropertyName": "Date", "FilterValue": "2025-01-01..2025-12-31" }],
      "orderBy": "Date",
      "limit": 200
    }
  }
  ```
</CodeGroup>

<Note>
  This connector vaults the Server-Login User (username + password) and Company ID
  with **no upstream validation at connect time**, so an invalid credential, a user
  that is not a Server-Login User, or a wrong Company ID surfaces here as a "reconnect
  required" error on the first call rather than at connect. Each upstream call has a
  15-second timeout, and the session JWT is a 1-hour artefact minted per tool call and
  never stored. See [Errors & limits](/developers/errors-and-limits).
</Note>
