---
title: "Change an approval flow"
method: PATCH
path: "/api/v1/rest/workflow/flows/{id}"
tags: ["Workflows"]
---

# Change an approval flow

`PATCH /api/v1/rest/workflow/flows/{id}`

## Request

- Base URL: `https://api.custodo.ai`
- URL: `https://api.custodo.ai/api/v1/rest/workflow/flows/{id}`
- Auth: HTTP bearer

Changes a flow: send ONLY the parts that change. `fields` and `steps` each replace the whole list — read the flow with workflow_get_flow first and send every field/step that should remain: an existing field keeps its `key`, an existing step is either sent in full with its `id`, or kept untouched with { keep_step: "<id>" } (always do that for automated steps). `active: true` switches the flow on — it starts asking people, and an automatic trigger starts on its own. The person approves the change before it is saved.

## Path parameters

- `id` string, uuid, required

## Headers

- `X-Tenant-Id` string, uuid

## Request body

- object
  - `name` string
  - `description` string, nullable
  - `trigger` 'manual' | 'document_ready' | 'document_typed' | 'email_received' | 'crm_deal_won' | 'spese_report_submitted'
  - `document_type_id` string, uuid, nullable
  - `trigger_config` object: The automatic trigger’s filter: document_* {titleContains}; email_received {mailboxIds, subjectContains, fromContains, toContains, requireAttachments, pec: any|only|exclude}; crm_deal_won {pipelineIds, minAmount}; spese_report_submitted {minTotalCents}. Omit for none — but ALWAYS narrow email_received, or every synced message opens a run.
  - `priority` 'low' | 'normal' | 'high'
  - `fields` object[]: The complete new field list.
    - `key` string: Stable key conditions refer to. Omit to derive it from the label.
    - `label` string, required
    - `type` 'text' | 'textarea' | 'number' | 'date' | 'boolean' | 'select', required
    - `required` boolean
    - `options` string[]
    - `help` string
  - `steps` union[]: The complete new step list.
    - union
      - object
        - `keep_step` string, required: The id of an existing step.
      - object
        - `id` string: workflow_update_flow only: the id of the existing step this replaces.
        - `name` string, required
        - `assignees` object[], required
          - `role` 'admin' | 'user': `admin` = every administrator; `user` = every member with approval rights.
          - `user_id` string, uuid: One member — from custodo_list_members.
          - `team_id` string, uuid: A reparto — from custodo_list_teams.
        - `mode` 'all' | 'any' | 'quorum': With several assignees: all must approve, any one may, or a quorum.
        - `quorum` integer
        - `timeout_hours` integer
        - `parallel_with_previous` boolean: Asked at the same time as the step above instead of after it.
        - `condition` object: Omit to run the step always.
          - `match` 'all' | 'any'
          - `rules` object[], required
            - `field` string, required: A field key (or label) of this flow, or a run fact such as @totalCents.
            - `op` 'eq' | 'ne' | 'gt' | 'gte' | 'lt' | 'lte' | 'in' | 'contains' | 'truthy' | 'falsy', required
            - `value` union: Omit for truthy/falsy. For a select, one of its options exactly as written.
              - …
  - `active` boolean: true switches the flow on, false off. Omit to leave it as it is.

## Response `200`

Done. `data` is the tool’s own answer.

- RestResult
  - `ok` true, required
  - `data` unknown, required

## Other responses

- `400`: The arguments did not validate: `error.message` names the field, what it expects and what arrived.
- `401`: No API key, or one that is malformed, unknown, revoked or expired.
- `403`: The call never ran: the module is off for this organisation, the credential lacks the permission or the module, the tier does not cover it, or the tool is destructive and the key was not minted for that.
- `404`: Nothing with that id in this organisation.
- `409`: The record is in a state that does not allow it — under legal hold, already sent, already closed. `error.code` says which.
- `422`: The tool ran and refused, in a sentence of its own (`TOOL_REFUSED`): the message says what to change. Retrying the same call will not help.
- `429`: The API key has spent its minute, or its day. Every request a key makes counts. See `Retry-After`.

---

[API](https://skmtc.dev/custodo/apis/custodo-integrazioni.md) · [All operations](https://skmtc.dev/custodo/apis/custodo-integrazioni/llms.txt) · [OpenAPI document](https://skmtc.dev/custodo/apis/custodo-integrazioni/revisions/16d336d3ec2a?raw)
