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

# Add campaign step

> Add a step to the end of the campaign. People already enrolled keep the steps they were enrolled with and will not get this one, which the `existing_enrollees_will_not_receive_this_step` warning tells you. Needs `campaigns:write`.



## OpenAPI

````yaml /api-reference/openapi-v1.json post /v1/campaigns/{id}/steps
openapi: 3.1.0
info:
  title: Stardex API (v1)
  version: 1.0.0
  description: >-
    Stardex ATS API — manage candidates, jobs, companies, and recruiting
    workflows.
servers:
  - url: https://api.stardex.ai
    description: Production API server
security:
  - bearerAuth: []
tags:
  - name: Persons
    description: Manage person records — contacts, work history, and custom fields.
  - name: Jobs
    description: Manage job postings — pipeline stages, team members, and custom fields.
  - name: Candidates
    description: Manage candidate records and pipeline stage transitions.
  - name: Companies
    description: Browse and retrieve company records.
  - name: Lists
    description: Create, search, and retrieve saved person and company lists.
  - name: Person Activities
    description: Create and manage activity records (notes, emails, meetings) for persons.
  - name: Team Members
    description: List team members for use in search filters and assignments.
  - name: Custom Fields
    description: Retrieve custom field definitions and tag options for search filters.
  - name: Campaigns
    description: >-
      Create and edit email campaigns, enroll people through enrollment batches,
      and manage who is enrolled.
paths:
  /v1/campaigns/{id}/steps:
    post:
      tags:
        - Campaigns
      summary: Add campaign step
      description: >-
        Add a step to the end of the campaign. People already enrolled keep the
        steps they were enrolled with and will not get this one, which the
        `existing_enrollees_will_not_receive_this_step` warning tells you. Needs
        `campaigns:write`.
      operationId: addCampaignStep
      parameters:
        - schema:
            type: string
            format: uuid
            description: Campaign ID.
          required: true
          description: Campaign ID.
          name: id
          in: path
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CampaignStepInput'
            example:
              type: email
              send_after_days: 4
              body_html: >-
                <div>Hi {{first_name}}, closing the loop on this. Happy to share
                more whenever
                suits.</div><div><br></div><div>{{sender_first_name}}</div>
              time_window_start: '09:00'
              time_window_end: '17:00'
              include_signature: true
      responses:
        '201':
          description: Step added
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CampaignStepResponse'
              example:
                success: true
                data:
                  step:
                    id: 2b7d9f1a-5c3e-4a8b-9d6f-0e2c4a6b8d31
                    order: 4
                    type: email
                    send_after_days: 4
                    subject: 'Re: {{search_name}} role at {{search_client}}'
                    body_html: >-
                      <div>Hi {{first_name}}, closing the loop on this. Happy to
                      share more whenever
                      suits.</div><div><br></div><div>{{sender_first_name}}</div>
                    timezone: Europe/London
                    time_window_start: '09:00'
                    time_window_end: '17:00'
                    include_signature: true
                    block_until_task_complete: false
                    ai_variables: []
                    attachments: []
                    created_at: '2026-10-14T09:02:00.000Z'
                    updated_at: '2026-10-14T09:02:00.000Z'
                  warnings:
                    - code: existing_enrollees_will_not_receive_this_step
                      message: >-
                        People already in this campaign keep their current steps
                        and will not get this one. Only people enrolled from now
                        on will.
        '400':
          description: Validation error
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    enum:
                      - false
                    description: Always false for error responses.
                  error:
                    type: object
                    properties:
                      code:
                        type: string
                        description: >-
                          Machine-readable error code (e.g. "VALIDATION_ERROR",
                          "NOT_FOUND").
                      message:
                        type: string
                        description: Human-readable error description.
                      details:
                        type: object
                        additionalProperties: {}
                        description: >-
                          Extra facts about the error when they help you fix it,
                          such as a limit and when it resets.
                    required:
                      - code
                      - message
                required:
                  - success
                  - error
        '403':
          description: No access to campaigns, or the API key lacks the permission
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    enum:
                      - false
                    description: Always false for error responses.
                  error:
                    type: object
                    properties:
                      code:
                        type: string
                        description: >-
                          Machine-readable error code (e.g. "VALIDATION_ERROR",
                          "NOT_FOUND").
                      message:
                        type: string
                        description: Human-readable error description.
                      details:
                        type: object
                        additionalProperties: {}
                        description: >-
                          Extra facts about the error when they help you fix it,
                          such as a limit and when it resets.
                    required:
                      - code
                      - message
                required:
                  - success
                  - error
        '404':
          description: Resource not found
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    enum:
                      - false
                    description: Always false for error responses.
                  error:
                    type: object
                    properties:
                      code:
                        type: string
                        description: >-
                          Machine-readable error code (e.g. "VALIDATION_ERROR",
                          "NOT_FOUND").
                      message:
                        type: string
                        description: Human-readable error description.
                      details:
                        type: object
                        additionalProperties: {}
                        description: >-
                          Extra facts about the error when they help you fix it,
                          such as a limit and when it resets.
                    required:
                      - code
                      - message
                required:
                  - success
                  - error
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    enum:
                      - false
                    description: Always false for error responses.
                  error:
                    type: object
                    properties:
                      code:
                        type: string
                        description: >-
                          Machine-readable error code (e.g. "VALIDATION_ERROR",
                          "NOT_FOUND").
                      message:
                        type: string
                        description: Human-readable error description.
                      details:
                        type: object
                        additionalProperties: {}
                        description: >-
                          Extra facts about the error when they help you fix it,
                          such as a limit and when it resets.
                    required:
                      - code
                      - message
                required:
                  - success
                  - error
