Skip to main content

Workflow Templates

A workflow template defines an ordered list of stages (e.g. backlog → in_progress → review → done) that crews attach to their issue trackers. The frontend renders these as column headers on board views; the issue handler enforces the stage transitions when an issue moves between columns. Implementation: internal/api/workflow_templates_handler.go. Backed by the workflow_templates table (schema introduced in migration v19, see internal/database/migrate_consts_v16_v25.go).
All endpoints require an authenticated session and workspace context. Mutating verbs additionally require OWNER, ADMIN, or MANAGER role (requireRole("create")).

Endpoints

Template shape

Stage shape

Stages live inside template_json as a JSON array. Each stage: Validation rules enforced by validateTemplateJSON:
  • At least one stage.
  • Exactly one stage with type: open.
  • At least one stage with type: completed.
  • All name values unique; all position values unique.
Violations return 400 with a single-sentence message describing the failing constraint.

Endpoint reference

CRUD over templates. Built-in rows are server-controlled and surface first on List.

GET /api/v1/workflow-templates

List every template visible to the current workspace. Built-in rows surface first (is_builtin DESC), then user-created rows by created_at ASC. Auth: authenticated session + workspace context. Response: 200 OK — JSON array (never null).

POST /api/v1/workflow-templates

Create a new user-owned template. Auth: authenticated session + workspace context + requireRole("create"). Request body: Response: 201 Created with the full template object. Broadcasts workflow_template.created on the workspace WS channel with {"id": "<id>"}.

GET /api/v1/workflow-templates/{id}

Fetch a single template by id, scoped to the calling workspace. Auth: authenticated session + workspace context. Response: 200 OK with the template object.

PATCH /api/v1/workflow-templates/{id}

Partial update. Only the mutable subset (name, description, template_json, icon, color) is writable. is_builtin, created_at, and id are immutable; updated_at is set to “now” on every successful write. Auth: authenticated session + workspace context + requireRole("create"). Request body: every field optional; only provided (non-null) keys are written. Response: 200 OK with the freshly-updated template (so callers don’t need to re-GET). Broadcasts workflow_template.updated on the workspace WS channel with {"id": "<id>"}.

DELETE /api/v1/workflow-templates/{id}

Hard delete. Templates are reference data — crews that still point at the deleted template fall back to the runtime default lifecycle at next render rather than failing.
Hard delete (no soft delete). Crews still pointing at the removed template fall back to the runtime default lifecycle on next render rather than failing.
Auth: authenticated session + workspace context + requireRole("create"). Response: 204 No Content. Broadcasts workflow_template.deleted on the workspace WS channel with {"id": "<id>"}.

See also