Departments
Hierarchical org-structure model for grouping users into a company's department tree — manager linkage, cost centers, and headcount.
Overview
A Department record represents a node in a tenant's organisational tree. Departments can nest under one another via parentId, forming an arbitrary-depth hierarchy (e.g. Engineering → Platform → SRE). Each department optionally points at a manager (a User) and a cost center code for finance/chargeback reporting. Departments are referenced from ITSM records viadepartmentId (see the organisational references on the data model page) and from Locations for site assignment.
Schema
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| tenantId | string | required | — | Tenant ID. Auto-set, indexed. |
| name | string | required | — | Department display name. |
| code | string | optional | null | Short machine-friendly department code. |
| parentId | ObjectId | optional | null | Parent department — enables the org tree. Null for a top-level (root) department. |
| managerId | ObjectId | optional | null | References a User — the department head/manager. |
| headcount | number | optional | 0 | Number of people in the department. Not auto-computed from user assignments — set directly. |
| costCenter | string | optional | null | Cost center code used for budget/chargeback reporting. |
| description | string | optional | "" | Free-text description. |
| isActive | boolean | optional | true | Soft-delete flag. DELETE sets this to false rather than removing the record. |
| createdAt | date | optional | — | Auto-set. |
| updatedAt | date | optional | — | Auto-set. |
Indexed on { tenantId, name } and { tenantId, parentId } — the latter is what makes tree traversal (fetching a department's direct children) efficient.
Endpoints
All routes are mounted at /api/departments and require authentication plus a resolved tenant/workspace context.
/api/departmentsList departments (flat list, sorted by name). Excludes inactive departments unless ?includeInactive=true is passed. Supports dynamic field filtering via query params.
/api/departments/treeReturns the department hierarchy as a nested tree — each node has a children array built from parentId relationships. Only active departments are included.
/api/departmentsCreate a department. Requires name.
/api/departments/:idGet a single department by ID, with managerId and parentId populated.
/api/departments/:idUpdate department fields.
/api/departments/:idSoft-delete — sets isActive to false. The record is not removed from the database.
List response — manager populated
GET /api/departments populates managerId with firstName, lastName, and email from the User table.
{
"success": true,
"data": [
{
"_id": "651f...",
"name": "Platform Engineering",
"code": "ENG-PLAT",
"parentId": "651e...",
"managerId": { "_id": "651a...", "firstName": "Ada", "lastName": "Lovelace", "email": "ada@acme.com" },
"headcount": 14,
"costCenter": "CC-1042",
"isActive": true
}
]
}Tree response
GET /api/departments/tree returns only root-level departments (no parentId) at the top of the array, each carrying a nested children array:
{
"success": true,
"data": [
{
"_id": "651e...",
"name": "Engineering",
"parentId": null,
"children": [
{ "_id": "651f...", "name": "Platform Engineering", "parentId": "651e...", "children": [] },
{ "_id": "6520...", "name": "Mobile", "parentId": "651e...", "children": [] }
]
}
]
}headcount is a plain stored number, not a live rollup — it is not automatically recalculated when users are added to or removed from the department. Update it explicitly via PATCH if you want it to stay accurate.