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

# Update a draft campaign

> Update a DRAFT campaign in place: campaign settings and/or the full step sequence. `steps` uses the same simplified step model as `POST /v1/campaigns` and, when provided, replaces the whole stored sequence — fetch the current steps with `GET /v1/campaign/{campaignId}`, modify them, and resubmit. Rich-text formatting of steps whose text you did not change is preserved automatically. Campaigns that are not in DRAFT status cannot be updated; clone them instead.

Responses include direct Enginy app URLs when available. Responses include an `appUrl` that opens the updated campaign in Enginy. MCP agents should return those URLs to users whenever they are present in the response.

    > **Required scope:** `CAMPAIGNS_WRITE`
    >
    > **Rate limit:** 30 requests per minute



## OpenAPI

````yaml https://openapi.enginy.ai/definitions.json patch /v1/campaign/{campaignId}
openapi: 3.1.0
info:
  title: Enginy API
  version: 1.0.0
  description: Public API for Enginy platform
servers:
  - url: https://openapi.enginy.ai
    description: Configured server
security: []
tags:
  - name: AI Variables
    description: >-
      Manage AI variables and discover the entity fields you can reference in
      prompts and entity requests.
  - name: Inbox
    description: >-
      Inbox endpoints for listing contact threads, reading thread messages,
      managing tags, and sending manual replies.
  - name: Workflows
    description: >-
      Build, validate, publish, run, and inspect advanced (graph) workflows,
      plus the block/condition catalog needed to author a workflow plan.
