> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pingmee.co.il/llms.txt
> Use this file to discover all available pages before exploring further.

# Update Workflow

> Update a workflow. `name`, `isActive`, `settings`, and `associatedToBusinessId` can be sent alone — including `{ isActive: true }` to activate without sending a graph. If `data` or `parsedData` is present, this is a graph update: also send `trigger`, `triggerType`, `variables`, and `lastModified` from the last GET or create, or the API returns 409. Always send both `data` and `parsedData` plus `trigger` / `triggerType` on graph save. Do not send `analytics`. A graph PUT prunes stored analytics for node, edge, and button ids that are no longer on the graph — GET fresh analytics before rewriting.

Before building `data` / `parsedData`, read `/build-workflows/overview` and `/build-workflows/analytics`. Path `workflowId` must be URL-encoded.

Partial update — send only the fields you want to change. URL-encode `workflowId` in the path.

`name`, `isActive`, `settings`, and `associatedToBusinessId` can be sent alone. Create always stores a workflow inactive; activate without sending a graph:

```json theme={null}
{
  "isActive": true
}
```

Set `associatedToBusinessId` (and `platformType` on **create**) from [GET phone numbers](/api-reference/business/get-phone-numbers). PUT persists `associatedToBusinessId` without a graph; `platformType` is stored from the create body.

## Graph updates and optimistic lock

If `data` or `parsedData` is present, this is a graph update. Also send `trigger`, `triggerType`, `variables`, and `lastModified` from the last [GET](/api-reference/workflows/get) or [create](/api-reference/workflows/create). Always send **both** `data` and `parsedData` plus `trigger` / `triggerType`.

When `lastModified` does not match the server, the API returns **409** with the current `lastModified`. Reload and retry.

A graph PUT **prunes** stored `analytics` for node / edge / button ids that are no longer on the graph. GET fresh analytics before you rewrite, and do not send `analytics` in the body. See [Workflow analytics](/build-workflows/analytics).

<Note>
  Before building `data` or `parsedData`, read [Build workflows](/build-workflows/overview) and the related cookbook pages.
</Note>


## OpenAPI

````yaml PUT /workflows/{workflowId}
openapi: 3.1.0
info:
  title: Pingmee API
  description: A complete guide to Pingmee micro service architecture.
  version: 1.0.0
servers:
  - url: https://api.pingmee.co.il
security:
  - cookieAuth: []
    ApiKeyAuth: []
paths:
  /workflows/{workflowId}:
    servers:
      - url: https://workflows.pingmee.co.il
        description: Workflows service
    put:
      description: >-
        Update a workflow. `name`, `isActive`, `settings`, and
        `associatedToBusinessId` can be sent alone — including `{ isActive: true
        }` to activate without sending a graph. If `data` or `parsedData` is
        present, this is a graph update: also send `trigger`, `triggerType`,
        `variables`, and `lastModified` from the last GET or create, or the API
        returns 409. Always send both `data` and `parsedData` plus `trigger` /
        `triggerType` on graph save. Do not send `analytics`. A graph PUT prunes
        stored analytics for node, edge, and button ids that are no longer on
        the graph — GET fresh analytics before rewriting.


        Before building `data` / `parsedData`, read `/build-workflows/overview`
        and `/build-workflows/analytics`. Path `workflowId` must be URL-encoded.
      parameters:
        - name: workflowId
          in: path
          required: true
          description: Workflow identifier. Must be URL-encoded when used in the path.
          schema:
            type: string
      requestBody:
        required: true
        description: >-
          Partial update. Send only the fields you want to change. Graph updates
          (`data` or `parsedData` present) require `lastModified` from the last
          GET or create.
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                isActive:
                  type: boolean
                  description: >-
                    Set `true` to activate. Create always stores `false`;
                    activate with a separate PUT `{ isActive: true }` (no graph
                    required).
                lastModified:
                  type: integer
                  description: >-
                    Required when `data` or `parsedData` is present. Echo the
                    value from the last GET or create, or the API returns 409.
                associatedToBusinessId:
                  type: string
                  description: >-
                    WhatsApp phone-number id from GET `/phone-numbers` (row
                    `id`). PUT can change this field without sending a graph.
                triggerType:
                  type: string
                trigger:
                  $ref: '#/components/schemas/WorkflowNode'
                variables:
                  type: object
                  additionalProperties: true
                data:
                  $ref: '#/components/schemas/WorkflowCanvas'
                parsedData:
                  type: array
                  items:
                    $ref: '#/components/schemas/WorkflowNode'
                settings:
                  type: object
                  additionalProperties: true
                notes:
                  type: string
              additionalProperties: true
      responses:
        '200':
          description: Workflow updated
          content:
            application/json:
              schema:
                type: object
                required:
                  - message
                  - lastModified
                properties:
                  message:
                    type: string
                    example: Workflow 'wf_welcome' updated successfully.
                  lastModified:
                    type: integer
                    description: >-
                      New Unix timestamp (seconds). Echo this on the next graph
                      PUT.
                additionalProperties: false
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: Workflow not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '409':
          description: >-
            Optimistic lock conflict — workflow was updated elsewhere. Reload
            with GET and retry using the returned `lastModified`.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    example: Workflow was updated elsewhere. Reload and try again.
                  lastModified:
                    type: integer
                    description: Current `lastModified` on the server.
                additionalProperties: false
