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

# Create campaign

> Create a draft campaign from the public simplified sequence model. Best for new campaigns or rewrites that fit the supported public step types; this endpoint does not preserve arbitrary internal editor-only graph wiring from an existing campaign.

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

Create a draft campaign from the public `steps` format.

How to structure the request:
- Start `steps` with the first action that should happen.
- Keep adding the next action in the order it should run.
- Use `condition` when you want to branch on lead data.
- Use `linkedin_connection` with `waitForAcceptance` when you want to branch on connection acceptance after sending a connection request. Omit `waitForAcceptance` for a fire-and-forget connection request.
- Use `linkedin_message` with `content`, `attachment`, or both. Attachment-only messages are valid.
- Use `whatsapp_message` only when the workspace and sending identity are configured for WhatsApp.
- Put shared follow-up work after the branching step instead of duplicating the same steps inside both branches.

Before you send a request:
- Send an ordered `steps` array that describes the campaign flow from first action to last action.
- Use branch arrays on `condition` and `linkedin_connection` steps to describe branch-specific work.
- Place shared follow-up steps after a branching step when both live branches should continue together.
- `waitForAcceptance.unit` must be `days` and `waitForAcceptance.value` must be an integer greater than or equal to `1`.
- Use `GET /v1/tasks/owners` first when your campaign includes `task` steps. If owners are returned, every `task` step must include `ownerId`.
- Validation errors use full paths like `steps[0].onTrue[1].subject` so nested input issues are easy to fix.
- Personalization placeholders use Enginy single-brace syntax such as `{firstName}`, `{company}`, and `{identity.name}`. Do not send Handlebars-style placeholders like `{{firstName}}`.

Supported `condition.type` values:
- `has_linkedin_profile`: `onTrue` runs when the lead has a LinkedIn profile.
- `has_professional_email`: `onTrue` runs when the lead has a professional email.
- `is_already_connected`: `onTrue` runs when the lead is already a LinkedIn connection.
- `has_been_contacted`: `onTrue` runs when the lead has already been contacted.
- `has_whatsapp_account`: `onTrue` runs when the lead has a WhatsApp account.
- `email_opened`: `onTrue` runs when the lead opens the preceding email within `waitFor`. Must follow an `email` step. Requires `waitFor` (`value`, `unit`).
- `email_clicked`: `onTrue` runs when the lead clicks a link in the preceding email within `waitFor`. Must follow an `email` step. Requires `waitFor` (`value`, `unit`).
- `task_completed`: `onTrue` runs when the preceding `task` step is marked complete within `waitFor`. Must follow a `task` step. Requires `waitFor` (`value`, `unit`).
- `connection_accepted`: `onTrue` runs when the lead accepts a previous LinkedIn connection request within `waitFor`. Requires `waitFor` (`value`, `unit`).
- `lead_field`: `onTrue` runs when the contact `field` matches the `operator` (and `value`, where applicable). Use this to branch on any built-in column or custom field. Requires `field` and `operator`. `value` is required for every operator except `IS_EMPTY` and `IS_NOT_EMPTY`. Supported operators: `EQUALS`, `NOT_EQUALS`, `CONTAINS`, `NOT_CONTAINS`, `GREATER_THAN`, `LESS_THAN`, `GREATER_THAN_OR_EQUALS`, `LESS_THAN_OR_EQUALS`, `IS_EMPTY`, `IS_NOT_EMPTY`.

Branch fields:
- `condition` uses `onTrue` and `onFalse`.
- `linkedin_connection` uses `onAccepted` and `onNotAccepted` only when `waitForAcceptance` is set.
- Use `[{ "type": "end" }]` when a branch should stop explicitly.

Routing into another campaign:
- Use `add_to_another_campaign` with a `campaignId` to route the lead into an existing campaign in the same workspace.
- The referenced `campaignId` must belong to the same client as the API key. If you are cloning campaigns across workspaces, remap each `campaignId` to the equivalent campaign in the destination workspace before posting.
- Can be followed by additional steps in the same branch.

For examples and a full step-by-step guide, see `/api-reference/campaigns-guide` in the docs site.

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



## OpenAPI

