# Oscar API reference

> Generated by `pnpm gen:docs` from the public OpenAPI schema. The same schema as JSON: `/docs/api/openapi.json`.

The one API of Oscar, for the frontend, integrations, MCP clients and the agent.

- Version: `0.1.0`.
- Base path: `/api/`, on the domain of the Oscar app.
- Authentication: `Authorization: Bearer <API key>`. See `/docs/api/guides/authentication.md`.
- A permission names what the caller must be allowed to do in the company or the organization. `none` means any authenticated caller.
- Every error is an RFC 9457 problem with a stable `code`. See `/docs/api/guides/errors.md`.

## Operations

- `GET /api/companies/{company_id}/tax-account/balance/`: The tax account from the stored copy, with its as-of time, the access status and the notices (`companies_tax_account_balance`)
- `GET /api/companies/{company_id}/accounts/`: List accounts (`books_accounts_list`)
- `GET /api/companies/{company_id}/bank-accounts/`: List bank accounts (`books_bank_accounts_list`)
- `GET /api/companies/{company_id}/bank-transactions/`: List bank transactions (`books_bank_transactions_list`)
- `GET /api/companies/{company_id}/bank-transactions/{bank_transaction_id}/`: Get a bank transaction (`books_bank_transactions_retrieve`)
- `GET /api/companies/{company_id}/dimensions/`: List dimensions (`books_dimensions_list`)
- `GET /api/companies/{company_id}/documents/`: List document records (`books_documents_list`)
- `GET /api/companies/{company_id}/documents/{document_id}/`: Get a document record (`books_documents_retrieve`)
- `GET /api/companies/{company_id}/general-ledger/`: Get the general ledger (`books_general_ledger_retrieve`)
- `GET /api/companies/{company_id}/invoices/`: List invoices (`books_invoices_list`)
- `GET /api/companies/{company_id}/invoices/{invoice_id}/`: Get an invoice (`books_invoices_retrieve`)
- `GET /api/companies/{company_id}/open-items/`: Get the open items (`books_open_items_retrieve`)
- `GET /api/companies/{company_id}/parties/`: List parties (`books_parties_list`)
- `GET /api/companies/{company_id}/parties/{party_id}/`: Get a party (`books_parties_retrieve`)
- `GET /api/companies/{company_id}/periods/`: List periods (`books_periods_list`)
- `GET /api/companies/{company_id}/reports/balance-sheet/`: Get the balance sheet (`books_reports_balance_sheet_retrieve`)
- `GET /api/companies/{company_id}/reports/profit-and-loss/`: Get the profit and loss statement (`books_reports_profit_and_loss_retrieve`)
- `GET /api/companies/{company_id}/trial-balance/`: Get the trial balance (`books_trial_balance_retrieve`)
- `GET /api/companies/{company_id}/vat-codes/`: List VAT codes (`books_vat_codes_list`)
- `GET /api/companies/{company_id}/vat-preview/`: Preview a VAT return (`books_vat_preview_retrieve`)
- `POST /api/companies/{company_id}/invoices`: Record a draft invoice (`commands_record_invoice`)
- `POST /api/companies/{company_id}/invoices/{invoice_id}/cancel`: Cancel an issued sales invoice or a posted purchase invoice: the number is kept and a posted entry is reversed (`commands_cancel_invoice`)
- `POST /api/companies/{company_id}/invoices/{invoice_id}/issue`: Issue a sales invoice (`commands_issue_invoice`)
- `POST /api/companies/{company_id}/invoices/{invoice_id}/revise`: Revise an invoice (`commands_revise_invoice`)
- `POST /api/companies/{company_id}/parties`: Create a party (`commands_create_party`)
- `GET /api/companies/{company_id}/`: Return the company (`companies_retrieve`)
- `GET /api/companies/{company_id}/files/`: One page of the company's files, newest first (`companies_files_list`)
- `POST /api/companies/{company_id}/files/`: Upload a file and record it in the books (`companies_files_create`)
- `GET /api/companies/{company_id}/files/{file_id}/`: One file (`companies_files_retrieve`)
- `GET /api/companies/{company_id}/files/{file_id}/content/`: The bytes of the file, after the permission check (`companies_files_content`)
- `GET /api/companies/{company_id}/employees/`: One page of the employees, newest first, each with the facts of its newest employment (`companies_employees_list`)
- `GET /api/companies/{company_id}/employees/submissions/`: One page of the submissions, newest first, with their status and the reason of a refusal (`companies_employees_submissions_list`)
- `POST /api/companies/{company_id}/employees/submissions/`: Submit a new employee, a new employment, a change, a suspension or an end, for the firm to review (`companies_employees_submissions_create`)
- `GET /api/companies/{company_id}/employees/submissions/{submission_id}/`: One submission: its status, the reason of a refusal, TÖR's messages, the TÖR id once registered (`companies_employees_submissions_retrieve`)
- `GET /api/companies/{company_id}/employees/{employee_id}/`: One employee, with every employment (the TÖR id and state, the suspensions) and the absences (`companies_employees_retrieve`)
- `GET /api/companies/{company_id}/inbox/`: The private forwarding address of the company, made on the first read, and what came in (`companies_inbox_retrieve`)
- `GET /api/companies/{company_id}/inbox/emails/`: One page of the received mails, newest first: the sender, the outcome, the files, the attachments not kept (`companies_inbox_emails_list`)
- `POST /api/companies/{company_id}/inbox/rotate/`: Revoke the address at once and make a new one (`companies_inbox_rotate_create`)
- `GET /api/me/`: Return the caller (`me_retrieve`)
- `GET /api/organizations/`: One page of the visible organizations (`organizations_list`)
- `GET /api/organizations/{organization_id}/`: Return the organization (`organizations_retrieve`)
- `GET /api/organizations/{organization_id}/companies/`: One page of the companies, newest first (`organizations_companies_list`)
- `GET /api/companies/{company_id}/payroll/pay-runs/`: One page of the pay runs, newest month first, with their totals and the net pay not paid yet (`companies_payroll_pay_runs_list`)
- `GET /api/companies/{company_id}/payroll/pay-runs/{pay_run_id}/`: One pay run with every employee: the inputs, the gross and the net, the net not paid yet, the payments (`companies_payroll_pay_runs_retrieve`)

## Tax account

### The tax account from the stored copy, with its as-of time, the access status and the notices

`GET /api/companies/{company_id}/tax-account/balance/`

- Operation id: `companies_tax_account_balance`
- Permission: `books.read`

The tax account from the stored copy, with its as-of time, the access status and the notices.

Nothing is read from EMTA here: the copy is refreshed every night, after
a filing or a tax payment, and by staff. Before the first refresh every
amount is null and `access_status` is `never`.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `company_id` | path | `string` | yes |   |

**Response 200** (`application/json`) `TaxAccountBalance`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `access_status` | `"never" \| "ok" \| "rights_missing" \| "failed"` | yes | How the last refresh went: `ok`; `rights_missing`, the company has not granted `ACCOUNTING_XROAD` to OscarAI in e-MTA; `failed`; `never`, no refresh yet. * `never` - Never refreshed * `ok` - OK * `rights_missing` - Rights missing * `failed` - Failed |
| `access_error_code` | `string` | yes | The code of the last failure; empty when ok. |
| `last_attempt_at` | `string (date-time) \| null` | yes |   |
| `last_success_at` | `string (date-time) \| null` | yes |   |
| `as_of` | `string (date-time) \| null` | yes | When the stored copy was read from EMTA; null before the first read. |
| `request_date` | `string (date) \| null` | yes | The day of the balance at EMTA. |
| `total` | `string (decimal) \| null` | yes | The balance of the claims. Above zero: the company owes it. |
| `interest` | `string (decimal) \| null` | yes | The interest on the taxes not paid in time. |
| `prepayment_balance` | `string (decimal) \| null` | yes | The balance of the prepayment account (E). |
| `account_balances` | `object` | yes | The balance of each account by its EMTA code (E: the prepayment account). |
| `claims` | `array of TaxAccountClaim` | yes |   |
| `notices` | `array of TaxAccountNotice` | yes |   |
| `refresh_pending` | `boolean` | yes | A refresh is queued or running. |

## books

### List accounts

`GET /api/companies/{company_id}/accounts/`

- Operation id: `books_accounts_list`
- Permission: `books.read`

The chart of accounts, ordered by code.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `active` | query | `boolean \| null` | no | Active (true) or inactive (false) accounts only. |
| `company_id` | path | `string` | yes |   |
| `control_kind` | query | `"payable" \| "receivable" \| "suspense_payable" \| "suspense_receivable" \| "bank" \| "transit" \| "vat"` | no | Accounts with this control kind only. * `payable` - payable * `receivable` - receivable * `suspense_payable` - suspense_payable * `suspense_receivable` - suspense_receivable * `bank` - bank * `transit` - transit * `vat` - vat |
| `cursor` | query | `string` | no | The `next_cursor` of the previous page. Omit it for the first page. |
| `limit` | query | `integer` | no | The page size, 1 to 200. Default 50. |
| `search` | query | `string` | no | A code prefix, or text anywhere in the name. |
| `type` | query | `"asset" \| "liability" \| "equity" \| "income" \| "expense"` | no | Accounts of this type only. * `asset` - asset * `liability` - liability * `equity` - equity * `income` - income * `expense` - expense |

**Response 200** (`application/json`) `BooksAccountPage`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `items` | `array of BooksAccount` | yes |   |
| `next_cursor` | `string \| null` | yes | Send it back as `cursor` for the next page; null on the last page. |

**Errors**

| Status | Description |
| --- | --- |
| 400 | A parameter is not valid (`validation_error`, `invalid_payload`). |
| 401 | Not authenticated. |
| 403 | The caller lacks `books.read` (`permission_denied`) or the `read` scope (`insufficient_scope`). |
| 404 | The company, or the object, does not exist or is not visible (`not_found`). |
| 409 | The books of the company are not provisioned yet (`company_not_ready`). |
| 503 | The books are not available (`books_unavailable`). |

### List bank accounts

`GET /api/companies/{company_id}/bank-accounts/`

- Operation id: `books_bank_accounts_list`
- Permission: `books.read`

The bank feeds with their ledger account, transaction count and ledger balance. Ordered by label.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `active` | query | `boolean \| null` | no | Active (true) or inactive (false) bank accounts only. |
| `company_id` | path | `string` | yes |   |
| `cursor` | query | `string` | no | The `next_cursor` of the previous page. Omit it for the first page. |
| `limit` | query | `integer` | no | The page size, 1 to 200. Default 50. |

**Response 200** (`application/json`) `BooksBankAccountPage`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `items` | `array of BooksBankAccount` | yes |   |
| `next_cursor` | `string \| null` | yes | Send it back as `cursor` for the next page; null on the last page. |

**Errors**

| Status | Description |
| --- | --- |
| 400 | A parameter is not valid (`validation_error`, `invalid_payload`). |
| 401 | Not authenticated. |
| 403 | The caller lacks `books.read` (`permission_denied`) or the `read` scope (`insufficient_scope`). |
| 404 | The company, or the object, does not exist or is not visible (`not_found`). |
| 409 | The books of the company are not provisioned yet (`company_not_ready`). |
| 503 | The books are not available (`books_unavailable`). |

### List bank transactions

`GET /api/companies/{company_id}/bank-transactions/`

- Operation id: `books_bank_transactions_list`
- Permission: `books.read`

The bank transactions with their settlement status, derived on read. Ordered by booking date.

`has_document` and `file_ids` name the uploaded files that explain a
transaction (an upload with `bank_transaction_id`). `to_explain=true`
lists the payments to explain: money out still open that no file explains.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `bank_account_id` | query | `string` | no | Transactions of this bank account only. |
| `company_id` | path | `string` | yes |   |
| `cursor` | query | `string` | no | The `next_cursor` of the previous page. Omit it for the first page. |
| `date_from` | query | `string (date)` | no | The earliest booking date, inclusive. |
| `date_to` | query | `string (date)` | no | The latest booking date, inclusive. |
| `direction` | query | `"in" \| "out"` | no | Money in or money out only. * `in` - in * `out` - out |
| `has_document` | query | `boolean \| null` | no | Only transactions an uploaded file explains (true) or that none explains (false). |
| `limit` | query | `integer` | no | The page size, 1 to 200. Default 50. |
| `ordering` | query | `"booking_date" \| "-booking_date" \| "amount" \| "-amount" \| "counterparty" \| "-counterparty"` | no | `booking_date` (the default) is oldest first, `-booking_date` newest first. `amount` orders by the amount that moved (the absolute `total_minor`), `counterparty` by the payee (`party_name`, else `counterparty_name`) in any case. A leading `-` is descending. The id breaks ties. * `booking_date` - booking_date * `-booking_date` - -booking_date * `amount` - amount * `-amount` - -amount * `counterparty` - counterparty * `-counterparty` - -counterparty |
| `party_id` | query | `string` | no | Transactions of this party only. |
| `q` | query | `string` | no | Keywords: the transactions whose payee (`party_name`, `counterparty_name`) or details (`description`, `reference`) contain this text, in any case. Trimmed; empty is no filter. |
| `statement_id` | query | `string` | no | Transactions of this statement only. |
| `status` | query | `"unmatched" \| "part_matched" \| "matched" \| "exempted" \| "classified" \| "transfer_matched" \| "transfer_unmatched" \| "posted" \| "open"` | no | Transactions with this status; `open` is `unmatched` and `part_matched`. * `unmatched` - unmatched * `part_matched` - part_matched * `matched` - matched * `exempted` - exempted * `classified` - classified * `transfer_matched` - transfer_matched * `transfer_unmatched` - transfer_unmatched * `posted` - posted * `open` - open |
| `to_explain` | query | `boolean \| null` | no | The payments to explain (true): money out still open (`status` `open`) that no uploaded file explains. Excludes `status`, `direction` and `has_document`. |

**Response 200** (`application/json`) `BooksBankTransactionPage`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `items` | `array of BooksBankTransaction` | yes |   |
| `next_cursor` | `string \| null` | yes | Send it back as `cursor` for the next page; null on the last page. |

**Errors**

| Status | Description |
| --- | --- |
| 400 | A parameter is not valid (`validation_error`, `invalid_payload`). |
| 401 | Not authenticated. |
| 403 | The caller lacks `books.read` (`permission_denied`) or the `read` scope (`insufficient_scope`). |
| 404 | The company, or the object, does not exist or is not visible (`not_found`). |
| 409 | The books of the company are not provisioned yet (`company_not_ready`). |
| 503 | The books are not available (`books_unavailable`). |

### Get a bank transaction

`GET /api/companies/{company_id}/bank-transactions/{bank_transaction_id}/`

- Operation id: `books_bank_transactions_retrieve`
- Permission: `books.read`

One bank transaction with its source row, entries, allocations, the judgement on it, and its files.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `bank_transaction_id` | path | `string` | yes | The core ULID of the object, 26 characters. |
| `company_id` | path | `string` | yes |   |

**Response 200** (`application/json`) `BooksBankTransactionDetail`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | `string` | yes |   |
| `bank_account_id` | `string` | yes |   |
| `bank_account_label` | `string` | yes |   |
| `currency` | `string` | yes |   |
| `statement_id` | `string \| null` | yes |   |
| `external_id` | `string \| null` | yes |   |
| `booking_date` | `string (date)` | yes |   |
| `value_date` | `string (date) \| null` | yes |   |
| `direction` | `"in" \| "out"` | yes | * `in` - in * `out` - out |
| `method` | `string \| null` | yes |   |
| `amount_minor` | `integer` | yes |   |
| `fee_minor` | `integer` | yes |   |
| `total_minor` | `integer` | yes | Signed: money out is negative. |
| `orig_currency` | `string \| null` | yes |   |
| `orig_minor` | `integer \| null` | yes | The amount in `orig_currency`. |
| `bank_rate` | `string \| null` | yes | The bank's exchange rate, a decimal string. |
| `balance_after_minor` | `integer \| null` | yes |   |
| `counterparty_name` | `string \| null` | yes |   |
| `counterparty_account` | `string \| null` | yes |   |
| `counterparty_bic` | `string \| null` | yes |   |
| `description` | `string \| null` | yes |   |
| `reference` | `string \| null` | yes |   |
| `card_last4` | `string \| null` | yes |   |
| `mcc` | `string \| null` | yes |   |
| `is_internal` | `boolean` | yes |   |
| `party_id` | `string \| null` | yes |   |
| `party_name` | `string \| null` | yes |   |
| `party_source` | `"alias" \| "human" \| NullEnum` | yes | How the party was set. * `alias` - alias * `human` - human |
| `created_at` | `string (date-time)` | yes |   |
| `suspense_residual_minor` | `integer \| null` | yes | The unsettled part of the suspense line; 0 once a judgement (an exemption, a money-in class) clears it; null without one. |
| `status` | `"unmatched" \| "part_matched" \| "matched" \| "exempted" \| "classified" \| "transfer_matched" \| "transfer_unmatched" \| "posted"` | yes | * `unmatched` - unmatched * `part_matched` - part_matched * `matched` - matched * `exempted` - exempted * `classified` - classified * `transfer_matched` - transfer_matched * `transfer_unmatched` - transfer_unmatched * `posted` - posted |
| `has_document` | `boolean` | yes | True when an uploaded file explains the transaction. |
| `file_ids` | `array of string` | yes | The sqids of the uploaded files that explain it (`files/{file_id}/`). |
| `raw` | `any` | yes | The source row as the statement parser stored it. |
| `entries` | `array of BooksBankTransactionEntry` | yes |   |
| `allocations` | `array of BooksAllocation` | yes |   |
| `exemption` | `BooksExemption \| null` | yes |   |
| `money_in` | `BooksMoneyIn \| null` | yes |   |
| `transfer_match` | `BooksTransferMatch \| null` | yes |   |

**Errors**

| Status | Description |
| --- | --- |
| 400 | A parameter is not valid (`validation_error`, `invalid_payload`). |
| 401 | Not authenticated. |
| 403 | The caller lacks `books.read` (`permission_denied`) or the `read` scope (`insufficient_scope`). |
| 404 | The company, or the object, does not exist or is not visible (`not_found`). |
| 409 | The books of the company are not provisioned yet (`company_not_ready`). |
| 503 | The books are not available (`books_unavailable`). |

### List dimensions

`GET /api/companies/{company_id}/dimensions/`

- Operation id: `books_dimensions_list`
- Permission: `books.read`

The dimension axes, each with all its values. Ordered by code.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `active` | query | `boolean \| null` | no | Active (true) or inactive (false) dimensions only. |
| `company_id` | path | `string` | yes |   |
| `cursor` | query | `string` | no | The `next_cursor` of the previous page. Omit it for the first page. |
| `kind` | query | `"project" \| "grant" \| "client" \| "department" \| "other"` | no | Dimensions of this kind only. * `project` - project * `grant` - grant * `client` - client * `department` - department * `other` - other |
| `limit` | query | `integer` | no | The page size, 1 to 200. Default 50. |

**Response 200** (`application/json`) `BooksDimensionPage`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `items` | `array of BooksDimension` | yes |   |
| `next_cursor` | `string \| null` | yes | Send it back as `cursor` for the next page; null on the last page. |

**Errors**

| Status | Description |
| --- | --- |
| 400 | A parameter is not valid (`validation_error`, `invalid_payload`). |
| 401 | Not authenticated. |
| 403 | The caller lacks `books.read` (`permission_denied`) or the `read` scope (`insufficient_scope`). |
| 404 | The company, or the object, does not exist or is not visible (`not_found`). |
| 409 | The books of the company are not provisioned yet (`company_not_ready`). |
| 503 | The books are not available (`books_unavailable`). |

### List document records

`GET /api/companies/{company_id}/documents/`

- Operation id: `books_documents_list`
- Permission: `books.read`

The document records of the books. Ordered by creation; `ordering=-created_at` is newest first.

`referenced=false` lists the documents nothing in the books refers to
yet: the uploads still to book. `bank_feed=false` leaves out the
statements the bank feed stored (its JSON files), `bank_feed=true` lists
only them. `file_id` and `download_url` name the stored file.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `bank_feed` | query | `boolean \| null` | no | Only the statements the bank feed stored (true) or every document but them (false). A statement a person uploaded is never a bank feed statement. |
| `company_id` | path | `string` | yes |   |
| `cursor` | query | `string` | no | The `next_cursor` of the previous page. Omit it for the first page. |
| `kind` | query | `"invoice" \| "receipt" \| "credit_note" \| "statement" \| "contract" \| "other"` | no | Documents of this kind only. * `invoice` - invoice * `receipt` - receipt * `credit_note` - credit_note * `statement` - statement * `contract` - contract * `other` - other |
| `limit` | query | `integer` | no | The page size, 1 to 200. Default 50. |
| `ordering` | query | `"created_at" \| "-created_at"` | no | `created_at` (the default) is oldest first, `-created_at` newest first. The id breaks ties. * `created_at` - created_at * `-created_at` - -created_at |
| `received_from` | query | `string (date)` | no | The earliest received date, inclusive. Leaves out documents without one. |
| `received_to` | query | `string (date)` | no | The latest received date, inclusive. Leaves out documents without one. |
| `referenced` | query | `boolean \| null` | no | Only documents the books refer to (true: booked) or that nothing refers to yet (false: to book). |
| `sha256` | query | `string` | no | The SHA-256 of the file, lowercase hex. |

**Response 200** (`application/json`) `BooksDocumentPage`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `items` | `array of BooksDocument` | yes |   |
| `next_cursor` | `string \| null` | yes | Send it back as `cursor` for the next page; null on the last page. |

**Errors**

| Status | Description |
| --- | --- |
| 400 | A parameter is not valid (`validation_error`, `invalid_payload`). |
| 401 | Not authenticated. |
| 403 | The caller lacks `books.read` (`permission_denied`) or the `read` scope (`insufficient_scope`). |
| 404 | The company, or the object, does not exist or is not visible (`not_found`). |
| 409 | The books of the company are not provisioned yet (`company_not_ready`). |
| 503 | The books are not available (`books_unavailable`). |

### Get a document record

`GET /api/companies/{company_id}/documents/{document_id}/`

- Operation id: `books_documents_retrieve`
- Permission: `books.read`

One document record with the invoices, statements, events and VAT returns that refer to it.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `company_id` | path | `string` | yes |   |
| `document_id` | path | `string` | yes | The core ULID of the object, 26 characters. |

**Response 200** (`application/json`) `BooksDocumentDetail`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | `string` | yes |   |
| `sha256` | `string` | yes |   |
| `legacy_sha1` | `string \| null` | yes |   |
| `kind` | `"invoice" \| "receipt" \| "credit_note" \| "statement" \| "contract" \| "other"` | yes | * `invoice` - invoice * `receipt` - receipt * `credit_note` - credit_note * `statement` - statement * `contract` - contract * `other` - other |
| `filename` | `string` | yes |   |
| `media_type` | `string \| null` | yes |   |
| `size_bytes` | `integer \| null` | yes |   |
| `storage_ref` | `string \| null` | yes | The sqid of the Django document that holds the file. |
| `received_on` | `string (date) \| null` | yes |   |
| `retention_until` | `string (date) \| null` | yes |   |
| `legal_hold` | `boolean` | yes |   |
| `created_at` | `string (date-time)` | yes |   |
| `referenced` | `boolean` | yes | True when the books refer to the document (an invoice, a statement, an event, a return). |
| `file_id` | `string \| null` | yes | The sqid of the stored file (`files/{file_id}/`), or null when none is stored. |
| `download_url` | `string \| null` | yes | The API path that gives a short-lived URL of the bytes (`files/{file_id}/download/`), or null. |
| `invoices` | `array of BooksDocumentInvoice` | yes |   |
| `bank_statements` | `array of BooksDocumentStatement` | yes |   |
| `accounting_events` | `array of BooksDocumentEvent` | yes |   |
| `vat_returns` | `array of BooksDocumentVatReturn` | yes |   |

**Errors**

| Status | Description |
| --- | --- |
| 400 | A parameter is not valid (`validation_error`, `invalid_payload`). |
| 401 | Not authenticated. |
| 403 | The caller lacks `books.read` (`permission_denied`) or the `read` scope (`insufficient_scope`). |
| 404 | The company, or the object, does not exist or is not visible (`not_found`). |
| 409 | The books of the company are not provisioned yet (`company_not_ready`). |
| 503 | The books are not available (`books_unavailable`). |

### Get the general ledger

`GET /api/companies/{company_id}/general-ledger/`

- Operation id: `books_general_ledger_retrieve`
- Permission: `books.read`

The general ledger: each account with its lines and running balance, in the base currency.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `account_code` | query | `string` | no | One account only. |
| `company_id` | path | `string` | yes |   |
| `date_from` | query | `string (date)` | no | The first day of the range, inclusive. Before it is the opening balance. |
| `date_to` | query | `string (date)` | no | The last day of the range, inclusive. |

**Response 200** (`application/json`) `BooksGeneralLedger`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `base_currency` | `string` | yes | The currency of every `*_base_minor` amount: the base currency of the books. |
| `accounts` | `array of BooksLedgerAccount` | yes |   |

**Errors**

| Status | Description |
| --- | --- |
| 400 | A parameter is not valid (`validation_error`, `invalid_payload`). |
| 401 | Not authenticated. |
| 403 | The caller lacks `books.read` (`permission_denied`) or the `read` scope (`insufficient_scope`). |
| 404 | The company, or the object, does not exist or is not visible (`not_found`). |
| 409 | The books of the company are not provisioned yet (`company_not_ready`). |
| 429 | Too many expensive reads (`throttled`). |
| 503 | The books are not available (`books_unavailable`). |

### List invoices

