> ## 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.

# Create Workflow

> Create a workflow. Client supplies `workflowId` in the path (URL-encode it). Required query: `folderId`. Body requires `name`. Before saving, GET `/phone-numbers`, ask the user which number to bind, and set `associatedToBusinessId` to that row's `id` plus `platformType`. Infer intent: if the bot **opens** a WhatsApp conversation (starter/outbound, `workflowTrigger`, POST `/trigger`), GET `/templates` and use an APPROVED template on the first WhatsApp node; inbound reply bots (`pingmeeTrigger`) use `messageType: custom` and should not fetch templates unless the user named one. Graph fields (`data`, `parsedData`, `trigger`, `triggerType`, `variables`) are optional — you can send a full document. The server overwrites `id`, `associatedTo` (from the Cookie), `folderId`, `isActive` (always `false`), `created`, `lastModified`, `executionCount`, `lastExecution`, and `analytics`. Returns `{ message, created, lastModified }`.

Before building `data` / `parsedData`, read `/build-workflows/overview` and the related Build workflows cookbook pages. Recommended save sequence: optional POST `/folders/{id}` → POST this endpoint (name + phone ids + optional graph) → PUT `{ isActive: true }`. Graph PUTs must echo `lastModified`.

You supply `workflowId` in the path (URL-encode it). `folderId` is a **required** query parameter — create a folder first or reuse one from [List workflows](/api-reference/workflows/get-minimal).

The body needs at least `name`. Also send `associatedToBusinessId` (phone-number `id` from [GET phone numbers](/api-reference/business/get-phone-numbers)) and `platformType`. You can also send a full graph (`data`, `parsedData`, `trigger`, `triggerType`, `variables`). The server always stores `isActive: false` and sets `associatedTo` from the Cookie.

Returns `{ message, created, lastModified }`. Keep `lastModified` for later graph PUTs.

<Note>
  Before building `data` or `parsedData`, read [Build workflows](/build-workflows/overview). Fetch phones, ask the user which number to bind, then **infer intent**: a WhatsApp **template** only if this bot **opens** the conversation; inbound reply bots use `messageType: "custom"`. An AI that only writes `data` will not run; one that only writes `parsedData` will not open correctly on the board.
</Note>

## Recommended save sequence

1. Optional: [Create folder](/api-reference/workflows/create-folder) — `POST /folders/{id}` with `{ "name": "..." }`
2. `POST /workflows/{workflowId}?folderId=...` with `name` and optional graph
3. [Update workflow](/api-reference/workflows/update) — `PUT` `{ "isActive": true }` (no graph required)

Graph PUTs must echo `lastModified` from this create response (or a later GET), or the API returns **409**.


## OpenAPI

````yaml POST /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
    post:
      description: >-
        Create a workflow. Client supplies `workflowId` in the path (URL-encode
        it). Required query: `folderId`. Body requires `name`. Before saving,
        GET `/phone-numbers`, ask the user which number to bind, and set
        `associatedToBusinessId` to that row's `id` plus `platformType`. Infer
        intent: if the bot **opens** a WhatsApp conversation (starter/outbound,
        `workflowTrigger`, POST `/trigger`), GET `/templates` and use an
        APPROVED template on the first WhatsApp node; inbound reply bots
        (`pingmeeTrigger`) use `messageType: custom` and should not fetch
        templates unless the user named one. Graph fields (`data`, `parsedData`,
        `trigger`, `triggerType`, `variables`) are optional — you can send a
        full document. The server overwrites `id`, `associatedTo` (from the
        Cookie), `folderId`, `isActive` (always `false`), `created`,
        `lastModified`, `executionCount`, `lastExecution`, and `analytics`.
        Returns `{ message, created, lastModified }`.


        Before building `data` / `parsedData`, read `/build-workflows/overview`
        and the related Build workflows cookbook pages. Recommended save
        sequence: optional POST `/folders/{id}` → POST this endpoint (name +
        phone ids + optional graph) → PUT `{ isActive: true }`. Graph PUTs must
        echo `lastModified`.
      parameters:
        - name: workflowId
          in: path
          required: true
          description: >-
            Client-supplied workflow identifier. Must be URL-encoded when used
            in the path.
          schema:
            type: string
        - name: folderId
          in: query
          required: true
          description: >-
            Folder to place the workflow in. Create a folder with POST
            `/folders/{id}` or reuse `folderId` from the minimal list.
          schema:
            type: string
      requestBody:
        required: true
        description: >-
          At least `name`. Optionally include the full dual graph (`data`,
          `parsedData`, `trigger`, `triggerType`, `variables`) and other
          Workflow fields. `isActive` in the body is ignored — the server always
          stores `false`.
        content:
          application/json:
            schema:
              type: object
              required:
                - name
              properties:
                name:
                  type: string
                  description: Workflow name.
                associatedToBusinessId:
                  type: string
                  description: >-
                    WhatsApp phone-number id from GET `/phone-numbers` (row
                    `id`, not `associatedBusinessId` / WABA). Required for
                    WhatsApp send. Ask the user if more than one number exists.
                associatedToPlatformId:
                  type: string
                  description: >-
                    Optional alias of the same phone-number / page id as
                    `associatedToBusinessId`.
                platformType:
                  type: string
                  description: >-
                    `whatsapp`, `facebookMessenger`, `instagram`, or `web`. Set
                    on create together with `associatedToBusinessId`.
                triggerType:
                  type: string
                  description: >-
                    Usually `trigger.data.eventType`. Trigger is not inside
                    `parsedData`.
                trigger:
                  $ref: '#/components/schemas/WorkflowNode'
                variables:
                  type: object
                  description: Workflow-level variable map. Usually `{}` unless set.
                  additionalProperties: true
                data:
                  $ref: '#/components/schemas/WorkflowCanvas'
                parsedData:
                  type: array
                  description: >-
                    Execution graph: parent nodes only. Sub-nodes hang off
                    `parent.subNodes[]`.
                  items:
                    $ref: '#/components/schemas/WorkflowNode'
                settings:
                  type: object
                  additionalProperties: true
                notes:
                  type: string
              additionalProperties: true
      responses:
        '201':
          description: Workflow created (always inactive)
          content:
            application/json:
              schema:
                type: object
                required:
                  - message
                  - created
                  - lastModified
                properties:
                  message:
                    type: string
                    example: Workflow 'wf_welcome' created.
                  created:
                    type: integer
                    description: Unix timestamp (seconds).
                  lastModified:
                    type: integer
                    description: Unix timestamp (seconds). Echo this on later graph PUTs.
                additionalProperties: false
        '400':
          description: Invalid request (missing `folderId` or empty `name`)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
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

````