````yaml https://openapi.enginy.ai/definitions.json post /v1/campaigns
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/campaigns:
    post:
      tags:
        - Campaigns
      summary: Create campaign
      description: >-
        Create a draft campaign from the public simplified sequence model. Best
        for new campaigns or rewrites that fit the supported public step types;
        this endpoint does not preserve arbitrary internal editor-only graph
        wiring from an existing campaign.


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


        Create a draft campaign from the public `steps` format.


        How to structure the request:

        - Start `steps` with the first action that should happen.

        - Keep adding the next action in the order it should run.

        - Use `condition` when you want to branch on lead data.

        - Use `linkedin_connection` with `waitForAcceptance` when you want to
        branch on connection acceptance after sending a connection request. Omit
        `waitForAcceptance` for a fire-and-forget connection request.

        - Use `linkedin_message` with `content`, `attachment`, or both.
        Attachment-only messages are valid.

        - Use `whatsapp_message` only when the workspace and sending identity
        are configured for WhatsApp.

        - Put shared follow-up work after the branching step instead of
        duplicating the same steps inside both branches.


        Before you send a request:

        - Send an ordered `steps` array that describes the campaign flow from
        first action to last action.

        - Use branch arrays on `condition` and `linkedin_connection` steps to
        describe branch-specific work.

        - Place shared follow-up steps after a branching step when both live
        branches should continue together.

        - `waitForAcceptance.unit` must be `days` and `waitForAcceptance.value`
        must be an integer greater than or equal to `1`.

        - Use `GET /v1/tasks/owners` first when your campaign includes `task`
        steps. If owners are returned, every `task` step must include `ownerId`.

        - Validation errors use full paths like `steps[0].onTrue[1].subject` so
        nested input issues are easy to fix.

        - Personalization placeholders use Enginy single-brace syntax such as
        `{firstName}`, `{company}`, and `{identity.name}`. Do not send
        Handlebars-style placeholders like `{{firstName}}`.


        Supported `condition.type` values:

        - `has_linkedin_profile`: `onTrue` runs when the lead has a LinkedIn
        profile.

        - `has_professional_email`: `onTrue` runs when the lead has a
        professional email.

        - `is_already_connected`: `onTrue` runs when the lead is already a
        LinkedIn connection.

        - `has_been_contacted`: `onTrue` runs when the lead has already been
        contacted.

        - `has_whatsapp_account`: `onTrue` runs when the lead has a WhatsApp
        account.

        - `email_opened`: `onTrue` runs when the lead opens the preceding email
        within `waitFor`. Must follow an `email` step. Requires `waitFor`
        (`value`, `unit`).

        - `email_clicked`: `onTrue` runs when the lead clicks a link in the
        preceding email within `waitFor`. Must follow an `email` step. Requires
        `waitFor` (`value`, `unit`).

        - `task_completed`: `onTrue` runs when the preceding `task` step is
        marked complete within `waitFor`. Must follow a `task` step. Requires
        `waitFor` (`value`, `unit`).

        - `connection_accepted`: `onTrue` runs when the lead accepts a previous
        LinkedIn connection request within `waitFor`. Requires `waitFor`
        (`value`, `unit`).

        - `lead_field`: `onTrue` runs when the contact `field` matches the
        `operator` (and `value`, where applicable). Use this to branch on any
        built-in column or custom field. Requires `field` and `operator`.
        `value` is required for every operator except `IS_EMPTY` and
        `IS_NOT_EMPTY`. Supported operators: `EQUALS`, `NOT_EQUALS`, `CONTAINS`,
        `NOT_CONTAINS`, `GREATER_THAN`, `LESS_THAN`, `GREATER_THAN_OR_EQUALS`,
        `LESS_THAN_OR_EQUALS`, `IS_EMPTY`, `IS_NOT_EMPTY`.


        Branch fields:

        - `condition` uses `onTrue` and `onFalse`.

        - `linkedin_connection` uses `onAccepted` and `onNotAccepted` only when
        `waitForAcceptance` is set.

        - Use `[{ "type": "end" }]` when a branch should stop explicitly.


        Routing into another campaign:

        - Use `add_to_another_campaign` with a `campaignId` to route the lead
        into an existing campaign in the same workspace.

        - The referenced `campaignId` must belong to the same client as the API
        key. If you are cloning campaigns across workspaces, remap each
        `campaignId` to the equivalent campaign in the destination workspace
        before posting.

        - Can be followed by additional steps in the same branch.


        For examples and a full step-by-step guide, see
        `/api-reference/campaigns-guide` in the docs site.

            > **Required scope:** `CAMPAIGNS_WRITE`
            >
            > **Rate limit:** 30 requests per minute
      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
                            minLength: 1
                          content:
                            type: string
                            minLength: 1
                          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
                          - subject
                          - content
                        additionalProperties: false
                        title: email
                      - type: object
                        properties:
                          type:
                            type: string
                            enum:
                              - linkedin_message
                          content:
                            type: string
                            minLength: 1
                            description: >-
                              LinkedIn message body. Required unless
                              `attachment` 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
                          content:
                            type: string
                            minLength: 1
                          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
                          - subject
                          - content
                        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
                                    description: >-
                                      Optional email verification statuses to
                                      include when matching.
                                  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:
                                      - 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`, `task_completed`,
                              `connection_accepted`, and `lead_field`. The
                              email, 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
                          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.
              required:
                - name
                - steps
              additionalProperties: false
            examples:
              conditionFirst:
                summary: Start with a condition and run different work on each branch
                value:
                  name: Email or fallback task
                  identityId: 323
                  steps:
                    - type: condition
                      condition:
                        type: has_professional_email
                      onTrue:
                        - type: email
                          subject: Great to connect
                          content: Sharing a quick overview.
                      onFalse:
                        - type: task
                          taskType: TODO
                          title: Find email first
                          ownerId: owner-1
              linkedinAcceptance:
                summary: >-
                  Branch on LinkedIn connection acceptance and continue after
                  the branch
                value:
                  name: LinkedIn acceptance flow
                  identityId: 323
                  steps:
                    - type: linkedin_connection
                      delay:
                        value: 1
                        unit: days
                      waitForAcceptance:
                        value: 5
                        unit: days
                      onAccepted:
                        - type: linkedin_message
                          content: Thanks for accepting.
                          delay:
                            value: 2
                            unit: hours
                      onNotAccepted:
                        - type: task
                          taskType: TODO
                          title: Review no-response path
                          ownerId: owner-1
                    - type: email
                      subject: Following up
                      content: Continuing after the LinkedIn decision.
                      delay:
                        value: 1
                        unit: days
              voiceMessageWithVideoFollowup:
                summary: LinkedIn voice message followed by a video message
                value:
                  name: Voice + video outreach
                  identityId: 323
                  steps:
                    - type: linkedin_voice_message
                      content: >-
                        Hey {firstName}, sharing a quick voice intro about
                        {company}.
                      voiceId: bIHbv24MWmeRgasZH58o
                      voiceSettings:
                        voiceSpeed: 1
                        voiceStability: 80
                        backgroundNoise: none
                        backgroundVolume: 25
                    - type: linkedin_message
                      content: Following up with the demo video.
                      attachment: https://example.com/uploads/demo.mp4
                      attachmentName: demo.mp4
                      contentType: VIDEO
                      delay:
                        value: 1
                        unit: days
              taskRoutingFallbacks:
                summary: Route multiple fallback branches into different task owners
                value:
                  name: Task routing fallback flow
                  identityId: 323
                  steps:
                    - type: condition
                      condition:
                        type: has_professional_email
                      onTrue:
                        - type: email
                          subject: Initial outreach
                          content: Opening with email when contact data is ready.
                        - type: linkedin_connection
                          waitForAcceptance:
                            value: 4
                            unit: days
                          onAccepted:
                            - type: task
                              taskType: CALL
                              title: Call after positive signal
                              note: >-
                                They accepted the connection and saw the first
                                email.
                              ownerId: owner-1
                              delay:
                                value: 1
                                unit: days
                          onNotAccepted:
                            - type: task
                              taskType: TODO
                              title: Review cold branch manually
                              ownerId: owner-2
                      onFalse:
                        - type: task
                          taskType: TODO
                          title: Find email before launching sequence
                          ownerId: owner-3
      responses:
        '201':
          description: Campaign created successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    enum:
                      - success
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: number
                        description: Created campaign ID.
                      appUrl:
                        type: string
                        format: uri
                        description: >-
                          Direct Enginy app URL for opening the created
                          campaign.
                      name:
                        type: string
                        description: Created campaign name.
                      status:
                        type: string
                        enum:
                          - DRAFT
                          - PENDING
                          - ACTIVE
                          - COMPLETED
                          - DELETED
                        description: Created campaign status.
                      identityId:
                        type:
                          - number
                          - 'null'
                        description: Assigned sender identity ID.
                      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).
        '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.
      security:
        - apiKey: []
components:
  securitySchemes:
    apiKey:
      type: apiKey
      in: header
      name: x-api-key

````