ITSM

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

FieldTypeRequiredDefaultDescription
tenantIdstringrequiredTenant ID. Auto-set, indexed.
namestringrequiredDepartment display name.
codestringoptionalnullShort machine-friendly department code.
parentIdObjectIdoptionalnullParent department — enables the org tree. Null for a top-level (root) department.
managerIdObjectIdoptionalnullReferences a User — the department head/manager.
headcountnumberoptional0Number of people in the department. Not auto-computed from user assignments — set directly.
costCenterstringoptionalnullCost center code used for budget/chargeback reporting.
descriptionstringoptional""Free-text description.
isActivebooleanoptionaltrueSoft-delete flag. DELETE sets this to false rather than removing the record.
createdAtdateoptionalAuto-set.
updatedAtdateoptionalAuto-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.

GET
/api/departments

List departments (flat list, sorted by name). Excludes inactive departments unless ?includeInactive=true is passed. Supports dynamic field filtering via query params.

GET
/api/departments/tree

Returns the department hierarchy as a nested tree — each node has a children array built from parentId relationships. Only active departments are included.

POST
/api/departments

Create a department. Requires name.

GET
/api/departments/:id

Get a single department by ID, with managerId and parentId populated.

PATCH
/api/departments/:id

Update department fields.

DELETE
/api/departments/:id

Soft-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.

json
{
  "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:

json
{
  "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.