Skip to content

Update a workspace workflow hook ​

PATCH/api/v2/workspaces/{slug}/workflows/{workflow_id}/state-transitions/{transition_id}/hooks/{pk}/

Turn a hook on or off, or change its settings. phase and handler_name are fixed at creation. Sending either one returns 400, even with the current value. To change them, delete the hook and create a new one.

PATCH is partial. Plane checks the plan feature for the hook's handler again on every update, so you can't edit a hook whose feature has left your plan.

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.

workflow_id:requiredstring (uuid)

The catalog workflow the transition belongs to.

transition_id:requiredstring (uuid)

The transition the hooks run on. It must belong to the workflow in the path, or the request returns 404.

pk:requiredstring (uuid)

The id of the hook.

Body Parameters ​

execution_order isn't writable.

is_enabled:optionalboolean

Whether the hook runs. A disabled hook stays listed but doesn't run.

config:optionalobject

New handler settings, in the same shape as on create. What you send merges with what is stored:

  • run_script: the keys you send replace the stored ones, and keys you leave out keep their values, so a config without script_id keeps the current script.
  • send_webhook: an omitted url keeps the stored URL, and an omitted headers keeps the stored headers. A headers array replaces the stored list. In it, a secret header sent without value keeps its stored value when the stored header with the same key is also secret. A new header, or one that stops being secret, needs a value. The signing secret never changes here.

Response shaping ​

fields:optionalstring

Comma-separated list of fields to return. Unrequested keys are omitted from the response, not returned as null, so absent means "not requested" and null means "actually null". id always comes back whether or not you name it.

Pass all for every requestable field. An unknown name is a 400 that lists the valid set and suggests the closest match, so a typo can't silently cost you the saving.

Requestable here: config, created_at, execution_order, handler_name, id, is_enabled, phase, project_id, updated_at, workflow_transition_id.

See Sparse fields.

Scopes ​

workspaces.workflows:write

Errors ​

StatusCodeCause
400invalid_requestThe body has phase or handler_name, or config failed validation.
401unauthorizedMissing or invalid credentials.
402payment_requiredWorkflows isn't on your plan, or the hook's handler feature isn't: Plane Runner for run_script, Webhook transition conditions for send_webhook.
403forbiddenYour role or token scope can't edit workspace workflows.
404not_foundNo such workflow, transition, or hook, or the hook was deleted.
406not_acceptableThe Accept header asks for a representation the API can't produce.
409governance_migration_in_progressA governance migration is running in this workspace, so writes are paused. Retry after it finishes.
409states_managed_at_projectThe workspace doesn't have governance turned on. Use the project's workflows instead.
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 a workspace workflow hook
bash
curl -X PATCH \
  "https://api.plane.so/api/v2/workspaces/my-team/workflows/9c1f0b3d-6d2e-4c9a-8b41-2f7e5a0d6c88/state-transitions/d7a3f5c9-0b2e-4d81-b6f4-9e1c3a5d7b20/hooks/e4b7c9a2-3d1f-4e68-8a52-9f0c6b3d7e15/" \
  -H "X-Api-Key: $PLANE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "is_enabled": false
}'
Response200
json
{
  "id": "e4b7c9a2-3d1f-4e68-8a52-9f0c6b3d7e15",
  "workflow_transition_id": "d7a3f5c9-0b2e-4d81-b6f4-9e1c3a5d7b20",
  "project_id": null,
  "phase": "post",
  "handler_name": "send_webhook",
  "is_enabled": false,
  "execution_order": 1,
  "config": {
    "url": "https://hooks.example.com/plane",
    "headers": [
      {
        "key": "X-Team",
        "value": "platform",
        "is_secret": false
      }
    ]
  },
  "created_at": "2026-01-15T11:04:52.660219Z",
  "updated_at": "2026-02-03T16:45:12.904117Z"
}
Response400
json
{
  "type": "invalid_request",
  "code": "invalid_request",
  "detail": "`phase` is immutable after creation."
}