`GET /api/companies/{company_id}/invoices/`

- Operation id: `books_invoices_list`
- Permission: `books.read`

The invoices, purchase and sales, with the header facts of their current revision and their settlement.

Oldest first by invoice date; `ordering=-invoice_date` is newest first.
`settlement` filters by `settlement_state`: `open` is unpaid or part
paid, `overdue` an open invoice due before today in the time zone of the books.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `company_id` | path | `string` | yes |   |
| `cursor` | query | `string` | no | The `next_cursor` of the previous page. Omit it for the first page. |
| `date_from` | query | `string (date)` | no | The earliest invoice date, inclusive. |
| `date_to` | query | `string (date)` | no | The latest invoice date, inclusive. |
| `direction` | query | `"purchase" \| "sales"` | no | Purchase or sales invoices only. * `purchase` - purchase * `sales` - sales |
| `external_source_prefix` | query | `string` | no | Imported invoices whose external series starts with this text: `stripe` selects every Stripe series. |
| `kind` | query | `"invoice" \| "receipt" \| "credit_note" \| "prepayment"` | no | Invoices of this kind only. * `invoice` - invoice * `receipt` - receipt * `credit_note` - credit_note * `prepayment` - prepayment |
| `limit` | query | `integer` | no | The page size, 1 to 200. Default 50. |
| `needs_review` | query | `boolean \| null` | no | Only invoices that need review (true) or that do not (false). |
| `number` | query | `string` | no | The exact invoice number. |
| `ordering` | query | `"invoice_date" \| "-invoice_date"` | no | `invoice_date` (the default) is oldest first, `-invoice_date` newest first. The id breaks ties. * `invoice_date` - invoice_date * `-invoice_date` - -invoice_date |
| `party_id` | query | `string` | no | Invoices of this party only. |
| `settlement` | query | `"unposted" \| "unpaid" \| "part_paid" \| "paid" \| "open" \| "overdue"` | no | Invoices in this settlement state; `open` is `unpaid` and `part_paid`, `overdue` is an open invoice due before today. * `unposted` - unposted * `unpaid` - unpaid * `part_paid` - part_paid * `paid` - paid * `open` - open * `overdue` - overdue |
| `state` | query | `"recorded" \| "issued" \| "posted" \| "cancelled" \| "void"` | no | Invoices in this state only. * `recorded` - recorded * `issued` - issued * `posted` - posted * `cancelled` - cancelled * `void` - void |

**Response 200** (`application/json`) `BooksInvoicePage`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `items` | `array of BooksInvoice` | yes |   |
| `next_cursor` | `string \| null` | yes | Send it back as `cursor` for the next page; null on the last page. |

**Errors**

| Status | Description |
| --- | --- |
| 400 | A parameter is not valid (`validation_error`, `invalid_payload`). |
| 401 | Not authenticated. |
| 403 | The caller lacks `books.read` (`permission_denied`) or the `read` scope (`insufficient_scope`). |
| 404 | The company, or the object, does not exist or is not visible (`not_found`). |
| 409 | The books of the company are not provisioned yet (`company_not_ready`). |
| 503 | The books are not available (`books_unavailable`). |

### Get an invoice

`GET /api/companies/{company_id}/invoices/{invoice_id}/`

- Operation id: `books_invoices_retrieve`
- Permission: `books.read`

One invoice: its current revision with lines and documents, its revisions, its entries and its settlement.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `company_id` | path | `string` | yes |   |
| `invoice_id` | path | `string` | yes | The core ULID of the object, 26 characters. |

**Response 200** (`application/json`) `BooksInvoiceDetail`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | `string` | yes |   |
| `direction` | `"purchase" \| "sales"` | yes | * `purchase` - purchase * `sales` - sales |
| `kind` | `"invoice" \| "receipt" \| "credit_note" \| "prepayment"` | yes | * `invoice` - invoice * `receipt` - receipt * `credit_note` - credit_note * `prepayment` - prepayment |
| `sign` | `integer` | yes | 1, or -1 for a credit note. |
| `state` | `"recorded" \| "issued" \| "posted" \| "cancelled" \| "void"` | yes | * `recorded` - recorded * `issued` - issued * `posted` - posted * `cancelled` - cancelled * `void` - void |
| `number` | `string \| null` | yes |   |
| `party_id` | `string` | yes |   |
| `party_name` | `string` | yes |   |
| `corrects_invoice_id` | `string \| null` | yes | The invoice a credit note corrects. |
| `origin` | `string` | yes | Who created it (`human`, `import`, ...). |
| `issued_at` | `string (date-time) \| null` | yes |   |
| `cancelled_at` | `string (date-time) \| null` | yes |   |
| `cancel_reason` | `string \| null` | yes |   |
| `created_at` | `string (date-time)` | yes |   |
| `reference_number` | `string \| null` | yes | An issued sales invoice: its Estonian reference number (viitenumber), the 7-3-1 check digit last. Null for every other invoice. |
| `external_source` | `string \| null` | yes | An imported sales invoice: the source of its external number series (`stripe`, `manual`, ...). Null for every other invoice. |
| `revision_id` | `string` | yes | The current revision. |
| `revision_no` | `integer` | yes |   |
| `invoice_date` | `string (date)` | yes |   |
| `supply_date` | `string (date) \| null` | yes |   |
| `due_date` | `string (date) \| null` | yes |   |
| `currency` | `string` | yes |   |
| `net_minor` | `integer` | yes |   |
| `tax_minor` | `integer` | yes |   |
| `gross_minor` | `integer` | yes |   |
| `prepaid_minor` | `integer` | yes |   |
| `rounding_minor` | `integer` | yes |   |
| `amount_due_minor` | `integer` | yes |   |
| `base_gross_minor` | `integer \| null` | yes | The gross amount in the base currency; null until the rate is known. |
| `base_currency` | `string` | yes | The currency of every `*_base_minor` amount: the base currency of the books. |
| `needs_review` | `boolean` | yes |   |
| `review_note` | `string \| null` | yes |   |
| `open_minor` | `integer \| null` | yes | What is still open of the posted invoice, in its currency: 0 when settled; null while not posted. |
| `settlement_state` | `"unposted" \| "unpaid" \| "part_paid" \| "paid" \| "overdue"` | yes | `unposted`, `unpaid`, `part_paid`, `paid`, or `overdue`: unpaid or part paid, due before today. |
| `posted_at` | `string (date-time) \| null` | yes | When the current revision was posted to the ledger; null while not posted. |
| `revision` | `BooksInvoiceRevision` | yes | The current revision of an invoice, with its lines and documents. |
| `revisions` | `array of BooksInvoiceRevisionSummary` | yes |   |
| `entries` | `array of BooksInvoiceEntry` | yes |   |
| `settlement` | `BooksSettlement \| null` | yes |   |
| `allocations` | `array of BooksInvoiceAllocation` | yes |   |

**Errors**

| Status | Description |
| --- | --- |
| 400 | A parameter is not valid (`validation_error`, `invalid_payload`). |
| 401 | Not authenticated. |
| 403 | The caller lacks `books.read` (`permission_denied`) or the `read` scope (`insufficient_scope`). |
| 404 | The company, or the object, does not exist or is not visible (`not_found`). |
| 409 | The books of the company are not provisioned yet (`company_not_ready`). |
| 503 | The books are not available (`books_unavailable`). |

### Get the open items

`GET /api/companies/{company_id}/open-items/`

- Operation id: `books_open_items_retrieve`
- Permission: `books.read`

Every open-item line with its residual, as of a date (`as_of`, default today), aged at that date.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `account_code` | query | `string` | no | Open items on this account only. |
| `as_of` | query | `string (date)` | no | The residuals as of this date: the lines of entries dated by it, the allocations effective by it. Default today. |
| `company_id` | path | `string` | yes |   |
| `party_id` | query | `string` | no | Open items of this party only. |

**Response 200** (`application/json`) `BooksOpenItems`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `as_of` | `string (date)` | yes |   |
| `base_currency` | `string` | yes | The currency of every `*_base_minor` amount: the base currency of the books. |
| `items` | `array of BooksOpenItem` | yes |   |

**Errors**

| Status | Description |
| --- | --- |
| 400 | A parameter is not valid (`validation_error`, `invalid_payload`). |
| 401 | Not authenticated. |
| 403 | The caller lacks `books.read` (`permission_denied`) or the `read` scope (`insufficient_scope`). |
| 404 | The company, or the object, does not exist or is not visible (`not_found`). |
| 409 | The books of the company are not provisioned yet (`company_not_ready`). |
| 429 | Too many expensive reads (`throttled`). |
| 503 | The books are not available (`books_unavailable`). |

### List parties

`GET /api/companies/{company_id}/parties/`

- Operation id: `books_parties_list`
- Permission: `books.read`

The parties, ordered by their cleaned name. Merged parties are left out unless asked for.

`roles` says what each party is to the company, from its kind, its invoices and its open purchase drafts;
`role` filters on the roles the books derive (an open draft aside), and `exclude_kind=employee` leaves out
the employees, as the list of customers and suppliers does.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `company_id` | path | `string` | yes |   |
| `cursor` | query | `string` | no | The `next_cursor` of the previous page. Omit it for the first page. |
| `exclude_kind` | query | `"supplier" \| "customer" \| "employee" \| "authority" \| "group_company" \| "other"` | no | Leave out the parties of this kind: `employee` on the list of customers and suppliers. * `supplier` - supplier * `customer` - customer * `employee` - employee * `authority` - authority * `group_company` - group_company * `other` - other |
| `external_key` | query | `string` | no | The exact key of the party in another system. |
| `include_merged` | query | `boolean \| null` | no | Include parties merged into another. Default false. |
| `include_settled_external` | query | `boolean \| null` | no | Include the parties with a key in another system (a Stripe customer) that have no open item. Default false: the list leaves them out unless it is filtered by `search`, `reg_code`, `vat_number` or `external_key`. |
| `kind` | query | `"supplier" \| "customer" \| "employee" \| "authority" \| "group_company" \| "other"` | no | Parties of this kind only. * `supplier` - supplier * `customer` - customer * `employee` - employee * `authority` - authority * `group_company` - group_company * `other` - other |
| `limit` | query | `integer` | no | The page size, 1 to 200. Default 50. |
| `reg_code` | query | `string` | no | The exact registry code. |
| `role` | query | `"supplier" \| "customer"` | no | Only the parties that play this role, as `roles` derives it from the kind and the invoices. * `supplier` - supplier * `customer` - customer |
| `search` | query | `string` | no | Text anywhere in the name, or in the cleaned matching key. |
| `vat_number` | query | `string` | no | The exact VAT number. |

**Response 200** (`application/json`) `BooksPartyPage`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `items` | `array of BooksParty` | yes |   |
| `next_cursor` | `string \| null` | yes | Send it back as `cursor` for the next page; null on the last page. |

**Errors**

| Status | Description |
| --- | --- |
| 400 | A parameter is not valid (`validation_error`, `invalid_payload`). |
| 401 | Not authenticated. |
| 403 | The caller lacks `books.read` (`permission_denied`) or the `read` scope (`insufficient_scope`). |
| 404 | The company, or the object, does not exist or is not visible (`not_found`). |
| 409 | The books of the company are not provisioned yet (`company_not_ready`). |
| 503 | The books are not available (`books_unavailable`). |

### Get a party

`GET /api/companies/{company_id}/parties/{party_id}/`

- Operation id: `books_parties_retrieve`
- Permission: `books.read`

One party with its defaults and its roles.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `company_id` | path | `string` | yes |   |
| `party_id` | path | `string` | yes | The core ULID of the object, 26 characters. |

**Response 200** (`application/json`) `BooksPartyDetail`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | `string` | yes |   |
| `name` | `string` | yes |   |
| `name_key` | `string` | yes | The cleaned matching key of the name. |
| `kind` | `"supplier" \| "customer" \| "employee" \| "authority" \| "group_company" \| "other"` | yes | * `supplier` - supplier * `customer` - customer * `employee` - employee * `authority` - authority * `group_company` - group_company * `other` - other |
| `country` | `string \| null` | yes |   |
| `vat_area` | `string \| null` | yes | `domestic`, `eu`, `non_eu`. |
| `vat_area_source` | `string \| null` | yes |   |
| `vat_number` | `string \| null` | yes |   |
| `vies_checked_at` | `string (date-time) \| null` | yes |   |
| `reg_code` | `string \| null` | yes |   |
| `expects_document` | `boolean` | yes |   |
| `is_confirmed` | `boolean` | yes |   |
| `merged_into_id` | `string \| null` | yes | The party this one was merged into. |
| `notes` | `string \| null` | yes |   |
| `created_at` | `string (date-time)` | yes |   |
| `external_key` | `string \| null` | yes | The key of the party in another system, for example a Stripe customer. |
| `private_persons` | `boolean` | yes | The party pools private persons (card buyers): the KMD INF annex leaves it out. |
| `address` | `string \| null` | yes | The postal address printed on an invoice, one or more lines. |
| `email` | `string \| null` | yes | The email address of the party. |
| `phone` | `string \| null` | yes | The phone number of the party. |
| `roles` | `array of "supplier" \| "customer"` | yes | What the party is to the company: `supplier` when its kind is supplier or it has a purchase invoice (or an open purchase draft), `customer` when its kind is customer or it has a sales invoice. Void invoices do not count. Empty for a party of another kind with no invoice. |
| `defaults` | `BooksPartyDefaults \| null` | yes |   |

**Errors**

| Status | Description |
| --- | --- |
| 400 | A parameter is not valid (`validation_error`, `invalid_payload`). |
| 401 | Not authenticated. |
| 403 | The caller lacks `books.read` (`permission_denied`) or the `read` scope (`insufficient_scope`). |
| 404 | The company, or the object, does not exist or is not visible (`not_found`). |
| 409 | The books of the company are not provisioned yet (`company_not_ready`). |
| 503 | The books are not available (`books_unavailable`). |

### List periods

`GET /api/companies/{company_id}/periods/`

- Operation id: `books_periods_list`
- Permission: `books.read`

The accounting periods with their fiscal year, ordered by start date.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `company_id` | path | `string` | yes |   |
| `cursor` | query | `string` | no | The `next_cursor` of the previous page. Omit it for the first page. |
| `date` | query | `string (date)` | no | The period that contains this date. |
| `fiscal_year` | query | `string` | no | The fiscal year label (`2026`). |
| `limit` | query | `integer` | no | The page size, 1 to 200. Default 50. |
| `state` | query | `"open" \| "soft_closed" \| "locked"` | no | Periods in this state only. * `open` - open * `soft_closed` - soft_closed * `locked` - locked |

**Response 200** (`application/json`) `BooksPeriodPage`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `items` | `array of BooksPeriod` | yes |   |
| `next_cursor` | `string \| null` | yes | Send it back as `cursor` for the next page; null on the last page. |

**Errors**

| Status | Description |
| --- | --- |
| 400 | A parameter is not valid (`validation_error`, `invalid_payload`). |
| 401 | Not authenticated. |
| 403 | The caller lacks `books.read` (`permission_denied`) or the `read` scope (`insufficient_scope`). |
| 404 | The company, or the object, does not exist or is not visible (`not_found`). |
| 409 | The books of the company are not provisioned yet (`company_not_ready`). |
| 503 | The books are not available (`books_unavailable`). |

### Get the balance sheet

`GET /api/companies/{company_id}/reports/balance-sheet/`

- Operation id: `books_reports_balance_sheet_retrieve`
- Permission: `books.read`

The balance sheet at a date (Estonian scheme 1), with an optional comparison date and a simplified grouping.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `company_id` | path | `string` | yes |   |
| `compare_date` | query | `string (date)` | no | A second date to compare with, for example the end of the previous year. |
| `date` | query | `string (date)` | yes | The day of the balance sheet. |
| `omit_empty` | query | `boolean \| null` | no | Leave out the lines whose amount and comparison amount are both 0, and a heading with every row under it when none of its lines is kept. The totals, cash, receivables, issued capital, retained earnings and the profit for the year always show. Default false: the full scheme. |
| `schema` | query | `string` | no | A reporting schema key. Default the latest balance sheet schema of the books. |
| `simplified` | query | `boolean \| null` | no | Group the statement into a few rows. Default false: the full statutory scheme. |

**Response 200** (`application/json`) `BooksBalanceSheet`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `schema` | `BooksReportSchema` | yes | The reporting schema a statement was drawn from. |
| `currency` | `string` | yes |   |
| `compare_date` | `string (date) \| null` | yes |   |
| `simplified` | `boolean` | yes |   |
| `rows` | `array of BooksStatementRow` | yes |   |
| `total_assets_minor` | `integer` | yes |   |
| `total_liabilities_and_equity_minor` | `integer` | yes |   |
| `balanced` | `boolean` | yes | Total assets equal total liabilities and equity. |
| `compare_balanced` | `boolean \| null` | yes | The same at the comparison date; null without one. |
| `unmapped_accounts` | `array of string` | yes | The codes of accounts with a balance and no line of the scheme. |
| `date` | `string (date)` | yes |   |

**Errors**

| Status | Description |
| --- | --- |
| 400 | A parameter is not valid (`validation_error`, `invalid_payload`). |
| 401 | Not authenticated. |
| 403 | The caller lacks `books.read` (`permission_denied`) or the `read` scope (`insufficient_scope`). |
| 404 | The company, or the object, does not exist or is not visible (`not_found`). |
| 409 | The books of the company are not provisioned yet (`company_not_ready`). |
| 429 | Too many expensive reads (`throttled`). |
| 503 | The books are not available (`books_unavailable`). |

### Get the profit and loss statement

`GET /api/companies/{company_id}/reports/profit-and-loss/`

- Operation id: `books_reports_profit_and_loss_retrieve`
- Permission: `books.read`

The income statement of a period (Estonian scheme 1, costs by type), with an optional comparison period and a simplified grouping.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `company_id` | path | `string` | yes |   |
| `compare_from` | query | `string (date)` | no | The first day of a period to compare with. Goes with `compare_to`. |
| `compare_to` | query | `string (date)` | no | The last day of a period to compare with. Goes with `compare_from`. |
| `date_from` | query | `string (date)` | yes | The first day of the period. |
| `date_to` | query | `string (date)` | yes | The last day of the period. |
| `omit_empty` | query | `boolean \| null` | no | Leave out the lines whose amount and comparison amount are both 0, and a heading with every row under it when none of its lines is kept. The totals, cash, receivables, issued capital, retained earnings and the profit for the year always show. Default false: the full scheme. |
| `schema` | query | `string` | no | A reporting schema key. Default the latest income statement schema of the books. |
| `simplified` | query | `boolean \| null` | no | Group the statement into a few rows. Default false: the full statutory scheme. |

**Response 200** (`application/json`) `BooksIncomeStatement`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `schema` | `BooksReportSchema` | yes | The reporting schema a statement was drawn from. |
| `currency` | `string` | yes |   |
| `compare_from` | `string (date) \| null` | yes |   |
| `compare_to` | `string (date) \| null` | yes |   |
| `simplified` | `boolean` | yes |   |
| `rows` | `array of BooksStatementRow` | yes |   |
| `result_minor` | `integer` | yes | The profit (positive) or the loss (negative) of the period. |
| `compare_result_minor` | `integer \| null` | yes | The same for the comparison period; null without one. |
| `unmapped_accounts` | `array of string` | yes | The codes of accounts with a balance and no line of the scheme. |
| `from` | `string (date)` | yes |   |
| `to` | `string (date)` | yes |   |

**Errors**

| Status | Description |
| --- | --- |
| 400 | A parameter is not valid (`validation_error`, `invalid_payload`). |
| 401 | Not authenticated. |
| 403 | The caller lacks `books.read` (`permission_denied`) or the `read` scope (`insufficient_scope`). |
| 404 | The company, or the object, does not exist or is not visible (`not_found`). |
| 409 | The books of the company are not provisioned yet (`company_not_ready`). |
| 429 | Too many expensive reads (`throttled`). |
| 503 | The books are not available (`books_unavailable`). |

### Get the trial balance

`GET /api/companies/{company_id}/trial-balance/`

- Operation id: `books_trial_balance_retrieve`
- Permission: `books.read`

The trial balance of a date range or a period, in the base currency.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `company_id` | path | `string` | yes |   |
| `date_from` | query | `string (date)` | no | The first day of the range, inclusive. Before it is the opening balance. |
| `date_to` | query | `string (date)` | no | The last day of the range, inclusive. |
| `period` | query | `string` | no | A period code (`2026-03`) or id. Excludes `date_from` and `date_to`. |

**Response 200** (`application/json`) `BooksTrialBalance`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `base_currency` | `string` | yes | The currency of every `*_base_minor` amount: the base currency of the books. |
| `rows` | `array of BooksTrialBalanceRow` | yes |   |
| `total_debit_base_minor` | `integer` | yes |   |
| `total_credit_base_minor` | `integer` | yes |   |
| `balanced` | `boolean` | yes |   |
| `from` | `string (date) \| null` | yes |   |
| `to` | `string (date) \| null` | yes |   |

**Errors**

| Status | Description |
| --- | --- |
| 400 | A parameter is not valid (`validation_error`, `invalid_payload`). |
| 401 | Not authenticated. |
| 403 | The caller lacks `books.read` (`permission_denied`) or the `read` scope (`insufficient_scope`). |
| 404 | The company, or the object, does not exist or is not visible (`not_found`). |
| 409 | The books of the company are not provisioned yet (`company_not_ready`). |
| 429 | Too many expensive reads (`throttled`). |
| 503 | The books are not available (`books_unavailable`). |

### List VAT codes

`GET /api/companies/{company_id}/vat-codes/`

- Operation id: `books_vat_codes_list`
- Permission: `books.read`

The VAT codes of the books with their rates, ordered by code. `direction` keeps the codes of one side.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `active` | query | `boolean \| null` | no | Active (true) or inactive (false) codes only. |
| `company_id` | path | `string` | yes |   |
| `cursor` | query | `string` | no | The `next_cursor` of the previous page. Omit it for the first page. |
| `direction` | query | `"purchase" \| "sales"` | no | The codes of this side, and those of both sides. * `purchase` - purchase * `sales` - sales |
| `limit` | query | `integer` | no | The page size, 1 to 200. Default 50. |
| `treatment` | query | `"standard" \| "reduced" \| "zero" \| "exempt" \| "out_of_scope" \| "rc_eu_services" \| "rc_eu_goods" \| "rc_domestic" \| "rc_non_eu" \| "foreign_vat" \| "oss" \| "unknown"` | no | Codes with this treatment only. * `standard` - standard * `reduced` - reduced * `zero` - zero * `exempt` - exempt * `out_of_scope` - out_of_scope * `rc_eu_services` - rc_eu_services * `rc_eu_goods` - rc_eu_goods * `rc_domestic` - rc_domestic * `rc_non_eu` - rc_non_eu * `foreign_vat` - foreign_vat * `oss` - oss * `unknown` - unknown |

**Response 200** (`application/json`) `BooksVatCodePage`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `items` | `array of BooksVatCode` | yes |   |
| `next_cursor` | `string \| null` | yes | Send it back as `cursor` for the next page; null on the last page. |

**Errors**

| Status | Description |
| --- | --- |
| 400 | A parameter is not valid (`validation_error`, `invalid_payload`). |
| 401 | Not authenticated. |
| 403 | The caller lacks `books.read` (`permission_denied`) or the `read` scope (`insufficient_scope`). |
| 404 | The company, or the object, does not exist or is not visible (`not_found`). |
| 409 | The books of the company are not provisioned yet (`company_not_ready`). |
| 503 | The books are not available (`books_unavailable`). |

### Preview a VAT return

`GET /api/companies/{company_id}/vat-preview/`

- Operation id: `books_vat_preview_retrieve`
- Permission: `books.read`

What preparing the VAT return of a period would write, without writing it.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `company_id` | path | `string` | yes |   |
| `form` | query | `string` | no | The return form. Default the company's form (`KMD`). |
| `period_from` | query | `string (date)` | yes | The first day of the return period. |
| `period_to` | query | `string (date)` | yes | The last day of the return period. |

**Response 200** (`application/json`) `BooksVatPreview`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `form` | `string` | yes |   |
| `form_version` | `string` | yes |   |
| `period_from` | `string (date)` | yes |   |
| `period_to` | `string (date)` | yes |   |
| `boxes` | `object` | yes | Box to amount in minor units of the base currency. |
| `base_currency` | `string` | yes | The currency of every `*_base_minor` amount: the base currency of the books. |
| `recognitions` | `integer` | yes | The VAT recognitions the return would include. |
| `due_date` | `string (date) \| null` | no | The deadline of the return of the period: the 20th of the next month, moved to the next working day after a weekend or a public holiday. Null when the period is not one calendar month. |

**Errors**

| Status | Description |
| --- | --- |
| 400 | A parameter is not valid (`validation_error`, `invalid_payload`). |
| 401 | Not authenticated. |
| 403 | The caller lacks `books.read` (`permission_denied`) or the `read` scope (`insufficient_scope`). |
| 404 | The company, or the object, does not exist or is not visible (`not_found`). |
| 409 | The books of the company are not provisioned yet (`company_not_ready`). |
| 429 | Too many expensive reads (`throttled`). |
| 503 | The books are not available (`books_unavailable`). |

## commands

### Record a draft invoice

`POST /api/companies/{company_id}/invoices`

- Operation id: `commands_record_invoice`
- Permission: `invoices.write`

Runs the core command `record_invoice`. Permission: `invoices.write`.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `Idempotency-Key` | header | `string` | no | The request key of the command (section 11.6). A repeat with the same body replays. |
| `company_id` | path | `string` | yes | The sqid of the company. |

