---
title: "Create Gl Account"
method: POST
path: "/companies/{company_id}/gl/accounts"
tags: ["gl"]
---

# Create Gl Account

`POST /companies/{company_id}/gl/accounts`

## 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/accounts`
- Auth: none declared

Create one chart account (accountant). 409 on a duplicate code in the target year.

The chart is **FY-scoped** — identity is ``(company, fiscal_year, code)`` — so this
writes into exactly one year. ``body.fiscal_year`` names it (ZET-266): the requested
year, **created if absent**; else the company's **working** year — an open year,
preferring one with a chart, then the newest (not simply the newest, which after a
rollover is next year's empty shell); else, when no year is open, the newest (sealed,
so refused); else the current calendar year. A **closed** year is refused with 409, its
chart being sealed. The response
echoes both ``fiscal_year_id`` and its ``fiscal_year`` label, so the caller can see
where the row landed instead of inferring it.

## Path parameters

- `company_id` string, required

## Headers

- `authorization` string, nullable

## Cookies

- `access_token` string, nullable

## Request body

- GlAccountCreate
  - `code` string, required
  - `name` string, required
  - `account_class` 'asset' | 'liability' | 'equity' | 'revenue' | 'expense', required
  - `normal_side` 'credit' | 'debit', required
  - `control_type` 'none' | 'ar' | 'ap' | 'bank' | 'vat_input' | 'vat_output' | 'payroll_liability' | 'fixed_asset' | 'inventory' | 'clearing' | 'suspense' | 'cash'
  - `is_postable` boolean
  - `currency` string, nullable
  - `is_contra` boolean
  - `category` 'asset' | 'liability' | 'equity' | 'income' | 'expense' | 'tax' | 'other' | 'unknown': The account-type axis of a ledger account (Swiss-KMU chart of accounts). Distinct from — but derived from — ``LineRole`` (the journal-line semantic role). ``unknown`` is the conservative default when classification can't decide; ``other`` covers genuinely ambiguous / closing (9xxx) accounts.
  - `is_intentional` boolean
  - `account_number_guess` string, nullable
  - `fiscal_year` integer, nullable

## Response `201`

Successful Response

- GlAccountOut
  - `id` string, required
  - `company_id` string, required
  - `fiscal_year_id` string, required: The fiscal year whose chart this account belongs to. Chart identity is (company, fiscal_year, code) — each year owns its chart, so a request that omits ?fiscal_year returns every year's row for a code. Match on this field (or on the `fiscal_year` label beside it, or filter by ?fiscal_year) rather than picking a repeated code by created_at. A year's chart is cloned from the prior year ONCE, when that year's chart is first materialised — an account created afterwards exists only in the year that created it, and is carried into the next year by the year-end rollforward (ZET-266), not automatically.
  - `fiscal_year` integer, nullable: The year label of `fiscal_year_id` (e.g. 2026).
  - `code` string, required
  - `name` string, required
  - `account_class` string, required
  - `normal_side` string, required
  - `is_postable` boolean, required
  - `control_type` string, required
  - `currency` string, nullable
  - `is_active` boolean, required
  - `is_contra` boolean
  - `category` string, nullable
  - `is_intentional` boolean
  - `account_number_guess` string, nullable
  - `created_at` string, date-time, required
  - `updated_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)
