Skip to content

Update work item type governance ​

PATCH/api/v2/workspaces/{slug}/work-item-types/{type_id}/governance/

Move a work item type to a new governance mode: any, constrained, or required. The response is the type's governance object after the change.

Every request names the target mode. A change that takes a workflow away from projects already using it needs acknowledge: true. A change that strands work items in states the new workflow doesn't contain needs a state_mapping. See Changing the mode and The orphan gate.

Mandating a workflow is a dry run until you acknowledge it

"mode": "required" without "acknowledge": true changes nothing. It returns 200 with a preview object that counts the work items the mandate would move. Send the same body again with "acknowledge": true to apply it.

Path Parameters ​

slug:requiredstring

The workspace slug. It appears in your Plane URLs. In https://app.plane.so/my-team/projects/, the slug is my-team.

type_id:requiredstring (uuid)

The work item type. It can be any type in the workspace.

Body Parameters ​

mode:requiredstring

The target mode. One of any, constrained, or required. Plane ignores fields that the target mode doesn't use.

  • any: clears the allowlist and keeps pins. Nothing else changes.
  • constrained: replaces the allowlist with workflow_ids.
  • required: mandates required_workflow_id for every project that uses the type.
workflow_ids:optionalarray of string (uuid)

Required when mode is constrained. The new allowlist. Every id must be an active catalog workflow in this workspace, or the request returns 400 invalid_request.

If a workflow that a project's pick uses is missing from this list, the request returns 409 workflow_allowlist_excludes_in_use unless acknowledge is true.

required_workflow_id:optionalstring (uuid)

Required when mode is required. The workflow to mandate. It must be an active catalog workflow in this workspace.

acknowledge:optionalboolean

Defaults to false. Set it to true to confirm a consequence you have already previewed:

  • under constrained, dropping workflows that projects' picks use. Those projects fall back to the workspace default workflow, and Plane deletes pins outside the new allowlist.
  • under required, applying the mandate instead of returning a dry run.

acknowledge doesn't bypass the orphan gate. Stranded work items still need state_mapping.

state_mapping:optionalobject

Maps a current state id to a state id in the target workflow, for work items whose state the target workflow doesn't contain. Values must be UUIDs. Plane ignores a key that isn't a valid UUID.

The target workflow is the workspace default workflow for projects a constrained change strands, and the mandated workflow for required. If the mapping doesn't cover every stranded state, or points at a state outside the target workflow, the request returns 409 workflow_state_orphans.

Scopes ​

workspaces.workflows:write

Errors ​

StatusCodeCause
400invalid_requestmode missing or outside the enum, workflow_ids missing for constrained, required_workflow_id missing for required, an unknown or inactive workflow, or a non-UUID state_mapping value.
401unauthorizedMissing or invalid credentials.
402payment_requiredWorkspace governance isn't on your plan.
403forbiddenYour role or token scope can't edit workspace workflows.
404not_foundNo such work item type in this workspace.
406not_acceptableThe Accept header asks for a representation the API can't produce.
409states_managed_at_projectThe workspace doesn't have governance turned on.
409workflow_allowlist_excludes_in_useA constrained allowlist leaves out workflows that projects' picks use, and acknowledge isn't true. The body lists them in workflows.
409workflow_state_orphansThe change strands work items and state_mapping doesn't cover their states. The body carries the orphans report.
413payload_too_largeThe request body is over the size limit.
415unsupported_media_typeThe Content-Type isn't one this endpoint accepts.
429rate_limitedThrottled. Honor the Retry-After header before retrying.
Update work item type governance
bash
curl -X PATCH \
  "https://api.plane.so/api/v2/workspaces/my-team/work-item-types/d1e7a4c9-2b58-4f36-9a0e-7c3b5d81f240/governance/" \
  -H "X-Api-Key: $PLANE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "mode": "constrained",
  "workflow_ids": [
    "a1f4c7e2-3b98-4d61-8e25-6c0b9d7f3a14",
    "e6b2d9f1-48a7-4c3e-9f50-1d7a8c2b6e93"
  ]
}'
Response200
json
{
  "mode": "constrained",
  "required_workflow_id": null,
  "allowlist": [
    {
      "workflow_id": "a1f4c7e2-3b98-4d61-8e25-6c0b9d7f3a14",
      "name": "Standard delivery",
      "locked": true,
      "in_use_by_project_ids": ["4af68566-94a4-4eb3-94aa-50dc9427067b"]
    },
    {
      "workflow_id": "e6b2d9f1-48a7-4c3e-9f50-1d7a8c2b6e93",
      "name": "Regulated release",
      "locked": false,
      "in_use_by_project_ids": []
    }
  ]
}
Response200
json
{
  "preview": {
    "total": 12,
    "per_state": [
      {
        "state_id": "b7e42a19-3c5d-4f80-9a26-8d1c0f4e7b53",
        "count": 12
      }
    ]
  }
}
Response409
json
{
  "type": "conflict",
  "code": "workflow_allowlist_excludes_in_use",
  "detail": "The allowlist excludes workflows that projects are currently using. Re-send with acknowledge=true to drop those picks.",
  "workflows": [
    {
      "id": "e6b2d9f1-48a7-4c3e-9f50-1d7a8c2b6e93",
      "name": "Regulated release"
    }
  ]
}
Response409
json
{
  "type": "conflict",
  "code": "workflow_state_orphans",
  "detail": "This change strands work items outside the target workflow; supply a state_mapping that covers them.",
  "orphans": {
    "error": "Some work items are in states that are not part of the new chain — map every affected state to a state in it.",
    "code": "orphaned_states",
    "orphans": [
      {
        "state_id": "b7e42a19-3c5d-4f80-9a26-8d1c0f4e7b53",
        "state_name": "In Review",
        "count": 12,
        "per_project": [
          {
            "project_id": "4af68566-94a4-4eb3-94aa-50dc9427067b",
            "count": 12
          }
        ]
      }
    ],
    "invalid_targets": []
  }
}

Mandating a workflow, step by step ​

  1. Preview the move with Preview a governance change, or send the PATCH without acknowledge and read the preview object.
  2. Send the PATCH with "acknowledge": true.
  3. If it returns 409 workflow_state_orphans, map every state in orphans.orphans to a state in the mandated workflow and send the request again with that state_mapping.
json
{
  "mode": "required",
  "required_workflow_id": "e6b2d9f1-48a7-4c3e-9f50-1d7a8c2b6e93",
  "acknowledge": true,
  "state_mapping": {
    "b7e42a19-3c5d-4f80-9a26-8d1c0f4e7b53": "f960d3c2-8524-4a41-b8eb-055ce4be2a7f"
  }
}

On success, every project pick for the type points at the mandated workflow, every pin for the type is deleted, and the stranded work items move to the states you mapped. Projects can no longer change the workflow for this type. A request to set their pick returns 403 workflow_mandated.

Loosening is always safe

Moving to any never strands anything, so it needs no acknowledge and no state_mapping. It clears the allowlist and leaves every pick and pin in place.