Skip to content

API — Demand

Purpose

Demand plans (the matrix of required coverage by date/terminal/shift) and demand templates (reusable shapes you apply to create a plan).

Auth & roles

  • Demand plans — base /api/demand/plans · read demand.read, write demand.write (SYS_ADMIN + HR_ADMIN + PLANNER).
  • Demand templates — base /api/demand/templates · read demand.template_read, apply demand.write.

See the RBAC matrix.

Endpoints

Demand plans/api/demand/plans

Method Path Purpose Gate
GET /api/demand/plans List plans (filterable by date/terminal/state) demand.read
POST /api/demand/plans Create a plan demand.write
GET /api/demand/plans/{id} Plan detail (the matrix) demand.read
PATCH /api/demand/plans/{id} Edit cells / status demand.write
DELETE /api/demand/plans/{id} Delete a plan demand.write

Demand templates/api/demand/templates

Method Path Purpose Gate
GET /api/demand/templates · /{id} List / read templates demand.template_read
POST /api/demand/templates/{id}/apply Apply a template (dry-run + commit) demand.write

Shapes & errors

A plan has a status state machine and a cell-edit surface; apply-template supports a dry-run then commit (sheet 08). Editing a locked plan returns 409. Standard ProblemDetails.

Gotchas

  • DemandPlanStatus.Locked is a defined-but-unreachable enum value (F1). The enum declares Locked, but no code path transitions a plan into it — publishing a roster does not lock its demand plan. Treat Locked as dead for plans; don't write logic assuming a plan can reach it.
  • The locked-edit 409 still exists in the API contract for plan cells, but the plan-level Locked status itself is unreachable — these are different things; the cell-level guard is real.
  • Demand reasons referenced by plans are managed via the admin CRUD (/api/admin/demand-reasons) and read via lookups.