**Request body** (`application/json`) `RecordInvoicePayloadRequest`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `direction` | `string` | yes | `sales` or `purchase`. |
| `kind` | `string` | no | Default `invoice`. |
| `party_id` | `string` | yes |   |
| `number` | `string \| null` | no |   |
| `corrects_invoice_id` | `string \| null` | no |   |
| `origin` | `string` | no | Default `human`. |
| `revision` | `InvoiceRevisionRequest` | yes | The content of an invoice: one revision. A chosen `exchange_rate_id` is a human judgement. |

**Response 201** (`application/json`) `RecordInvoiceOutcome`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `command` | `string` | yes |   |
| `command_id` | `string` | yes | The core id of the command, a ULID. |
| `commit_seq` | `integer` | yes | The commit sequence of the file after it. |
| `replayed` | `boolean` | yes |   |
| `result` | `RecordInvoiceResult` | yes | The result of `record_invoice`. |

**Errors**

| Status | Description |
| --- | --- |
| 400 | The payload is not valid (`validation_error`, core codes). |
| 401 | Not authenticated. |
| 403 | `permission_denied`, `insufficient_scope`, or `human_actor_required` for a judgement from an API key or an OAuth client: propose it instead. |
| 404 | The company or a books object does not exist. |
| 409 | A state conflict of the core, `idempotency_conflict`, `company_not_ready`. |
| 503 | The books are not available (`books_unavailable`). |

### Cancel an issued sales invoice or a posted purchase invoice: the number is kept and a posted entry is reversed

`POST /api/companies/{company_id}/invoices/{invoice_id}/cancel`

- Operation id: `commands_cancel_invoice`
- Permission: `invoices.write`

Runs the core command `cancel_invoice`. Permission: `invoices.write` for a sales invoice, `invoices.post_purchase` for a purchase invoice. The path carries `invoice_id`.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `Idempotency-Key` | header | `string` | no | The request key of the command (section 11.6). A repeat with the same body replays. |
| `company_id` | path | `string` | yes | The sqid of the company. |
| `invoice_id` | path | `string` | yes | A core id (ULID). |

**Request body** (`application/json`) `CancelInvoiceBodyRequest`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `reason` | `string` | yes |   |

**Response 200** (`application/json`) `CommandOutcome`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `command` | `string` | yes |   |
| `command_id` | `string` | yes | The core id of the command, a ULID. |
| `commit_seq` | `integer` | yes | The commit sequence of the file after it. |
| `replayed` | `boolean` | yes |   |
| `result` | `any` | yes | The command's result: the ids it created, and more. |

**Errors**

| Status | Description |
| --- | --- |
| 400 | The payload is not valid (`validation_error`, core codes). |
| 401 | Not authenticated. |
| 403 | `permission_denied`, `insufficient_scope`, or `human_actor_required` for a judgement from an API key or an OAuth client: propose it instead. |
| 404 | The company or a books object does not exist. |
| 409 | A state conflict of the core, `idempotency_conflict`, `company_not_ready`. |
| 503 | The books are not available (`books_unavailable`). |

### Issue a sales invoice

`POST /api/companies/{company_id}/invoices/{invoice_id}/issue`

- Operation id: `commands_issue_invoice`
- Permission: `invoices.issue`

Runs the core command `issue_invoice`. Permission: `invoices.issue`. The path carries `invoice_id`.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `Idempotency-Key` | header | `string` | no | The request key of the command (section 11.6). A repeat with the same body replays. |
| `company_id` | path | `string` | yes | The sqid of the company. |
| `invoice_id` | path | `string` | yes | A core id (ULID). |

**Request body** (`application/json`) `IssueInvoiceBodyRequest`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `number` | `string \| null` | no | Only under a `free` numbering policy. |
| `seller_snapshot` | `any \| null` | no |   |
| `buyer_snapshot` | `any \| null` | no |   |
| `seller_address` | `string \| null` | no | The seller's postal address frozen into the seller snapshot. Without it the API takes the company's address from the Business Register. A VAT-registered company issues no invoice without the seller's and the buyer's address: 400 `seller_address_missing` or `buyer_address_missing` (EE-VAT-020). |

**Response 200** (`application/json`) `IssueInvoiceOutcome`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `command` | `string` | yes |   |
| `command_id` | `string` | yes | The core id of the command, a ULID. |
| `commit_seq` | `integer` | yes | The commit sequence of the file after it. |
| `replayed` | `boolean` | yes |   |
| `result` | `IssueInvoiceResult` | yes | The result of `issue_invoice`. |

**Errors**

| Status | Description |
| --- | --- |
| 400 | The payload is not valid (`validation_error`, core codes). |
| 401 | Not authenticated. |
| 403 | `permission_denied`, `insufficient_scope`, or `human_actor_required` for a judgement from an API key or an OAuth client: propose it instead. |
| 404 | The company or a books object does not exist. |
| 409 | A state conflict of the core, `idempotency_conflict`, `company_not_ready`. |
| 503 | The books are not available (`books_unavailable`). |

### Revise an invoice

`POST /api/companies/{company_id}/invoices/{invoice_id}/revise`

- Operation id: `commands_revise_invoice`
- Permission: `invoices.write`

Runs the core command `revise_invoice`. Permission: `invoices.write`. The path carries `invoice_id`.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `Idempotency-Key` | header | `string` | no | The request key of the command (section 11.6). A repeat with the same body replays. |
| `company_id` | path | `string` | yes | The sqid of the company. |
| `invoice_id` | path | `string` | yes | A core id (ULID). |

**Request body** (`application/json`) `ReviseInvoiceBodyRequest`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `reason` | `string` | yes |   |
| `party_id` | `string \| null` | no |   |
| `revision` | `InvoiceRevisionRequest` | yes | The content of an invoice: one revision. A chosen `exchange_rate_id` is a human judgement. |

**Response 200** (`application/json`) `CommandOutcome`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `command` | `string` | yes |   |
| `command_id` | `string` | yes | The core id of the command, a ULID. |
| `commit_seq` | `integer` | yes | The commit sequence of the file after it. |
| `replayed` | `boolean` | yes |   |
| `result` | `any` | yes | The command's result: the ids it created, and more. |

**Errors**

| Status | Description |
| --- | --- |
| 400 | The payload is not valid (`validation_error`, core codes). |
| 401 | Not authenticated. |
| 403 | `permission_denied`, `insufficient_scope`, or `human_actor_required` for a judgement from an API key or an OAuth client: propose it instead. |
| 404 | The company or a books object does not exist. |
| 409 | A state conflict of the core, `idempotency_conflict`, `company_not_ready`. |
| 503 | The books are not available (`books_unavailable`). |

### Create a party

`POST /api/companies/{company_id}/parties`

- Operation id: `commands_create_party`
- Permission: `parties.write`

Runs the core command `create_party`. Permission: `parties.write`.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `Idempotency-Key` | header | `string` | no | The request key of the command (section 11.6). A repeat with the same body replays. |
| `company_id` | path | `string` | yes | The sqid of the company. |

**Request body** (`application/json`) `CreatePartyPayloadRequest`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `name` | `string` | yes |   |
| `kind` | `"supplier" \| "customer" \| "employee" \| "authority" \| "group_company" \| "other"` | yes | * `supplier` - supplier * `customer` - customer * `employee` - employee * `authority` - authority * `group_company` - group_company * `other` - other |
| `country` | `string \| null` | no |   |
| `vat_area` | `string \| null` | no |   |
| `vat_number` | `string \| null` | no |   |
| `reg_code` | `string \| null` | no |   |
| `expects_document` | `boolean` | no | Default true. |
| `is_confirmed` | `boolean` | no |   |
| `notes` | `string \| null` | no |   |
| `external_key` | `string \| null` | no | The key of the party in another system, for example `stripe:acct_…:cus_…`. Unique; with it, a party with the same name is allowed. |
| `private_persons` | `boolean` | no | The party pools private persons (card buyers): the KMD INF annex leaves it out. No registry code. Default false. |
| `address` | `string \| null` | no | The postal address printed on an invoice, one or more lines; the country is `country`. At most 500 characters. |
| `email` | `string \| null` | no | The email address of the party. Trimmed; blank is null. At most 254 characters, no whitespace, and exactly one `@` with text on both sides, else 400 `invalid_payload`. |
| `phone` | `string \| null` | no | The phone number of the party. Trimmed; blank is null. At most 40 characters: digits, spaces and `+ - ( ) .`, with at least 5 digits, else 400 `invalid_payload`. |

**Response 201** (`application/json`) `CreatePartyOutcome`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `command` | `string` | yes |   |
| `command_id` | `string` | yes | The core id of the command, a ULID. |
| `commit_seq` | `integer` | yes | The commit sequence of the file after it. |
| `replayed` | `boolean` | yes |   |
| `result` | `CreatePartyResult` | yes | The result of `create_party`. |

**Errors**

| Status | Description |
| --- | --- |
| 400 | The payload is not valid (`validation_error`, core codes). |
| 401 | Not authenticated. |
| 403 | `permission_denied`, `insufficient_scope`, or `human_actor_required` for a judgement from an API key or an OAuth client: propose it instead. |
| 404 | The company or a books object does not exist. |
| 409 | A state conflict of the core, `idempotency_conflict`, `company_not_ready`. |
| 503 | The books are not available (`books_unavailable`). |

## companies

### Return the company

`GET /api/companies/{company_id}/`

- Operation id: `companies_retrieve`
- Permission: `organization.read`

Return the company.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `company_id` | path | `string` | yes |   |

**Response 200** (`application/json`) `CompanyDetail`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | `string` | yes |   |
| `organization_id` | `string` | yes | The sqid of the company's organization, without loading it. |
| `name` | `string` | yes |   |
| `registry_code` | `string` | yes |   |
| `vat_number` | `string` | yes | The VAT number of the latest VAT registration by date. It changes only through `POST vat-registrations` (`record_vat_registration`). |
| `vat_status` | `"registered" \| "limited" \| "unregistered"` | yes | The status of the latest VAT registration by date. The books apply the status by date: `GET vat-registration/`. * `registered` - VAT-registered * `limited` - Limited taxable person * `unregistered` - Not VAT-registered |
| `vat_status_from` | `string (date) \| null` | yes | The first day of `vat_status`; null for the status at creation. |
| `legal_form` | `"ou" \| "as" \| "fie" \| "mtu" \| "sa" \| "tu" \| "uu" \| "other"` | yes | * `ou` - Osaühing (OÜ) * `as` - Aktsiaselts (AS) * `fie` - Füüsilisest isikust ettevõtja (FIE) * `mtu` - Mittetulundusühing (MTÜ) * `sa` - Sihtasutus (SA) * `tu` - Täisühing (TÜ) * `uu` - Usaldusühing (UÜ) * `other` - Other |
| `files_tsd_monthly` | `boolean` | yes | The accountant set that the company files a TSD every month. False: the TSD reminder of a month comes only when the books show payroll, a dividend payment or a distribution tax in it. Changed with `PATCH /api/companies/{company_id}/`. |
| `state` | `"provisioning" \| "ready" \| "failed" \| "deleted"` | yes | * `provisioning` - Provisioning * `ready` - Ready * `failed` - Failed * `deleted` - Data deleted |
| `core_company_id` | `string \| null` | yes |   |
| `base_currency` | `string` | yes | The base currency of the books (ISO 4217): every amount without its own currency is in it. |
| `created_at` | `string (date-time)` | yes |   |
| `updated_at` | `string (date-time)` | yes |   |
| `role` | `"owner" \| "member" \| "viewer" \| NullEnum` | yes |   |
| `permissions` | `array of "organization.read" \| "members.read" \| "api_keys.read" \| "audit.read" \| "books.read" \| "documents.read" \| "payments.read" \| "organization.manage" \| "members.manage" \| "api_keys.manage" \| "companies.create" \| "books.setup" \| "parties.write" \| "documents.write" \| "bank.import" \| "bank.classify" \| "bank.connect" \| "invoices.write" \| "invoices.issue" \| "invoices.post_purchase" \| "invoices.void" \| "allocations.write" \| "reconciliation.decide" \| "events.write" \| "periods.close" \| "periods.reopen" \| "vat.prepare" \| "vat.file" \| "payments.manage" \| "employees.submit" \| "agent.use"` | yes |   |
| `view_as` | `"owner" \| "member" \| "viewer" \| NullEnum` | yes |   |
| `status` | `CompanyStatus \| null` | yes |   |
| `refresh_pending` | `boolean` | yes | True while a rebuild of the status counts is queued or running: a change was made that the counts may not show yet. Read again until it is false. |

### One page of the company's files, newest first

`GET /api/companies/{company_id}/files/`

- Operation id: `companies_files_list`
- Permission: `documents.read`

One page of the company's files, newest first. Filter: `kind`.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `company_id` | path | `string` | yes |   |
| `cursor` | query | `string` | no | The pagination cursor value. |
| `kind` | query | `"contract" \| "credit_note" \| "invoice" \| "other" \| "receipt" \| "statement"` | no | * `invoice` - Invoice * `receipt` - Receipt * `credit_note` - Credit note * `statement` - Bank statement * `contract` - Contract * `other` - Other |
| `limit` | query | `integer` | no | Number of results to return per page. |

**Response 200** (`application/json`) `PaginatedStoredDocumentList`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `items` | `array of StoredDocument` | yes |   |
| `next_cursor` | `string \| null` | yes |   |

### Upload a file and record it in the books

`POST /api/companies/{company_id}/files/`

- Operation id: `companies_files_create`
- Permission: `documents.write`

Upload a file and record it in the books.

A confident extraction of an invoice, receipt or credit note is recorded and posted without a person,
within what the uploader may do. With `auto_process` (the batch import), the uploader must hold
`invoices.write`: 403 `permission_denied` for `auto_process` without `invoices.write`, 409 `not_extractable`
for `auto_process` on a file that is not a PDF of kind invoice, receipt or credit note.
413 `file_too_large`, 400 `empty_file`, 415 `unsupported_file_type`.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `Idempotency-Key` | header | `string` | no | The request key of the command (section 11.6). A repeat with the same body replays. |
| `company_id` | path | `string` | yes |   |

**Request body** (`multipart/form-data`) `UploadRequest`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `file` | `string (binary)` | yes |   |
| `kind` | `"invoice" \| "receipt" \| "credit_note" \| "statement" \| "contract" \| "other"` | no | * `invoice` - invoice * `receipt` - receipt * `credit_note` - credit_note * `statement` - statement * `contract` - contract * `other` - other |
| `received_on` | `string (date) \| null` | no |   |
| `bank_transaction_id` | `string \| null` | no | The core ULID of the bank transaction this file explains (a receipt for a payment). |
| `auto_process` | `boolean` | no | The batch import. Every upload of an invoice, receipt or credit note is recorded and posted without a person when the extraction is confident and the company switch `invoice_auto_book` is on, and the reconciliation matcher links it to its bank line; `auto_process` also refuses the upload without `invoices.write` (403) and a file the extraction does not read: only a PDF of kind invoice, receipt or credit note (409 `not_extractable` otherwise). The post needs `invoices.post_purchase`. A draft that is not confident waits for a person. Follow it with `GET extractions/?file=`. |

**Response 200** (`application/json`) `StoredDocument`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | `string` | yes | The sqid of the file. |
| `kind` | `"invoice" \| "receipt" \| "credit_note" \| "statement" \| "contract" \| "other"` | yes | * `invoice` - invoice * `receipt` - receipt * `credit_note` - credit_note * `statement` - statement * `contract` - contract * `other` - other |
| `name` | `string` | yes |   |
| `content_type` | `string` | yes |   |
| `size_bytes` | `integer` | yes |   |
| `sha256` | `string` | yes |   |
| `received_on` | `string (date) \| null` | yes |   |
| `core_document_id` | `string \| null` | yes | The ULID of the document in the books. |
| `bank_transaction_ids` | `array of string` | yes | The core ULIDs of the bank transactions this file explains. |
| `uploaded_by` | `string \| null` | yes | The sqid of the user who uploaded the file. |
| `origin` | `InboxOrigin \| null` | yes | The mail the file came from, when it came from the invoice inbox; null for an upload. |
| `created_at` | `string (date-time)` | yes |   |

**Response 201** (`application/json`) `StoredDocument`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | `string` | yes | The sqid of the file. |
| `kind` | `"invoice" \| "receipt" \| "credit_note" \| "statement" \| "contract" \| "other"` | yes | * `invoice` - invoice * `receipt` - receipt * `credit_note` - credit_note * `statement` - statement * `contract` - contract * `other` - other |
| `name` | `string` | yes |   |
| `content_type` | `string` | yes |   |
| `size_bytes` | `integer` | yes |   |
| `sha256` | `string` | yes |   |
| `received_on` | `string (date) \| null` | yes |   |
| `core_document_id` | `string \| null` | yes | The ULID of the document in the books. |
| `bank_transaction_ids` | `array of string` | yes | The core ULIDs of the bank transactions this file explains. |
| `uploaded_by` | `string \| null` | yes | The sqid of the user who uploaded the file. |
| `origin` | `InboxOrigin \| null` | yes | The mail the file came from, when it came from the invoice inbox; null for an upload. |
| `created_at` | `string (date-time)` | yes |   |

### One file

`GET /api/companies/{company_id}/files/{file_id}/`

- Operation id: `companies_files_retrieve`
- Permission: `documents.read`

One file.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `company_id` | path | `string` | yes |   |
| `file_id` | path | `string` | yes |   |

**Response 200** (`application/json`) `StoredDocument`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | `string` | yes | The sqid of the file. |
| `kind` | `"invoice" \| "receipt" \| "credit_note" \| "statement" \| "contract" \| "other"` | yes | * `invoice` - invoice * `receipt` - receipt * `credit_note` - credit_note * `statement` - statement * `contract` - contract * `other` - other |
| `name` | `string` | yes |   |
| `content_type` | `string` | yes |   |
| `size_bytes` | `integer` | yes |   |
| `sha256` | `string` | yes |   |
| `received_on` | `string (date) \| null` | yes |   |
| `core_document_id` | `string \| null` | yes | The ULID of the document in the books. |
| `bank_transaction_ids` | `array of string` | yes | The core ULIDs of the bank transactions this file explains. |
| `uploaded_by` | `string \| null` | yes | The sqid of the user who uploaded the file. |
| `origin` | `InboxOrigin \| null` | yes | The mail the file came from, when it came from the invoice inbox; null for an upload. |
| `created_at` | `string (date-time)` | yes |   |

### The bytes of the file, after the permission check

`GET /api/companies/{company_id}/files/{file_id}/content/`

- Operation id: `companies_files_content`
- Permission: `documents.read`

The bytes of the file, after the permission check. PDF and images show inline.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `company_id` | path | `string` | yes |   |
| `file_id` | path | `string` | yes |   |
| `format` | query | `"bin" \| "json"` | no |   |

**Response 200** (`*/*`): The bytes of the file.

Type: `string (binary)`

## employees

### One page of the employees, newest first, each with the facts of its newest employment

`GET /api/companies/{company_id}/employees/`

- Operation id: `companies_employees_list`
- Permission: `books.read`

One page of the employees, newest first, each with the facts of its newest employment.

`source` `tor_external` and `registered_outside` mark what TÖR showed
that was not made through OscarAI. The personal code is masked.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `company_id` | path | `string` | yes |   |
| `cursor` | query | `string` | no | The pagination cursor value. |
| `limit` | query | `integer` | no | Number of results to return per page. |

**Response 200** (`application/json`) `PaginatedEmployeeList`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `items` | `array of Employee` | yes |   |
| `next_cursor` | `string \| null` | yes |   |

**Errors**

| Status | Description |
| --- | --- |
| 409 | `employees_disabled`: the register is off on this server. |

### One page of the submissions, newest first, with their status and the reason of a refusal

`GET /api/companies/{company_id}/employees/submissions/`

- Operation id: `companies_employees_submissions_list`
- Permission: `books.read`

One page of the submissions, newest first, with their status and the reason of a refusal.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `company_id` | path | `string` | yes |   |
| `cursor` | query | `string` | no | The pagination cursor value. |
| `limit` | query | `integer` | no | Number of results to return per page. |

**Response 200** (`application/json`) `PaginatedSubmissionList`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `items` | `array of Submission` | yes |   |
| `next_cursor` | `string \| null` | yes |   |

**Errors**

| Status | Description |
| --- | --- |
| 409 | `employees_disabled`: the register is off on this server. |

### Submit a new employee, a new employment, a change, a suspension or an end, for the firm to review

`POST /api/companies/{company_id}/employees/submissions/`

- Operation id: `companies_employees_submissions_create`
- Permission: `employees.submit`

Submit a new employee, a new employment, a change, a suspension or an end, for the firm to review.

Staff review it; on approval OscarAI registers the event in TÖR. The
personal code of a new employee is sealed and never returned. The
event is checked as TÖR checks it (400 `tor_invalid_event`).

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `company_id` | path | `string` | yes |   |

**Request body** (`application/json`) `SubmissionRequestRequest`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `kind` | `"new_employee" \| "new_employment" \| "change" \| "suspension" \| "end"` | yes | * `new_employee` - New employee * `new_employment` - New employment * `change` - Change * `suspension` - Suspension * `end` - End |
| `employee_id` | `string` | no | A new employment: the employee. |
| `employment_id` | `string` | no | A change, a suspension, an end: the employment. |
| `employee` | `EmployeeInputRequest` | no | The person of a new employee, or the changed fields of an employee. |
| `employment` | `EmploymentInputRequest` | no | The employment of a start, or the changed fields of an employment. |
| `suspension` | `SuspensionInputRequest` | no | A suspension of an employment. |
| `end` | `EndInputRequest` | no | The end of an employment. |
| `event_date` | `string (date)` | no | A change: the day it applies from. Default today. |

**Response 201** (`application/json`) `Submission`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | `string` | yes |   |
| `kind` | `"new_employee" \| "new_employment" \| "change" \| "suspension" \| "end"` | yes | * `new_employee` - New employee * `new_employment` - New employment * `change` - Change * `suspension` - Suspension * `end` - End |
| `status` | `"submitted" \| "approved" \| "registered" \| "applied" \| "rejected"` | yes | * `submitted` - Submitted * `approved` - Approved * `registered` - Registered * `applied` - Applied * `rejected` - Rejected |
| `event_date` | `string (date)` | yes |   |
| `employee_id` | `string` | yes | The employee of the submission. |
| `employee_name` | `string` | yes | The name of the employee. |
| `employment_id` | `string` | yes |   |
| `data` | `any` | yes | The submitted values by field name. Never a personal code. |
| `submitted_at` | `string (date-time)` | yes |   |
| `submitted_by_staff` | `boolean` | yes |   |
| `reviewed_at` | `string (date-time) \| null` | yes |   |
| `review_reason` | `string` | yes | Why staff rejected it. |
| `toot_id` | `integer \| null` | yes | TÖR's id of the employment, once registered. |
| `tor_messages` | `array of TorMessage` | yes | The messages of TÖR on a refused event. |
| `tor_error_code` | `string` | yes | Why the last send to TÖR did not finish; empty when it did. |
| `registered_at` | `string (date-time) \| null` | yes |   |

**Errors**

| Status | Description |
| --- | --- |
| 409 | `employees_disabled`: the register is off on this server. |

### One submission: its status, the reason of a refusal, TÖR's messages, the TÖR id once registered

`GET /api/companies/{company_id}/employees/submissions/{submission_id}/`

- Operation id: `companies_employees_submissions_retrieve`
- Permission: `books.read`

One submission: its status, the reason of a refusal, TÖR's messages, the TÖR id once registered.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `company_id` | path | `string` | yes |   |
| `submission_id` | path | `string` | yes |   |

**Response 200** (`application/json`) `Submission`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | `string` | yes |   |
| `kind` | `"new_employee" \| "new_employment" \| "change" \| "suspension" \| "end"` | yes | * `new_employee` - New employee * `new_employment` - New employment * `change` - Change * `suspension` - Suspension * `end` - End |
| `status` | `"submitted" \| "approved" \| "registered" \| "applied" \| "rejected"` | yes | * `submitted` - Submitted * `approved` - Approved * `registered` - Registered * `applied` - Applied * `rejected` - Rejected |
| `event_date` | `string (date)` | yes |   |
| `employee_id` | `string` | yes | The employee of the submission. |
| `employee_name` | `string` | yes | The name of the employee. |
| `employment_id` | `string` | yes |   |
| `data` | `any` | yes | The submitted values by field name. Never a personal code. |
| `submitted_at` | `string (date-time)` | yes |   |
| `submitted_by_staff` | `boolean` | yes |   |
| `reviewed_at` | `string (date-time) \| null` | yes |   |
| `review_reason` | `string` | yes | Why staff rejected it. |
| `toot_id` | `integer \| null` | yes | TÖR's id of the employment, once registered. |
| `tor_messages` | `array of TorMessage` | yes | The messages of TÖR on a refused event. |
| `tor_error_code` | `string` | yes | Why the last send to TÖR did not finish; empty when it did. |
| `registered_at` | `string (date-time) \| null` | yes |   |

**Errors**

| Status | Description |
| --- | --- |
| 409 | `employees_disabled`: the register is off on this server. |

### One employee, with every employment (the TÖR id and state, the suspensions) and the absences

`GET /api/companies/{company_id}/employees/{employee_id}/`

- Operation id: `companies_employees_retrieve`
- Permission: `books.read`

One employee, with every employment (the TÖR id and state, the suspensions) and the absences.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `company_id` | path | `string` | yes |   |
| `employee_id` | path | `string` | yes |   |

