---
title: "Create Gl Journal Entry"
method: POST
path: "/companies/{company_id}/gl/journal-entries"
tags: ["gl"]
---

# Create Gl Journal Entry

`POST /companies/{company_id}/gl/journal-entries`

## Request

- Base URL: `https://app.zeno-works.ch` (the document declares no server; this is the origin it was published from)
- URL: `https://app.zeno-works.ch/companies/{company_id}/gl/journal-entries`
- Auth: none declared

Create a **draft** journal entry by hand — accountant. It carries NO source document
unless you name one.

Only the pipeline paths stamp ``source_ref_type``/``source_ref_id`` (an ingested
document is ``'item'``), so by default a booking made here cannot be traced back to
what justified it. ``document_id`` is the retrofit: name an existing ``gl_document``
(create one with ``POST …/gl/documents``) and it is attached as the entry's source
document, so the entry is not evidence-less. The same attach is available afterwards
at ``POST …/gl/journal-entries/{id}/documents`` — including on a posted entry.

Use it for bookings with genuinely no document behind them — reclassifications,
provisions, accruals, year-end adjustments. **Do not transcribe a document into it and
then attach the file** — that files the evidence beside a booking nobody derived from
it. Each of these has a door that keeps the evidence attached:

- an invoice, receipt or statement → ingest the file (``POST …/uploads/`` or
  ``…/intake``), then accept what the coder proposes (``…/autopost-decisions``);
- an already-ingested item → ``POST …/gl/items/{item_id}/coding``;
- a bank movement with no document → ``POST /bank-entries/{entry_id}/manual-coding``;
- opening balances → ``POST …/opening-entries`` and post the proposal.

``auto_reverse_date`` arms the entry as a one-shot accrual (ZCT-527): once posted, the
auto-reversal executor reverses it in full on/after that date. It must be after
``posting_date`` (422 otherwise), and it can only be set while the entry is a draft —
on the create here or on the ``PUT`` replace.

Drafts do not touch the books until ``…/post``. See ``doc/pipeline.md §"Accounting"``.

## Path parameters

- `company_id` string, required

## Headers

- `authorization` string, nullable

## Cookies

- `access_token` string, nullable

## Request body

- GlJournalEntryDraftCreate: ``POST …/gl/journal-entries`` body — the create only. Deliberately a subclass rather than a field on :class:`GlJournalEntryCreate`, which is *also* the ``PUT`` (full-object replace) body. A ``document_id`` there would have to mean either "replace the attached set" (destructive — the PUT would silently detach evidence) or "attach additively" (a field on a replace body that does not replace). Neither reads right; the split makes the question disappear. Attaching to an entry that already exists is ``POST …/gl/journal-entries/{id}/documents``.
  - `period_id` string, required
  - `posting_date` string, date, required
  - `currency` string, nullable
  - `entry_type` 'manual' | 'invoice' | 'payment' | 'bank' | 'vat' | 'payroll' | 'accrual' | 'deferral' | 'depreciation' | 'inventory' | 'closing' | 'adjustment' | 'reversal'
  - `description` string, nullable
  - `lines` GlJournalLineIn[], required
    - `account_id` string, required
    - `amount_base` union
      - number
      - string
    - `amount_currency` union
      - number
      - string
    - `line_role` 'bank' | 'ar' | 'ap' | 'revenue' | 'expense' | 'vat' | 'payroll_liability' | 'salary_expense' | 'fixed_asset' | 'depreciation' | 'inventory' | 'cogs' | 'clearing' | 'rounding' | 'fx_gain_loss' | 'suspense', required
    - `currency` string, nullable
    - `counterparty_id` string, nullable
    - `open_item_id` string, nullable
    - `description` string, nullable
    - `vat` GlLineVatIn: VAT tag for a manual journal line (Gap B — manual-booking metadata completeness). Tag **both** legs of a taxable movement with the same ``code`` (a company ``gl_vat_code``): the taxable **base** line *and* its paired **VAT-control** line — posting groups the entry's lines by this tag to pair base with VAT line, and the composition guard refuses (409) any VAT-control line left untagged (ZET-158: a base-line-only tag has no working path). One tagged control line per code. ``amount`` (the tax, a magnitude) is read from the **base** line's tag and falls back to the paired VAT line's amount — when several base lines share one VAT line, give each base line its own ``amount``, or every pair books the full VAT-line amount. Exception: a catalog-linked **zero-rated output** code (0 % rate) books no VAT-control line at all — tag only the base line(s); each line tagged with such a code declares its turnover once. On post the entry gains ``gl_vat_posting`` rows so the lines reach the MWST-Abrechnung (``doc/pipeline.md §"VAT"``).
      - `code` string, required
      - `amount` union
        - number
        - string
    - `open_item` GlLineOpenItemIn: Open a new AR/AP subledger item from a manual control line (Gap B). Set ``create=true`` on the line posting to the AR/AP control account; ``due_date`` seeds aging. Direction is derived from the account's ``control_type``. To settle/adjust an *existing* item instead, pass ``open_item_id`` on the line (its balance is rebuilt on post).
      - `create` boolean
      - `due_date` string, date, nullable
  - `auto_reverse_date` string, date, nullable
  - `document_id` string, nullable