components:
  schemas:
    WorkflowNode:
      type: object
      description: >-
        Execution node used in `parsedData`, `trigger`, and `subNodes`.
        Branching is which sub-node's `connections.out` — there are no handle
        ids here. Node `data` is a loose object; read
        `/build-workflows/overview` before building it.
      required:
        - id
        - type
        - category
        - data
        - connections
      properties:
        id:
          type: string
        parentId:
          type: string
          description: Parent node id when this node is a sub-node.
        type:
          type: string
          description: >-
            NodeType string, for example `pingmeeTrigger`, `whatsapp`, `if`,
            `conditionEvaluation`.
        category:
          type: string
          description: '`Trigger`, `Condition`, `Action`, `Operation`, `Note`, or `Answer`.'
        title:
          type: string
          description: >-
            Used by the engine for some branches (If/Else matches
            `title.toLowerCase()` of `true` / `false`).
        data:
          type: object
          description: >-
            Node form payload. Shape depends on `type` — see
            `/build-workflows/overview`.
          additionalProperties: true
        connections:
          type: object
          description: 'Typically `{ out: string[] }` of target node ids. No handle ids.'
          additionalProperties:
            type: array
            items:
              type: string
        subNodes:
          type: array
          description: >-
            Child branch nodes (answers, true/false, switch cases, fallback,
            timeout). Not used on canvas `data.nodes` — those are siblings with
            `parentId`.
          items:
            $ref: '#/components/schemas/WorkflowNode'
      additionalProperties: true
    WorkflowCanvas:
      type: object
      description: >-
        React Flow canvas (`workflow.data` from `toObject()`). Required for the
        editor. Always send together with `parsedData` + `trigger` when saving a
        graph. Node form payloads are not fully specified here — read
        `/build-workflows/overview` before building `data`.
      properties:
        nodes:
          type: array
          description: >-
            Canvas nodes. Sub-nodes are siblings in this array (they have
            `parentId`), not nested.
          items:
            type: object
            properties:
              id:
                type: string
              type:
                type: string
                description: >-
                  NodeType string, for example `pingmeeTrigger`, `whatsapp`,
                  `if`.
              category:
                type: string
                description: >-
                  `Trigger`, `Condition`, `Action`, `Operation`, `Note`, or
                  `Answer`.
              position:
                type: object
                properties:
                  x:
                    type: number
                  'y':
                    type: number
                additionalProperties: true
              parentId:
                type: string
                description: >-
                  Set on sub-nodes. Sub-nodes are siblings in `data.nodes`, not
                  nested.
              draggable:
                type: boolean
              selected:
                type: boolean
              data:
                type: object
                description: >-
                  Node form payload. Shape depends on `type` — see
                  `/build-workflows/overview`. Do not invent every field from
                  this schema.
                additionalProperties: true
            additionalProperties: true
        edges:
          type: array
          items:
            $ref: '#/components/schemas/WorkflowEdge'
      additionalProperties: true
    Error:
      required:
        - error
        - message
      type: object
      properties:
        error:
          type: string
        message:
          type: string
    WorkflowEdge:
      type: object
      description: >-
        React Flow edge. Copy every edge into execution `connections.out` with
        matching node ids (see `/build-workflows/canvas-vs-execution`). Root
        node output handle is `out`; input is `in`. Sub-node output handle is
        also `in` (downstream edges from a branch use `sourceHandle: "in"`).
        Type is usually `buttonedge`.
      properties:
        id:
          type: string
        source:
          type: string
          description: Source node id. Must match a `data.nodes[].id`.
        target:
          type: string
          description: Target node id. Must match a `data.nodes[].id`.
        sourceHandle:
          type: string
          description: Root output is `out`. Sub-node output is `in`.
        targetHandle:
          type: string
          description: Usually `in`.
        type:
          type: string
          description: Usually `buttonedge`.
      additionalProperties: true
  securitySchemes:
    cookieAuth:
      type: apiKey
      in: header
      name: Cookie
      description: Personal access token from Pingmee Settings → Developer Tools
    ApiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key
      description: Business API key from Pingmee Settings → Developer Tools

````