Loops Workflow nodes API

Create, read, update, delete and reroute the nodes of a workflow graph. 7 operation(s) in the Loops REST API v1 (OpenAPI 1.21.6).

Operations 7

POST /v1/workflows/{workflowId}/nodes Create a workflow node #
POST /v1/workflows/{workflowId}/nodes/{nodeId}/add-branch Add a branch #
GET /v1/workflows/{workflowId}/nodes/{nodeId} Get a workflow node #
POST /v1/workflows/{workflowId}/nodes/{nodeId} Update a workflow node #
DELETE /v1/workflows/{workflowId}/nodes/{nodeId} Delete a workflow node #
POST /v1/workflows/{workflowId}/nodes/{nodeId}/reroute Reroute a node connection #
DELETE /v1/workflows/{workflowId}/nodes/{nodeId}/recursive Delete workflow nodes recursively #

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/loops-workflow-nodes-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Discovery needs no key. Ratings and market analysis are Pro.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

loops-workflow-nodes-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: Loops OpenAPI Spec Workflow nodes API
  description: This is the OpenAPI Spec for the [Loops API](https://loops.so/docs/api).
  version: 1.21.6
servers:
- url: https://app.loops.so/api
tags:
- name: Workflow nodes
  description: View and mutate workflow nodes
paths:
  /v1/workflows/{workflowId}/nodes:
    parameters:
    - name: workflowId
      in: path
      required: true
      description: The ID of the workflow.
      schema:
        type: string
    post:
      tags:
      - Workflow nodes
      summary: Create a workflow node
      operationId: createWorkflowNode
      description: 'Create a new default workflow node and return it with the latest workflow.


        Choose where the node goes with `insertMode`: `between` places it between an existing `fromNodeId` -> `toNodeId` connection, `before` places it before `toNodeId`, and `after` places it after `fromNodeId` when that node has exactly one outgoing connection. `after` is a convenience for simple linear paths, so callers do not need to fetch and pass the current child node ID. It is invalid when `fromNodeId` has no outgoing nodes, multiple outgoing nodes, or is an exit node. When the source has multiple outgoing nodes, use `between` with the exact `toNodeId` instead. For `before`, deprecated `beforeNodeId` requests are still accepted for compatibility, but new callers should use `toNodeId`.


        New nodes start with default settings; update the node after creation to configure it. Branch nodes create their default paths too: `BranchNode` creates two `AudienceFilter` children, and `ExperimentBranchNode` creates two regular `VariantNode` children plus one control `VariantNode`. Public workflows can have up to 300 nodes. Generated children count toward that limit, so a normal create adds 1 node, `BranchNode` adds 3, and `ExperimentBranchNode` adds 4. To add a sibling child path to a branch or experiment branch, use the `POST /v1/workflows/{workflowId}/nodes/{nodeId}/add-branch` endpoint. Branch paths can be edited with create-node, but a workflow cannot be started unless each direct `BranchNode` child is an `AudienceFilter`. For experiments, use create-node only to insert a missing `VariantNode` before non-variant content; use add-branch for another variant path.'
      x-mint:
        href: /api-reference/create-workflow-node
        content: 'Choose where the node goes with `insertMode`:

          - `between` places it between an existing `fromNodeId` -> `toNodeId` connection

          - `before` places it before `toNodeId`

          - `after` places it after `fromNodeId` when that node has exactly one outgoing connection.


          Use `after` for simple linear paths when you do not want to fetch and pass the current child node ID. `after` is invalid when `fromNodeId` has no outgoing nodes, multiple outgoing nodes, or is an exit node. When the source has multiple outgoing nodes, use `between` with the exact `toNodeId` instead. For `before`, deprecated `beforeNodeId` requests are still accepted for compatibility, but new callers should use `toNodeId`.


          New nodes start with default settings; update the node after creation to configure it. Branch nodes create their default paths too: `BranchNode` creates two `AudienceFilter` children, and `ExperimentBranchNode` creates two regular `VariantNode` children plus one control `VariantNode`.


          Public workflows can have up to 300 nodes. Generated children count toward that limit, so a normal create adds 1 node, `BranchNode` adds 3, and `ExperimentBranchNode` adds 4. To add a sibling child path to a branch or experiment branch, use the `POST /v1/workflows/{workflowId}/nodes/{nodeId}/add-branch` endpoint. Branch paths can be edited with create-node, but a workflow cannot be started unless each direct `BranchNode` child is an `AudienceFilter`. For experiments, use create-node only to insert a missing `VariantNode` before non-variant content; use add-branch for another variant path.'
        metadata:
          sidebarTitle: Create a node
          description: Create a new default workflow node and return it with the latest workflow
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateWorkflowNodeRequest'
      responses:
        '200':
          description: Workflow node created.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateWorkflowNodeResponse'
        '400':
          description: Invalid request. Details will be shown in `message`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WorkflowFailureResponse'
        '401':
          description: Invalid API key.
        '404':
          description: Workflow or workflow node not found.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WorkflowFailureResponse'
        '405':
          description: Wrong HTTP request method.
        '409':
          description: '`expectedRevisionId` is stale.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WorkflowFailureResponse'
      security:
      - apiKey: []
  /v1/workflows/{workflowId}/nodes/{nodeId}/add-branch:
    parameters:
    - name: workflowId
      in: path
      required: true
      description: The ID of the workflow.
      schema:
        type: string
    - name: nodeId
      in: path
      required: true
      description: The ID of the BranchNode or ExperimentBranchNode that should receive one new child.
      schema:
        type: string
    post:
      tags:
      - Workflow nodes
      summary: Add a branch
      operationId: addWorkflowBranch
      description: 'Add a branch and a child node under an existing Branch or Experiment node. Returns the created child node plus the latest workflow.


        - Adding a branch to a `BranchNode` creates one `AudienceFilter` child node.

        - Adding a branch to an `ExperimentBranchNode` creates one `VariantNode` child node.


        This endpoint does not accept node configuration fields; update the child node with `POST /v1/workflows/{workflowId}/nodes/{nodeId}` after creation. Public workflows are limited to 300 nodes, and this endpoint adds 1 node.'
      x-mint:
        href: /api-reference/add-workflow-branch
        content: 'Adding a branch to a `BranchNode` creates one `AudienceFilter` child node.

          Adding a branch to an `ExperimentBranchNode` creates one `VariantNode` child node.


          This endpoint does not accept node configuration fields; [update the child node](/api-reference/update-workflow-node) after creation. Public workflows are limited to 300 nodes, and this endpoint adds 1 node.'
        metadata:
          sidebarTitle: Add a branch
          description: Add a branch and a child node under an existing Branch or Experiment node.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AddWorkflowBranchRequest'
      responses:
        '200':
          description: Branch added.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AddWorkflowBranchResponse'
        '400':
          description: Invalid `workflowId`, `nodeId`, request body, branch target, workflow state, or workflow node cap.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WorkflowFailureResponse'
        '401':
          description: Invalid API key.
        '404':
          description: Workflow or workflow node not found.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WorkflowFailureResponse'
        '405':
          description: Wrong HTTP request method.
        '409':
          description: '`expectedRevisionId` is stale.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WorkflowFailureResponse'
      security:
      - apiKey: []
  /v1/workflows/{workflowId}/nodes/{nodeId}:
    parameters:
    - name: workflowId
      in: path
      required: true
      description: The ID of the workflow.
      schema:
        type: string
        examples:
        - clw1a3b5c7d9e1f3g5h7i9j1
    - name: nodeId
      in: path
      required: true
      description: The ID of the workflow node.
      schema:
        type: string
        examples:
        - cln8p0q2r4s6t8u0v2w4x6z8
    get:
      tags:
      - Workflow nodes
      summary: Get a workflow node
      operationId: getWorkflowNode
      description: Retrieve detailed data for a single workflow node.
      x-mint:
        href: /api-reference/get-workflow-node
        metadata:
          sidebarTitle: Get a node
      responses:
        '200':
          description: Successful.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WorkflowNodeWithRevision'
        '400':
          description: Invalid `workflowId` or `nodeId`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WorkflowFailureResponse'
        '401':
          description: Invalid API key.
        '404':
          description: Workflow or workflow node not found.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WorkflowFailureResponse'
        '405':
          description: Wrong HTTP request method.
      security:
      - apiKey: []
    post:
      tags:
      - Workflow nodes
      summary: Update a workflow node
      operationId: updateWorkflowNode
      description: Update workflow-node-owned fields for a single node. Shared resources such as email messages and audience segments should be updated through their own APIs.
      x-mint:
        href: /api-reference/update-workflow-node
        content: Shared resources such as email messages and audience segments should be updated through their own APIs.
        metadata:
          sidebarTitle: Update a node
          description: Update workflow-node-owned fields for a single node.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateWorkflowNodeRequest'
      responses:
        '200':
          description: Workflow node updated.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UpdateWorkflowNodeResponse'
        '400':
          description: Invalid `workflowId`, `nodeId`, request body, or node update.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WorkflowFailureResponse'
        '401':
          description: Invalid API key.
        '404':
          description: Workflow or workflow node not found.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WorkflowFailureResponse'
        '405':
          description: Wrong HTTP request method.
        '409':
          description: '`expectedRevisionId` is stale.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WorkflowFailureResponse'
        '501':
          description: This node update is not implemented.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WorkflowFailureResponse'
      security:
      - apiKey: []
    delete:
      tags:
      - Workflow nodes
      summary: Delete a workflow node
      operationId: deleteWorkflowNode
      description: 'Delete a single workflow node. If contacts are queued at the node, Loops returns with `"status": "queuedContactsFound"` instead of deleting. Retry with `queuedContactPolicy: "discard"` to delete the node and discard those queued contacts. Confirmed deletion responses include the simplified workflow after the node is removed.'
      x-mint:
        href: /api-reference/delete-workflow-node
        content: 'Delete a node from a workflow.


          Make a dry run request using `dryRun: true`.


          If contacts are queued at the node, Loops returns with `"status": "queuedContactsFound"` instead of deleting. Retry with `queuedContactPolicy: "discard"` to delete the node and discard those queued contacts.


          Confirmed deletion responses include the simplified workflow after the node is removed.'
        metadata:
          sidebarTitle: Delete a node
          description: Delete a single workflow node.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/DeleteWorkflowNodeRequest'
      responses:
        '200':
          description: Delete dry run, queued-contact warning, or deletion result. Confirmed deletion responses include the simplified workflow after the node is removed.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DeleteWorkflowNodeResponse'
        '400':
          description: Invalid `workflowId`, `nodeId`, request body, or delete target.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WorkflowFailureResponse'
        '401':
          description: Invalid API key.
        '404':
          description: Workflow or workflow node not found.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WorkflowFailureResponse'
        '405':
          description: Wrong HTTP request method.
        '409':
          description: '`expectedRevisionId` is stale.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WorkflowFailureResponse'
      security:
      - apiKey: []
  /v1/workflows/{workflowId}/nodes/{nodeId}/reroute:
    parameters:
    - name: workflowId
      in: path
      required: true
      description: The ID of the workflow.
      schema:
        type: string
        examples:
        - clw1a3b5c7d9e1f3g5h7i9j1
    - name: nodeId
      in: path
      required: true
      description: The ID of the source workflow node whose outgoing connection should be moved.
      schema:
        type: string
        examples:
        - cln1a3b5c7d9e1f3g5h7i9j1
    post:
      tags:
      - Workflow nodes
      summary: Reroute a node connection
      operationId: rerouteNodeConnection
      description: Reroute the source node's existing connection to another valid target node. Returns the updated source node and the latest workflow.
      x-mint:
        href: /api-reference/reroute-node-connection
        content: 'Use this endpoint to modify an existing node connection to another target. Send the source node in the URL path and the new target in the request body.


          The source node must have exactly one outgoing connection. Branch and experiment branch nodes cannot be rerouted with this endpoint because they have multiple branch-specific outputs. The current target must still have another incoming connection after the reroute, and the new target must be valid for the source node. The workflow cannot be edited while in a `SENDING` state.'
        metadata:
          sidebarTitle: Reroute a node
          description: Reroute one existing node connection to another valid target node.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RerouteNodeConnectionRequest'
      responses:
        '200':
          description: Node connection rerouted.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RerouteNodeConnectionResponse'
        '400':
          description: Invalid `workflowId`, `nodeId`, request body, node connection selection, reroute target, or workflow state.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WorkflowFailureResponse'
        '401':
          description: Invalid API key.
        '404':
          description: Workflow or workflow node not found.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WorkflowFailureResponse'
        '405':
          description: Wrong HTTP request method.
        '409':
          description: '`expectedRevisionId` is stale.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WorkflowFailureResponse'
      security:
      - apiKey: []
  /v1/workflows/{workflowId}/nodes/{nodeId}/recursive:
    parameters:
    - name: workflowId
      in: path
      required: true
      description: The ID of the workflow.
      schema:
        type: string
    - name: nodeId
      in: path
      required: true
      description: The root node ID of the subtree to delete.
      schema:
        type: string
    delete:
      tags:
      - Workflow nodes
      summary: Delete workflow nodes recursively
      operationId: deleteWorkflowNodeRecursively
      description: 'Delete a node and its downstream subtree. If contacts are queued at any node that would be deleted, Loops returns with `"status": "queuedContactsFound"` instead of deleting. Retry with `queuedContactPolicy: "discard"` to delete the nodes and discard those queued contacts. Confirmed deletion responses include the simplified workflow after the nodes are removed.'
      x-mint:
        href: /api-reference/delete-workflow-nodes
        content: 'Delete a node and its downstream subtree.


          Make a dry run request using `dryRun: true`.


          If contacts are queued at any node that would be deleted, Loops returns with `"status": "queuedContactsFound"` instead of deleting. Retry with `queuedContactPolicy: "discard"` to delete the nodes and discard those queued contacts.


          Confirmed deletion responses include the simplified workflow after the nodes are removed.'
        metadata:
          sidebarTitle: Delete nodes
          description: Delete a node and its downstream subtree.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/DeleteWorkflowNodeRequest'
      responses:
        '200':
          description: Delete dry run, queued-contact warning, or deletion result. Confirmed deletion responses include the simplified workflow after the nodes are removed.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DeleteWorkflowNodeResponse'
        '400':
          description: Invalid `workflowId`, `nodeId`, request body, or delete target.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WorkflowFailureResponse'
        '401':
          description: Invalid API key.
        '404':
          description: Workflow or workflow node not found.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WorkflowFailureResponse'
        '405':
          description: Wrong HTTP request method.
        '409':
          description: '`expectedRevisionId` is stale.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WorkflowFailureResponse'
      security:
      - apiKey: []
components:
  schemas:
    AudienceFilterCondition:
      oneOf:
      - $ref: '#/components/schemas/PropertyCondition'
      - $ref: '#/components/schemas/OptInCondition'
      - $ref: '#/components/schemas/ActivityCondition'
      discriminator:
        propertyName: type
    BlankTriggerWorkflowNode:
      type: object
      properties:
        id:
          type: string
          examples:
          - cln8p0q2r4s6t8u0v2w4x6z8
        workflowId:
          type: string
          examples:
          - clw1a3b5c7d9e1f3g5h7i9j1
        typeName:
          type: string
          enum:
          - BlankTrigger
        nextNodeIds:
          $ref: '#/components/schemas/WorkflowNextNodeIds'
      required:
      - id
      - workflowId
      - typeName
      - nextNodeIds
      additionalProperties: false
    AddToListTriggerWorkflowMutationNodeWithRevision:
      allOf:
      - $ref: '#/components/schemas/AddToListTriggerWorkflowMutationNode'
      - $ref: '#/components/schemas/WorkflowMutationNodeRevision'
    CreatedWorkflowNode:
      allOf:
      - $ref: '#/components/schemas/WorkflowMutationNodeWithRevision'
      - type: object
        properties:
          createdChildNodes:
            type: array
            description: Default child nodes created along with the requested node. BranchNode creation returns two AudienceFilter children. ExperimentBranchNode creation returns two regular VariantNode children and one control VariantNode.
            items:
              $ref: '#/components/schemas/WorkflowMutationNode'
    WorkflowTimerActionPayload:
      type: object
      minProperties: 1
      description: Configuration for the timer action node.
      properties:
        amount:
          $ref: '#/components/schemas/WorkflowTimerAmount'
        unit:
          $ref: '#/components/schemas/WorkflowTimerUnit'
      additionalProperties: false
    CreateWorkflowNodeBetweenRequest:
      type: object
      description: Insert a new node between two existing nodes, `fromNodeId` and `toNodeId`. When `fromNodeId` is an `ExperimentBranchNode`, `nodeTypeName` must be `VariantNode`, and `toNodeId` cannot already be a `VariantNode`; use add-branch to add sibling variants. Branch paths can be edited with create-node, but a workflow cannot be started unless each direct `BranchNode` child is an `AudienceFilter`.
      properties:
        expectedRevisionId:
          $ref: '#/components/schemas/WorkflowExpectedRevisionId'
        insertMode:
          type: string
          enum:
          - between
        nodeTypeName:
          $ref: '#/components/schemas/CreateWorkflowNodeTypeName'
        fromNodeId:
          type: string
          description: The node to insert after. This node must currently point to `toNodeId`. If this is an `ExperimentBranchNode`, `nodeTypeName` must be `VariantNode` and `toNodeId` cannot already be a `VariantNode`.
        toNodeId:
          type: string
          description: The node to insert before.
      required:
      - expectedRevisionId
      - insertMode
      - nodeTypeName
      - fromNodeId
      - toNodeId
      additionalProperties: false
    VariantWorkflowMutationNodeWithRevision:
      allOf:
      - $ref: '#/components/schemas/VariantWorkflowMutationNode'
      - $ref: '#/components/schemas/WorkflowMutationNodeRevision'
    SimplifiedSendEmailActionWorkflowNode:
      type: object
      properties:
        typeName:
          type: string
          enum:
          - SendEmailAction
        nextNodeIds:
          $ref: '#/components/schemas/WorkflowNextNodeIds'
        emailMessageId:
          type:
          - string
          - 'null'
          description: The ID of the email message to send. To edit this email, use the `POST /v1/email-messages/{emailMessageId}` endpoint.
        subject:
          type: string
          description: The subject of the email message (reference only).
      required:
      - typeName
      - nextNodeIds
      - emailMessageId
      - subject
      additionalProperties: false
      examples:
      - typeName: SendEmailAction
        nextNodeIds: []
        emailMessageId: cle5f7g9h1i3j5k7l9m1n3p5
        subject: Welcome to Acme!
    CreateWorkflowNodeAfterRequest:
      type: object
      description: Insert a new node after `fromNodeId`. This is valid only when `fromNodeId` has exactly one outgoing node. It is invalid when `fromNodeId` has no outgoing nodes, multiple outgoing nodes, or is an exit node. When the source has multiple outgoing nodes, use `between` with the exact `toNodeId` instead.
      properties:
        expectedRevisionId:
          $ref: '#/components/schemas/WorkflowExpectedRevisionId'
        insertMode:
          type: string
          enum:
          - after
        nodeTypeName:
          $ref: '#/components/schemas/CreateWorkflowNodeTypeName'
        fromNodeId:
          type: string
          description: The node to insert after. This node must currently have exactly one outgoing node.
      required:
      - expectedRevisionId
      - insertMode
      - nodeTypeName
      - fromNodeId
      additionalProperties: false
    ExitActionWorkflowMutationNode:
      type: object
      properties:
        id:
          type: string
        typeName:
          type: string
          enum:
          - ExitAction
        nextNodeIds:
          $ref: '#/components/schemas/WorkflowNextNodeIds'
      required:
      - id
      - typeName
      - nextNodeIds
    AddWorkflowBranchResponse:
      type: object
      properties:
        node:
          $ref: '#/components/schemas/WorkflowMutationNodeWithRevision'
        workflow:
          $ref: '#/components/schemas/SimplifiedWorkflow'
      required:
      - node
      - workflow
      additionalProperties: false
    UpdateWorkflowNodeResponse:
      description: The updated workflow node, plus the latest simplified workflow.
      allOf:
      - $ref: '#/components/schemas/WorkflowMutationNodeWithRevision'
      - type: object
        properties:
          workflow:
            $ref: '#/components/schemas/SimplifiedWorkflow'
        required:
        - workflow
    SignupTriggerWorkflowMutationNode:
      type: object
      properties:
        id:
          type: string
        typeName:
          type: string
          enum:
          - SignupTrigger
        nextNodeIds:
          $ref: '#/components/schemas/WorkflowNextNodeIds'
      required:
      - id
      - typeName
      - nextNodeIds
    WorkflowMutationNodeRevision:
      type: object
      properties:
        workflowRevisionId:
          $ref: '#/components/schemas/WorkflowRevisionId'
      required:
      - workflowRevisionId
    WorkflowContactPropertyQuery:
      type: object
      description: Define the contact property change that triggers the workflow. In update requests, `key` must resolve to an existing contact property that is available for Contact Updated triggers. Hidden or unsupported fields, such as `createdAt`, `notes`, and computed contact properties, are rejected.
      properties:
        key:
          type: string
          description: The camel-cased `key` of the contact property to query. The property must exist for the team and must be available for Contact Updated triggers.
          examples:
          - firstName
          - email
          - planName
        is:
          description: Comparison for the new contact property value after the update.
          $ref: '#/components/schemas/WorkflowContactPropertyComparison'
        was:
          description: Comparison for the previous contact property value before the update.
          $ref: '#/components/schemas/WorkflowContactPropertyComparison'
      required:
      - key
      - is
      - was
    ExperimentBranchWorkflowMutationNode:
      type: object
      properties:
        id:
          type: string
        typeName:
          type: string
          enum:
          - ExperimentBranchNode
        nextNodeIds:
          $ref: '#/components/schemas/WorkflowNextNodeIds'
        samplingRate:
          type: number
          description: The percentage of contacts that will be sent to variant branches, between `0` and `100`. The remaining percentage will be sent to the control branch. `100` sends all contacts to variant branches.
      required:
      - id
      - typeName
      - nextNodeIds
      - samplingRate
    WorkflowContactPropertyComparison:
      type: object
      description: For Contact Updated triggers, the API validates `operator` against the selected contact property's type and the side of the comparison. The `was` comparison can use any operator supported by the selected property type. The `is` comparison uses the same operators, except number and boolean properties cannot use `empty`. String properties support `any`, `equal`, `not_equal`, `contains`, `not_contains`, `empty`, and `not_empty`. Number properties support `any`, `greater_than`, `less_than`, `numeric_equal`, `numeric_not_equal`, `empty`, and `not_empty`. Boolean properties support `any`, `true`, `false`, `empty`, and `not_empty`. Date properties support `any`, `empty`, `not_empty`, `after`, `before`, and `between`.
      properties:
        value:
          oneOf:
          - type: string
          - type: number
          - type: boolean
        operator:
          type: string
          description: The comparison operator. It must be valid for the selected contact property's type and for the `is` or `was` side of the comparison. Number and boolean properties allow `empty` on `was`, but not on `is`.
          enum:
          - any
          - contains
          - not_contains
          - empty
          - not_empty
          - equal
          - not_equal
          - greater_than
          - less_than
          - 'true'
          - 'false'
          - numeric_equal
          - numeric_not_equal
          - after
          - before
          - between
      required:
      - value
      - operator
    WorkflowEventTriggerPayload:
      type: object
      description: Updates an event trigger, or changes an existing trigger node to an event trigger. Assign the event pattern with either `eventPatternId` or `eventName`, not both. Set either field to `null` to clear the event-pattern relationship.
      minProperties: 1
      properties:
        typeName:
          type: string
          enum:
          - EventTrigger
        eventPatternId:
          type:
          - string
          - 'null'
          description: The ID of the event pattern to trigger on. Use either `eventPatternId` or `eventName`, not both. Set to `null` to clear the event-pattern relationship.
        eventName:
          type:
          - string
          - 'null'
          description: The name of the event pattern to trigger on. Use this when you know the event name but not the internal event pattern ID. Use either `eventName` or `eventPatternId`, not both. Set to `null` to clear the event-pattern relationship.
        reEligible:
          $ref: '#/components/schemas/WorkflowReEligible'
      additionalProperties: false
    CreateWorkflowNodeRequest:
      oneOf:
      - $ref: '#/components/schemas/CreateWorkflowNodeBetweenRequest'
      - $ref: '#/components/schemas/CreateWorkflowNodeBeforeRequest'
      - $ref: '#/components/schemas/CreateWorkflowNodeAfterRequest'
      description: Create a new workflow node with an explicit `insertMode`. To configure the node after creation, use the `POST /v1/workflows/{workflowId}/nodes/{nodeId}` endpoint.
      discriminator:
        propertyName: insertMode
        mapping:
          between: '#/components/schemas/CreateWorkflowNodeBetweenRequest'
          before: '#/components/schemas/CreateWorkflowNodeBeforeRequest'
          after: '#/components/schemas/CreateWorkflowNodeAfterRequest'
    SendEmailActionWorkflowMutationNodeWithRevision:
      allOf:
      - $ref: '#/components/schemas/SendEmailActionWorkflowMutationNode'
      - $ref: '#/components/schemas/WorkflowMutationNodeRevision'
    WorkflowAddToListTriggerPayload:
      type: object
      description: Updates an add-to-list trigger, or changes an existing trigger node to an add-to-list trigger.
      minProperties: 1
      properties:
        typeName:
          type: string
          enum:
          - AddToListTrigger
        reEligible:
          $ref: '#/components/schemas/WorkflowReEligible'
      additionalProperties: false
    TimerActionWorkflowMutationNodeWithRevision:
      allOf:
      - $ref: '#/components/schemas/TimerActionWorkflowMutationNode'
      - $ref: '#/components/schemas/WorkflowMutationNodeRevision'
    RerouteNodeConnectionRequest:
      type: object
      description: Reroute the source node's only outgoing connection to `newTargetNodeI

# --- truncated at 32 KB (75 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/loops/refs/heads/main/openapi/loops-workflow-nodes-api-openapi.yml