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

# Create campaign

> Create a campaign and its steps in one request. Creating a campaign sends nothing.

**Subjects**: only the first email step needs a subject. Later email steps reply in the same thread, so their subject is set to `Re: <first subject>`.

**Variables**: use names from `GET /v1/campaigns/variables`, your own manual names, or `{{ai:name}}` with a description in the step `ai_variables`.

**Nurture campaigns** (`candidate_nurture`, `client_nurture`) keep going after a reply and never move people through a pipeline, so `stop_on_response` and `enable_sequence_automation` are always false for them.

**Owner**: signed-in users own what they create. API keys can set `owner_team_member_id`; otherwise the admin who created the key owns it. Needs `campaigns:write`.



## OpenAPI

````yaml /api-reference/openapi-v1.json post /v1/campaigns
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:
    post:
      tags:
        - Campaigns
      summary: Create campaign
      description: >-
        Create a campaign and its steps in one request. Creating a campaign
        sends nothing.


        **Subjects**: only the first email step needs a subject. Later email
        steps reply in the same thread, so their subject is set to `Re: <first
        subject>`.


        **Variables**: use names from `GET /v1/campaigns/variables`, your own
        manual names, or `{{ai:name}}` with a description in the step
        `ai_variables`.


        **Nurture campaigns** (`candidate_nurture`, `client_nurture`) keep going
        after a reply and never move people through a pipeline, so
        `stop_on_response` and `enable_sequence_automation` are always false for
        them.


        **Owner**: signed-in users own what they create. API keys can set
        `owner_team_member_id`; otherwise the admin who created the key owns it.
        Needs `campaigns:write`.
      operationId: createCampaign
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CampaignCreateRequest'
            example:
              name: Senior Backend Engineer, Monzo
              sequence_type: candidate
              owner_team_member_id: 7c1e4a9b-3d6f-4b2e-8a5c-9f1d3b7e5a20
              enable_sequence_automation: true
              stop_on_response: true
              link_tracking: true
              open_tracking: false
              steps:
                - type: email
                  send_after_days: 0
                  subject: '{{search_name}} role at {{search_client}}'
                  body_html: >-
                    <div>Hi
                    {{first_name}},</div><div><br></div><div>{{ai:opening_line}}
                    I'm hiring a <strong>{{search_name}}</strong> at
                    {{search_client}}.
                    {{personalization_line}}</div><div><br></div><div>You can
                    see the role <a target="_blank" rel="noopener noreferrer
                    nofollow" href="{{application_link}}">here</a>. Open to a
                    chat?</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
                  ai_variables:
                    - name: opening_line
                      description: >-
                        One sentence on the most relevant thing they have built
                        or led recently.
                - type: email
                  send_after_days: 3
                  body_html: >-
                    <div>Hi {{first_name}}, following up on my note.
                    {{custom}}</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
                - type: manual
                  send_after_days: 2
                  body_html: >-
                    <div>Call {{first_name}} if they opened but did not
                    reply.</div>
                  block_until_task_complete: true
      responses:
        '201':
          description: Campaign created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CampaignResponse'
              example:
                success: true
                data:
                  id: 3f9a1c27-8e4b-4d2a-b6f0-7c1e5a9d2b84
                  name: Senior Backend Engineer, Monzo
                  sequence_type: candidate
                  is_archived: false
                  created_by: 7c1e4a9b-3d6f-4b2e-8a5c-9f1d3b7e5a20
                  step_count: 3
                  created_at: '2026-10-13T10:15:00.000Z'
                  updated_at: '2026-10-13T10:15:00.000Z'
                  enable_sequence_automation: true
                  stop_on_response: true
                  send_on_weekends: false
                  send_on_holidays: false
                  link_tracking: true
                  open_tracking: false
                  include_unsubscribe_link: false
                  steps:
                    - id: 5b0f3c8e-2a71-4d0e-9a51-6f0c2d7e1a43
                      order: 1
                      type: email
                      send_after_days: 0
                      subject: '{{search_name}} role at {{search_client}}'
                      body_html: >-
                        <div>Hi
                        {{first_name}},</div><div><br></div><div>{{ai:opening_line}}
                        I'm hiring a <strong>{{search_name}}</strong> at
                        {{search_client}}.
                        {{personalization_line}}</div><div><br></div><div>You
                        can see the role <a target="_blank" rel="noopener
                        noreferrer nofollow"
                        href="{{application_link}}">here</a>. Open to a
                        chat?</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:
                        - name: opening_line
                          description: >-
                            One sentence on the most relevant thing they have
                            built or led recently.
                      attachments: []
                      created_at: '2026-10-13T10:15:00.000Z'
                      updated_at: '2026-10-13T10:15:00.000Z'
                    - id: 9d2e7a14-61c3-4b8f-8f0e-3a5c9b2d4e17
                      order: 2
                      type: email
                      send_after_days: 3
                      subject: 'Re: {{search_name}} role at {{search_client}}'
                      body_html: >-
                        <div>Hi {{first_name}}, following up on my note.
                        {{custom}}</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-13T10:15:00.000Z'
                      updated_at: '2026-10-13T10:15:00.000Z'
                    - id: c4a8e2f1-7b3d-4e6a-9c1f-2d8b5a7e3f90
                      order: 3
                      type: manual
                      send_after_days: 2
                      subject: null
                      body_html: >-
                        <div>Call {{first_name}} if they opened but did not
                        reply.</div>
                      timezone: Europe/London
                      time_window_start: null
                      time_window_end: null
                      include_signature: false
                      block_until_task_complete: true
                      ai_variables: []
                      attachments: []
                      created_at: '2026-10-13T10:15:00.000Z'
                      updated_at: null
                  manual_variables:
                    - personalization_line
                    - custom
                  ai_variables:
                    - name: opening_line
                      description: >-
                        One sentence on the most relevant thing they have built
                        or led recently.
                      step_ids:
                        - 5b0f3c8e-2a71-4d0e-9a51-6f0c2d7e1a43
                  enrollment_counts:
                    total: 0
                    running: 0
                    awaiting_task: 0
                    replied: 0
                    meeting_booked: 0
                    bounced: 0
                    completed: 0
                    stopped: 0
                  engagement:
                    responded: 0
                    interested: 0
                    neutral: 0
                    not_interested: 0
                    opened: 0
                    clicked: 0
                    reply_rate: null
                    open_rate: null
                    click_rate: null
        '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:
    CampaignCreateRequest:
      type: object
      properties:
        name:
          type: string
          minLength: 1
          maxLength: 200
          description: Campaign name.
        sequence_type:
          type: string
          enum:
            - candidate
            - business_development
            - candidate_nurture
            - client_nurture
          default: candidate
          description: >-
            Who the campaign is for. See GET /v1/campaigns/types. Defaults to
            candidate.
        enable_sequence_automation:
          type: boolean
          description: >-
            Move people through the linked job pipeline as they reply. Always
            off for nurture campaigns.
        stop_on_response:
          type: boolean
          description: >-
            Stop emailing a person once they reply. Always off for nurture
            campaigns.
        send_on_weekends:
          type: boolean
          default: false
          description: Allow emails to go out on Saturdays and Sundays.
        send_on_holidays:
          type: boolean
          default: false
          description: >-
            Allow emails to go out on public holidays. When off, the campaign
            skips the holidays in your workspace's holiday calendar.
        link_tracking:
          type: boolean
          default: true
          description: Track link clicks.
        open_tracking:
          type: boolean
          default: false
          description: Track email opens.
        include_unsubscribe_link:
          type: boolean
          default: false
          description: Add an unsubscribe link to every email.
        owner_team_member_id:
          type: string
          format: uuid
          description: >-
            API keys only: the team member who owns the campaign. Defaults to
            the admin who created the key. Signed-in users always own the
            campaigns they create.
        steps:
          type: array
          items:
            $ref: '#/components/schemas/CampaignStepInput'
          minItems: 1
          maxItems: 20
          description: Steps in the order they run, up to 20.
      required:
        - name
        - steps
    CampaignResponse:
      type: object
      properties:
        success:
          type: boolean
          enum:
            - true
        data:
          $ref: '#/components/schemas/Campaign'
      required:
        - success
        - data
    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
    Campaign:
      allOf:
        - $ref: '#/components/schemas/CampaignSummary'
        - type: object
          properties:
            enable_sequence_automation:
              type: boolean
            stop_on_response:
              type: boolean
            send_on_weekends:
              type: boolean
            send_on_holidays:
              type: boolean
            link_tracking:
              type: boolean
            open_tracking:
              type: boolean
            include_unsubscribe_link:
              type: boolean
            steps:
              type: array
              items:
                $ref: '#/components/schemas/CampaignStep'
            manual_variables:
              type: array
              items:
                type: string
              description: >-
                Variables you fill in for each enrollment, such as
                personalization_line or your own names.
            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.
                  step_ids:
                    type: array
                    items:
                      type: string
                      format: uuid
                    description: Steps that use this AI variable.
                required:
                  - name
                  - description
                  - step_ids
              description: Variables the AI writes for each person.
            enrollment_counts:
              type: object
              properties:
                total:
                  type: integer
                running:
                  type: integer
                awaiting_task:
                  type: integer
                  description: >-
                    People held until a task step is marked complete. They are
                    also counted in running or bounced, so the groups can add up
                    to more than total.
                replied:
                  type: integer
                meeting_booked:
                  type: integer
                bounced:
                  type: integer
                completed:
                  type: integer
                stopped:
                  type: integer
              required:
                - total
                - running
                - awaiting_task
                - replied
                - meeting_booked
                - bounced
                - completed
                - stopped
              description: People in this campaign by status.
            engagement:
              type: object
              properties:
                responded:
                  type: integer
                  description: People who replied or booked a meeting.
                interested:
                  type: integer
                  description: >-
                    People whose reply was read as interested, not counting
                    bounced people.
                neutral:
                  type: integer
                  description: >-
                    People whose reply was read as neutral, not counting bounced
                    people.
                not_interested:
                  type: integer
                  description: >-
                    People whose reply was read as not interested, not counting
                    bounced people.
                opened:
                  type: integer
                  description: >-
                    People who opened at least one email, not counting bounced
                    people.
                clicked:
                  type: integer
                  description: >-
                    People who clicked at least one link, not counting bounced
                    people.
                reply_rate:
                  type:
                    - number
                    - 'null'
                  description: >-
                    responded out of everyone enrolled except bounced people, as
                    a percent with one decimal. null when nobody is enrolled or
                    everyone bounced.
                open_rate:
                  type:
                    - integer
                    - 'null'
                  description: >-
                    opened out of everyone enrolled except bounced people, as a
                    whole percent. null when open tracking is off, nobody is
                    enrolled or everyone bounced.
                click_rate:
                  type:
                    - integer
                    - 'null'
                  description: >-
                    clicked out of everyone enrolled except bounced people, as a
                    whole percent. null when link tracking is off, nobody is
                    enrolled or everyone bounced.
              required:
                - responded
                - interested
                - neutral
                - not_interested
                - opened
                - clicked
                - reply_rate
                - open_rate
                - click_rate
              description: Replies, opens and clicks, as on the campaign card.
          required:
            - enable_sequence_automation
            - stop_on_response
            - send_on_weekends
            - send_on_holidays
            - link_tracking
            - open_tracking
            - include_unsubscribe_link
            - steps
            - manual_variables
            - ai_variables
            - enrollment_counts
            - engagement
    CampaignSummary:
      type: object
      properties:
        id:
          type: string
          format: uuid
        name:
          type: string
        sequence_type:
          type: string
          enum:
            - candidate
            - business_development
            - candidate_nurture
            - client_nurture
        is_archived:
          type: boolean
        created_by:
          type: string
          format: uuid
          description: Team member who owns the campaign.
        step_count:
          type: integer
        created_at:
          type: string
        updated_at:
          type:
            - string
            - 'null'
      required:
        - id
        - name
        - sequence_type
        - is_archived
        - created_by
        - step_count
        - created_at
        - updated_at
    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.