**Response 200** (`application/json`) `EmployeeDetail`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | `string` | yes |   |
| `first_name` | `string` | yes |   |
| `last_name` | `string` | yes |   |
| `personal_code` | `string` | yes | The masked personal code: `*******` and 4 digits. |
| `birth_date` | `string (date) \| null` | yes |   |
| `citizenship` | `string` | yes |   |
| `iban` | `string` | yes |   |
| `email` | `string` | yes |   |
| `basic_exemption` | `"none" \| "full" \| "partial"` | yes | * `none` - No application * `full` - The whole exemption * `partial` - A part of the exemption |
| `basic_exemption_minor` | `integer \| null` | yes |   |
| `pension_rate` | `"none" \| "2" \| "4" \| "6"` | yes | * `none` - None * `2` - 2 percent * `4` - 4 percent * `6` - 6 percent |
| `source` | `"oscar" \| "tor_external"` | yes | * `oscar` - OscarAI * `tor_external` - Registered outside OscarAI |
| `employment_type` | `integer \| null` | yes | The type of the newest employment. |
| `start_date` | `string (date) \| null` | yes |   |
| `end_date` | `string (date) \| null` | yes |   |
| `status` | `"draft" \| "submitted" \| "approved" \| "registered" \| "rejected" \| "ended" \| "cancelled" \| NullEnum` | yes |   |
| `registered_outside` | `boolean` | yes | Whether TÖR shows an employment of the person, or a change of one, not made through OscarAI. |
| `created_at` | `string (date-time)` | yes |   |
| `employments` | `array of Employment` | yes |   |
| `absences` | `array of Absence` | yes |   |

**Errors**

| Status | Description |
| --- | --- |
| 409 | `employees_disabled`: the register is off on this server. |

## inbox

### The private forwarding address of the company, made on the first read, and what came in

`GET /api/companies/{company_id}/inbox/`

- Operation id: `companies_inbox_retrieve`
- Permission: `documents.read`

The private forwarding address of the company, made on the first read, and what came in.

Also the Gmail search strings to paste into a Gmail filter, and the newest Gmail forwarding confirmation
that oscarai forwarded to the Gmail address that asked for it (never its code or link).

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `company_id` | path | `string` | yes |   |

**Response 200** (`application/json`) `Inbox`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `address` | `string (email)` | yes | The private forwarding address of the company. |
| `address_created_at` | `string (date-time)` | yes |   |
| `counts` | `InboxCounts` | yes | The mails of the last 30 days. |
| `gmail_filter_query` | `string` | yes | The search string for a Gmail filter: known suppliers, or invoice words with an attachment. |
| `gmail_filter_query_broad` | `string` | yes | The search string that forwards every mail with a PDF. |
| `forwarding_confirmation` | `ForwardingConfirmation \| null` | yes |   |

**Errors**

| Status | Description |
| --- | --- |
| 409 | `inbox_disabled`: the invoice inbox is off on this server. |

### One page of the received mails, newest first: the sender, the outcome, the files, the attachments not kept

`GET /api/companies/{company_id}/inbox/emails/`

- Operation id: `companies_inbox_emails_list`
- Permission: `documents.read`

One page of the received mails, newest first: the sender, the outcome, the files, the attachments not kept.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `company_id` | path | `string` | yes |   |
| `cursor` | query | `string` | no | The pagination cursor value. |
| `limit` | query | `integer` | no | Number of results to return per page. |

**Response 200** (`application/json`) `PaginatedInboundEmailList`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `items` | `array of InboundEmail` | yes |   |
| `next_cursor` | `string \| null` | yes |   |

**Errors**

| Status | Description |
| --- | --- |
| 409 | `inbox_disabled`: the invoice inbox is off on this server. |

### Revoke the address at once and make a new one

`POST /api/companies/{company_id}/inbox/rotate/`

- Operation id: `companies_inbox_rotate_create`
- Permission: `documents.write`

Revoke the address at once and make a new one. Mail to the old address is ignored from now on.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `company_id` | path | `string` | yes |   |

**Response 200** (`application/json`) `Inbox`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `address` | `string (email)` | yes | The private forwarding address of the company. |
| `address_created_at` | `string (date-time)` | yes |   |
| `counts` | `InboxCounts` | yes | The mails of the last 30 days. |
| `gmail_filter_query` | `string` | yes | The search string for a Gmail filter: known suppliers, or invoice words with an attachment. |
| `gmail_filter_query_broad` | `string` | yes | The search string that forwards every mail with a PDF. |
| `forwarding_confirmation` | `ForwardingConfirmation \| null` | yes |   |

**Errors**

| Status | Description |
| --- | --- |
| 409 | `inbox_disabled`: the invoice inbox is off on this server. |

## me

### Return the caller

`GET /api/me/`

- Operation id: `me_retrieve`
- Permission: `none`

Return the caller. A staff session that sees organizations without a membership is audited.

So is every read by a staff key, which sees every organization.

**Response 200** (`application/json`) `Me`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `user` | `MeUser \| null` | yes | The session user, or the creator of the API key or OAuth grant. |
| `has_totp` | `boolean` | yes |   |
| `staff_mfa_required` | `boolean` | yes | True when the user is firm staff but this session did not pass a second factor (TOTP or a passkey): every staff power is off, and the firm API answers 403 mfa_required, until the user logs in with one. |
| `email_verified` | `boolean` | yes |   |
| `credential` | `MeCredential` | yes | How the call was authenticated. |
| `organizations` | `array of MeOrganization` | yes |   |
| `companies` | `array of MeCompany` | yes |   |
| `features` | `MeFeatures` | yes | The features this deployment turns on. The frontend hides what is off. |
| `cli_min_version` | `string` | no | The oldest version of the oscar CLI that may run the onboarding (semver). An older CLI asks the user to update first. Always returned; optional in the schema, so a client keeps working against a server older than the field. |

## organizations

### One page of the visible organizations

`GET /api/organizations/`

- Operation id: `organizations_list`
- Permission: `organization.read`

One page of the visible organizations. A staff list is written to the audit log.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `cursor` | query | `string` | no | The pagination cursor value. |
| `limit` | query | `integer` | no | Number of results to return per page. |

**Response 200** (`application/json`) `PaginatedOrganizationList`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `items` | `array of Organization` | yes |   |
| `next_cursor` | `string \| null` | yes |   |

### Return the organization

`GET /api/organizations/{organization_id}/`

- Operation id: `organizations_retrieve`
- Permission: `organization.read`

Return the organization.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `organization_id` | path | `string` | yes |   |

**Response 200** (`application/json`) `Organization`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | `string` | yes |   |
| `name` | `string` | yes |   |
| `role` | `"owner" \| "member" \| "viewer" \| NullEnum` | yes |   |
| `permissions` | `array of string` | yes |   |
| `companies` | `array of Company` | yes |   |
| `created_at` | `string (date-time)` | yes |   |
| `updated_at` | `string (date-time)` | yes |   |

### One page of the companies, newest first

`GET /api/organizations/{organization_id}/companies/`

- Operation id: `organizations_companies_list`
- Permission: `organization.read`

One page of the companies, newest first.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `cursor` | query | `string` | no | The pagination cursor value. |
| `limit` | query | `integer` | no | Number of results to return per page. |
| `organization_id` | path | `string` | yes |   |

**Response 200** (`application/json`) `PaginatedCompanyList`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `items` | `array of Company` | yes |   |
| `next_cursor` | `string \| null` | yes |   |

## payroll

### One page of the pay runs, newest month first, with their totals and the net pay not paid yet

`GET /api/companies/{company_id}/payroll/pay-runs/`

- Operation id: `companies_payroll_pay_runs_list`
- Permission: `books.read`

One page of the pay runs, newest month first, with their totals and the net pay not paid yet.

A client sees the posted runs; firm staff also the drafts and the approved ones.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `company_id` | path | `string` | yes |   |
| `cursor` | query | `string` | no | The pagination cursor value. |
| `limit` | query | `integer` | no | Number of results to return per page. |

**Response 200** (`application/json`) `PaginatedPayRunList`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `items` | `array of PayRun` | yes |   |
| `next_cursor` | `string \| null` | yes |   |

**Errors**

| Status | Description |
| --- | --- |
| 409 | `payroll_disabled`: payroll is off on this server. |

### One pay run with every employee: the inputs, the gross and the net, the net not paid yet, the payments

`GET /api/companies/{company_id}/payroll/pay-runs/{pay_run_id}/`

- Operation id: `companies_payroll_pay_runs_retrieve`
- Permission: `books.read`

One pay run with every employee: the inputs, the gross and the net, the net not paid yet, the payments.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `company_id` | path | `string` | yes |   |
| `pay_run_id` | path | `string` | yes |   |

**Response 200** (`application/json`) `PayRunDetail`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | `string` | yes |   |
| `month` | `string` | yes | YYYY-MM |
| `payday` | `string (date)` | yes |   |
| `status` | `"draft" \| "approved" \| "posting" \| "posted"` | yes | * `draft` - Draft * `approved` - Approved * `posting` - Posting * `posted` - Posted |
| `currency` | `string` | yes |   |
| `employee_count` | `integer` | yes |   |
| `gross_minor` | `integer \| null` | yes |   |
| `net_minor` | `integer \| null` | yes |   |
| `withheld_minor` | `integer \| null` | yes |   |
| `employer_tax_minor` | `integer \| null` | yes |   |
| `expense_minor` | `integer \| null` | yes |   |
| `open_net_minor` | `integer \| null` | yes | Posted: the net pay not paid yet. |
| `calculation_error` | `string` | yes | A draft: why the calculation of the books failed. |
| `pay_run_id` | `string \| null` | yes | Posted: the pay run in the books. |
| `approved_at` | `string (date-time) \| null` | yes |   |
| `posted_at` | `string (date-time) \| null` | yes |   |
| `employees` | `array of PayRunEmployee` | yes |   |

**Errors**

| Status | Description |
| --- | --- |
| 409 | `payroll_disabled`: payroll is off on this server. |

## Schemas

The objects that the operations above take and return.

### Absence

A holiday or a sick leave.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | `string` | yes |   |
| `kind` | `"holiday" \| "sick_leave"` | yes | * `holiday` - Holiday * `sick_leave` - Sick leave |
| `start_date` | `string (date)` | yes |   |
| `end_date` | `string (date)` | yes |   |
| `note` | `string` | yes |   |

### AbsenceKindEnum

* `holiday` - Holiday
* `sick_leave` - Sick leave

One of: `"holiday"`, `"sick_leave"`.

### BasicExemptionEnum

* `none` - No application
* `full` - The whole exemption
* `partial` - A part of the exemption

One of: `"none"`, `"full"`, `"partial"`.

### BlankEnum

One of: `""`.

### BooksAccount

An account of the chart.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | `string` | yes |   |
| `code` | `string` | yes |   |
| `name` | `string` | yes |   |
| `name_en` | `string \| null` | yes |   |
| `type` | `"asset" \| "liability" \| "equity" \| "income" \| "expense"` | yes | * `asset` - asset * `liability` - liability * `equity` - equity * `income` - income * `expense` - expense |
| `normal_side` | `"debit" \| "credit"` | yes | * `debit` - debit * `credit` - credit |
| `parent_code` | `string \| null` | yes |   |
| `currency` | `string \| null` | yes | An account kept in one currency only, or null. |
| `control_kind` | `"payable" \| "receivable" \| "suspense_payable" \| "suspense_receivable" \| "bank" \| "transit" \| "vat" \| NullEnum` | yes |   |
| `requires_party` | `boolean` | yes |   |
| `is_open_item` | `boolean` | yes |   |
| `source` | `"seed" \| "manual"` | yes | * `seed` - seed * `manual` - manual |
| `active` | `boolean` | yes |   |
| `created_at` | `string (date-time)` | yes |   |
| `fixed_asset_class` | `"tangible" \| "intangible" \| "under_construction" \| "investment_property" \| "prepayment" \| NullEnum` | yes | The fixed asset class of the account, or null: a purchase line posted here buys a fixed asset. * `tangible` - tangible * `intangible` - intangible * `under_construction` - under_construction * `investment_property` - investment_property * `prepayment` - prepayment |

### BooksAccountFixedAssetClassEnum

* `tangible` - tangible
* `intangible` - intangible
* `under_construction` - under_construction
* `investment_property` - investment_property
* `prepayment` - prepayment

One of: `"tangible"`, `"intangible"`, `"under_construction"`, `"investment_property"`, `"prepayment"`.

### BooksAccountPage

One page of BooksAccount items, and the cursor of the next page.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `items` | `array of BooksAccount` | yes |   |
| `next_cursor` | `string \| null` | yes | Send it back as `cursor` for the next page; null on the last page. |

### BooksAccountSourceEnum

* `seed` - seed
* `manual` - manual

One of: `"seed"`, `"manual"`.

### BooksAccountTypeEnum

* `asset` - asset
* `liability` - liability
* `equity` - equity
* `income` - income
* `expense` - expense

One of: `"asset"`, `"liability"`, `"equity"`, `"income"`, `"expense"`.

### BooksAgingBucketEnum

* `no_due_date` - no_due_date
* `not_due` - not_due
* `1_30` - 1_30
* `31_60` - 31_60
* `61_90` - 61_90
* `over_90` - over_90

One of: `"no_due_date"`, `"not_due"`, `"1_30"`, `"31_60"`, `"61_90"`, `"over_90"`.

### BooksAllocation

An allocation between an open item and its counter line.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | `string` | yes |   |
| `kind` | `"payment" \| "refund" \| "credit_offset" \| "prepayment_apply"` | yes | * `payment` - payment * `refund` - refund * `credit_offset` - credit_offset * `prepayment_apply` - prepayment_apply |
| `state` | `"active" \| "reversed"` | yes | * `active` - active * `reversed` - reversed |
| `item_line_id` | `string` | yes |   |
| `counter_line_id` | `string` | yes |   |
| `item_currency` | `string` | yes |   |
| `item_minor` | `integer` | yes |   |
| `counter_currency` | `string` | yes |   |
| `counter_minor` | `integer` | yes |   |
| `effective_date` | `string (date)` | yes |   |
| `entry_id` | `string \| null` | yes |   |
| `origin` | `string` | yes |   |

### BooksAllocationKindEnum

* `payment` - payment
* `refund` - refund
* `credit_offset` - credit_offset
* `prepayment_apply` - prepayment_apply

One of: `"payment"`, `"refund"`, `"credit_offset"`, `"prepayment_apply"`.

### BooksAllocationStateEnum

* `active` - active
* `reversed` - reversed

One of: `"active"`, `"reversed"`.

### BooksBalanceSheet

The balance sheet at a date, in the base currency.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `schema` | `BooksReportSchema` | yes | The reporting schema a statement was drawn from. |
| `currency` | `string` | yes |   |
| `compare_date` | `string (date) \| null` | yes |   |
| `simplified` | `boolean` | yes |   |
| `rows` | `array of BooksStatementRow` | yes |   |
| `total_assets_minor` | `integer` | yes |   |
| `total_liabilities_and_equity_minor` | `integer` | yes |   |
| `balanced` | `boolean` | yes | Total assets equal total liabilities and equity. |
| `compare_balanced` | `boolean \| null` | yes | The same at the comparison date; null without one. |
| `unmapped_accounts` | `array of string` | yes | The codes of accounts with a balance and no line of the scheme. |
| `date` | `string (date)` | yes |   |

### BooksBankAccount

A bank feed and its ledger account.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | `string` | yes |   |
| `provider` | `string` | yes |   |
| `label` | `string` | yes |   |
| `iban` | `string \| null` | yes |   |
| `bic` | `string \| null` | yes |   |
| `currency` | `string` | yes |   |
| `account_id` | `string` | yes | The ledger account of the feed. |
| `account_code` | `string` | yes |   |
| `is_debtor` | `boolean` | yes |   |
| `active` | `boolean` | yes |   |
| `created_at` | `string (date-time)` | yes |   |
| `external_account_id` | `string \| null` | yes | A payment provider feed: the account at the provider (`acct_…`). |
| `livemode` | `boolean \| null` | yes | A payment provider feed: live (true) or test (false) data. |
| `fee_accrual_account_code` | `string \| null` | yes | A payment provider feed: the account its fees accrue on. |
| `dispute_account_code` | `string \| null` | yes | A payment provider feed: the account of disputed payments. |
| `reserve_account_code` | `string \| null` | yes | A payment provider feed: the account of funds the provider holds back. |
| `customer_party_id` | `string \| null` | yes | A payment provider feed: the pooled customer party of its receipts. |
| `transaction_count` | `integer` | yes |   |
| `last_booking_date` | `string (date) \| null` | yes |   |
| `ledger_balance_minor` | `integer` | yes | The balance of the ledger account in the feed currency. |
| `bank_balance_minor` | `integer \| null` | yes | The tie-out of verify: the latest closing balance a statement of the account printed (a bank feed sync or a statement file); null when none printed one. |
| `bank_balance_on` | `string (date) \| null` | yes | The day `bank_balance_minor` is valid for (the end of that day). |
| `ledger_balance_on_bank_date_minor` | `integer \| null` | yes | The balance of the ledger account at the end of `bank_balance_on`; null without a bank balance. |
| `bank_difference_minor` | `integer \| null` | yes | The ledger balance less the bank balance on `bank_balance_on`: not 0 when an opening balance or older lines are missing from the books; null without a bank balance. |

### BooksBankAccountPage

One page of BooksBankAccount items, and the cursor of the next page.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `items` | `array of BooksBankAccount` | yes |   |
| `next_cursor` | `string \| null` | yes | Send it back as `cursor` for the next page; null on the last page. |

### BooksBankDirectionEnum

* `in` - in
* `out` - out

One of: `"in"`, `"out"`.

### BooksBankTransaction

A bank transaction with its settlement status, derived on read.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | `string` | yes |   |
| `bank_account_id` | `string` | yes |   |
| `bank_account_label` | `string` | yes |   |
| `currency` | `string` | yes |   |
| `statement_id` | `string \| null` | yes |   |
| `external_id` | `string \| null` | yes |   |
| `booking_date` | `string (date)` | yes |   |
| `value_date` | `string (date) \| null` | yes |   |
| `direction` | `"in" \| "out"` | yes | * `in` - in * `out` - out |
| `method` | `string \| null` | yes |   |
| `amount_minor` | `integer` | yes |   |
| `fee_minor` | `integer` | yes |   |
| `total_minor` | `integer` | yes | Signed: money out is negative. |
| `orig_currency` | `string \| null` | yes |   |
| `orig_minor` | `integer \| null` | yes | The amount in `orig_currency`. |
| `bank_rate` | `string \| null` | yes | The bank's exchange rate, a decimal string. |
| `balance_after_minor` | `integer \| null` | yes |   |
| `counterparty_name` | `string \| null` | yes |   |
| `counterparty_account` | `string \| null` | yes |   |
| `counterparty_bic` | `string \| null` | yes |   |
| `description` | `string \| null` | yes |   |
| `reference` | `string \| null` | yes |   |
| `card_last4` | `string \| null` | yes |   |
| `mcc` | `string \| null` | yes |   |
| `is_internal` | `boolean` | yes |   |
| `party_id` | `string \| null` | yes |   |
| `party_name` | `string \| null` | yes |   |
| `party_source` | `"alias" \| "human" \| NullEnum` | yes | How the party was set. * `alias` - alias * `human` - human |
| `created_at` | `string (date-time)` | yes |   |
| `suspense_residual_minor` | `integer \| null` | yes | The unsettled part of the suspense line; 0 once a judgement (an exemption, a money-in class) clears it; null without one. |
| `status` | `"unmatched" \| "part_matched" \| "matched" \| "exempted" \| "classified" \| "transfer_matched" \| "transfer_unmatched" \| "posted"` | yes | * `unmatched` - unmatched * `part_matched` - part_matched * `matched` - matched * `exempted` - exempted * `classified` - classified * `transfer_matched` - transfer_matched * `transfer_unmatched` - transfer_unmatched * `posted` - posted |
| `has_document` | `boolean` | yes | True when an uploaded file explains the transaction. |
| `file_ids` | `array of string` | yes | The sqids of the uploaded files that explain it (`files/{file_id}/`). |

### BooksBankTransactionDetail

A bank transaction with its source row, entries, allocations and judgements.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | `string` | yes |   |
| `bank_account_id` | `string` | yes |   |
| `bank_account_label` | `string` | yes |   |
| `currency` | `string` | yes |   |
| `statement_id` | `string \| null` | yes |   |
| `external_id` | `string \| null` | yes |   |
| `booking_date` | `string (date)` | yes |   |
| `value_date` | `string (date) \| null` | yes |   |
| `direction` | `"in" \| "out"` | yes | * `in` - in * `out` - out |
| `method` | `string \| null` | yes |   |
| `amount_minor` | `integer` | yes |   |
| `fee_minor` | `integer` | yes |   |
| `total_minor` | `integer` | yes | Signed: money out is negative. |
| `orig_currency` | `string \| null` | yes |   |
| `orig_minor` | `integer \| null` | yes | The amount in `orig_currency`. |
| `bank_rate` | `string \| null` | yes | The bank's exchange rate, a decimal string. |
| `balance_after_minor` | `integer \| null` | yes |   |
| `counterparty_name` | `string \| null` | yes |   |
| `counterparty_account` | `string \| null` | yes |   |
| `counterparty_bic` | `string \| null` | yes |   |
| `description` | `string \| null` | yes |   |
| `reference` | `string \| null` | yes |   |
| `card_last4` | `string \| null` | yes |   |
| `mcc` | `string \| null` | yes |   |
| `is_internal` | `boolean` | yes |   |
| `party_id` | `string \| null` | yes |   |
| `party_name` | `string \| null` | yes |   |
| `party_source` | `"alias" \| "human" \| NullEnum` | yes | How the party was set. * `alias` - alias * `human` - human |
| `created_at` | `string (date-time)` | yes |   |
| `suspense_residual_minor` | `integer \| null` | yes | The unsettled part of the suspense line; 0 once a judgement (an exemption, a money-in class) clears it; null without one. |
| `status` | `"unmatched" \| "part_matched" \| "matched" \| "exempted" \| "classified" \| "transfer_matched" \| "transfer_unmatched" \| "posted"` | yes | * `unmatched` - unmatched * `part_matched` - part_matched * `matched` - matched * `exempted` - exempted * `classified` - classified * `transfer_matched` - transfer_matched * `transfer_unmatched` - transfer_unmatched * `posted` - posted |
| `has_document` | `boolean` | yes | True when an uploaded file explains the transaction. |
| `file_ids` | `array of string` | yes | The sqids of the uploaded files that explain it (`files/{file_id}/`). |
| `raw` | `any` | yes | The source row as the statement parser stored it. |
| `entries` | `array of BooksBankTransactionEntry` | yes |   |
| `allocations` | `array of BooksAllocation` | yes |   |
| `exemption` | `BooksExemption \| null` | yes |   |
| `money_in` | `BooksMoneyIn \| null` | yes |   |
| `transfer_match` | `BooksTransferMatch \| null` | yes |   |

### BooksBankTransactionEntry

A journal entry posted from a bank transaction.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | `string` | yes |   |
| `journal` | `"purchases" \| "sales" \| "bank" \| "general" \| "opening" \| "closing"` | yes | * `purchases` - purchases * `sales` - sales * `bank` - bank * `general` - general * `opening` - opening * `closing` - closing |
| `entry_no` | `integer` | yes |   |
| `economic_date` | `string (date)` | yes |   |
| `source_kind` | `"invoice_revision" \| "bank_transaction" \| "allocation" \| "transaction_exemption" \| "transaction_money_in" \| "accounting_event" \| "vat_return"` | yes | * `invoice_revision` - invoice_revision * `bank_transaction` - bank_transaction * `allocation` - allocation * `transaction_exemption` - transaction_exemption * `transaction_money_in` - transaction_money_in * `accounting_event` - accounting_event * `vat_return` - vat_return |
| `source_role` | `"primary" \| "reversal" \| "replacement"` | yes | * `primary` - primary * `reversal` - reversal * `replacement` - replacement |
| `state` | `"posted" \| "reversed"` | yes | * `posted` - posted * `reversed` - reversed |

### BooksBankTransactionPage

One page of BooksBankTransaction items, and the cursor of the next page.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `items` | `array of BooksBankTransaction` | yes |   |
| `next_cursor` | `string \| null` | yes | Send it back as `cursor` for the next page; null on the last page. |

### BooksBankTransactionStatusEnum

* `unmatched` - unmatched
* `part_matched` - part_matched
* `matched` - matched
* `exempted` - exempted
* `classified` - classified
* `transfer_matched` - transfer_matched
* `transfer_unmatched` - transfer_unmatched
* `posted` - posted

One of: `"unmatched"`, `"part_matched"`, `"matched"`, `"exempted"`, `"classified"`, `"transfer_matched"`, `"transfer_unmatched"`, `"posted"`.

### BooksControlKindEnum

* `payable` - payable
* `receivable` - receivable
* `suspense_payable` - suspense_payable
* `suspense_receivable` - suspense_receivable
* `bank` - bank
* `transit` - transit
* `vat` - vat

One of: `"payable"`, `"receivable"`, `"suspense_payable"`, `"suspense_receivable"`, `"bank"`, `"transit"`, `"vat"`.

### BooksDimension

A dimension axis with all its values.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | `string` | yes |   |
| `code` | `string` | yes |   |
| `name` | `string` | yes |   |
| `kind` | `"project" \| "grant" \| "client" \| "department" \| "other"` | yes | * `project` - project * `grant` - grant * `client` - client * `department` - department * `other` - other |
| `basis` | `string` | yes | `net` or `cost`. |
| `active` | `boolean` | yes |   |
| `created_at` | `string (date-time)` | yes |   |
| `values` | `array of BooksDimensionValue` | yes |   |