## Response `201`

Successful Response

- GlJournalEntryDetailOut
  - `id` string, required
  - `company_id` string, required
  - `entry_no` integer, nullable
  - `period_id` string, required
  - `posting_date` string, date, required
  - `status` string, required
  - `entry_type` string, required
  - `origin` string, required
  - `description` string, nullable
  - `debit_total_base` string, required
  - `credit_total_base` string, required
  - `line_count` integer, required
  - `version_no` integer, required
  - `reversal_of_entry_id` string, nullable
  - `reversed_by_entry_id` string, nullable
  - `auto_reverse_date` string, date, nullable
  - `coding_guessed` boolean
  - `untagged_subledger_control` boolean
  - `source_ref_type` string, nullable
  - `source_ref_id` string, nullable
  - `source_action` string, nullable
  - `created_at` string, date-time, required
  - `posted_by` string, nullable
  - `created_by` string, nullable
  - `posted_at` string, date-time, nullable
  - `lines` GlJournalLineOut[]
    - `id` string, required
    - `line_no` integer, required
    - `account_id` string, required
    - `amount_base` string, required
    - `currency` string, required
    - `amount_currency` string, required
    - `line_role` string, required
    - `counterparty_id` string, nullable
    - `open_item_id` string, nullable
    - `description` string, nullable
    - `vat_code` string, nullable
    - `vat_amount` string, nullable
    - `open_item` GlLineOpenItemIn: Open a new AR/AP subledger item from a manual control line (Gap B). Set ``create=true`` on the line posting to the AR/AP control account; ``due_date`` seeds aging. Direction is derived from the account's ``control_type``. To settle/adjust an *existing* item instead, pass ``open_item_id`` on the line (its balance is rebuilt on post).
      - `create` boolean
      - `due_date` string, date, nullable
  - `vat_postings` GlVatPostingOut[]
    - `id` string, required
    - `journal_entry_id` string, required
    - `base_line_id` string, required
    - `vat_line_id` string, required
    - `vat_code_id` string, required
    - `vat_code` string, nullable
    - `vat_period_id` string, nullable
    - `base_amount` string, required
    - `vat_amount` string, required
    - `gross_amount` string, required
    - `deductibility_percent` string, required
    - `non_deductible_amount` string, required
    - `return_box_code` string, nullable
  - `vat_zero_postings` GlVatZeroPostingOut[]
    - `id` string, required
    - `journal_entry_id` string, required
    - `base_line_id` string, required
    - `vat_code_id` string, required
    - `vat_code` string, nullable
    - `vat_period_id` string, nullable
    - `base_amount` string, required
    - `return_box_code` string, nullable
  - `open_items` GlOpenItemOut[]
    - `id` string, required
    - `company_id` string, required
    - `direction` string, required
    - `counterparty_id` string, nullable
    - `control_account_id` string, required
    - `original_amount_base` string, required
    - `open_amount_base` string, required
    - `currency` string, required
    - `original_amount_currency` string, nullable
    - `open_amount_currency` string, nullable
    - `base_currency` string, nullable
    - `due_date` string, date, nullable
    - `status` string, required
    - `created_at` string, date-time, required
  - `documents` GlDocumentOut[]
    - `id` string, required
    - `company_id` string, required
    - `document_type` string, required
    - `file_id` string, nullable
    - `filename` string, nullable
    - `issue_date` string, date, nullable
    - `created_at` string, date-time, required

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/zeno-works/apis/zeno-api.md) · [All operations](https://skmtc.dev/zeno-works/apis/zeno-api/llms.txt) · [OpenAPI document](https://skmtc.dev/zeno-works/apis/zeno-api/revisions/1eb93dde146c?raw)
