> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sintropix.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Sintropix Entities API: Manage Legal Companies and Books

> List, create, and configure the legal companies (Entities) that own separate books, currencies, and integrations in Sintropix.

An Entity is a legal company with its own books, functional currency, and integrations. Every ledger route in the API scopes by `entityId`. This page covers the Entity CRUD, ledger-lock date, and accounting policy endpoints.

<Info>
  Source: `apps/erp-backend/src/entity/entity.controller.ts`.
</Info>

## POST /api/entities

Create a new Entity. The client supplies the idempotency id, so a retried POST collides on the primary key instead of inserting a twin.

* **Staff only**
* **Body:** `CreateEntityDto` (from `createEntitySchema`)

| Field      | Type   | Required | Description                                          |
| ---------- | ------ | -------- | ---------------------------------------------------- |
| `id`       | UUID   | Yes      | Client-supplied idempotency id                       |
| `name`     | string | Yes      | Legal company name, non-empty                        |
| `country`  | string | Yes      | ISO country code, non-empty                          |
| `taxId`    | string | Yes      | Tax registration, non-empty; canonicalized for Chile |
| `currency` | string | Yes      | Functional currency code, non-empty                  |

* **Success response:** `entitySchema` (the created Entity)
* **Status:** 201

```bash theme={null}
curl -X POST https://<your-erp-backend-host>/api/entities \
  -H "Content-Type: application/json" \
  -H "x-api-key: $SINTROPIX_API_KEY" \
  -H "x-audit-actor: my-agent" \
  -d '{
    "id": "11111111-1111-4111-8111-111111111111",
    "name": "Acme SpA",
    "country": "CL",
    "taxId": "76.123.456-0",
    "currency": "CLP"
  }'
```

## GET /api/entities

List every Entity the caller can access. Staff see all Entities; clients see only the Entities they hold a membership for.

* **Success response:** Array of `entitySchema`
* **Status:** 200

```bash theme={null}
curl https://<your-erp-backend-host>/api/entities \
  -H "x-api-key: $SINTROPIX_API_KEY"
```

## GET /api/entities/:entityId/editability

Check whether the identity fields of an Entity (name, country, taxId, currency) are currently editable. Returns a single boolean flag.

* **Path param:** `entityId` (UUID)
* **Success response:** `entityEditabilitySchema` — `{ identityFieldsEditable: boolean }`
* **Status:** 200

```bash theme={null}
curl https://<your-erp-backend-host>/api/entities/$ENTITY_ID/editability \
  -H "x-api-key: $SINTROPIX_API_KEY"
```

## PATCH /api/entities/:entityId

Update the core identity fields of an Entity. At least one field must be provided. The update canonicalizes Chilean tax registrations and requires both `country` and `taxId` when either is supplied.

* **Path param:** `entityId` (UUID)
* **Body:** `UpdateEntityDto` (from `updateEntitySchema`)

| Field      | Type   | Required | Description         |
| ---------- | ------ | -------- | ------------------- |
| `name`     | string | No       | Legal company name  |
| `country`  | string | No       | ISO country code    |
| `taxId`    | string | No       | Tax registration    |
| `currency` | string | No       | Functional currency |

* **Success response:** `entitySchema`
* **Status:** 200

```bash theme={null}
curl -X PATCH https://<your-erp-backend-host>/api/entities/$ENTITY_ID \
  -H "Content-Type: application/json" \
  -H "x-api-key: $SINTROPIX_API_KEY" \
  -H "x-audit-actor: my-agent" \
  -d '{"name": "Acme SpA Updated"}'
```

## PATCH /api/entities/:entityId/ledger-lock-date

Set, move, or clear the ledger lock date. A date freezes the ledger up to and including that date; `null` clears the lock. The lock date cannot move to a date on or after any Scheduled Entry's Entry Date.

* **Path param:** `entityId` (UUID)
* **Body:** `UpdateEntityLedgerLockDateDto` (from `updateEntityLedgerLockDateSchema`)

| Field            | Type             | Required | Description                |
| ---------------- | ---------------- | -------- | -------------------------- |
| `ledgerLockDate` | ISO date or null | Yes      | Lock date or null to clear |