### BooksDimensionKindEnum

* `project` - project
* `grant` - grant
* `client` - client
* `department` - department
* `other` - other

One of: `"project"`, `"grant"`, `"client"`, `"department"`, `"other"`.

### BooksDimensionPage

One page of BooksDimension items, and the cursor of the next page.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `items` | `array of BooksDimension` | yes |   |
| `next_cursor` | `string \| null` | yes | Send it back as `cursor` for the next page; null on the last page. |

### BooksDimensionValue

A value of a dimension.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | `string` | yes |   |
| `code` | `string` | yes |   |
| `name` | `string` | yes |   |
| `valid_from` | `string (date) \| null` | yes |   |
| `valid_to` | `string (date) \| null` | yes |   |
| `active` | `boolean` | yes |   |

### BooksDocument

A document record of the books. The file bytes belong to the `documents` app.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | `string` | yes |   |
| `sha256` | `string` | yes |   |
| `legacy_sha1` | `string \| null` | yes |   |
| `kind` | `"invoice" \| "receipt" \| "credit_note" \| "statement" \| "contract" \| "other"` | yes | * `invoice` - invoice * `receipt` - receipt * `credit_note` - credit_note * `statement` - statement * `contract` - contract * `other` - other |
| `filename` | `string` | yes |   |
| `media_type` | `string \| null` | yes |   |
| `size_bytes` | `integer \| null` | yes |   |
| `storage_ref` | `string \| null` | yes | The sqid of the Django document that holds the file. |
| `received_on` | `string (date) \| null` | yes |   |
| `retention_until` | `string (date) \| null` | yes |   |
| `legal_hold` | `boolean` | yes |   |
| `created_at` | `string (date-time)` | yes |   |
| `referenced` | `boolean` | yes | True when the books refer to the document (an invoice, a statement, an event, a return). |
| `file_id` | `string \| null` | yes | The sqid of the stored file (`files/{file_id}/`), or null when none is stored. |
| `download_url` | `string \| null` | yes | The API path that gives a short-lived URL of the bytes (`files/{file_id}/download/`), or null. |

### BooksDocumentDetail

A document with everything in the books that refers to it.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | `string` | yes |   |
| `sha256` | `string` | yes |   |
| `legacy_sha1` | `string \| null` | yes |   |
| `kind` | `"invoice" \| "receipt" \| "credit_note" \| "statement" \| "contract" \| "other"` | yes | * `invoice` - invoice * `receipt` - receipt * `credit_note` - credit_note * `statement` - statement * `contract` - contract * `other` - other |
| `filename` | `string` | yes |   |
| `media_type` | `string \| null` | yes |   |
| `size_bytes` | `integer \| null` | yes |   |
| `storage_ref` | `string \| null` | yes | The sqid of the Django document that holds the file. |
| `received_on` | `string (date) \| null` | yes |   |
| `retention_until` | `string (date) \| null` | yes |   |
| `legal_hold` | `boolean` | yes |   |
| `created_at` | `string (date-time)` | yes |   |
| `referenced` | `boolean` | yes | True when the books refer to the document (an invoice, a statement, an event, a return). |
| `file_id` | `string \| null` | yes | The sqid of the stored file (`files/{file_id}/`), or null when none is stored. |
| `download_url` | `string \| null` | yes | The API path that gives a short-lived URL of the bytes (`files/{file_id}/download/`), or null. |
| `invoices` | `array of BooksDocumentInvoice` | yes |   |
| `bank_statements` | `array of BooksDocumentStatement` | yes |   |
| `accounting_events` | `array of BooksDocumentEvent` | yes |   |
| `vat_returns` | `array of BooksDocumentVatReturn` | yes |   |

### BooksDocumentEvent

An accounting event that refers to a document.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `event_id` | `string` | yes |   |
| `kind` | `string` | yes |   |
| `economic_date` | `string (date)` | yes |   |

### BooksDocumentInvoice

An invoice revision that refers to a document.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `invoice_id` | `string` | yes |   |
| `revision_id` | `string` | yes |   |
| `revision_no` | `integer` | yes |   |
| `revision_state` | `string` | yes |   |
| `role` | `string` | yes |   |

### BooksDocumentKindEnum

* `invoice` - invoice
* `receipt` - receipt
* `credit_note` - credit_note
* `statement` - statement
* `contract` - contract
* `other` - other

One of: `"invoice"`, `"receipt"`, `"credit_note"`, `"statement"`, `"contract"`, `"other"`.

### BooksDocumentPage

One page of BooksDocument items, and the cursor of the next page.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `items` | `array of BooksDocument` | yes |   |
| `next_cursor` | `string \| null` | yes | Send it back as `cursor` for the next page; null on the last page. |

### BooksDocumentStatement

A bank statement that refers to a document.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `statement_id` | `string` | yes |   |
| `bank_account_id` | `string` | yes |   |

### BooksDocumentVatReturn

A VAT return whose response is a document.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `return_id` | `string` | yes |   |
| `form` | `string` | yes |   |
| `period_from` | `string (date)` | yes |   |
| `revision_no` | `integer` | yes |   |

### BooksEntrySourceKindEnum

* `invoice_revision` - invoice_revision
* `bank_transaction` - bank_transaction
* `allocation` - allocation
* `transaction_exemption` - transaction_exemption
* `transaction_money_in` - transaction_money_in
* `accounting_event` - accounting_event
* `vat_return` - vat_return

One of: `"invoice_revision"`, `"bank_transaction"`, `"allocation"`, `"transaction_exemption"`, `"transaction_money_in"`, `"accounting_event"`, `"vat_return"`.

### BooksEntrySourceRoleEnum

* `primary` - primary
* `reversal` - reversal
* `replacement` - replacement

One of: `"primary"`, `"reversal"`, `"replacement"`.

### BooksEntryStateEnum

* `posted` - posted
* `reversed` - reversed

One of: `"posted"`, `"reversed"`.

### BooksExemption

The exemption that judges a bank transaction.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `counter_role` | `"transfer_transit" \| "supplier_prepayment" \| "customer_prepayment" \| "vat_input" \| "vat_input_rc" \| "vat_output" \| "vat_output_rc" \| "vat_payable" \| "vat_non_deductible" \| "tax_receivable" \| "expense_default" \| "software_expense" \| "hosting_expense" \| "prof_fees" \| "travel_expense" \| "bank_charges" \| "income_default" \| "interest_income" \| "interest_expense" \| "fx_gain" \| "fx_loss" \| "rounding" \| "payroll_expense" \| "payroll_liability" \| "payroll_tax" \| "grant_liability" \| "grant_income" \| "loan_payable" \| "loan_receivable" \| "owner_capital" \| "owner_drawings" \| "accrued_expense" \| "prepaid_expense" \| "deferred_income" \| "opening_balance" \| "retained_earnings" \| "current_year_result" \| "discount_received" \| "discount_allowed" \| "writeoff" \| "bad_debt" \| "dividend_payable" \| "distribution_tax_expense" \| "distribution_tax_liability" \| "share_capital" \| "legal_reserve"` | yes | * `transfer_transit` - transfer_transit * `supplier_prepayment` - supplier_prepayment * `customer_prepayment` - customer_prepayment * `vat_input` - vat_input * `vat_input_rc` - vat_input_rc * `vat_output` - vat_output * `vat_output_rc` - vat_output_rc * `vat_payable` - vat_payable * `vat_non_deductible` - vat_non_deductible * `tax_receivable` - tax_receivable * `expense_default` - expense_default * `software_expense` - software_expense * `hosting_expense` - hosting_expense * `prof_fees` - prof_fees * `travel_expense` - travel_expense * `bank_charges` - bank_charges * `income_default` - income_default * `interest_income` - interest_income * `interest_expense` - interest_expense * `fx_gain` - fx_gain * `fx_loss` - fx_loss * `rounding` - rounding * `payroll_expense` - payroll_expense * `payroll_liability` - payroll_liability * `payroll_tax` - payroll_tax * `grant_liability` - grant_liability * `grant_income` - grant_income * `loan_payable` - loan_payable * `loan_receivable` - loan_receivable * `owner_capital` - owner_capital * `owner_drawings` - owner_drawings * `accrued_expense` - accrued_expense * `prepaid_expense` - prepaid_expense * `deferred_income` - deferred_income * `opening_balance` - opening_balance * `retained_earnings` - retained_earnings * `current_year_result` - current_year_result * `discount_received` - discount_received * `discount_allowed` - discount_allowed * `writeoff` - writeoff * `bad_debt` - bad_debt * `dividend_payable` - dividend_payable * `distribution_tax_expense` - distribution_tax_expense * `distribution_tax_liability` - distribution_tax_liability * `share_capital` - share_capital * `legal_reserve` - legal_reserve |
| `reason` | `string` | yes |   |
| `created_at` | `string (date-time)` | yes |   |

### BooksExemptionRoleEnum

* `transfer_transit` - transfer_transit
* `supplier_prepayment` - supplier_prepayment
* `customer_prepayment` - customer_prepayment
* `vat_input` - vat_input
* `vat_input_rc` - vat_input_rc
* `vat_output` - vat_output
* `vat_output_rc` - vat_output_rc
* `vat_payable` - vat_payable
* `vat_non_deductible` - vat_non_deductible
* `tax_receivable` - tax_receivable
* `expense_default` - expense_default
* `software_expense` - software_expense
* `hosting_expense` - hosting_expense
* `prof_fees` - prof_fees
* `travel_expense` - travel_expense
* `bank_charges` - bank_charges
* `income_default` - income_default
* `interest_income` - interest_income
* `interest_expense` - interest_expense
* `fx_gain` - fx_gain
* `fx_loss` - fx_loss
* `rounding` - rounding
* `payroll_expense` - payroll_expense
* `payroll_liability` - payroll_liability
* `payroll_tax` - payroll_tax
* `grant_liability` - grant_liability
* `grant_income` - grant_income
* `loan_payable` - loan_payable
* `loan_receivable` - loan_receivable
* `owner_capital` - owner_capital
* `owner_drawings` - owner_drawings
* `accrued_expense` - accrued_expense
* `prepaid_expense` - prepaid_expense
* `deferred_income` - deferred_income
* `opening_balance` - opening_balance
* `retained_earnings` - retained_earnings
* `current_year_result` - current_year_result
* `discount_received` - discount_received
* `discount_allowed` - discount_allowed
* `writeoff` - writeoff
* `bad_debt` - bad_debt
* `dividend_payable` - dividend_payable
* `distribution_tax_expense` - distribution_tax_expense
* `distribution_tax_liability` - distribution_tax_liability
* `share_capital` - share_capital
* `legal_reserve` - legal_reserve

One of: `"transfer_transit"`, `"supplier_prepayment"`, `"customer_prepayment"`, `"vat_input"`, `"vat_input_rc"`, `"vat_output"`, `"vat_output_rc"`, `"vat_payable"`, `"vat_non_deductible"`, `"tax_receivable"`, `"expense_default"`, `"software_expense"`, `"hosting_expense"`, `"prof_fees"`, `"travel_expense"`, `"bank_charges"`, `"income_default"`, `"interest_income"`, `"interest_expense"`, `"fx_gain"`, `"fx_loss"`, `"rounding"`, `"payroll_expense"`, `"payroll_liability"`, `"payroll_tax"`, `"grant_liability"`, `"grant_income"`, `"loan_payable"`, `"loan_receivable"`, `"owner_capital"`, `"owner_drawings"`, `"accrued_expense"`, `"prepaid_expense"`, `"deferred_income"`, `"opening_balance"`, `"retained_earnings"`, `"current_year_result"`, `"discount_received"`, `"discount_allowed"`, `"writeoff"`, `"bad_debt"`, `"dividend_payable"`, `"distribution_tax_expense"`, `"distribution_tax_liability"`, `"share_capital"`, `"legal_reserve"`.

### BooksFiscalYearStateEnum

* `open` - open
* `closing` - closing
* `closed` - closed

One of: `"open"`, `"closing"`, `"closed"`.

### BooksFixedAssetLinkEnum

* `acquisition` - acquisition
* `improvement` - improvement
* `disposal_cost` - disposal_cost
* `disposal` - disposal

One of: `"acquisition"`, `"improvement"`, `"disposal_cost"`, `"disposal"`.

### BooksGeneralLedger

The general ledger, one account after the other.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `base_currency` | `string` | yes | The currency of every `*_base_minor` amount: the base currency of the books. |
| `accounts` | `array of BooksLedgerAccount` | yes |   |

### BooksIncomeStatement

The income statement of a period, in the base currency.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `schema` | `BooksReportSchema` | yes | The reporting schema a statement was drawn from. |
| `currency` | `string` | yes |   |
| `compare_from` | `string (date) \| null` | yes |   |
| `compare_to` | `string (date) \| null` | yes |   |
| `simplified` | `boolean` | yes |   |
| `rows` | `array of BooksStatementRow` | yes |   |
| `result_minor` | `integer` | yes | The profit (positive) or the loss (negative) of the period. |
| `compare_result_minor` | `integer \| null` | yes | The same for the comparison period; null without one. |
| `unmapped_accounts` | `array of string` | yes | The codes of accounts with a balance and no line of the scheme. |
| `from` | `string (date)` | yes |   |
| `to` | `string (date)` | yes |   |

### BooksInvoice

An invoice with the header facts of its current revision.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | `string` | yes |   |
| `direction` | `"purchase" \| "sales"` | yes | * `purchase` - purchase * `sales` - sales |
| `kind` | `"invoice" \| "receipt" \| "credit_note" \| "prepayment"` | yes | * `invoice` - invoice * `receipt` - receipt * `credit_note` - credit_note * `prepayment` - prepayment |
| `sign` | `integer` | yes | 1, or -1 for a credit note. |
| `state` | `"recorded" \| "issued" \| "posted" \| "cancelled" \| "void"` | yes | * `recorded` - recorded * `issued` - issued * `posted` - posted * `cancelled` - cancelled * `void` - void |
| `number` | `string \| null` | yes |   |
| `party_id` | `string` | yes |   |
| `party_name` | `string` | yes |   |
| `corrects_invoice_id` | `string \| null` | yes | The invoice a credit note corrects. |
| `origin` | `string` | yes | Who created it (`human`, `import`, ...). |
| `issued_at` | `string (date-time) \| null` | yes |   |
| `cancelled_at` | `string (date-time) \| null` | yes |   |
| `cancel_reason` | `string \| null` | yes |   |
| `created_at` | `string (date-time)` | yes |   |
| `reference_number` | `string \| null` | yes | An issued sales invoice: its Estonian reference number (viitenumber), the 7-3-1 check digit last. Null for every other invoice. |
| `external_source` | `string \| null` | yes | An imported sales invoice: the source of its external number series (`stripe`, `manual`, ...). Null for every other invoice. |
| `revision_id` | `string` | yes | The current revision. |
| `revision_no` | `integer` | yes |   |
| `invoice_date` | `string (date)` | yes |   |
| `supply_date` | `string (date) \| null` | yes |   |
| `due_date` | `string (date) \| null` | yes |   |
| `currency` | `string` | yes |   |
| `net_minor` | `integer` | yes |   |
| `tax_minor` | `integer` | yes |   |
| `gross_minor` | `integer` | yes |   |
| `prepaid_minor` | `integer` | yes |   |
| `rounding_minor` | `integer` | yes |   |
| `amount_due_minor` | `integer` | yes |   |
| `base_gross_minor` | `integer \| null` | yes | The gross amount in the base currency; null until the rate is known. |
| `base_currency` | `string` | yes | The currency of every `*_base_minor` amount: the base currency of the books. |
| `needs_review` | `boolean` | yes |   |
| `review_note` | `string \| null` | yes |   |
| `open_minor` | `integer \| null` | yes | What is still open of the posted invoice, in its currency: 0 when settled; null while not posted. |
| `settlement_state` | `"unposted" \| "unpaid" \| "part_paid" \| "paid" \| "overdue"` | yes | `unposted`, `unpaid`, `part_paid`, `paid`, or `overdue`: unpaid or part paid, due before today. |
| `posted_at` | `string (date-time) \| null` | yes | When the current revision was posted to the ledger; null while not posted. |

### BooksInvoiceAllocation

An active allocation that settles a line of the invoice: a payment, a refund, a credit note.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | `string` | yes |   |
| `kind` | `"payment" \| "refund" \| "credit_offset" \| "prepayment_apply"` | yes | * `payment` - payment * `refund` - refund * `credit_offset` - credit_offset * `prepayment_apply` - prepayment_apply |
| `origin` | `string` | yes | Who allocated it: `human`, `matcher`, `import` or `migration`. |
| `item_currency` | `string` | yes |   |
| `item_minor` | `integer` | yes |   |
| `counter_currency` | `string` | yes |   |
| `counter_minor` | `integer` | yes |   |
| `effective_date` | `string (date)` | yes |   |
| `created_at` | `string (date-time)` | yes |   |
| `bank_transaction_id` | `string \| null` | yes | The bank transaction of the other side; null when the other side is not a bank line (a credit note). |

### BooksInvoiceBaseVat

The VAT of a foreign-currency invoice in the base currency (KMS § 37 (7) p 10, EE-VAT-026).

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `currency` | `string` | yes |   |
| `tax_minor` | `integer` | yes | The VAT in minor units of the base currency. |
| `rates` | `array of BooksInvoiceBaseVatRate` | yes |   |
| `rate` | `BooksInvoiceBaseVatExchangeRate \| null` | yes |   |
| `frozen` | `boolean` | yes | True once the issue froze the rate; a draft shows the rate it would take today. |

### BooksInvoiceBaseVatExchangeRate

The exchange rate the VAT in the base currency was converted at.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `value` | `string` | yes | A decimal string: how many units of `quote` one unit of `base` buys. |
| `base` | `string` | yes |   |
| `quote` | `string` | yes |   |
| `date` | `string (date)` | yes |   |
| `rate_source` | `string` | yes | `ecb`, `market`, `bank` or `manual`. |

### BooksInvoiceBaseVatRate

The VAT of one rate, in the base currency.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `vat_rate_bps` | `integer` | yes | The VAT rate in basis points. |
| `tax_minor` | `integer` | yes | The VAT of the rate in minor units of the base currency. |

### BooksInvoiceDetail

An invoice with its current revision, its history, its entries and its settlement.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | `string` | yes |   |
| `direction` | `"purchase" \| "sales"` | yes | * `purchase` - purchase * `sales` - sales |
| `kind` | `"invoice" \| "receipt" \| "credit_note" \| "prepayment"` | yes | * `invoice` - invoice * `receipt` - receipt * `credit_note` - credit_note * `prepayment` - prepayment |
| `sign` | `integer` | yes | 1, or -1 for a credit note. |
| `state` | `"recorded" \| "issued" \| "posted" \| "cancelled" \| "void"` | yes | * `recorded` - recorded * `issued` - issued * `posted` - posted * `cancelled` - cancelled * `void` - void |
| `number` | `string \| null` | yes |   |
| `party_id` | `string` | yes |   |
| `party_name` | `string` | yes |   |
| `corrects_invoice_id` | `string \| null` | yes | The invoice a credit note corrects. |
| `origin` | `string` | yes | Who created it (`human`, `import`, ...). |
| `issued_at` | `string (date-time) \| null` | yes |   |
| `cancelled_at` | `string (date-time) \| null` | yes |   |
| `cancel_reason` | `string \| null` | yes |   |
| `created_at` | `string (date-time)` | yes |   |
| `reference_number` | `string \| null` | yes | An issued sales invoice: its Estonian reference number (viitenumber), the 7-3-1 check digit last. Null for every other invoice. |
| `external_source` | `string \| null` | yes | An imported sales invoice: the source of its external number series (`stripe`, `manual`, ...). Null for every other invoice. |
| `revision_id` | `string` | yes | The current revision. |
| `revision_no` | `integer` | yes |   |
| `invoice_date` | `string (date)` | yes |   |
| `supply_date` | `string (date) \| null` | yes |   |
| `due_date` | `string (date) \| null` | yes |   |
| `currency` | `string` | yes |   |
| `net_minor` | `integer` | yes |   |
| `tax_minor` | `integer` | yes |   |
| `gross_minor` | `integer` | yes |   |
| `prepaid_minor` | `integer` | yes |   |
| `rounding_minor` | `integer` | yes |   |
| `amount_due_minor` | `integer` | yes |   |
| `base_gross_minor` | `integer \| null` | yes | The gross amount in the base currency; null until the rate is known. |
| `base_currency` | `string` | yes | The currency of every `*_base_minor` amount: the base currency of the books. |
| `needs_review` | `boolean` | yes |   |
| `review_note` | `string \| null` | yes |   |
| `open_minor` | `integer \| null` | yes | What is still open of the posted invoice, in its currency: 0 when settled; null while not posted. |
| `settlement_state` | `"unposted" \| "unpaid" \| "part_paid" \| "paid" \| "overdue"` | yes | `unposted`, `unpaid`, `part_paid`, `paid`, or `overdue`: unpaid or part paid, due before today. |
| `posted_at` | `string (date-time) \| null` | yes | When the current revision was posted to the ledger; null while not posted. |
| `revision` | `BooksInvoiceRevision` | yes | The current revision of an invoice, with its lines and documents. |
| `revisions` | `array of BooksInvoiceRevisionSummary` | yes |   |
| `entries` | `array of BooksInvoiceEntry` | yes |   |
| `settlement` | `BooksSettlement \| null` | yes |   |
| `allocations` | `array of BooksInvoiceAllocation` | yes |   |

### BooksInvoiceDirectionEnum

* `purchase` - purchase
* `sales` - sales

One of: `"purchase"`, `"sales"`.

### BooksInvoiceDocument

A document attached to an invoice revision.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `document_id` | `string` | yes |   |
| `role` | `string` | yes | `original`, ... |
| `filename` | `string` | yes |   |
| `kind` | `"invoice" \| "receipt" \| "credit_note" \| "statement" \| "contract" \| "other"` | yes | * `invoice` - invoice * `receipt` - receipt * `credit_note` - credit_note * `statement` - statement * `contract` - contract * `other` - other |
| `file_id` | `string \| null` | yes | The sqid of the stored file (`files/{file_id}/`), or null when none is stored. |
| `download_url` | `string \| null` | yes | The API path that gives a short-lived URL of the bytes (`files/{file_id}/download/`), or null. |
| `source` | `string \| null` | yes | Where the stored file came from: `email` (the invoice inbox), `upload` (a person), `api` (an API key or an app connected through OAuth), `import` (a migration or a Stripe import), `generated` (made by Oscar) or `other`. More values may come. Null when no file is stored. |

### BooksInvoiceEntry

A journal entry posted from a revision of an invoice.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | `string` | yes |   |
| `revision_id` | `string` | yes |   |
| `journal` | `"purchases" \| "sales" \| "bank" \| "general" \| "opening" \| "closing"` | yes | * `purchases` - purchases * `sales` - sales * `bank` - bank * `general` - general * `opening` - opening * `closing` - closing |
| `entry_no` | `integer` | yes |   |
| `economic_date` | `string (date)` | yes |   |
| `source_role` | `"primary" \| "reversal" \| "replacement"` | yes | * `primary` - primary * `reversal` - reversal * `replacement` - replacement |
| `state` | `"posted" \| "reversed"` | yes | * `posted` - posted * `reversed` - reversed |

### BooksInvoiceKindEnum

* `invoice` - invoice
* `receipt` - receipt
* `credit_note` - credit_note
* `prepayment` - prepayment

One of: `"invoice"`, `"receipt"`, `"credit_note"`, `"prepayment"`.

### BooksInvoiceLine

One line of an invoice revision, in the revision's currency.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | `string` | yes |   |
| `line_no` | `integer` | yes |   |
| `kind` | `string` | yes | `item`, `vat_summary`, ... |
| `description` | `string \| null` | yes |   |
| `quantity` | `string \| null` | yes | A decimal string. |
| `unit` | `string \| null` | yes |   |
| `unit_price_minor` | `integer \| null` | yes | The unit price in whole minor units; null on an item line whose price has a fraction of a minor unit. |
| `unit_price` | `string \| null` | yes | The unit price in major units, a decimal string of at most 6 decimals without trailing zeros (`150.334`); null on a line without a price. |
| `allowance_minor` | `integer` | yes |   |
| `charge_minor` | `integer` | yes |   |
| `net_minor` | `integer` | yes |   |
| `vat_code` | `string` | yes |   |
| `vat_rate_bps` | `integer \| null` | yes | The VAT rate in basis points (2400 is 24 percent). |
| `tax_minor` | `integer` | yes |   |
| `gross_minor` | `integer` | yes |   |
| `account_id` | `string \| null` | yes |   |
| `account_code` | `string \| null` | yes |   |
| `expense_role` | `string \| null` | yes |   |
| `deductible_bps` | `integer \| null` | yes |   |
| `business_use_bps` | `integer \| null` | yes |   |
| `fixed_asset` | `boolean \| null` | yes | A purchase line: whether it buys a fixed asset (KMD row 5.2) as the line set it; null takes it from the account. |
| `fixed_asset_id` | `string \| null` | yes | The asset of the fixed asset register this line buys, improves or sells. |
| `fixed_asset_component_id` | `string \| null` | yes | The component of that asset. |
| `fixed_asset_link` | `"acquisition" \| "improvement" \| "disposal_cost" \| "disposal" \| NullEnum` | yes | `acquisition`, `improvement` or `disposal_cost` on a purchase; `disposal` on a sale. * `acquisition` - acquisition * `improvement` - improvement * `disposal_cost` - disposal_cost * `disposal` - disposal |

### BooksInvoicePage