components:
  schemas:
    CampaignStepInput:
      type: object
      properties:
        type:
          type: string
          enum:
            - email
            - manual
            - text
            - linkedin_message
            - linkedin_connection
            - call
          description: >-
            Step type. Email steps are sent automatically; the others create
            tasks.
        send_after_days:
          type: integer
          minimum: 0
          maximum: 365
          description: >-
            Days to wait after the previous step (or after enrollment, for the
            first step).
        subject:
          type:
            - string
            - 'null'
          maxLength: 998
          description: >-
            Email subject, or the InMail subject for LinkedIn message steps.
            Only the first email step has its own subject: later email steps
            always use "Re: <first subject>" so they land in the same thread (a
            "Re:" on the first email is removed). Editing a later email's
            subject is rejected. Can use {{variables}}.
        body_html:
          type: string
          maxLength: 100000
          description: >-
            Step body as HTML (paragraphs, headings, line breaks, bold, italic,
            underline, strikethrough, highlight, links, lists and images). Each
            <p> is followed by an empty line, as in the campaign builder; use
            <br> for a line break without a gap. Images need a public https URL
            and are shown as their own block. Can use {{variables}}, including
            inside link URLs. For non-email steps this is the task or message
            text; LinkedIn connection notes are limited to 300 characters.
        timezone:
          type:
            - string
            - 'null'
          description: >-
            IANA timezone for the sending window, for example Europe/London.
            Defaults to the timezone of the campaign owner's first connected
            mailbox. Without one, the step sends in New York business hours
            (America/New_York).
        time_window_start:
          type:
            - string
            - 'null'
          pattern: ^([01]\d|2[0-3]):[0-5]\d$
          description: >-
            Start of the sending window for email steps, in 24-hour HH:MM. Left
            empty, the step sends between 09:00 and 17:00 in its timezone.
        time_window_end:
          type:
            - string
            - 'null'
          pattern: ^([01]\d|2[0-3]):[0-5]\d$
          description: >-
            End of the sending window for email steps, in 24-hour HH:MM. Must
            differ from time_window_start.
        include_signature:
          type: boolean
          description: Add the sender's email signature to this email step.
        block_until_task_complete:
          type: boolean
          description: >-
            For task steps (not emails): hold the rest of the campaign until
            this task is marked complete. Turning it off releases anyone already
            waiting on the step.
        ai_variables:
          type: array
          items:
            type: object
            properties:
              name:
                type: string
                minLength: 1
                maxLength: 64
                description: >-
                  The name used in the template, without the ai: prefix.
                  {{ai:opening_line}} has the name opening_line.
              description:
                type: string
                minLength: 1
                maxLength: 1000
                description: >-
                  What the AI should write for each person, for example "One
                  sentence on their most relevant recent work". The value is
                  inserted exactly as written, so use the variable only where
                  that text fits: a sentence on its own, never mid-sentence.
            required:
              - name
              - description
          maxItems: 20
          description: >-
            A description for every {{ai:name}} used in this step. Descriptions
            for names not used in the step are ignored.
      required:
        - type
        - send_after_days
    CampaignStepResponse:
      type: object
      properties:
        success:
          type: boolean
          enum:
            - true
        data:
          type: object
          properties:
            step:
              $ref: '#/components/schemas/CampaignStep'
            warnings:
              type: array
              items:
                type: object
                properties:
                  code:
                    type: string
                    description: Machine-readable warning code.
                  message:
                    type: string
                    description: What it means for you.
                required:
                  - code
                  - message
          required:
            - step
            - warnings
      required:
        - success
        - data
    CampaignStep:
      type: object
      properties:
        id:
          type: string
          format: uuid
        order:
          type: integer
          description: 1-based position in the campaign.
        type:
          type: string
          enum:
            - email
            - manual
            - text
            - linkedin_message
            - linkedin_connection
            - call
        send_after_days:
          type: integer
        subject:
          type:
            - string
            - 'null'
        body_html:
          type: string
        timezone:
          type:
            - string
            - 'null'
        time_window_start:
          type:
            - string
            - 'null'
          description: >-
            HH:MM. null means the default sending hours, 09:00–17:00 in the
            step's timezone.
        time_window_end:
          type:
            - string
            - 'null'
          description: >-
            HH:MM. null means the default sending hours, 09:00–17:00 in the
            step's timezone.
        include_signature:
          type: boolean
        block_until_task_complete:
          type: boolean
        ai_variables:
          type: array
          items:
            type: object
            properties:
              name:
                type: string
                minLength: 1
                maxLength: 64
                description: >-
                  The name used in the template, without the ai: prefix.
                  {{ai:opening_line}} has the name opening_line.
              description:
                type: string
                minLength: 1
                maxLength: 1000
                description: >-
                  What the AI should write for each person, for example "One
                  sentence on their most relevant recent work". The value is
                  inserted exactly as written, so use the variable only where
                  that text fits: a sentence on its own, never mid-sentence.
            required:
              - name
              - description
        attachments:
          type: array
          items:
            type: object
            properties:
              file_name:
                type: string
              content_type:
                type:
                  - string
                  - 'null'
              size_bytes:
                type: integer
            required:
              - file_name
              - content_type
              - size_bytes
          description: >-
            Files sent with this step, added in the campaign builder.
            Attachments cannot be added through the API.
        created_at:
          type: string
        updated_at:
          type:
            - string
            - 'null'
      required:
        - id
        - order
        - type
        - send_after_days
        - subject
        - body_html
        - timezone
        - time_window_start
        - time_window_end
        - include_signature
        - block_until_task_complete
        - ai_variables
        - attachments
        - created_at
        - updated_at
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: >-
        Authenticate with a Bearer token: API key, OAuth token, or session
        token.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.