paths:
  /v1/campaign/{campaignId}:
    patch:
      tags:
        - Campaigns
      summary: Update a draft campaign
      description: >-
        Update a DRAFT campaign in place: campaign settings and/or the full step
        sequence. `steps` uses the same simplified step model as `POST
        /v1/campaigns` and, when provided, replaces the whole stored sequence —
        fetch the current steps with `GET /v1/campaign/{campaignId}`, modify
        them, and resubmit. Rich-text formatting of steps whose text you did not
        change is preserved automatically. Campaigns that are not in DRAFT
        status cannot be updated; clone them instead.


        Responses include direct Enginy app URLs when available. Responses
        include an `appUrl` that opens the updated campaign in Enginy. MCP
        agents should return those URLs to users whenever they are present in
        the response.

            > **Required scope:** `CAMPAIGNS_WRITE`
            >
            > **Rate limit:** 30 requests per minute
      parameters:
        - schema:
            type: string
            description: The campaign ID to update
          required: true
          description: The campaign ID to update
          name: campaignId
          in: path
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                  minLength: 1
                  description: Campaign name.
                description:
                  type:
                    - string
                    - 'null'
                  description: Optional campaign description.
                identityId:
                  type:
                    - integer
                    - 'null'
                  exclusiveMinimum: 0
                shouldAutomaticallySend:
                  type: boolean
                shouldSendTrackingPixel:
                  type: boolean
                shouldTrackEmailLinks:
                  type: boolean
                excludeContactedLeads:
                  type: boolean
                allowedEmails:
                  type: array
                  items:
                    type: string
                  description: Allowed sender email addresses for this campaign.
                steps:
                  type: array
                  items:
                    oneOf:
                      - type: object
                        properties:
                          type:
                            type: string
                            enum:
                              - email
                          subject:
                            type: string
                            description: >-
                              Email subject. Required with manual `content` for
                              the first email on every live path; follow-up
                              emails may pass an empty string (or omit it) to
                              reply in the existing thread. Omit when
                              `aiMessageId` is set — the AI message generates
                              it.
                          content:
                            type: string
                            minLength: 1
                            description: >-
                              Manual email body. Required unless `aiMessageId`
                              is provided.
                          aiMessageId:
                            type: string
                            minLength: 1
                            description: >-
                              ID of an AI message that generates this step's
                              message per contact at send time. Accepts a
                              workspace-owned AI message (see `GET
                              /v1/ai-variables/ai-messages`, or create one with
                              `POST /v1/ai-variables/ai-messages` to control
                              prompt, tone, model, and output length) or a
                              public prompt-library entry (see `GET
                              /v1/prompt-library/ai-messages`); either way the
                              campaign step gets its own copy. The AI message
                              channel must match the step type. Mutually
                              exclusive with manual `content`, `subject`, and
                              attachment fields. Requires the AI variable split
                              to be enabled for the workspace.
                          delay:
                            type: object
                            properties:
                              value:
                                type: number
                                minimum: 0
                                description: Delay amount.
                              unit:
                                type: string
                                enum:
                                  - seconds
                                  - minutes
                                  - hours
                                  - days
                                description: Delay unit.
                            required:
                              - value
                              - unit
                            additionalProperties: false
                        required:
                          - type
                        additionalProperties: false
                        title: email
                      - type: object
                        properties:
                          type:
                            type: string
                            enum:
                              - linkedin_message
                          aiMessageId:
                            type: string
                            minLength: 1
                            description: >-
                              ID of an AI message that generates this step's
                              message per contact at send time. Accepts a
                              workspace-owned AI message (see `GET
                              /v1/ai-variables/ai-messages`, or create one with
                              `POST /v1/ai-variables/ai-messages` to control
                              prompt, tone, model, and output length) or a
                              public prompt-library entry (see `GET
                              /v1/prompt-library/ai-messages`); either way the
                              campaign step gets its own copy. The AI message
                              channel must match the step type. Mutually
                              exclusive with manual `content`, `subject`, and
                              attachment fields. Requires the AI variable split
                              to be enabled for the workspace.
                          content:
                            type: string
                            minLength: 1
                            description: >-
                              LinkedIn message body. Required unless
                              `attachment` or `aiMessageId` is provided.
                          attachment:
                            type: string
                            minLength: 1
                            description: >-
                              Optional URL or storage key of the file to send
                              alongside the message.
                          attachmentName:
                            type: string
                            minLength: 1
                            description: Optional display name for the attachment.
                          contentType:
                            type: string
                            enum:
                              - AUDIO
                              - IMAGE
                              - FILE
                              - VIDEO
                            description: >-
                              Attachment kind. Recommended when `attachment` is
                              set. Use `VIDEO` for video files.
                          delay:
                            type: object
                            properties:
                              value:
                                type: number
                                minimum: 0
                                description: Delay amount.
                              unit:
                                type: string
                                enum:
                                  - seconds
                                  - minutes
                                  - hours
                                  - days
                                description: Delay unit.
                            required:
                              - value
                              - unit
                            additionalProperties: false
                        required:
                          - type
                        additionalProperties: false
                        title: linkedin_message
                      - type: object
                        properties:
                          type:
                            type: string
                            enum:
                              - linkedin_message_bundle
                          messages:
                            type: array
                            items:
                              type: object
                              properties:
                                content:
                                  type: string
                                  minLength: 1
                                  description: Text body of the bundle message.
                                attachment:
                                  type: string
                                  minLength: 1
                                  description: URL or storage key of the file to send.
                                attachmentName:
                                  type: string
                                  minLength: 1
                                  description: Display name for the attachment.
                                contentType:
                                  type: string
                                  enum:
                                    - AUDIO
                                    - IMAGE
                                    - FILE
                                    - VIDEO
                                  description: >-
                                    Attachment kind. Recommended when
                                    `attachment` is set. Use `VIDEO` for video
                                    files.
                              additionalProperties: false
                            minItems: 1
                            description: >-
                              Ordered list of messages sent back-to-back as a
                              single bundle.
                          delay:
                            type: object
                            properties:
                              value:
                                type: number
                                minimum: 0
                                description: Delay amount.
                              unit:
                                type: string
                                enum:
                                  - seconds
                                  - minutes
                                  - hours
                                  - days
                                description: Delay unit.
                            required:
                              - value
                              - unit
                            additionalProperties: false
                        required:
                          - type
                          - messages
                        additionalProperties: false
                        title: linkedin_message_bundle
                      - type: object
                        properties:
                          type:
                            type: string
                            enum:
                              - linkedin_voice_message
                          content:
                            type: string
                            minLength: 1
                            description: >-
                              Text body that will be synthesized to speech via
                              the configured `voiceId`.
                          voiceId:
                            type: string
                            minLength: 1
                            description: >-
                              ID of a system voice or an identity-cloned voice.
                              Use `GET /v1/voices` to list valid voice IDs.
                          attachment:
                            type: string
                            minLength: 1
                            description: >-
                              URL or storage key for a pre-recorded audio
                              message.
                          attachmentName:
                            type: string
                            minLength: 1
                            description: Optional display name for the audio file.
                          contentType:
                            type: string
                            enum:
                              - AUDIO
                            description: Set to `AUDIO` when `attachment` is provided.
                          voiceSettings:
                            type: object
                            properties:
                              voiceSpeed:
                                type: number
                                minimum: 0.5
                                maximum: 2
                                description: >-
                                  Speech rate multiplier. Range 0.5–2.0.
                                  Defaults are applied server-side when omitted.
                              voiceStability:
                                type: number
                                minimum: 0
                                maximum: 100
                                description: >-
                                  Voice stability percentage (0–100). Higher is
                                  steadier, lower is more expressive.
                              backgroundNoise:
                                type: string
                                minLength: 1
                                description: >-
                                  Optional background noise preset (e.g. `none`,
                                  `office`). Server defaults to `none`.
                              backgroundVolume:
                                type: number
                                minimum: 0
                                maximum: 100
                                description: >-
                                  Background noise volume (0–100). Ignored when
                                  `backgroundNoise` is `none`.
                            additionalProperties: false
                            description: >-
                              Optional fine-tuning of the synthesized voice and
                              background audio.
                          delay:
                            type: object
                            properties:
                              value:
                                type: number
                                minimum: 0
                                description: Delay amount.
                              unit:
                                type: string
                                enum:
                                  - seconds
                                  - minutes
                                  - hours
                                  - days
                                description: Delay unit.
                            required:
                              - value
                              - unit
                            additionalProperties: false
                        required:
                          - type
                        additionalProperties: false
                        title: linkedin_voice_message
                      - type: object
                        properties:
                          type:
                            type: string
                            enum:
                              - linkedin_inmail
                          subject:
                            type: string
                            minLength: 1
                            description: >-
                              InMail subject. Required with manual `content`.
                              Omit when `aiMessageId` is set.
                          content:
                            type: string
                            minLength: 1
                            description: >-
                              Manual InMail body. Required unless `aiMessageId`
                              is provided.
                          aiMessageId:
                            type: string
                            minLength: 1
                            description: >-
                              ID of an AI message that generates this step's
                              message per contact at send time. Accepts a
                              workspace-owned AI message (see `GET
                              /v1/ai-variables/ai-messages`, or create one with
                              `POST /v1/ai-variables/ai-messages` to control
                              prompt, tone, model, and output length) or a
                              public prompt-library entry (see `GET
                              /v1/prompt-library/ai-messages`); either way the
                              campaign step gets its own copy. The AI message
                              channel must match the step type. Mutually
                              exclusive with manual `content`, `subject`, and
                              attachment fields. Requires the AI variable split
                              to be enabled for the workspace.
                          delay:
                            type: object
                            properties:
                              value:
                                type: number
                                minimum: 0
                                description: Delay amount.
                              unit:
                                type: string
                                enum:
                                  - seconds
                                  - minutes
                                  - hours
                                  - days
                                description: Delay unit.
                            required:
                              - value
                              - unit
                            additionalProperties: false
                        required:
                          - type
                        additionalProperties: false
                        title: linkedin_inmail
                      - type: object
                        properties:
                          type:
                            type: string
                            enum:
                              - linkedin_visit_profile
                          delay:
                            type: object
                            properties:
                              value:
                                type: number
                                minimum: 0
                                description: Delay amount.
                              unit:
                                type: string
                                enum:
                                  - seconds
                                  - minutes
                                  - hours
                                  - days
                                description: Delay unit.
                            required:
                              - value
                              - unit
                            additionalProperties: false
                        required:
                          - type
                        additionalProperties: false
                        title: linkedin_visit_profile
                      - type: object
                        properties:
                          type:
                            type: string
                            enum:
                              - linkedin_like_last_post
                          delay:
                            type: object
                            properties:
                              value:
                                type: number
                                minimum: 0
                                description: Delay amount.
                              unit:
                                type: string
                                enum:
                                  - seconds
                                  - minutes
                                  - hours
                                  - days
                                description: Delay unit.
                            required:
                              - value
                              - unit
                            additionalProperties: false
                          reactionType:
                            type: string
                            minLength: 1
                        required:
                          - type
                        additionalProperties: false
                        title: linkedin_like_last_post
                      - type: object
                        properties:
                          type:
                            type: string
                            enum:
                              - whatsapp_message
                          content:
                            type: string
                            minLength: 1
                            description: >-
                              WhatsApp message body. Requires WhatsApp support
                              on the workspace and identity.
                          delay:
                            type: object
                            properties:
                              value:
                                type: number
                                minimum: 0
                                description: Delay amount.
                              unit:
                                type: string
                                enum:
                                  - seconds
                                  - minutes
                                  - hours
                                  - days
                                description: Delay unit.
                            required:
                              - value
                              - unit
                            additionalProperties: false
                        required:
                          - type
                          - content
                        additionalProperties: false
                        title: whatsapp_message
                      - type: object
                        properties:
                          type:
                            type: string
                            enum:
                              - condition
                          condition:
                            oneOf:
                              - type: object
                                properties:
                                  type:
                                    type: string
                                    enum:
                                      - has_linkedin_profile
                                    description: Lead has a LinkedIn profile.
                                  field:
                                    type: string
                                    enum:
                                      - linkedinProfileUrl
                                      - linkedInProfileId
                                    description: >-
                                      Stored lead field to check. Defaults to
                                      `linkedinProfileUrl`.
                                required:
                                  - type
                                additionalProperties: false
                                title: has_linkedin_profile
                              - type: object
                                properties:
                                  type:
                                    type: string
                                    enum:
                                      - has_professional_email
                                    description: Lead has a professional email.
                                  verificationStatuses:
                                    type: array
                                    items:
                                      type: string
                                    minItems: 1
                                    description: >-
                                      Optional email verification statuses to
                                      include when matching. When provided it
                                      must be non-empty; omit it to match any
                                      status.
                                  includeEmpty:
                                    type: boolean
                                    description: >-
                                      Whether empty professional email values
                                      match.
                                required:
                                  - type
                                additionalProperties: false
                                title: has_professional_email
                              - type: object
                                properties:
                                  type:
                                    type: string
                                    enum:
                                      - is_already_connected
                                    description: Lead is already a LinkedIn connection.
                                required:
                                  - type
                                additionalProperties: false
                                title: is_already_connected
                              - type: object
                                properties:
                                  type:
                                    type: string
                                    enum:
                                      - has_been_contacted
                                    description: Lead has already been contacted.
                                required:
                                  - type
                                additionalProperties: false
                                title: has_been_contacted
                              - type: object
                                properties:
                                  type:
                                    type: string
                                    enum:
                                      - has_whatsapp_account
                                    description: Lead has a WhatsApp account.
                                required:
                                  - type
                                additionalProperties: false
                                title: has_whatsapp_account
                              - type: object
                                properties:
                                  type:
                                    type: string
                                    enum:
                                      - email_opened
                                    description: >-
                                      Branch on whether the preceding email is
                                      opened within `waitFor`.
                                  waitFor:
                                    type: object
                                    properties:
                                      value:
                                        type: number
                                        exclusiveMinimum: 0
                                        description: Wait amount.
                                      unit:
                                        type: string
                                        enum:
                                          - seconds
                                          - minutes
                                          - hours
                                          - days
                                        description: Wait unit.
                                    required:
                                      - value
                                      - unit
                                    additionalProperties: false
                                    description: >-
                                      How long to wait for the lead to open the
                                      preceding email. Required.
                                required:
                                  - type
                                  - waitFor
                                additionalProperties: false
                                title: email_opened
                              - type: object
                                properties:
                                  type:
                                    type: string
                                    enum:
                                      - email_clicked
                                    description: >-
                                      Branch on whether a link in the preceding
                                      email is clicked within `waitFor`.
                                  waitFor:
                                    type: object
                                    properties:
                                      value:
                                        type: number
                                        exclusiveMinimum: 0
                                        description: Wait amount.
                                      unit:
                                        type: string
                                        enum:
                                          - seconds
                                          - minutes
                                          - hours
                                          - days
                                        description: Wait unit.
                                    required:
                                      - value
                                      - unit
                                    additionalProperties: false
                                    description: >-
                                      How long to wait for the lead to click a
                                      link in the preceding email. Required.
                                required:
                                  - type
                                  - waitFor
                                additionalProperties: false
                                title: email_clicked
                              - type: object
                                properties:
                                  type:
                                    type: string
                                    enum:
                                      - linkedin_message_viewed
                                    description: >-
                                      Branch on whether the preceding LinkedIn
                                      message is viewed within `waitFor`.
                                  waitFor:
                                    type: object
                                    properties:
                                      value:
                                        type: number
                                        exclusiveMinimum: 0
                                        description: Wait amount.
                                      unit:
                                        type: string
                                        enum:
                                          - seconds
                                          - minutes
                                          - hours
                                          - days
                                        description: Wait unit.
                                    required:
                                      - value
                                      - unit
                                    additionalProperties: false
                                    description: >-
                                      How long to wait for the lead to view the
                                      preceding LinkedIn message. Required.
                                required:
                                  - type
                                  - waitFor
                                additionalProperties: false
                                title: linkedin_message_viewed
                              - type: object
                                properties:
                                  type:
                                    type: string
                                    enum:
                                      - task_completed
                                    description: >-
                                      Branch on whether the preceding task is
                                      marked complete within `waitFor`.
                                  waitFor:
                                    type: object
                                    properties:
                                      value:
                                        type: number
                                        exclusiveMinimum: 0
                                        description: Wait amount.
                                      unit:
                                        type: string
                                        enum:
                                          - seconds
                                          - minutes
                                          - hours
                                          - days
                                        description: Wait unit.
                                    required:
                                      - value
                                      - unit
                                    additionalProperties: false
                                    description: >-
                                      How long to wait for the task to be marked
                                      complete. Required.
                                required:
                                  - type
                                  - waitFor
                                additionalProperties: false
                                title: task_completed
                              - type: object
                                properties:
                                  type:
                                    type: string
                                    enum:
                                      - connection_accepted
                                    description: >-
                                      Branch on whether the lead accepts a
                                      previous LinkedIn connection request.
                                  waitFor:
                                    type: object
                                    properties:
                                      value:
                                        type: number
                                        exclusiveMinimum: 0
                                        description: Wait amount.
                                      unit:
                                        type: string
                                        enum:
                                          - seconds
                                          - minutes
                                          - hours
                                          - days
                                        description: Wait unit.
                                    required:
                                      - value
                                      - unit
                                    additionalProperties: false
                                    description: >-
                                      How long to wait for the lead to accept
                                      the previous LinkedIn connection request.
                                      Required.
                                required:
                                  - type
                                  - waitFor
                                additionalProperties: false
                                title: connection_accepted
                              - type: object
                                properties:
                                  type:
                                    type: string
                                    enum:
                                      - lead_field
                                    description: Branch on a lead field value.
                                  field:
                                    type: string
                                    minLength: 1
                                    description: >-
                                      Built-in column name (e.g.
                                      `professionalEmail`, `mobilePhone`) or
                                      custom field name.
                                  operator:
                                    type: string
                                    enum:
                                      - EQUALS
                                      - NOT_EQUALS
                                      - CONTAINS
                                      - NOT_CONTAINS
                                      - GREATER_THAN
                                      - LESS_THAN
                                      - GREATER_THAN_OR_EQUALS
                                      - LESS_THAN_OR_EQUALS
                                      - IS_EMPTY
                                      - IS_NOT_EMPTY
                                    description: >-
                                      Comparison operator. `IS_EMPTY` and
                                      `IS_NOT_EMPTY` ignore `value`; all others
                                      require it.
                                  value:
                                    anyOf:
                                      - type: string
                                      - type: number
                                      - type: boolean
                                      - type: array
                                        items:
                                          type: string
                                      - type: array
                                        items:
                                          type: number
                                      - type: array
                                        items:
                                          type: boolean
                                    description: >-
                                      Comparison value. Required for every
                                      operator except `IS_EMPTY` and
                                      `IS_NOT_EMPTY`.
                                required:
                                  - type
                                  - field
                                  - operator
                                additionalProperties: false
                                title: lead_field
                            description: >-
                              Condition evaluated at this point in the sequence.
                              Supported `condition.type` values are
                              `has_linkedin_profile`, `has_professional_email`,
                              `is_already_connected`, `has_been_contacted`,
                              `has_whatsapp_account`, `email_opened`,
                              `email_clicked`, `linkedin_message_viewed`,
                              `task_completed`, `connection_accepted`, and
                              `lead_field`. The email, LinkedIn-message-viewed,
                              task, and connection-accepted variants require a
                              `waitFor` object with `value` and `unit`. The
                              `lead_field` variant requires `field` and
                              `operator`, and a `value` for every operator
                              except `IS_EMPTY` and `IS_NOT_EMPTY`.
                          onTrue:
                            type: array
                            items:
                              type: object
                              properties:
                                type:
                                  type: string
                                  description: Nested branch step type.
                              required:
                                - type
                              additionalProperties: {}
                              description: >-
                                Nested branch step. Use the same step payload
                                shape as top-level `steps` items.
                            minItems: 1
                            description: >-
                              Steps to run when the condition matches. If
                              provided, it must contain at least one step. Use
                              `{ "type": "end" }` to stop that branch
                              explicitly.
                          onFalse:
                            type: array
                            items:
                              type: object
                              properties:
                                type:
                                  type: string
                                  description: Nested branch step type.
                              required:
                                - type
                              additionalProperties: {}
                              description: >-
                                Nested branch step. Use the same step payload
                                shape as top-level `steps` items.
                            minItems: 1
                            description: >-
                              Steps to run when the condition does not match. If
                              provided, it must contain at least one step. Use
                              `{ "type": "end" }` to stop that branch
                              explicitly.
                        required:
                          - type
                          - condition
                        additionalProperties: false
                        title: condition
                      - type: object
                        properties:
                          type:
                            type: string
                            enum:
                              - linkedin_connection
                          delay:
                            type: object
                            properties:
                              value:
                                type: number
                                minimum: 0
                                description: Delay amount.
                              unit:
                                type: string
                                enum:
                                  - seconds
                                  - minutes
                                  - hours
                                  - days
                                description: Delay unit.
                            required:
                              - value
                              - unit
                            additionalProperties: false
                          content:
                            type: string
                            minLength: 1
                            description: >-
                              Manual connection note. Mutually exclusive with
                              `aiMessageId`.
                          aiMessageId:
                            type: string
                            minLength: 1
                            description: >-
                              ID of an AI message that generates this step's
                              message per contact at send time. Accepts a
                              workspace-owned AI message (see `GET
                              /v1/ai-variables/ai-messages`, or create one with
                              `POST /v1/ai-variables/ai-messages` to control
                              prompt, tone, model, and output length) or a
                              public prompt-library entry (see `GET
                              /v1/prompt-library/ai-messages`); either way the
                              campaign step gets its own copy. The AI message
                              channel must match the step type. Mutually
                              exclusive with manual `content`, `subject`, and
                              attachment fields. Requires the AI variable split
                              to be enabled for the workspace.
                          waitForAcceptance:
                            type: object
                            properties:
                              value:
                                type: integer
                                minimum: 1
                                description: whole number of days to wait. Minimum 1 day.
                              unit:
                                type: string
                                enum:
                                  - days
                                description: Connection wait unit. Must be `days`.
                            required:
                              - value
                              - unit
                            additionalProperties: false
                            description: >-
                              Optional. Provide an acceptance window to branch
                              the flow on whether the lead accepted the request.
                              Omit to send the request without an inline
                              acceptance check; the campaign continues with
                              whatever follows.
                          onAccepted:
                            type: array
                            items:
                              type: object
                              properties:
                                type:
                                  type: string
                                  description: Nested branch step type.
                              required:
                                - type
                              additionalProperties: {}
                              description: >-
                                Nested branch step. Use the same step payload
                                shape as top-level `steps` items.
                            minItems: 1
                            description: >-
                              Accepted branch steps. Only valid when
                              `waitForAcceptance` is set. If provided, it must
                              contain at least one step. Use `{ "type": "end" }`
                              to stop that branch explicitly.
                          onNotAccepted:
                            type: array
                            items:
                              type: object
                              properties:
                                type:
                                  type: string
                                  description: Nested branch step type.
                              required:
                                - type
                              additionalProperties: {}
                              description: >-
                                Nested branch step. Use the same step payload
                                shape as top-level `steps` items.
                            minItems: 1
                            description: >-
                              Not-accepted branch steps. Only valid when
                              `waitForAcceptance` is set. If provided, it must
                              contain at least one step. Use `{ "type": "end" }`
                              to stop that branch explicitly.
                        required:
                          - type
                        additionalProperties: false
                        title: linkedin_connection
                      - type: object
                        properties:
                          type:
                            type: string
                            enum:
                              - task
                          taskType:
                            type: string
                            minLength: 1
                            description: >-
                              Task type. Allowed values depend on the connected
                              CRM. For HubSpot use one of: CALL, EMAIL, or TODO.
                              Do not invent variants such as "COLD_CALL" — use
                              the closest standard value (e.g. "CALL").
                            example: CALL
                          title:
                            type: string
                            minLength: 1
                            description: Required task title shown in the UI.
                          note:
                            type: string
                            minLength: 1
                            description: Optional task note shown in the UI.
                          ownerId:
                            type:
                              - string
                              - 'null'
                            minLength: 1
                            description: >-
                              Required when `GET /v1/tasks/owners` returns one
                              or more owners.
                          delay:
                            type: object
                            properties:
                              value:
                                type: number
                                minimum: 0
                                description: Delay amount.
                              unit:
                                type: string
                                enum:
                                  - seconds
                                  - minutes
                                  - hours
                                  - days
                                description: Delay unit.
                            required:
                              - value
                              - unit
                            additionalProperties: false
                        required:
                          - type
                          - taskType
                          - title
                        additionalProperties: false
                        title: task
                      - type: object
                        properties:
                          type:
                            type: string
                            enum:
                              - add_to_another_campaign
                            description: >-
                              Routes the lead into another campaign owned by the
                              same workspace, then ends this branch.
                          campaignId:
                            type: integer
                            exclusiveMinimum: 0
                            description: >-
                              ID of a campaign owned by the same client as the
                              API key making the request.
                          delay:
                            type: object
                            properties:
                              value:
                                type: number
                                minimum: 0
                                description: Delay amount.
                              unit:
                                type: string
                                enum:
                                  - seconds
                                  - minutes
                                  - hours
                                  - days
                                description: Delay unit.
                            required:
                              - value
                              - unit
                            additionalProperties: false
                        required:
                          - type
                          - campaignId
                        additionalProperties: false
                        title: add_to_another_campaign
                      - type: object
                        properties:
                          type:
                            type: string
                            enum:
                              - end
                        required:
                          - type
                        additionalProperties: false
                        title: end
                  minItems: 1
                  description: >-
                    Ordered campaign steps. Use branch arrays like `onTrue`,
                    `onFalse`, `onAccepted`, and `onNotAccepted` for branching.
                    Steps returned by `GET /v1/campaign/{campaignId}` can be
                    resubmitted: the read-only `stepId`, `connectionId`,
                    `nextConnectionId`, and `advanced` fields are accepted and
                    ignored.
              additionalProperties: false
      responses:
        '200':
          description: Campaign updated successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    enum:
                      - success
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: number
                        description: Updated campaign ID.
                      appUrl:
                        type: string
                        format: uri
                        description: >-
                          Direct Enginy app URL for opening the updated
                          campaign.
                      name:
                        type: string
                        description: Campaign name after the update.
                      status:
                        type: string
                        enum:
                          - DRAFT
                          - PENDING
                          - ACTIVE
                          - COMPLETED
                          - DELETED
                        description: >-
                          Campaign status (always DRAFT for updatable
                          campaigns).
                      identityId:
                        type:
                          - number
                          - 'null'
                        description: Assigned sender identity ID after the update.
                      warnings:
                        type: array
                        items:
                          type: string
                        description: >-
                          Non-blocking sequence warnings returned by shared
                          campaign validation.
                    required:
                      - id
                      - appUrl
                      - name
                      - status
                      - identityId
                      - warnings
                required:
                  - status
                  - message
                  - data
        '400':
          description: >-
            Bad request - the campaign payload does not match the public
            simplified schema.

            Common causes:

            - Referenced identity (`identityId`) does not exist in this
            workspace.

            - Unrecognized field on a step or branch (e.g. `delay` is not a
            valid key on conditional `onAccepted`/`onTrue`/`onFalse` branches —
            use a dedicated wait/delay node inside the branch instead).

            - Required field missing (the response `errors[].path` indicates
            which body location failed validation).
        '404':
          description: Campaign not found
        '409':
          description: >-
            Conflict - the campaign is not editable in its current status.

            Only campaigns in DRAFT status can be updated through this endpoint.
            To modify a launched campaign:

            - Clone it (`POST /v1/campaign/{campaignId}/clone`) and edit the
            clone, or

            - If it has never contacted anyone and you intend to relaunch it,
            move it back to draft first (`PATCH
            /v1/campaign/{campaignId}/status` with `{"status": "DRAFT"}`),
            update it, then reactivate it.

            Conflict - the campaign has send history from a previous launch, so
            its steps cannot be replaced.

            Clone the campaign (`POST /v1/campaign/{campaignId}/clone`) and edit
            the clone instead.
        '422':
          description: >-
            Unprocessable entity - the campaign steps are structurally invalid.

            Common causes the agent should fix before retrying:

            - EMAIL_OPENED / NOT_EMAIL_OPENED conditions may only appear *after*
            an EMAIL node in the same branch. Add the EMAIL node first or remove
            the condition.

            - Every conditional branch
            (`onAccepted`/`onNotAccepted`/`onTrue`/`onFalse`) must contain at
            least one node. Use `[{ "type": "end" }]` to terminate a branch
            explicitly instead of leaving it empty.

            - Templated fields (e.g. `{firstName}`, `{companyName}`) must
            reference AI variables or standard fields that exist for the
            campaign's entity. Use GET /v1/contacts/fields or GET
            /v1/companies/fields to discover valid placeholders before composing
            message bodies.

            - Reply emails inside the same thread may omit `subject`, but the
            first email in any thread must have a non-empty subject.

            - `aiMessageId` must reference a workspace AI message (GET
            /v1/ai-variables/ai-messages) or a prompt-library entry (GET
            /v1/prompt-library/ai-messages) whose channel matches the step type,
            and cannot be combined with manual `content`/`subject`.
      security:
        - apiKey: []
components:
  securitySchemes:
    apiKey:
      type: apiKey
      in: header
      name: x-api-key

````