* **Success response:** `entitySchema`
* **Status:** 200

```bash theme={null}
curl -X PATCH https://<your-erp-backend-host>/api/entities/$ENTITY_ID/ledger-lock-date \
  -H "Content-Type: application/json" \
  -H "x-api-key: $SINTROPIX_API_KEY" \
  -H "x-audit-actor: my-agent" \
  -d '{"ledgerLockDate": "2026-01-31"}'
```

## PATCH /api/entities/:entityId/parent

Set or clear the parent Entity that controls this one. An id names the controlling Entity; `null` makes it a root. The parent must exist, must not be the Entity itself, and must not create a cycle.

* **Staff only**
* **Path param:** `entityId` (UUID)
* **Body:** `UpdateEntityParentDto` (from `updateEntityParentSchema`)

| Field            | Type         | Required | Description                   |
| ---------------- | ------------ | -------- | ----------------------------- |
| `parentEntityId` | UUID or null | Yes      | Controlling Entity id or null |

* **Success response:** `entitySchema`
* **Status:** 200

```bash theme={null}
curl -X PATCH https://<your-erp-backend-host>/api/entities/$ENTITY_ID/parent \
  -H "Content-Type: application/json" \
  -H "x-api-key: $SINTROPIX_API_KEY" \
  -H "x-audit-actor: my-agent" \
  -d '{"parentEntityId": "22222222-2222-4222-8222-222222222222"}'
```

## PATCH /api/entities/:entityId/accounting-policies

Set or remove the free-text accounting policies of an Entity. Free text sets the rules; `null` removes them.

* **Staff only**
* **Path param:** `entityId` (UUID)
* **Body:** `UpdateEntityAccountingPoliciesDto` (from `updateEntityAccountingPoliciesSchema`)

| Field                | Type           | Required | Description                     |
| -------------------- | -------------- | -------- | ------------------------------- |
| `accountingPolicies` | string or null | Yes      | Policies text or null to remove |

* **Success response:** `entitySchema`
* **Status:** 200

```bash theme={null}
curl -X PATCH https://<your-erp-backend-host>/api/entities/$ENTITY_ID/accounting-policies \
  -H "Content-Type: application/json" \
  -H "x-api-key: $SINTROPIX_API_KEY" \
  -H "x-audit-actor: my-agent" \
  -d '{"accountingPolicies": "Purchases below 100000 CLP go to expenses."}'
```

## Response shape

The `entitySchema` read shape includes:

| Field                | Type             | Description                |
| -------------------- | ---------------- | -------------------------- |
| `id`                 | UUID             | Entity id                  |
| `name`               | string           | Legal company name         |
| `country`            | string           | ISO country code           |
| `taxId`              | string           | Canonical tax registration |
| `currency`           | string           | Functional currency        |
| `ledgerLockDate`     | ISO date or null | Ledger freeze date         |
| `accountingPolicies` | string or null   | Free-text policies         |
| `parentEntityId`     | UUID or null     | Controlling Entity         |
| `createdAt`          | ISO datetime     | Creation timestamp         |
| `updatedAt`          | ISO datetime     | Last update timestamp      |

## Domain error codes

| Code                                          | Meaning                                 |
| --------------------------------------------- | --------------------------------------- |
| `ENTITY_LOCK_DATE_OVER_SCHEDULED_ENTRY_ERROR` | Lock date would cover a Scheduled Entry |
| `ENTITY_PARENT_NOT_FOUND_ERROR`               | Named parent Entity does not exist      |
| `ENTITY_SELF_PARENT_ERROR`                    | An Entity cannot control itself         |
| `ENTITY_PARENT_CYCLE_ERROR`                   | Parent would create a control cycle     |

## Status codes

| Status | Meaning                            |
| ------ | ---------------------------------- |
| 200    | Success (GET, PATCH)               |
| 201    | Created (POST)                     |
| 400    | Validation error                   |
| 401    | Unauthenticated                    |
| 403    | Forbidden (staff-only endpoint)    |
| 404    | Entity not found                   |
| 409    | Domain rule violation (see `code`) |