One page of BooksInvoice items, and the cursor of the next page.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `items` | `array of BooksInvoice` | yes |   |
| `next_cursor` | `string \| null` | yes | Send it back as `cursor` for the next page; null on the last page. |

### BooksInvoiceRevision

The current revision of an invoice, with its lines and documents.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | `string` | yes |   |
| `revision_no` | `integer` | yes |   |
| `state` | `string` | yes | `current` or `superseded`. |
| `party_id` | `string` | yes |   |
| `party_name_raw` | `string \| null` | yes | The party name as the source gave it. |
| `invoice_date` | `string (date)` | yes |   |
| `supply_date` | `string (date) \| null` | yes |   |
| `due_date` | `string (date) \| null` | yes |   |
| `service_from` | `string (date) \| null` | yes |   |
| `service_to` | `string (date) \| null` | yes |   |
| `currency` | `string` | yes |   |
| `net_minor` | `integer` | yes |   |
| `tax_minor` | `integer` | yes |   |
| `gross_minor` | `integer` | yes |   |
| `prepaid_minor` | `integer` | yes |   |
| `rounding_minor` | `integer` | yes |   |
| `amount_due_minor` | `integer` | yes |   |
| `base_gross_minor` | `integer \| null` | yes |   |
| `base_currency` | `string` | yes | The currency of every `*_base_minor` amount: the base currency of the books. |
| `exchange_rate_id` | `string \| null` | yes |   |
| `fx_rate_source` | `string \| null` | yes |   |
| `vat_code_source` | `string \| null` | yes |   |
| `supplier_vat_number` | `string \| null` | yes |   |
| `buyer_vat_number` | `string \| null` | yes |   |
| `seller_snapshot` | `any` | yes | The seller as the document named it, or null. |
| `buyer_snapshot` | `any` | yes | The buyer as the document named it, or null. |
| `source_payload` | `any` | yes | The payload the invoice was recorded from, or null. |
| `needs_review` | `boolean` | yes |   |
| `review_note` | `string \| null` | yes |   |
| `reason` | `string \| null` | yes |   |
| `customer_note` | `string \| null` | yes | An own sales invoice: the note printed for the customer. |
| `prices_include_vat` | `boolean` | yes | An own sales invoice: the unit prices of the item lines include VAT; the books computed each net. |
| `language` | `string \| null` | yes | An own sales invoice: the language of its document, `et` or `en`; null when unset. |
| `base_vat` | `BooksInvoiceBaseVat \| null` | yes | The VAT in the base currency of a revision in another currency that charges VAT; null otherwise, and for a draft while no rate is known. |
| `created_at` | `string (date-time)` | yes |   |
| `actor_id` | `string` | yes | The core actor who recorded the revision. |
| `command_id` | `string` | yes |   |
| `lines` | `array of BooksInvoiceLine` | yes |   |
| `documents` | `array of BooksInvoiceDocument` | yes |   |

### BooksInvoiceRevisionSummary

One revision in the history of an invoice.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | `string` | yes |   |
| `revision_no` | `integer` | yes |   |
| `state` | `string` | yes |   |
| `invoice_date` | `string (date)` | yes |   |
| `gross_minor` | `integer` | yes | In the currency of that revision. |
| `reason` | `string \| null` | yes |   |
| `created_at` | `string (date-time)` | yes |   |

### BooksInvoiceSettlementStateEnum

One of: `"unposted"`, `"unpaid"`, `"part_paid"`, `"paid"`, `"overdue"`.

### BooksInvoiceStateEnum

* `recorded` - recorded
* `issued` - issued
* `posted` - posted
* `cancelled` - cancelled
* `void` - void

One of: `"recorded"`, `"issued"`, `"posted"`, `"cancelled"`, `"void"`.

### BooksJournalEnum

* `purchases` - purchases
* `sales` - sales
* `bank` - bank
* `general` - general
* `opening` - opening
* `closing` - closing

One of: `"purchases"`, `"sales"`, `"bank"`, `"general"`, `"opening"`, `"closing"`.

### BooksLedgerAccount

One account of the general ledger with its lines.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `account_code` | `string` | yes |   |
| `account_name` | `string` | yes |   |
| `account_name_en` | `string \| null` | yes | The English name of the account; null when it has none. |
| `opening_base_minor` | `integer` | yes |   |
| `closing_base_minor` | `integer` | yes |   |
| `lines` | `array of BooksLedgerLine` | yes |   |

### BooksLedgerLine

One line of the general ledger, with the running balance of its account.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `account_code` | `string` | yes |   |
| `economic_date` | `string (date)` | yes |   |
| `journal` | `"purchases" \| "sales" \| "bank" \| "general" \| "opening" \| "closing"` | yes | * `purchases` - purchases * `sales` - sales * `bank` - bank * `general` - general * `opening` - opening * `closing` - closing |
| `entry_no` | `integer` | yes |   |
| `entry_id` | `string` | yes |   |
| `entry_state` | `"posted" \| "reversed"` | yes | * `posted` - posted * `reversed` - reversed |
| `line_no` | `integer` | yes |   |
| `party_id` | `string \| null` | yes |   |
| `currency` | `string` | yes |   |
| `amount_minor` | `integer` | yes | Signed, debit positive, in `currency`. |
| `base_minor` | `integer` | yes |   |
| `running_base_minor` | `integer` | yes |   |
| `memo` | `string \| null` | yes |   |

### BooksMoneyIn

The money-in classification that judges a bank transaction.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `kind` | `"refund" \| "intercompany" \| "owner" \| "tax_refund" \| "grant" \| "loan"` | yes | * `refund` - refund * `intercompany` - intercompany * `owner` - owner * `tax_refund` - tax_refund * `grant` - grant * `loan` - loan |
| `reason` | `string \| null` | yes |   |
| `refund_invoice_id` | `string \| null` | yes |   |
| `refund_bank_transaction_id` | `string \| null` | yes |   |
| `created_at` | `string (date-time)` | yes |   |

### BooksMoneyInKindEnum

* `refund` - refund
* `intercompany` - intercompany
* `owner` - owner
* `tax_refund` - tax_refund
* `grant` - grant
* `loan` - loan

One of: `"refund"`, `"intercompany"`, `"owner"`, `"tax_refund"`, `"grant"`, `"loan"`.

### BooksNormalSideEnum

* `debit` - debit
* `credit` - credit

One of: `"debit"`, `"credit"`.

### BooksOpenItem

An open-item line with its residual.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `line_id` | `string` | yes |   |
| `entry_id` | `string` | yes |   |
| `account_code` | `string` | yes |   |
| `control_kind` | `"payable" \| "receivable" \| "suspense_payable" \| "suspense_receivable" \| "bank" \| "transit" \| "vat" \| NullEnum` | yes |   |
| `party_id` | `string \| null` | yes |   |
| `party_name` | `string \| null` | yes |   |
| `currency` | `string` | yes |   |
| `side` | `string` | yes | `debit` or `credit`: the side the item sits on. |
| `amount_minor` | `integer` | yes |   |
| `base_minor` | `integer` | yes |   |
| `residual_minor` | `integer` | yes |   |
| `residual_base_minor` | `integer` | yes |   |
| `due_date` | `string (date) \| null` | yes |   |
| `economic_date` | `string (date)` | yes |   |
| `invoice_id` | `string \| null` | yes |   |
| `invoice_number` | `string \| null` | yes | The number of the invoice of the item; null without one, or for a draft. |
| `bank_transaction_id` | `string \| null` | yes |   |
| `days_overdue` | `integer \| null` | yes | Days past the due date at the as-of date; 0 or less when not due; null without one. |
| `aging_bucket` | `"no_due_date" \| "not_due" \| "1_30" \| "31_60" \| "61_90" \| "over_90"` | yes | The aging at the as-of date. * `no_due_date` - no_due_date * `not_due` - not_due * `1_30` - 1_30 * `31_60` - 31_60 * `61_90` - 61_90 * `over_90` - over_90 |

### BooksOpenItems

Every open-item line with a residual, as of a date, with its aging.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `as_of` | `string (date)` | yes |   |
| `base_currency` | `string` | yes | The currency of every `*_base_minor` amount: the base currency of the books. |
| `items` | `array of BooksOpenItem` | yes |   |

### BooksParty

A party: a supplier, a customer, an authority, ...

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | `string` | yes |   |
| `name` | `string` | yes |   |
| `name_key` | `string` | yes | The cleaned matching key of the name. |
| `kind` | `"supplier" \| "customer" \| "employee" \| "authority" \| "group_company" \| "other"` | yes | * `supplier` - supplier * `customer` - customer * `employee` - employee * `authority` - authority * `group_company` - group_company * `other` - other |
| `country` | `string \| null` | yes |   |
| `vat_area` | `string \| null` | yes | `domestic`, `eu`, `non_eu`. |
| `vat_area_source` | `string \| null` | yes |   |
| `vat_number` | `string \| null` | yes |   |
| `vies_checked_at` | `string (date-time) \| null` | yes |   |
| `reg_code` | `string \| null` | yes |   |
| `expects_document` | `boolean` | yes |   |
| `is_confirmed` | `boolean` | yes |   |
| `merged_into_id` | `string \| null` | yes | The party this one was merged into. |
| `notes` | `string \| null` | yes |   |
| `created_at` | `string (date-time)` | yes |   |
| `external_key` | `string \| null` | yes | The key of the party in another system, for example a Stripe customer. |
| `private_persons` | `boolean` | yes | The party pools private persons (card buyers): the KMD INF annex leaves it out. |
| `address` | `string \| null` | yes | The postal address printed on an invoice, one or more lines. |
| `email` | `string \| null` | yes | The email address of the party. |
| `phone` | `string \| null` | yes | The phone number of the party. |
| `roles` | `array of "supplier" \| "customer"` | yes | What the party is to the company: `supplier` when its kind is supplier or it has a purchase invoice (or an open purchase draft), `customer` when its kind is customer or it has a sales invoice. Void invoices do not count. Empty for a party of another kind with no invoice. |

### BooksPartyDefaults

The defaults the books apply to a party's invoices.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `expense_role` | `string \| null` | yes |   |
| `vat_code` | `string \| null` | yes |   |
| `currency` | `string \| null` | yes |   |
| `payment_days` | `integer \| null` | yes |   |
| `language` | `"et" \| "en" \| NullEnum` | yes | The language a new own sales invoice to the party starts in; null: no preference. * `et` - et * `en` - en |

### BooksPartyDetail

A party with its defaults.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | `string` | yes |   |
| `name` | `string` | yes |   |
| `name_key` | `string` | yes | The cleaned matching key of the name. |
| `kind` | `"supplier" \| "customer" \| "employee" \| "authority" \| "group_company" \| "other"` | yes | * `supplier` - supplier * `customer` - customer * `employee` - employee * `authority` - authority * `group_company` - group_company * `other` - other |
| `country` | `string \| null` | yes |   |
| `vat_area` | `string \| null` | yes | `domestic`, `eu`, `non_eu`. |
| `vat_area_source` | `string \| null` | yes |   |
| `vat_number` | `string \| null` | yes |   |
| `vies_checked_at` | `string (date-time) \| null` | yes |   |
| `reg_code` | `string \| null` | yes |   |
| `expects_document` | `boolean` | yes |   |
| `is_confirmed` | `boolean` | yes |   |
| `merged_into_id` | `string \| null` | yes | The party this one was merged into. |
| `notes` | `string \| null` | yes |   |
| `created_at` | `string (date-time)` | yes |   |
| `external_key` | `string \| null` | yes | The key of the party in another system, for example a Stripe customer. |
| `private_persons` | `boolean` | yes | The party pools private persons (card buyers): the KMD INF annex leaves it out. |
| `address` | `string \| null` | yes | The postal address printed on an invoice, one or more lines. |
| `email` | `string \| null` | yes | The email address of the party. |
| `phone` | `string \| null` | yes | The phone number of the party. |
| `roles` | `array of "supplier" \| "customer"` | yes | What the party is to the company: `supplier` when its kind is supplier or it has a purchase invoice (or an open purchase draft), `customer` when its kind is customer or it has a sales invoice. Void invoices do not count. Empty for a party of another kind with no invoice. |
| `defaults` | `BooksPartyDefaults \| null` | yes |   |

### BooksPartyKindEnum

* `supplier` - supplier
* `customer` - customer
* `employee` - employee
* `authority` - authority
* `group_company` - group_company
* `other` - other

One of: `"supplier"`, `"customer"`, `"employee"`, `"authority"`, `"group_company"`, `"other"`.

### BooksPartyPage

One page of BooksParty items, and the cursor of the next page.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `items` | `array of BooksParty` | yes |   |
| `next_cursor` | `string \| null` | yes | Send it back as `cursor` for the next page; null on the last page. |

### BooksPartySourceEnum

* `alias` - alias
* `human` - human

One of: `"alias"`, `"human"`.

### BooksPeriod

An accounting period and its fiscal year.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | `string` | yes |   |
| `fiscal_year_id` | `string` | yes |   |
| `fiscal_year_label` | `string` | yes |   |
| `fiscal_year_state` | `"open" \| "closing" \| "closed"` | yes | * `open` - open * `closing` - closing * `closed` - closed |
| `code` | `string` | yes | `2026-03`. |
| `start_date` | `string (date)` | yes |   |
| `end_date` | `string (date)` | yes |   |
| `state` | `"open" \| "soft_closed" \| "locked"` | yes | * `open` - open * `soft_closed` - soft_closed * `locked` - locked |
| `locked_at` | `string (date-time) \| null` | yes |   |
| `locked_reason` | `string \| null` | yes |   |
| `close_generation` | `integer` | yes |   |

### BooksPeriodPage

One page of BooksPeriod items, and the cursor of the next page.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `items` | `array of BooksPeriod` | yes |   |
| `next_cursor` | `string \| null` | yes | Send it back as `cursor` for the next page; null on the last page. |

### BooksPeriodStateEnum

* `open` - open
* `soft_closed` - soft_closed
* `locked` - locked

One of: `"open"`, `"soft_closed"`, `"locked"`.

### BooksProblem

An RFC 9457 problem details body (section 11.5).

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `type` | `string` | yes | A URL that names the problem. |
| `title` | `string` | yes |   |
| `status` | `integer` | yes |   |
| `code` | `string` | yes | Stable and machine-readable; for a core error, the core's code. |
| `detail` | `string` | yes |   |
| `errors` | `array of BooksProblemFieldError` | yes |   |

### BooksProblemFieldError

One invalid field of a validation problem.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `field` | `string \| null` | yes | The field or query parameter, dotted for nested fields; null for the whole request. |
| `code` | `string` | yes |   |
| `detail` | `string` | yes |   |

### BooksReportSchema

The reporting schema a statement was drawn from.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `key` | `string` | yes |   |
| `version` | `string` | yes |   |
| `jurisdiction` | `string` | yes | The country of the scheme (`EE`). |
| `kind` | `string` | yes | `balance_sheet` or `income_statement`. |
| `name` | `string` | yes |   |
| `content_hash` | `string` | yes | The SHA-256 of the schema, so a report names the exact scheme it used. |

### BooksReviewStateEnum

* `provisional` - provisional
* `verified` - verified

One of: `"provisional"`, `"verified"`.

### BooksSettlement

How far an invoice is settled. `paid` and `credited` are derived, never stored.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `invoice_id` | `string` | yes |   |
| `number` | `string \| null` | yes |   |
| `direction` | `"purchase" \| "sales"` | yes | * `purchase` - purchase * `sales` - sales |
| `kind` | `"invoice" \| "receipt" \| "credit_note" \| "prepayment"` | yes | * `invoice` - invoice * `receipt` - receipt * `credit_note` - credit_note * `prepayment` - prepayment |
| `state` | `"recorded" \| "issued" \| "posted" \| "cancelled" \| "void"` | yes | * `recorded` - recorded * `issued` - issued * `posted` - posted * `cancelled` - cancelled * `void` - void |
| `party_id` | `string` | yes |   |
| `currency` | `string` | yes |   |
| `gross_minor` | `integer` | yes |   |
| `residual_minor` | `integer \| null` | yes | What is still open; null while the invoice is not posted. |
| `status` | `"open" \| "part_settled" \| "settled" \| "unposted"` | yes | * `open` - open * `part_settled` - part_settled * `settled` - settled * `unposted` - unposted |
| `paid` | `boolean` | yes | Settled to zero through cash-backed allocations. |
| `credited` | `boolean` | yes | A posted credit note names this invoice. |
| `written_off` | `boolean` | yes | Settled with a write-off: settled but not paid. |

### BooksSettlementStatusEnum

* `open` - open
* `part_settled` - part_settled
* `settled` - settled
* `unposted` - unposted

One of: `"open"`, `"part_settled"`, `"settled"`, `"unposted"`.

### BooksStatementAccount

One account inside a line of a statement.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `account_code` | `string` | yes |   |
| `account_name` | `string` | yes |   |
| `account_name_en` | `string \| null` | yes |   |
| `amount_minor` | `integer` | yes | In minor units of the base currency. |
| `compare_minor` | `integer \| null` | yes | The amount at the comparison date or period; null without one. |

### BooksStatementRow

One row of a statement: a heading, a line or a total.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `code` | `string` | yes |   |
| `label` | `string` | yes |   |
| `label_et` | `string \| null` | yes | The Estonian label. |
| `level` | `integer` | yes | The depth of the row, 0 at the top. |
| `kind` | `"heading" \| "line" \| "total"` | yes | `heading` has no amount. * `heading` - heading * `line` - line * `total` - total |
| `amount_minor` | `integer \| null` | yes | In minor units of the base currency; null on a heading. |
| `compare_minor` | `integer \| null` | yes | The amount at the comparison date or period; null without one. |
| `accounts` | `array of BooksStatementAccount` | yes | Empty on a heading, a total and in the simplified view. |

### BooksStatementRowKindEnum

* `heading` - heading
* `line` - line
* `total` - total

One of: `"heading"`, `"line"`, `"total"`.

### BooksTransferMatch

The match of the two legs of an internal transfer.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | `string` | yes |   |
| `out_transaction_id` | `string` | yes |   |
| `in_transaction_id` | `string` | yes |   |
| `residue_base_minor` | `integer \| null` | yes |   |
| `base_currency` | `string` | yes | The currency of every `*_base_minor` amount: the base currency of the books. |
| `accounting_event_id` | `string \| null` | yes |   |

### BooksTrialBalance

The trial balance of a range, in the base currency.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `base_currency` | `string` | yes | The currency of every `*_base_minor` amount: the base currency of the books. |
| `rows` | `array of BooksTrialBalanceRow` | yes |   |
| `total_debit_base_minor` | `integer` | yes |   |
| `total_credit_base_minor` | `integer` | yes |   |
| `balanced` | `boolean` | yes |   |
| `from` | `string (date) \| null` | yes |   |
| `to` | `string (date) \| null` | yes |   |

### BooksTrialBalanceRow

One account of the trial balance, in the base currency.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `account_code` | `string` | yes |   |
| `account_name` | `string` | yes |   |
| `account_name_en` | `string \| null` | yes | The English name of the account; null when it has none. |
| `account_type` | `"asset" \| "liability" \| "equity" \| "income" \| "expense"` | yes | * `asset` - asset * `liability` - liability * `equity` - equity * `income` - income * `expense` - expense |
| `opening_base_minor` | `integer` | yes |   |
| `debit_base_minor` | `integer` | yes |   |
| `credit_base_minor` | `integer` | yes |   |
| `closing_base_minor` | `integer` | yes |   |

### BooksVatCode

A VAT code with its rates.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | `string` | yes |   |
| `code` | `string` | yes | `EE-SAL-STD`. |
| `name` | `string` | yes | The name in English. |
| `name_et` | `string \| null` | yes | The name in Estonian; null when the code has none (show `name`). |
| `country` | `string` | yes |   |
| `direction` | `"purchase" \| "sales" \| "both"` | yes | * `purchase` - purchase * `sales` - sales * `both` - both |
| `treatment` | `"standard" \| "reduced" \| "zero" \| "exempt" \| "out_of_scope" \| "rc_eu_services" \| "rc_eu_goods" \| "rc_domestic" \| "rc_non_eu" \| "foreign_vat" \| "oss" \| "unknown"` | yes | * `standard` - standard * `reduced` - reduced * `zero` - zero * `exempt` - exempt * `out_of_scope` - out_of_scope * `rc_eu_services` - rc_eu_services * `rc_eu_goods` - rc_eu_goods * `rc_domestic` - rc_domestic * `rc_non_eu` - rc_non_eu * `foreign_vat` - foreign_vat * `oss` - oss * `unknown` - unknown |
| `self_assess` | `boolean` | yes |   |
| `deductible_bps` | `integer` | yes |   |
| `exigibility` | `"invoice" \| "payment"` | yes | * `invoice` - invoice * `payment` - payment |
| `ec_sales` | `boolean` | yes |   |
| `requires_party_vat` | `boolean` | yes |   |
| `review_state` | `"provisional" \| "verified"` | yes | * `provisional` - provisional * `verified` - verified |
| `exempt_category` | `string \| null` | yes | An exempt code: `real_estate`, `insurance`, `financial` (counted in the VAT registration turnover) or `other` (not counted); null when not classified (counted). |
| `active` | `boolean` | yes |   |
| `created_at` | `string (date-time)` | yes |   |
| `rates` | `array of BooksVatRate` | yes |   |

### BooksVatCodeDirectionEnum

* `purchase` - purchase
* `sales` - sales
* `both` - both

One of: `"purchase"`, `"sales"`, `"both"`.

### BooksVatCodePage

One page of BooksVatCode items, and the cursor of the next page.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `items` | `array of BooksVatCode` | yes |   |
| `next_cursor` | `string \| null` | yes | Send it back as `cursor` for the next page; null on the last page. |

### BooksVatExigibilityEnum

* `invoice` - invoice
* `payment` - payment

One of: `"invoice"`, `"payment"`.

### BooksVatPreview

What preparing the VAT return of a period would write, without writing it.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `form` | `string` | yes |   |
| `form_version` | `string` | yes |   |
| `period_from` | `string (date)` | yes |   |
| `period_to` | `string (date)` | yes |   |
| `boxes` | `object` | yes | Box to amount in minor units of the base currency. |
| `base_currency` | `string` | yes | The currency of every `*_base_minor` amount: the base currency of the books. |
| `recognitions` | `integer` | yes | The VAT recognitions the return would include. |
| `due_date` | `string (date) \| null` | no | The deadline of the return of the period: the 20th of the next month, moved to the next working day after a weekend or a public holiday. Null when the period is not one calendar month. |

### BooksVatRate

A rate of a VAT code over a range of dates.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | `string` | yes |   |
| `valid_from` | `string (date)` | yes |   |
| `valid_to` | `string (date) \| null` | yes |   |
| `rate_bps` | `integer` | yes | The rate in basis points: 2400 is 24 percent. |
| `review_state` | `"provisional" \| "verified"` | yes | * `provisional` - provisional * `verified` - verified |

### BooksVatTreatmentEnum

* `standard` - standard
* `reduced` - reduced
* `zero` - zero
* `exempt` - exempt
* `out_of_scope` - out_of_scope
* `rc_eu_services` - rc_eu_services
* `rc_eu_goods` - rc_eu_goods
* `rc_domestic` - rc_domestic
* `rc_non_eu` - rc_non_eu
* `foreign_vat` - foreign_vat
* `oss` - oss
* `unknown` - unknown

One of: `"standard"`, `"reduced"`, `"zero"`, `"exempt"`, `"out_of_scope"`, `"rc_eu_services"`, `"rc_eu_goods"`, `"rc_domestic"`, `"rc_non_eu"`, `"foreign_vat"`, `"oss"`, `"unknown"`.

### CancelInvoiceBodyRequest

`cancel_invoice`: withdraw an issued sales invoice or a posted purchase invoice; the number is kept, a posted entry is reversed.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `reason` | `string` | yes |   |

### CommandOutcome

The core's `CommandOutcome`: what one command did.

A repeat with the same `Idempotency-Key` and the same body returns the
stored outcome with `replayed` true.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `command` | `string` | yes |   |
| `command_id` | `string` | yes | The core id of the command, a ULID. |
| `commit_seq` | `integer` | yes | The commit sequence of the file after it. |
| `replayed` | `boolean` | yes |   |
| `result` | `any` | yes | The command's result: the ids it created, and more. |

### Company

A company as the API shows it. `core_company_id` is null until provisioning chose it.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | `string` | yes |   |
| `organization_id` | `string` | yes | The sqid of the company's organization, without loading it. |
| `name` | `string` | yes |   |
| `registry_code` | `string` | yes |   |
| `vat_number` | `string` | yes | The VAT number of the latest VAT registration by date. It changes only through `POST vat-registrations` (`record_vat_registration`). |
| `vat_status` | `"registered" \| "limited" \| "unregistered"` | yes | The status of the latest VAT registration by date. The books apply the status by date: `GET vat-registration/`. * `registered` - VAT-registered * `limited` - Limited taxable person * `unregistered` - Not VAT-registered |
| `vat_status_from` | `string (date) \| null` | yes | The first day of `vat_status`; null for the status at creation. |
| `legal_form` | `"ou" \| "as" \| "fie" \| "mtu" \| "sa" \| "tu" \| "uu" \| "other"` | yes | * `ou` - Osaühing (OÜ) * `as` - Aktsiaselts (AS) * `fie` - Füüsilisest isikust ettevõtja (FIE) * `mtu` - Mittetulundusühing (MTÜ) * `sa` - Sihtasutus (SA) * `tu` - Täisühing (TÜ) * `uu` - Usaldusühing (UÜ) * `other` - Other |
| `files_tsd_monthly` | `boolean` | yes | The accountant set that the company files a TSD every month. False: the TSD reminder of a month comes only when the books show payroll, a dividend payment or a distribution tax in it. Changed with `PATCH /api/companies/{company_id}/`. |
| `state` | `"provisioning" \| "ready" \| "failed" \| "deleted"` | yes | * `provisioning` - Provisioning * `ready` - Ready * `failed` - Failed * `deleted` - Data deleted |
| `core_company_id` | `string \| null` | yes |   |
| `base_currency` | `string` | yes | The base currency of the books (ISO 4217): every amount without its own currency is in it. |
| `created_at` | `string (date-time)` | yes |   |
| `updated_at` | `string (date-time)` | yes |   |

