---
title: "Create Company"
method: POST
path: "/companies/"
tags: ["companies"]
---

# Create Company

`POST /companies/`

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

Create a BARE company (admin only) — almost certainly not the one you want.

**There are two `create_company` operations and they are not interchangeable.**
This one writes the tenant row and nothing else: no chart of accounts, no fiscal
year, no opening balances, and no membership for anybody — a company that cannot
be booked in and that nobody can see. It exists for provisioning a tenant an
administrator will populate by other means.

**The normal path is `onboarding_create_company`** (`POST /onboarding/companies`),
which collects the chart, the fiscal year, the opening balances and the VAT setup
and grants the creator `owner`. Any user who is an administrator, an owner of an
existing company, or a member of none may call it.

Picking the wrong one is easy and the failure is quiet, which is why both say so:
a non-admin calling THIS operation is refused for a different reason than the
same caller being ineligible for the wizard, and before this the two 403s were
indistinguishable.

409 if the ADMIN — who becomes this company's payer — already has one by that name.
Company names are unique per payer, not platform-wide (`uq_company_payer_lower_name`),
so a name another customer holds is free. Records the admin as `created_by` (SP-06)
and as the payer (PRE-02); note that makes every tenant provisioned this way share
the admin's name-space until `PUT /companies/{id}/payer` moves it.

## Headers

- `authorization` string, nullable

## Cookies

- `access_token` string, nullable

## Request body

- CompanyCreate: ``POST /companies/`` body (admin).
  - `company_name` string, required
  - `active` boolean
  - `ingest_lookback_months` 3 | 6 | 12, nullable
  - `language` 'de' | 'en' | 'fr' | 'it', nullable
  - `industry` string, nullable

## Response `201`

Successful Response

- CompanyResponse: ``POST/PUT /companies/<id>`` → ``{"company": ...}`` (tenant fields only). Note: membership management (``user_company``) is NOT a company sub-resource in the api-contract — there are no member/role routes. Membership is edited via the users domain (the ``companies`` array or ``memberships`` list on ``POST/PUT /users/<id>``, A2); each membership carries a ``role`` (owner/accountant/member — doc/architecture.md §"Authentication & tenancy"; global ``User.is_admin`` bypasses role gates). See the companies router docstring + the agent report for this judgment call.
  - `company` CompanyOut, required: Serialized company tenant row + derived integration-presence flags.
    - `id` string, required
    - `company_name` string, required
    - `active` boolean, required
    - `is_demo` boolean
    - `ingest_lookback_months` 3 | 6 | 12, required
    - `language` 'de' | 'en' | 'fr' | 'it', required
    - `industry` string, nullable
    - `has_email` boolean
    - `has_epost` boolean
    - `has_bexio` boolean
    - `has_abacus` boolean
    - `has_storage` boolean
    - `has_accounting_settings` boolean

## 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)
