# Edara API v3: Classifications

Read the [guide](../guide.md) first: authentication, paging, errors, rate limits and the shared `PagedResult`, `BatchResult` and `*Reference` shapes.

- `GET /v3/classifications/stock-items`: Lists stock-item classifications.
- `GET /v3/classifications/stock-items/tree/{userId}`: Gets the stock-item classification tree for a user.
- `POST /v3/classifications/stock-items`: Creates a stock-item classification.
- `GET /v3/classifications/common`: Lists common classifications.
- `GET /v3/classifications/common/{id}`: Gets a common classification by id.

## Endpoints

### `GET /v3/classifications/stock-items`: Lists stock-item classifications.

Operation `GetStockItemClassifications` · permission `read:classification`

**Query string**: `GetStockItemClassificationsQuery`

| field | type | default | validation | description |
|---|---|---|---|---|
| `offset` | `int?` | 0 | **no validator**: negative silently becomes 0 | Number of items to skip before returning results. Defaults to 0. |
| `limit` | `int?` | 100 | **no validator**: out of 1..1000 silently becomes 100 | Maximum number of items to return. Defaults to 100, maximum 1000. |

**Responses**: OK `PagedResult<StockItemClassificationResponse>`: Paged list of stock-item classifications.

**Notes**

- The list includes inactive classifications and comes back in tree order.

---

### `GET /v3/classifications/stock-items/tree/{userId}`: Gets the stock-item classification tree for a user.

Operation `GetStockItemClassificationTree` · permission `read:classification`

**Parameters**

| name | in | type | default | description |
|---|---|---|---|---|
| `userId` | route | `int` |  | The user id. |

**Responses**: OK `IReadOnlyCollection<StockItemClassificationTreeResponse>`: Stock-item classification tree.

**Notes**

- The tree contains the classifications that the user in `userId` is permitted to see. If that user has no classification permissions, the response is an empty list.
- Each leaf classification lists its stock items, including inactive ones.
- The response contains the whole tree, so its size and response time grow with the catalogue.
- The balance value on tree entries is always 0.

---

### `POST /v3/classifications/stock-items`: Creates a stock-item classification.

Operation `CreateStockItemClassification` · permission `create:classification`

**Body**: `StockItemClassificationUpsertRequest`

| field | type | default | validation | description |
|---|---|---|---|---|
| `code` | `string` |  | NotEmpty() .MaximumLength(50) .Must(code => code == null \|\| !code.Contains("-")) | Classification code. Required; must not contain dashes. |
| `description` | `string` |  | NotEmpty() .MaximumLength(70) | Classification description. Required. |
| `parentId` | `int?` |  | NotNull() .GreaterThan(0) | Parent classification identifier. Required; must be a non-leaf node. |

**Responses**: Created `StockItemClassificationResponse`: Classification created.

**Business errors** (HTTP 409, match on `errorCode`):

- `ClassificationParentIsLeafWithStockItems`: The parent classification is a leaf containing stock items; pick a non-leaf parent.
- `DupplicatedCode`: Another stock-item classification already uses the same code.
- `DupplicatedName`: Another stock-item classification already uses the same description.

**Notes**

- `code` and `description` are trimmed. `type` is always `StockItems`.
- You cannot add a child under a parent that has no children and already holds stock items. This returns `409` with `errorCode` `ClassificationParentIsLeafWithStockItems`.
- A duplicate `description` returns `409` with `errorCode` `DupplicatedName`. A duplicate `code` among stock-item classifications returns `409` with `errorCode` `DupplicatedCode`.
- The user who creates the classification is given access to it automatically. Other users do not see it in permission-filtered views until they are granted access.
- `treeLevel` in the response is always 0, whatever the real depth.

---

### `GET /v3/classifications/common`: Lists common classifications.

Operation `GetCommonClassifications` · permission `read:classification`

**Query string**: `GetCommonClassificationsQuery`

| field | type | default | validation | description |
|---|---|---|---|---|
| `offset` | `int?` | 0 | **no validator**: negative silently becomes 0 | Number of items to skip before returning results. Defaults to 0. |
| `limit` | `int?` | 100 | **no validator**: out of 1..1000 silently becomes 100 | Maximum number of items to return. Defaults to 100, maximum 1000. |
| `description` | `string` |  | Must(value => !string.IsNullOrWhiteSpace(value))  .MaximumLength(50) ; }) | Optional description filter; exact match when supplied. |

**Responses**: OK `PagedResult<CommonClassificationResponse>`: Paged list of common classifications.

**Notes**

- Returns active classifications of every type, for example stock items, warehouses and customers. Inactive ones are left out.
- `description` is trimmed and matched exactly, not as a partial match.
- Results are ordered by description, then id. A page past the end returns `totalCount` 0.

---

### `GET /v3/classifications/common/{id}`: Gets a common classification by id.

Operation `GetCommonClassificationById` · permission `read:classification`

**Parameters**

| name | in | type | default | description |
|---|---|---|---|---|
| `id` | route | `int` |  | The classification id. |

**Responses**: OK `CommonClassificationResponse`: The common classification.

**Notes**

- The id can belong to a classification of any type. An inactive classification returns `404`.

## Types

### `CommonClassificationResponse`

Response describing a common classification.

| field | type | description |
|---|---|---|
| `id` | `int` | The classification identifier. |
| `code` | `string` | The classification code. |
| `description` | `string` | The classification description. |
| `type` | `string` | The classification type. |
| `parentId` | `int?` | The optional parent classification identifier. |

### `StockItemClassificationResponse`

Response describing a stock-item classification node.

| field | type | description |
|---|---|---|
| `id` | `int` | Classification identifier. |
| `code` | `string` | Classification code. |
| `description` | `string` | Classification description. |
| `parentId` | `int?` | Parent classification identifier; null for roots. |
| `treeLevel` | `int` | Depth within the tree; roots are level 0. |

### `StockItemClassificationTreeResponse`

Response describing a stock-item classification tree row.

| field | type | description |
|---|---|---|
| `id` | `int` | Tree row identifier. |
| `stockItemId` | `int` | Stock-item identifier when this row is a leaf. |
| `stockItem` | `string` | Stock-item description when this row is a leaf. |
| `nodeId` | `int` | Classification node identifier. |
| `parentId` | `int` | Parent classification identifier. |
| `treeLevel` | `int` | Depth within the tree. |
