Workflow

Read the workspace workflow (kinds, states, priorities, labels, and settings) with an API token, and the browser-only operations that change it, through the SAQ REST API.

Written for
integration-developer
Roles
owner, admin, member, elevated-client-user, agent
Requires
API token with read scope for GET /workflow; All changes: browser session, Owner or Admin
Feature
workflow

The workflow is workspace-wide: one set of kinds, states, priorities, and labels for every project. Tickets reference them by id, so read the workflow once and cache the ids before creating or filtering tickets. SAQ has no state machine; any state can be chosen by an actor who may change state.

GET /api/w/{slug}/workflow

The whole workflow. Token: yes, read. Archived kinds, states, and priorities are not listed.

Request

curl https://saq.no/api/w/acme/workflow \
  -H 'Authorization: Bearer saq_YOUR_TOKEN'

Response 200 (Workflow)

{
  "kinds": [
    {
      "id": "01924c3e-0001-7000-8000-000000000001",
      "key": "bug",
      "name": "Bug",
      "position": 2
    }
  ],
  "priorities": [
    {
      "id": "01924c3e-0003-7000-8000-000000000002",
      "key": "medium",
      "name": "Medium",
      "position": 2
    }
  ],
  "states": [
    {
      "id": "01924c3e-0002-7000-8000-000000000001",
      "key": "backlog",
      "name": "Backlog",
      "category": "open",
      "position": 0,
      "reopenTarget": true
    },
    {
      "id": "01924c3e-0002-7000-8000-000000000005",
      "key": "done",
      "name": "Done",
      "category": "closed",
      "position": 4,
      "reopenTarget": false
    }
  ],
  "labels": [
    { "id": "01924c3e-0006-7000-8000-000000000001", "name": "frontend" }
  ],
  "inboundKindId": "01924c3e-0001-7000-8000-000000000004",
  "defaultPriorityId": "01924c3e-0003-7000-8000-000000000002",
  "customerResolveStateId": "01924c3e-0002-7000-8000-000000000005",
  "reopenWindowDays": 14
}
Field Meaning
kinds[] (Kind) id, key, name, position
priorities[] (Priority) id, key, name, position; ordered lowest first
states[] (State) id, key, name, category (open or closed), position, reopenTarget (exactly one open state)
labels[] (Label) id, name
inboundKindId Kind given to tickets started by email or by client users
defaultPriorityId Priority given to new tickets
customerResolveStateId The closed state a regular client user may move their own ticket to, or null
reopenWindowDays Days after closing during which an email reply reopens a ticket (0–365)

PATCH /api/w/{slug}/workflow

Change the workflow settings. Token: no (browser session only). Owner or Admin.

Body (UpdateWorkflowSettings), all optional: inboundKindId (uuid), defaultPriorityId (uuid), customerResolveStateId (uuid or null; must be a closed state), reopenWindowDays (integer 0–365). Response 200 (Workflow).

Kinds, states, priorities, and labels

All operations below are browser-session only, Owner or Admin. Keys are normalised (trimmed, lower-cased, spaces and hyphens become underscores) and must match ^[a-z][a-z0-9_]{1,31}$; a key is fixed after creation. Names are 1–60 characters. Archiving hides an item from the workflow but keeps existing tickets intact.

Operation Body Response
POST /workflow/kinds CreateKind: key, name 201 Kind
PATCH /workflow/kinds/{id} UpdateKind: name?, position? (integer ≥ 0) 200 { "ok": true }
DELETE /workflow/kinds/{id} 200 { "ok": true } (archived; refused for the inbound kind or the last kind)
POST /workflow/priorities key, name (same shape as CreateKind) 201 Priority
PATCH /workflow/priorities/{id} name?, position? 200 { "ok": true }
DELETE /workflow/priorities/{id} 200 { "ok": true } (archived; refused for the default priority or one in use)
POST /workflow/states CreateState: key, name, category (open or closed) 201 State
PATCH /workflow/states/{id} UpdateState: name?, category?, position?, reopenTarget? 200 { "ok": true }
DELETE /workflow/states/{id} 200 { "ok": true } (archived; refused while tickets are in it or it is the reopen target)
POST /workflow/labels LabelInput: name (unique per workspace) 201 Label
PATCH /workflow/labels/{id} LabelInput: name 200 { "ok": true } (renamed)
DELETE /workflow/labels/{id} 200 { "ok": true } (deleted)

Paths are relative to /api/w/{slug}.

Error Status When
forbidden 403 Not Owner or Admin, or an API token ("This action is not available to API tokens")
invalid 400 Validation failed (key or name format, unknown category)
conflict 409 Duplicate key or name, or an archive refused by the rules above
not_found 404 Unknown id