### CompanyDetail

A company with the caller's role and effective permissions in it. Needs `principal` in the context.

The frontend shows or hides each action from `permissions`; it never
computes permissions itself.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | `string` | yes |   |
| `organization_id` | `string` | yes | The sqid of the company's organization, without loading it. |
| `name` | `string` | yes |   |
| `registry_code` | `string` | yes |   |
| `vat_number` | `string` | yes | The VAT number of the latest VAT registration by date. It changes only through `POST vat-registrations` (`record_vat_registration`). |
| `vat_status` | `"registered" \| "limited" \| "unregistered"` | yes | The status of the latest VAT registration by date. The books apply the status by date: `GET vat-registration/`. * `registered` - VAT-registered * `limited` - Limited taxable person * `unregistered` - Not VAT-registered |
| `vat_status_from` | `string (date) \| null` | yes | The first day of `vat_status`; null for the status at creation. |
| `legal_form` | `"ou" \| "as" \| "fie" \| "mtu" \| "sa" \| "tu" \| "uu" \| "other"` | yes | * `ou` - Osaühing (OÜ) * `as` - Aktsiaselts (AS) * `fie` - Füüsilisest isikust ettevõtja (FIE) * `mtu` - Mittetulundusühing (MTÜ) * `sa` - Sihtasutus (SA) * `tu` - Täisühing (TÜ) * `uu` - Usaldusühing (UÜ) * `other` - Other |
| `files_tsd_monthly` | `boolean` | yes | The accountant set that the company files a TSD every month. False: the TSD reminder of a month comes only when the books show payroll, a dividend payment or a distribution tax in it. Changed with `PATCH /api/companies/{company_id}/`. |
| `state` | `"provisioning" \| "ready" \| "failed" \| "deleted"` | yes | * `provisioning` - Provisioning * `ready` - Ready * `failed` - Failed * `deleted` - Data deleted |
| `core_company_id` | `string \| null` | yes |   |
| `base_currency` | `string` | yes | The base currency of the books (ISO 4217): every amount without its own currency is in it. |
| `created_at` | `string (date-time)` | yes |   |
| `updated_at` | `string (date-time)` | yes |   |
| `role` | `"owner" \| "member" \| "viewer" \| NullEnum` | yes |   |
| `permissions` | `array of "organization.read" \| "members.read" \| "api_keys.read" \| "audit.read" \| "books.read" \| "documents.read" \| "payments.read" \| "organization.manage" \| "members.manage" \| "api_keys.manage" \| "companies.create" \| "books.setup" \| "parties.write" \| "documents.write" \| "bank.import" \| "bank.classify" \| "bank.connect" \| "invoices.write" \| "invoices.issue" \| "invoices.post_purchase" \| "invoices.void" \| "allocations.write" \| "reconciliation.decide" \| "events.write" \| "periods.close" \| "periods.reopen" \| "vat.prepare" \| "vat.file" \| "payments.manage" \| "employees.submit" \| "agent.use"` | yes |   |
| `view_as` | `"owner" \| "member" \| "viewer" \| NullEnum` | yes |   |
| `status` | `CompanyStatus \| null` | yes |   |
| `refresh_pending` | `boolean` | yes | True while a rebuild of the status counts is queued or running: a change was made that the counts may not show yet. Read again until it is false. |

### CompanyStateEnum

* `provisioning` - Provisioning
* `ready` - Ready
* `failed` - Failed
* `deleted` - Data deleted

One of: `"provisioning"`, `"ready"`, `"failed"`, `"deleted"`.

### CompanyStatus

The status counts of a company, as the last refresh left them (`books.models.CompanyStatus`).

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `bank_lines_to_classify` | `integer` | yes |   |
| `payments_to_explain` | `integer` | yes | Money out still open that no uploaded file explains. |
| `documents_to_book` | `integer` | yes | Uploaded invoices and receipts nothing in the books refers to, recorded purchase invoices not posted, and open drafts. |
| `pending_proposals` | `integer` | yes |   |
| `open_periods` | `integer` | yes |   |
| `vat_returns_due` | `integer` | yes |   |
| `next_vat_due_date` | `string (date) \| null` | yes | The due date of the next VAT return (KMD): the 20th of the next month, moved to the next working day after a weekend or a public holiday. |
| `last_bank_import_at` | `string (date-time) \| null` | yes |   |
| `overdue_receivables` | `integer` | yes |   |
| `overdue_receivables_minor` | `integer` | yes | The residual of the overdue receivables in the base currency, in cents. |
| `refreshed_at` | `string (date-time) \| null` | yes |   |
| `refresh_error` | `string` | yes | Why the last refresh failed; empty when it did not. |

### CreatePartyOutcome

The `CommandOutcome` of `create_party`, with its result.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `command` | `string` | yes |   |
| `command_id` | `string` | yes | The core id of the command, a ULID. |
| `commit_seq` | `integer` | yes | The commit sequence of the file after it. |
| `replayed` | `boolean` | yes |   |
| `result` | `CreatePartyResult` | yes | The result of `create_party`. |

### CreatePartyPayloadRequest

`create_party`: a customer, a supplier or another counterparty. A manual `vat_area` is a human judgement.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `name` | `string` | yes |   |
| `kind` | `"supplier" \| "customer" \| "employee" \| "authority" \| "group_company" \| "other"` | yes | * `supplier` - supplier * `customer` - customer * `employee` - employee * `authority` - authority * `group_company` - group_company * `other` - other |
| `country` | `string \| null` | no |   |
| `vat_area` | `string \| null` | no |   |
| `vat_number` | `string \| null` | no |   |
| `reg_code` | `string \| null` | no |   |
| `expects_document` | `boolean` | no | Default true. |
| `is_confirmed` | `boolean` | no |   |
| `notes` | `string \| null` | no |   |
| `external_key` | `string \| null` | no | The key of the party in another system, for example `stripe:acct_…:cus_…`. Unique; with it, a party with the same name is allowed. |
| `private_persons` | `boolean` | no | The party pools private persons (card buyers): the KMD INF annex leaves it out. No registry code. Default false. |
| `address` | `string \| null` | no | The postal address printed on an invoice, one or more lines; the country is `country`. At most 500 characters. |
| `email` | `string \| null` | no | The email address of the party. Trimmed; blank is null. At most 254 characters, no whitespace, and exactly one `@` with text on both sides, else 400 `invalid_payload`. |
| `phone` | `string \| null` | no | The phone number of the party. Trimmed; blank is null. At most 40 characters: digits, spaces and `+ - ( ) .`, with at least 5 digits, else 400 `invalid_payload`. |

### CreatePartyResult

The result of `create_party`.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `vat_area` | `string \| null` | yes |   |
| `party_id` | `string` | yes |   |
| `name_key` | `string` | yes |   |

### DraftStateEnum

* `open` - Open
* `recorded` - Recorded
* `discarded` - Discarded
* `duplicate` - Duplicate

One of: `"open"`, `"recorded"`, `"discarded"`, `"duplicate"`.

### Employee

An employee of the company, with the facts of the newest employment. The personal code is masked.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | `string` | yes |   |
| `first_name` | `string` | yes |   |
| `last_name` | `string` | yes |   |
| `personal_code` | `string` | yes | The masked personal code: `*******` and 4 digits. |
| `birth_date` | `string (date) \| null` | yes |   |
| `citizenship` | `string` | yes |   |
| `iban` | `string` | yes |   |
| `email` | `string` | yes |   |
| `basic_exemption` | `"none" \| "full" \| "partial"` | yes | * `none` - No application * `full` - The whole exemption * `partial` - A part of the exemption |
| `basic_exemption_minor` | `integer \| null` | yes |   |
| `pension_rate` | `"none" \| "2" \| "4" \| "6"` | yes | * `none` - None * `2` - 2 percent * `4` - 4 percent * `6` - 6 percent |
| `source` | `"oscar" \| "tor_external"` | yes | * `oscar` - OscarAI * `tor_external` - Registered outside OscarAI |
| `employment_type` | `integer \| null` | yes | The type of the newest employment. |
| `start_date` | `string (date) \| null` | yes |   |
| `end_date` | `string (date) \| null` | yes |   |
| `status` | `"draft" \| "submitted" \| "approved" \| "registered" \| "rejected" \| "ended" \| "cancelled" \| NullEnum` | yes |   |
| `registered_outside` | `boolean` | yes | Whether TÖR shows an employment of the person, or a change of one, not made through OscarAI. |
| `created_at` | `string (date-time)` | yes |   |

### EmployeeDetail

An employee with every employment and its absences.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | `string` | yes |   |
| `first_name` | `string` | yes |   |
| `last_name` | `string` | yes |   |
| `personal_code` | `string` | yes | The masked personal code: `*******` and 4 digits. |
| `birth_date` | `string (date) \| null` | yes |   |
| `citizenship` | `string` | yes |   |
| `iban` | `string` | yes |   |
| `email` | `string` | yes |   |
| `basic_exemption` | `"none" \| "full" \| "partial"` | yes | * `none` - No application * `full` - The whole exemption * `partial` - A part of the exemption |
| `basic_exemption_minor` | `integer \| null` | yes |   |
| `pension_rate` | `"none" \| "2" \| "4" \| "6"` | yes | * `none` - None * `2` - 2 percent * `4` - 4 percent * `6` - 6 percent |
| `source` | `"oscar" \| "tor_external"` | yes | * `oscar` - OscarAI * `tor_external` - Registered outside OscarAI |
| `employment_type` | `integer \| null` | yes | The type of the newest employment. |
| `start_date` | `string (date) \| null` | yes |   |
| `end_date` | `string (date) \| null` | yes |   |
| `status` | `"draft" \| "submitted" \| "approved" \| "registered" \| "rejected" \| "ended" \| "cancelled" \| NullEnum` | yes |   |
| `registered_outside` | `boolean` | yes | Whether TÖR shows an employment of the person, or a change of one, not made through OscarAI. |
| `created_at` | `string (date-time)` | yes |   |
| `employments` | `array of Employment` | yes |   |
| `absences` | `array of Absence` | yes |   |

### EmployeeInputRequest

The person of a new employee, or the changed fields of an employee.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `first_name` | `string` | no |   |
| `last_name` | `string` | no |   |
| `personal_code` | `string` | no | The Estonian personal code: a new employee only. Sealed, never returned. |
| `birth_date` | `string (date) \| null` | no |   |
| `citizenship` | `string` | no |   |
| `iban` | `string` | no |   |
| `email` | `string (email) \| string` | no |   |
| `basic_exemption` | `"none" \| "full" \| "partial"` | no | * `none` - No application * `full` - The whole exemption * `partial` - A part of the exemption |
| `basic_exemption_minor` | `integer \| null` | no |   |
| `pension_rate` | `"none" \| "2" \| "4" \| "6"` | no | * `none` - None * `2` - 2 percent * `4` - 4 percent * `6` - 6 percent |

### EmployeeSourceEnum

* `oscar` - OscarAI
* `tor_external` - Registered outside OscarAI

One of: `"oscar"`, `"tor_external"`.

### EmployeeSubmissionKindEnum

* `new_employee` - New employee
* `new_employment` - New employment
* `change` - Change
* `suspension` - Suspension
* `end` - End

One of: `"new_employee"`, `"new_employment"`, `"change"`, `"suspension"`, `"end"`.

### EmployeeSubmissionStatusEnum

* `submitted` - Submitted
* `approved` - Approved
* `registered` - Registered
* `applied` - Applied
* `rejected` - Rejected

One of: `"submitted"`, `"approved"`, `"registered"`, `"applied"`, `"rejected"`.

### Employment

One employment as TÖR records it, with the status of the workflow. A 601 entry has no rate or workplace.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | `string` | yes |   |
| `toot_id` | `integer \| null` | yes | TÖR's id of the employment; null until registered. |
| `employment_type` | `integer` | yes | The TÖR type: 1 employment contract, 600 services contract, 601 board member, 501 unpaid work. |
| `employment_type_name` | `string` | yes |   |
| `start_date` | `string (date) \| null` | yes |   |
| `end_date` | `string (date) \| null` | yes |   |
| `end_reason_code` | `string` | yes |   |
| `work_time_rate` | `string (decimal) \| null` | yes |   |
| `occupation_code` | `string` | yes |   |
| `workplace_address_id` | `integer \| null` | yes |   |
| `contract_ref` | `string` | yes |   |
| `gross_salary_minor` | `integer \| null` | yes | The monthly contract gross, in cents. |
| `board_fee_minor` | `integer \| null` | yes | The monthly board member fee, in cents. |
| `currency` | `string` | yes |   |
| `suspensions` | `array of Suspension` | yes |   |
| `tor_state_code` | `string` | yes |   |
| `tor_state_name` | `string` | yes |   |
| `tor_seen_at` | `string (date-time) \| null` | yes |   |
| `source` | `"oscar" \| "tor_external"` | yes | * `oscar` - OscarAI * `tor_external` - Registered outside OscarAI |
| `status` | `"draft" \| "submitted" \| "approved" \| "registered" \| "rejected" \| "ended" \| "cancelled"` | yes | * `draft` - Draft * `submitted` - Submitted * `approved` - Approved * `registered` - Registered * `rejected` - Rejected * `ended` - Ended * `cancelled` - Cancelled in TÖR |
| `registered_outside` | `boolean` | yes | TÖR shows something of it not made through OscarAI. |

### EmploymentInputRequest

The employment of a start, or the changed fields of an employment.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `employment_type` | `integer` | no | The TÖR type: 1 employment contract, 600 services contract, 601 board member, 501 unpaid work. |
| `start_date` | `string (date)` | no |   |
| `end_date` | `string (date)` | no | A fixed term: the last day, given with a start. |
| `work_time_rate` | `string (decimal)` | no | 0.01 to 1.00. Required for type 1. |
| `occupation_code` | `string` | no | The occupation code of Statistics Estonia. |
| `workplace_address_id` | `integer` | no | The ADS address id (ADR_ID) of the workplace building. |
| `contract_ref` | `string` | no |   |
| `gross_salary_minor` | `integer \| null` | no |   |
| `board_fee_minor` | `integer \| null` | no |   |

### EmploymentStatusEnum

* `draft` - Draft
* `submitted` - Submitted
* `approved` - Approved
* `registered` - Registered
* `rejected` - Rejected
* `ended` - Ended
* `cancelled` - Cancelled in TÖR

One of: `"draft"`, `"submitted"`, `"approved"`, `"registered"`, `"rejected"`, `"ended"`, `"cancelled"`.

### EndInputRequest

The end of an employment.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `end_date` | `string (date)` | yes | The last day of the employment. |
| `reason_code` | `integer` | yes | The end reason code of the TLP classifier. |

### ForwardingConfirmation

The newest Gmail forwarding confirmation that oscarai forwarded to its requester. Never the code or the link.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `requesting_address` | `string` | yes | The Gmail address that asked to forward. |
| `status` | `"sent"` | yes | * `sent` - sent |
| `sent_at` | `string (date-time) \| null` | yes |   |
| `forwarding_works` | `boolean` | yes | A mail forwarded by the requesting address has arrived since the confirmation was sent. |

### ForwardingConfirmationStatusEnum

* `sent` - sent

One of: `"sent"`.

### HistoryMonth

One month of the pay history the average pay is taken from.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `month` | `string` | yes | YYYY-MM |
| `wages_minor` | `integer` | yes |   |
| `days` | `integer` | yes |   |

### InboundEmail

One mail the inbox received, and what came of it.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | `string` | yes | The sqid of the mail. |
| `received_at` | `string (date-time)` | yes |   |
| `sender` | `string` | yes |   |
| `forwarded_by` | `string` | yes | The member's address that forwarded the mail through a Gmail filter, empty when none did. Set only for an address whose Gmail forwarding confirmation oscarai verified and forwarded. |
| `subject` | `string` | yes |   |
| `status` | `"received" \| "processing" \| "done" \| "failed" \| "ignored"` | yes | * `received` - Received * `processing` - Processing * `done` - Done * `failed` - Failed * `ignored` - Ignored |
| `outcome` | `"documents" \| "body_rendered" \| "no_document" \| "not_an_invoice" \| "forwarding_confirmation" \| "forwarding_confirmation_unverified" \| "unknown_address" \| "revoked_address" \| "too_large" \| ""` | yes |   |
| `unknown_sender` | `boolean` | yes | Neither the sender nor the address that forwarded it is a member. |
| `not_authenticated` | `boolean` | yes | The DMARC check failed. |
| `files` | `array of InboundEmailFile` | yes | The files the mail made (the PDFs kept and the rendered body), each with its draft. |
| `raw_message_id` | `string \| null` | yes | The sqid of the raw message file, kept as evidence. |
| `skipped_attachments` | `array of SkippedAttachment` | yes |   |

### InboundEmailFile

A file a mail made: a PDF kept or the rendered body, and the draft its extraction opened.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | `string` | yes | The sqid of the file. |
| `filename` | `string` | yes | The file name, as the mail gave it. |
| `draft_id` | `string \| null` | yes | The sqid of the newest draft of the file, in any state (open, recorded, discarded or duplicate), or null when the extraction opened none. |

### InboundEmailFileRoleEnum

One of: `"attachment"`, `"rendered_body"`, `"copy"`, `"supporting"`.

### InboundEmailStatusEnum

* `received` - Received
* `processing` - Processing
* `done` - Done
* `failed` - Failed
* `ignored` - Ignored

One of: `"received"`, `"processing"`, `"done"`, `"failed"`, `"ignored"`.

### Inbox

The invoice inbox of a company: its private address and what came in.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `address` | `string (email)` | yes | The private forwarding address of the company. |
| `address_created_at` | `string (date-time)` | yes |   |
| `counts` | `InboxCounts` | yes | The mails of the last 30 days. |
| `gmail_filter_query` | `string` | yes | The search string for a Gmail filter: known suppliers, or invoice words with an attachment. |
| `gmail_filter_query_broad` | `string` | yes | The search string that forwards every mail with a PDF. |
| `forwarding_confirmation` | `ForwardingConfirmation \| null` | yes |   |

### InboxCounts

The mails of the last 30 days.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `received` | `integer` | yes |   |
| `documents` | `integer` | yes | The mails that made at least one file. |
| `not_an_invoice` | `integer` | yes | The mails whose every PDF and body were not invoices. |
| `failed` | `integer` | yes |   |

### InboxOrigin

Where a file came from when it came from the invoice inbox: the mail, its checks and the two flags.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `sender` | `string` | yes | The From address of the mail. |
| `subject` | `string` | yes |   |
| `received_at` | `string (date-time)` | yes |   |
| `spf` | `"pass" \| "fail" \| "gray" \| "processing_failed" \| "unknown"` | yes | The SPF result of the mail, as Resend reports it. * `pass` - pass * `fail` - fail * `gray` - gray * `processing_failed` - processing_failed * `unknown` - unknown |
| `dkim` | `"pass" \| "fail" \| "gray" \| "processing_failed" \| "unknown"` | yes | * `pass` - pass * `fail` - fail * `gray` - gray * `processing_failed` - processing_failed * `unknown` - unknown |
| `dmarc` | `"pass" \| "fail" \| "gray" \| "processing_failed" \| "unknown"` | yes | * `pass` - pass * `fail` - fail * `gray` - gray * `processing_failed` - processing_failed * `unknown` - unknown |
| `forwarded_by` | `string` | yes | The member's address that forwarded the mail through a Gmail filter, empty when none did. |
| `unknown_sender` | `boolean` | yes | Neither the sender nor the address that forwarded it is a member of the organization. |
| `not_authenticated` | `boolean` | yes | The DMARC check of the mail failed. |

### InvoiceDocumentRequest

A document linked to an invoice revision.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `document_id` | `string` | yes |   |
| `role` | `string` | no | `original` (the default) or `supporting`. An own sales invoice takes no `original`: its original is the PDF Oscar issues, so a document on a sales draft is `supporting`. |

### InvoiceLineRequest

One line of an invoice revision. A manual `vat_code` is a human judgement.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `kind` | `string` | no | Default `vat_summary`. |
| `description` | `string \| null` | no |   |
| `quantity` | `string (decimal) \| null \| string` | no |   |
| `unit` | `string \| null` | no |   |
| `unit_price_minor` | `integer \| null` | no | The unit price in whole minor units. `unit_price` also takes a fraction of a minor unit. |
| `unit_price` | `string (decimal) \| null \| string` | no | The unit price in major units, a decimal string of at most 6 decimals (`150.334`). The books compute the net as quantity x unit price, rounded half up to the minor unit. With `unit_price_minor` too, both must name the same price. |
| `allowance_minor` | `integer` | no |   |
| `charge_minor` | `integer` | no |   |
| `net_minor` | `integer \| null` | no |   |
| `vat_code` | `string \| null` | no |   |
| `vat_rate_bps` | `integer \| null` | no |   |
| `tax_minor` | `integer \| null` | no |   |
| `account_code` | `string \| null` | no |   |
| `expense_role` | `string \| null` | no |   |
| `deductible_bps` | `integer` | no | Default 10000. |
| `business_use_bps` | `integer` | no | Default 10000. |
| `fixed_asset` | `boolean \| null` | no | A purchase line only: true or false overrides whether it buys a fixed asset (KMD row 5.2). Null takes it from the account. |
| `fixed_asset_id` | `string \| null` | no | The asset of the fixed asset register this line buys, improves or sells. The link decides the account of the line; a line that names another account is refused. |
| `fixed_asset_component_id` | `string \| null` | no | A component of that asset; default the main component. Needs `fixed_asset_id`. |
| `fixed_asset_link` | `"acquisition" \| "improvement" \| "disposal_cost" \| "disposal" \| NullEnum` | no | `acquisition` (default for a planned asset) or `improvement` (default for an asset in use) or `disposal_cost` on a purchase; `disposal` on a sale. Needs `fixed_asset_id`. * `acquisition` - acquisition * `improvement` - improvement * `disposal_cost` - disposal_cost * `disposal` - disposal |

### InvoiceRevisionRequest

The content of an invoice: one revision. A chosen `exchange_rate_id` is a human judgement.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `party_name_raw` | `string \| null` | no |   |
| `invoice_date` | `string (date)` | yes |   |
| `supply_date` | `string (date) \| null \| string` | no |   |
| `due_date` | `string (date) \| null \| string` | no |   |
| `service_from` | `string (date) \| null \| string` | no |   |
| `service_to` | `string (date) \| null \| string` | no |   |
| `currency` | `string` | yes |   |
| `net_minor` | `integer \| null` | no |   |
| `tax_minor` | `integer \| null` | no |   |
| `gross_minor` | `integer \| null` | no |   |
| `prepaid_minor` | `integer` | no |   |
| `rounding_minor` | `integer` | no |   |
| `exchange_rate_id` | `string \| null` | no |   |
| `vat_code_source` | `string` | no | Default `derived`. |
| `supplier_vat_number` | `string \| null` | no |   |
| `buyer_vat_number` | `string \| null` | no |   |
| `source_payload` | `any \| null` | no |   |
| `needs_review` | `boolean` | no |   |
| `review_note` | `string \| null` | no |   |
| `received_date` | `string (date) \| null \| string` | no | A purchase invoice: the day it was received. It dates the input VAT when the return of the tax point month was filed before. |
| `base_tax_minor` | `integer \| null` | no | A foreign-currency purchase invoice: the VAT in euro it prints, deducted as printed. |
| `customer_note` | `string \| null` | no | An own sales invoice: a note printed for the customer, at most 2000 characters. |
| `prices_include_vat` | `boolean` | no | An own sales invoice: the unit prices, discounts and charges of the item lines include VAT. The books compute the net and the VAT of each line, so the total is the sum of the gross amounts. Every line is an `item` without `net_minor` or `tax_minor`. Default false. |
| `language` | `"et" \| "en" \| NullEnum` | no | An own sales invoice: the language of its document. Null: Estonian for a buyer in Estonia, else English. * `et` - et * `en` - en |
| `lines` | `array of InvoiceLineRequest` | yes |   |
| `documents` | `array of InvoiceDocumentRequest` | no |   |

### IssueInvoiceBodyRequest

`issue_invoice`: number a sales invoice and freeze it.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `number` | `string \| null` | no | Only under a `free` numbering policy. |
| `seller_snapshot` | `any \| null` | no |   |
| `buyer_snapshot` | `any \| null` | no |   |
| `seller_address` | `string \| null` | no | The seller's postal address frozen into the seller snapshot. Without it the API takes the company's address from the Business Register. A VAT-registered company issues no invoice without the seller's and the buyer's address: 400 `seller_address_missing` or `buyer_address_missing` (EE-VAT-020). |

### IssueInvoiceOutcome

The `CommandOutcome` of `issue_invoice`, with its result.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `command` | `string` | yes |   |
| `command_id` | `string` | yes | The core id of the command, a ULID. |
| `commit_seq` | `integer` | yes | The commit sequence of the file after it. |
| `replayed` | `boolean` | yes |   |
| `result` | `IssueInvoiceResult` | yes | The result of `issue_invoice`. |

### IssueInvoiceResult

