---
title: "Create Counterparty"
method: POST
path: "/companies/{company_id}/counterparties"
tags: ["counterparties"]
---

# Create Counterparty

`POST /companies/{company_id}/counterparties`

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

Manually create a counterparty (``normalized_name`` derived; ``auto_created=false``).

``CompanyAccountant`` (ZCT-257): a plain ``member`` is read-only. Declarative here
because the company is a path parameter — which also brings the API-key and
support-session confinement the row-keyed siblings below get from Ring 2 instead.

## Path parameters

- `company_id` string, required

## Headers

- `authorization` string, nullable

## Cookies

- `access_token` string, nullable

## Request body

- CounterpartyCreate: ``POST /companies/<id>/counterparties`` body (manual create). ``normalized_name`` is derived server-side; ``auto_created`` is forced false.
  - `kind` 'supplier' | 'customer' | 'both' | 'employee', required: Master-data axis of a counterparty (what the party primarily is). ``employee`` (payroll SP1, brief frozen decision 6) is set **only** on counterparties auto-created by ``payroll.master_data .ensure_employee_counterparty`` and is terminal — matching/merge flows never widen it to ``both``. Subledger participation rides the richer ``gl_counterparty_role`` table; payroll logic never branches on ``kind``.
  - `name` string, required
  - `street` string, nullable
  - `building` string, nullable
  - `postal_code` string, nullable
  - `town` string, nullable
  - `country` string, nullable
  - `address_lines` string, nullable
  - `vat_number` string, nullable

## Response `201`

Successful Response

- CounterpartyResponse: ``{"counterparty": ...}`` — get / create / update / merge survivor.
  - `counterparty` CounterpartyOut, required: Serialized counterparty — all columns + ``accounts`` + optional ``item_count``.
    - `id` string, required
    - `company_id` string, required
    - `kind` 'supplier' | 'customer' | 'both' | 'employee', required: Master-data axis of a counterparty (what the party primarily is). ``employee`` (payroll SP1, brief frozen decision 6) is set **only** on counterparties auto-created by ``payroll.master_data .ensure_employee_counterparty`` and is terminal — matching/merge flows never widen it to ``both``. Subledger participation rides the richer ``gl_counterparty_role`` table; payroll logic never branches on ``kind``.
    - `name` string, required
    - `normalized_name` string, required
    - `street` string, nullable
    - `building` string, nullable
    - `postal_code` string, nullable
    - `town` string, nullable
    - `country` string, nullable
    - `address_lines` string, nullable
    - `vat_number` string, nullable
    - `auto_created` boolean, required
    - `created_at` string, date-time, required
    - `accounts` CounterpartyAccountOut[]
      - `id` string, required
      - `counterparty_id` string, required
      - `company_id` string, required
      - `iban` string, required
      - `label` string, nullable
    - `item_count` integer, nullable

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