The result of `issue_invoice`.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `number` | `string` | yes |   |
| `reference_number` | `string` | yes | The Estonian reference number (viitenumber) the payer quotes. |
| `invoice_id` | `string` | yes |   |

### KycLanguageEnum

* `et` - et
* `en` - en

One of: `"et"`, `"en"`.

### LegalFormEnum

* `ou` - Osaühing (OÜ)
* `as` - Aktsiaselts (AS)
* `fie` - Füüsilisest isikust ettevõtja (FIE)
* `mtu` - Mittetulundusühing (MTÜ)
* `sa` - Sihtasutus (SA)
* `tu` - Täisühing (TÜ)
* `uu` - Usaldusühing (UÜ)
* `other` - Other

One of: `"ou"`, `"as"`, `"fie"`, `"mtu"`, `"sa"`, `"tu"`, `"uu"`, `"other"`.

### MailAuthResultEnum

* `pass` - pass
* `fail` - fail
* `gray` - gray
* `processing_failed` - processing_failed
* `unknown` - unknown

One of: `"pass"`, `"fail"`, `"gray"`, `"processing_failed"`, `"unknown"`.

### Me

`GET /api/me/`: the user, the credential, and the organizations and companies the caller can see.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `user` | `MeUser \| null` | yes | The session user, or the creator of the API key or OAuth grant. |
| `has_totp` | `boolean` | yes |   |
| `staff_mfa_required` | `boolean` | yes | True when the user is firm staff but this session did not pass a second factor (TOTP or a passkey): every staff power is off, and the firm API answers 403 mfa_required, until the user logs in with one. |
| `email_verified` | `boolean` | yes |   |
| `credential` | `MeCredential` | yes | How the call was authenticated. |
| `organizations` | `array of MeOrganization` | yes |   |
| `companies` | `array of MeCompany` | yes |   |
| `features` | `MeFeatures` | yes | The features this deployment turns on. The frontend hides what is off. |
| `cli_min_version` | `string` | no | The oldest version of the oscar CLI that may run the onboarding (semver). An older CLI asks the user to update first. Always returned; optional in the schema, so a client keeps working against a server older than the field. |

### MeCompany

A company the caller can see.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | `string` | yes |   |
| `organization_id` | `string` | yes |   |
| `name` | `string` | yes |   |
| `registry_code` | `string` | yes |   |
| `vat_number` | `string` | yes |   |
| `legal_form` | `"ou" \| "as" \| "fie" \| "mtu" \| "sa" \| "tu" \| "uu" \| "other"` | yes | * `ou` - Osaühing (OÜ) * `as` - Aktsiaselts (AS) * `fie` - Füüsilisest isikust ettevõtja (FIE) * `mtu` - Mittetulundusühing (MTÜ) * `sa` - Sihtasutus (SA) * `tu` - Täisühing (TÜ) * `uu` - Usaldusühing (UÜ) * `other` - Other |
| `state` | `"provisioning" \| "ready" \| "failed" \| "deleted"` | yes | Only a `ready` company has books. * `provisioning` - Provisioning * `ready` - Ready * `failed` - Failed * `deleted` - Data deleted |

### MeCredential

How the call was authenticated.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `kind` | `"session" \| "api_key" \| "oauth"` | yes | * `session` - session * `api_key` - api_key * `oauth` - oauth |
| `scopes` | `array of string \| null` | yes | The scopes of an API key or an OAuth token; null for a session, which is not narrowed. |
| `staff_key` | `boolean` | yes | True for a staff API key: a key of no organization that acts as owner in every organization, made in the admin by a superuser. `user` is then its creator. |

### MeCredentialKindEnum

* `session` - session
* `api_key` - api_key
* `oauth` - oauth

One of: `"session"`, `"api_key"`, `"oauth"`.

### MeFeatures

The features this deployment turns on. The frontend hides what is off.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `agent` | `boolean` | yes | The AI agent. Off, every agent endpoint answers 404 agent_disabled. |
| `inbox` | `boolean` | yes | The invoice inbox, a forwarding address for each company. Off, its endpoints answer 409 inbox_disabled. |
| `employees` | `boolean` | yes | The employee register and its sync with TÖR. Off, its endpoints answer 409 employees_disabled. |
| `payroll` | `boolean` | no | Payroll and the payroll tax returns (TSD). Off, their endpoints answer 409 payroll_disabled. |
| `kmd_submission` | `boolean` | no | The VAT return (KMD) is sent to the tax authority over X-tee. Off, the KMD submit answers 503 kmd_submission_disabled: download the file and upload it in e-MTA. |

### MeOrganization

An organization the caller can see, with its role there.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | `string` | yes |   |
| `name` | `string` | yes |   |
| `role` | `"owner" \| "member" \| "viewer" \| NullEnum` | yes |   |
| `is_member` | `boolean` | yes | False for staff who see the organization without a membership. |

### MeUser

The user behind the call.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | `string` | yes | The sqid of the user. |
| `email` | `string (email)` | yes |   |
| `name` | `string` | yes |   |
| `is_staff` | `boolean` | yes | Firm staff: sees every organization as owner. |
| `ui_mode` | `"simple" \| "advanced"` | yes | The mode of the client dashboard the user chose: simple or advanced. * `simple` - Simple * `advanced` - Advanced |

### NetPayment

A payment of an employee's net pay: an allocation in the books.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | `string` | yes | The allocation in the books. |
| `state` | `string` | yes |   |
| `effective_date` | `string (date)` | yes | The bank date. |
| `amount_minor` | `integer` | yes |   |
| `currency` | `string` | yes |   |
| `bank_transaction_id` | `string \| null` | yes |   |

### NullEnum

Type: `null`

### Organization

An organization, with the caller's role and effective permissions in it, and its companies.

Needs the caller's `principal` in the serializer context.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | `string` | yes |   |
| `name` | `string` | yes |   |
| `role` | `"owner" \| "member" \| "viewer" \| NullEnum` | yes |   |
| `permissions` | `array of string` | yes |   |
| `companies` | `array of Company` | yes |   |
| `created_at` | `string (date-time)` | yes |   |
| `updated_at` | `string (date-time)` | yes |   |

### OutcomeEnum

* `` - None yet
* `documents` - Documents
* `body_rendered` - Body rendered
* `no_document` - No document
* `not_an_invoice` - Not an invoice
* `forwarding_confirmation` - Forwarding confirmation
* `forwarding_confirmation_unverified` - Unverified forwarding confirmation
* `unknown_address` - Unknown address
* `revoked_address` - Revoked address
* `too_large` - Too large

One of: `"documents"`, `"body_rendered"`, `"no_document"`, `"not_an_invoice"`, `"forwarding_confirmation"`, `"forwarding_confirmation_unverified"`, `"unknown_address"`, `"revoked_address"`, `"too_large"`.

### PaginatedCompanyList

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `items` | `array of Company` | yes |   |
| `next_cursor` | `string \| null` | yes |   |

### PaginatedEmployeeList

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `items` | `array of Employee` | yes |   |
| `next_cursor` | `string \| null` | yes |   |

### PaginatedInboundEmailList

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `items` | `array of InboundEmail` | yes |   |
| `next_cursor` | `string \| null` | yes |   |

### PaginatedOrganizationList

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `items` | `array of Organization` | yes |   |
| `next_cursor` | `string \| null` | yes |   |

### PaginatedPayRunList

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `items` | `array of PayRun` | yes |   |
| `next_cursor` | `string \| null` | yes |   |

### PaginatedStoredDocumentList

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `items` | `array of StoredDocument` | yes |   |
| `next_cursor` | `string \| null` | yes |   |

### PaginatedSubmissionList

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `items` | `array of Submission` | yes |   |
| `next_cursor` | `string \| null` | yes |   |

### PartyRoleEnum

* `supplier` - supplier
* `customer` - customer

One of: `"supplier"`, `"customer"`.

### PayRun

A pay run: the month, the status, the totals.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | `string` | yes |   |
| `month` | `string` | yes | YYYY-MM |
| `payday` | `string (date)` | yes |   |
| `status` | `"draft" \| "approved" \| "posting" \| "posted"` | yes | * `draft` - Draft * `approved` - Approved * `posting` - Posting * `posted` - Posted |
| `currency` | `string` | yes |   |
| `employee_count` | `integer` | yes |   |
| `gross_minor` | `integer \| null` | yes |   |
| `net_minor` | `integer \| null` | yes |   |
| `withheld_minor` | `integer \| null` | yes |   |
| `employer_tax_minor` | `integer \| null` | yes |   |
| `expense_minor` | `integer \| null` | yes |   |
| `open_net_minor` | `integer \| null` | yes | Posted: the net pay not paid yet. |
| `calculation_error` | `string` | yes | A draft: why the calculation of the books failed. |
| `pay_run_id` | `string \| null` | yes | Posted: the pay run in the books. |
| `approved_at` | `string (date-time) \| null` | yes |   |
| `posted_at` | `string (date-time) \| null` | yes |   |

### PayRunDetail

A pay run with every employee.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | `string` | yes |   |
| `month` | `string` | yes | YYYY-MM |
| `payday` | `string (date)` | yes |   |
| `status` | `"draft" \| "approved" \| "posting" \| "posted"` | yes | * `draft` - Draft * `approved` - Approved * `posting` - Posting * `posted` - Posted |
| `currency` | `string` | yes |   |
| `employee_count` | `integer` | yes |   |
| `gross_minor` | `integer \| null` | yes |   |
| `net_minor` | `integer \| null` | yes |   |
| `withheld_minor` | `integer \| null` | yes |   |
| `employer_tax_minor` | `integer \| null` | yes |   |
| `expense_minor` | `integer \| null` | yes |   |
| `open_net_minor` | `integer \| null` | yes | Posted: the net pay not paid yet. |
| `calculation_error` | `string` | yes | A draft: why the calculation of the books failed. |
| `pay_run_id` | `string \| null` | yes | Posted: the pay run in the books. |
| `approved_at` | `string (date-time) \| null` | yes |   |
| `posted_at` | `string (date-time) \| null` | yes |   |
| `employees` | `array of PayRunEmployee` | yes |   |

### PayRunEmployee

One employee of a pay run: the inputs, and once posted the result, the open net pay and its payments.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | `string` | yes |   |
| `employee_id` | `string` | yes |   |
| `employee_name` | `string` | yes |   |
| `currency` | `string` | yes |   |
| `salary_minor` | `integer` | yes |   |
| `bonus_minor` | `integer` | yes |   |
| `board_fee_minor` | `integer` | yes |   |
| `fringe_benefit_minor` | `integer` | yes |   |
| `fringe_benefit_code` | `string` | yes | The TSD annex 4 code of the fringe benefits. |
| `holiday_days` | `integer` | yes |   |
| `sick_leaves` | `array of SickLeave` | yes |   |
| `pay_history` | `array of HistoryMonth \| null` | yes | The pay history staff gave; null: taken from the posted runs. |
| `pension_rate_bps` | `integer` | yes |   |
| `basic_exemption` | `"none" \| "full" \| "partial"` | yes | * `none` - No application * `full` - The whole exemption * `partial` - A part of the exemption |
| `basic_exemption_minor` | `integer \| null` | yes |   |
| `social_tax_minimum` | `"full" \| "prorated" \| "none"` | yes | * `full` - The whole minimum * `prorated` - In proportion to the days * `none` - None |
| `social_tax_minimum_days` | `integer \| null` | yes |   |
| `unemployment_insurance_employee` | `boolean` | yes |   |
| `gross_minor` | `integer \| null` | yes | Posted: the gross pay of the month. |
| `net_minor` | `integer \| null` | yes | Posted: the net pay. |
| `open_net_minor` | `integer \| null` | yes | Posted: the net pay not paid yet. |
| `payments` | `array of NetPayment` | yes |   |

### PayRunStatusEnum

* `draft` - Draft
* `approved` - Approved
* `posting` - Posting
* `posted` - Posted

One of: `"draft"`, `"approved"`, `"posting"`, `"posted"`.

### PensionRateEnum

* `none` - None
* `2` - 2 percent
* `4` - 4 percent
* `6` - 6 percent

One of: `"none"`, `"2"`, `"4"`, `"6"`.

### PermissionEnum

* `organization.read` - organization.read
* `members.read` - members.read
* `api_keys.read` - api_keys.read
* `audit.read` - audit.read
* `books.read` - books.read
* `documents.read` - documents.read
* `payments.read` - payments.read
* `organization.manage` - organization.manage
* `members.manage` - members.manage
* `api_keys.manage` - api_keys.manage
* `companies.create` - companies.create
* `books.setup` - books.setup
* `parties.write` - parties.write
* `documents.write` - documents.write
* `bank.import` - bank.import
* `bank.classify` - bank.classify
* `bank.connect` - bank.connect
* `invoices.write` - invoices.write
* `invoices.issue` - invoices.issue
* `invoices.post_purchase` - invoices.post_purchase
* `invoices.void` - invoices.void
* `allocations.write` - allocations.write
* `reconciliation.decide` - reconciliation.decide
* `events.write` - events.write
* `periods.close` - periods.close
* `periods.reopen` - periods.reopen
* `vat.prepare` - vat.prepare
* `vat.file` - vat.file
* `payments.manage` - payments.manage
* `employees.submit` - employees.submit
* `agent.use` - agent.use

One of: `"organization.read"`, `"members.read"`, `"api_keys.read"`, `"audit.read"`, `"books.read"`, `"documents.read"`, `"payments.read"`, `"organization.manage"`, `"members.manage"`, `"api_keys.manage"`, `"companies.create"`, `"books.setup"`, `"parties.write"`, `"documents.write"`, `"bank.import"`, `"bank.classify"`, `"bank.connect"`, `"invoices.write"`, `"invoices.issue"`, `"invoices.post_purchase"`, `"invoices.void"`, `"allocations.write"`, `"reconciliation.decide"`, `"events.write"`, `"periods.close"`, `"periods.reopen"`, `"vat.prepare"`, `"vat.file"`, `"payments.manage"`, `"employees.submit"`, `"agent.use"`.

### Problem

An RFC 9457 problem details body (section 11.5).

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `type` | `string` | yes |   |
| `title` | `string` | yes |   |
| `status` | `integer` | yes |   |
| `code` | `string` | yes |   |
| `detail` | `string` | yes |   |
| `errors` | `array of object` | yes |   |

### RecordInvoiceOutcome

The `CommandOutcome` of `record_invoice`, with its result.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `command` | `string` | yes |   |
| `command_id` | `string` | yes | The core id of the command, a ULID. |
| `commit_seq` | `integer` | yes | The commit sequence of the file after it. |
| `replayed` | `boolean` | yes |   |
| `result` | `RecordInvoiceResult` | yes | The result of `record_invoice`. |

### RecordInvoicePayloadRequest

`record_invoice`: a draft sales or purchase invoice.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `direction` | `string` | yes | `sales` or `purchase`. |
| `kind` | `string` | no | Default `invoice`. |
| `party_id` | `string` | yes |   |
| `number` | `string \| null` | no |   |
| `corrects_invoice_id` | `string \| null` | no |   |
| `origin` | `string` | no | Default `human`. |
| `revision` | `InvoiceRevisionRequest` | yes | The content of an invoice: one revision. A chosen `exchange_rate_id` is a human judgement. |

### RecordInvoiceResult

The result of `record_invoice`.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `line_ids` | `array of string` | yes |   |
| `invoice_id` | `string` | yes |   |
| `revision_id` | `string` | yes |   |

### ReviseInvoiceBodyRequest

`revise_invoice`: a new revision of an invoice.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `reason` | `string` | yes |   |
| `party_id` | `string \| null` | no |   |
| `revision` | `InvoiceRevisionRequest` | yes | The content of an invoice: one revision. A chosen `exchange_rate_id` is a human judgement. |

### RoleEnum

* `owner` - Owner
* `member` - Member
* `viewer` - Viewer

One of: `"owner"`, `"member"`, `"viewer"`.

### SickLeave

The days of one sick leave the run pays, counted from the first day of the leave (day 1).

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `from_day` | `integer` | yes |   |
| `to_day` | `integer` | yes |   |

### SkippedAttachment

An attachment that was not kept. Its bytes were never stored.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `filename` | `string` | yes |   |
| `size` | `integer \| null` | yes |   |
| `reason` | `"not_an_invoice" \| "not_pdf" \| "too_large" \| "too_many"` | yes | Why it was not kept. `too_many`: the mail had more attachments than the inbox reads. `not_an_invoice`: the judge of the file, or the grouping of the mail, read it as no invoice. * `not_an_invoice` - not_an_invoice * `not_pdf` - not_pdf * `too_large` - too_large * `too_many` - too_many |

### SkippedAttachmentReasonEnum

* `not_an_invoice` - not_an_invoice
* `not_pdf` - not_pdf
* `too_large` - too_large
* `too_many` - too_many

One of: `"not_an_invoice"`, `"not_pdf"`, `"too_large"`, `"too_many"`.

### SocialTaxMinimumEnum

* `full` - The whole minimum
* `prorated` - In proportion to the days
* `none` - None

One of: `"full"`, `"prorated"`, `"none"`.

### StoredDocument

A stored file of a company, as the API shows it. The storage name never leaves the server.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | `string` | yes | The sqid of the file. |
| `kind` | `"invoice" \| "receipt" \| "credit_note" \| "statement" \| "contract" \| "other"` | yes | * `invoice` - invoice * `receipt` - receipt * `credit_note` - credit_note * `statement` - statement * `contract` - contract * `other` - other |
| `name` | `string` | yes |   |
| `content_type` | `string` | yes |   |
| `size_bytes` | `integer` | yes |   |
| `sha256` | `string` | yes |   |
| `received_on` | `string (date) \| null` | yes |   |
| `core_document_id` | `string \| null` | yes | The ULID of the document in the books. |
| `bank_transaction_ids` | `array of string` | yes | The core ULIDs of the bank transactions this file explains. |
| `uploaded_by` | `string \| null` | yes | The sqid of the user who uploaded the file. |
| `origin` | `InboxOrigin \| null` | yes | The mail the file came from, when it came from the invoice inbox; null for an upload. |
| `created_at` | `string (date-time)` | yes |   |

### Submission

A submission and its review: the client reads its status, and the reason of a refusal.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | `string` | yes |   |
| `kind` | `"new_employee" \| "new_employment" \| "change" \| "suspension" \| "end"` | yes | * `new_employee` - New employee * `new_employment` - New employment * `change` - Change * `suspension` - Suspension * `end` - End |
| `status` | `"submitted" \| "approved" \| "registered" \| "applied" \| "rejected"` | yes | * `submitted` - Submitted * `approved` - Approved * `registered` - Registered * `applied` - Applied * `rejected` - Rejected |
| `event_date` | `string (date)` | yes |   |
| `employee_id` | `string` | yes | The employee of the submission. |
| `employee_name` | `string` | yes | The name of the employee. |
| `employment_id` | `string` | yes |   |
| `data` | `any` | yes | The submitted values by field name. Never a personal code. |
| `submitted_at` | `string (date-time)` | yes |   |
| `submitted_by_staff` | `boolean` | yes |   |
| `reviewed_at` | `string (date-time) \| null` | yes |   |
| `review_reason` | `string` | yes | Why staff rejected it. |
| `toot_id` | `integer \| null` | yes | TÖR's id of the employment, once registered. |
| `tor_messages` | `array of TorMessage` | yes | The messages of TÖR on a refused event. |
| `tor_error_code` | `string` | yes | Why the last send to TÖR did not finish; empty when it did. |
| `registered_at` | `string (date-time) \| null` | yes |   |

### SubmissionRequestRequest

A new employee, a new employment, a change, a suspension or an end, for staff to review.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `kind` | `"new_employee" \| "new_employment" \| "change" \| "suspension" \| "end"` | yes | * `new_employee` - New employee * `new_employment` - New employment * `change` - Change * `suspension` - Suspension * `end` - End |
| `employee_id` | `string` | no | A new employment: the employee. |
| `employment_id` | `string` | no | A change, a suspension, an end: the employment. |
| `employee` | `EmployeeInputRequest` | no | The person of a new employee, or the changed fields of an employee. |
| `employment` | `EmploymentInputRequest` | no | The employment of a start, or the changed fields of an employment. |
| `suspension` | `SuspensionInputRequest` | no | A suspension of an employment. |
| `end` | `EndInputRequest` | no | The end of an employment. |
| `event_date` | `string (date)` | no | A change: the day it applies from. Default today. |

### Suspension

One suspension of an employment, as TÖR holds it.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `suspension_id` | `integer \| null` | yes |   |
| `start` | `string (date) \| null` | yes |   |
| `end` | `string (date) \| null` | yes |   |
| `reason_code` | `string` | yes |   |
| `reason_name` | `string` | yes |   |

### SuspensionInputRequest

A suspension of an employment.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `start_date` | `string (date)` | yes |   |
| `reason_code` | `integer` | yes | The suspension reason code of TÖR. |
| `end_date` | `string (date)` | no |   |
| `first_start_date` | `string (date)` | no | When an existing suspension is changed: its first day as TÖR holds it. |

### TaxAccountAccessStatusEnum

* `never` - Never refreshed
* `ok` - OK
* `rights_missing` - Rights missing
* `failed` - Failed

One of: `"never"`, `"ok"`, `"rights_missing"`, `"failed"`.

### TaxAccountBalance

The tax account of the company at EMTA, from the stored copy of the last successful refresh.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `access_status` | `"never" \| "ok" \| "rights_missing" \| "failed"` | yes | How the last refresh went: `ok`; `rights_missing`, the company has not granted `ACCOUNTING_XROAD` to OscarAI in e-MTA; `failed`; `never`, no refresh yet. * `never` - Never refreshed * `ok` - OK * `rights_missing` - Rights missing * `failed` - Failed |
| `access_error_code` | `string` | yes | The code of the last failure; empty when ok. |
| `last_attempt_at` | `string (date-time) \| null` | yes |   |
| `last_success_at` | `string (date-time) \| null` | yes |   |
| `as_of` | `string (date-time) \| null` | yes | When the stored copy was read from EMTA; null before the first read. |
| `request_date` | `string (date) \| null` | yes | The day of the balance at EMTA. |
| `total` | `string (decimal) \| null` | yes | The balance of the claims. Above zero: the company owes it. |
| `interest` | `string (decimal) \| null` | yes | The interest on the taxes not paid in time. |
| `prepayment_balance` | `string (decimal) \| null` | yes | The balance of the prepayment account (E). |
| `account_balances` | `object` | yes | The balance of each account by its EMTA code (E: the prepayment account). |
| `claims` | `array of TaxAccountClaim` | yes |   |
| `notices` | `array of TaxAccountNotice` | yes |   |
| `refresh_pending` | `boolean` | yes | A refresh is queued or running. |

### TaxAccountClaim

One open claim of the tax account (`balanceOfClaimTypes`).

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `claim_type_code` | `string` | yes | EMTA's claim type, for example `KM` (VAT). |
| `tax_period_code` | `string` | yes |   |
| `document_nr` | `string` | yes |   |
| `document_type_code` | `string` | yes | `KMD` or `TSD`, as EMTA names it. |
| `claim_identifier` | `string` | yes |   |
| `balance` | `string (decimal) \| null` | yes | The balance of the claim. Above zero: the company owes it. |
| `tax_period_end` | `string (date) \| null` | yes |   |
| `due_date` | `string (date) \| null` | yes | The due date, from the stored movements of the claim; null when unknown. |

### TaxAccountNotice

A notice for the client: a tax debt, or a claim due within 7 days.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `kind` | `"debt" \| "claim_due_soon"` | yes | * `debt` - Debt * `claim_due_soon` - Claim due soon |
| `amount` | `string (decimal)` | yes |   |
| `due_date` | `string (date) \| null` | yes |   |
| `claim_type_code` | `string` | yes | Empty for a debt. |
| `tax_period_code` | `string` | yes |   |
| `document_nr` | `string` | yes |   |

### TaxAccountNoticeKindEnum

* `debt` - Debt
* `claim_due_soon` - Claim due soon

One of: `"debt"`, `"claim_due_soon"`.

### TorMessage

A message of TÖR on a refused event, personal codes masked.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `type` | `string` | yes | `E` an error, `W` a warning. |
| `field` | `string` | yes |   |
| `code` | `string` | yes |   |
| `description` | `string` | yes |   |

### UiModeEnum

* `simple` - Simple
* `advanced` - Advanced

One of: `"simple"`, `"advanced"`.

### UploadRequest

The multipart body of an upload.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `file` | `string (binary)` | yes |   |
| `kind` | `"invoice" \| "receipt" \| "credit_note" \| "statement" \| "contract" \| "other"` | no | * `invoice` - invoice * `receipt` - receipt * `credit_note` - credit_note * `statement` - statement * `contract` - contract * `other` - other |
| `received_on` | `string (date) \| null` | no |   |
| `bank_transaction_id` | `string \| null` | no | The core ULID of the bank transaction this file explains (a receipt for a payment). |
| `auto_process` | `boolean` | no | The batch import. Every upload of an invoice, receipt or credit note is recorded and posted without a person when the extraction is confident and the company switch `invoice_auto_book` is on, and the reconciliation matcher links it to its bank line; `auto_process` also refuses the upload without `invoices.write` (403) and a file the extraction does not read: only a PDF of kind invoice, receipt or credit note (409 `not_extractable` otherwise). The post needs `invoices.post_purchase`. A draft that is not confident waits for a person. Follow it with `GET extractions/?file=`. |

### VatStatusEnum

* `registered` - VAT-registered
* `limited` - Limited taxable person
* `unregistered` - Not VAT-registered

One of: `"registered"`, `"limited"`, `"unregistered"`.
