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

# Create a campaign

> Create a campaign. It is always created with status `draft`; use
`POST /v1/campaigns/{id}/start` to launch it. Optionally attach lead
lists at creation time via `lead_list_ids`; one `campaign_lead_lists`
row is created per id.




## OpenAPI

````yaml /api-reference/openapi.json post /v1/campaigns
openapi: 3.0.3
info:
  title: TopCalls Voice API
  description: >
    TopCalls Voice Gateway API for creating and managing AI-powered phone calls.


    ## Authentication


    All API requests require authentication. Include your API key in the
    `Authorization` header:


    ```

    Authorization: Bearer tc_live_xxxxx

    ```


    ## Rate Limits


    Direct call creation via `POST /v1/calls` is limited to your account's

    `max_calls_per_minute` setting (default: 20) per minute. Exceeding it
    returns

    `429 Too Many Requests` with a `Retry-After` header.

    All endpoints are additionally subject to a flat limit of 120 requests per

    minute per account (all methods).


    On a `429`, wait for the number of seconds in the `Retry-After` header, then

    retry the same request. For automated clients, back off progressively on

    repeated `429`s. Limits are per account and are shared by all API keys.


    ## Error Format


    All errors follow RFC 7807 Problem+JSON format:


    ```json

    {
      "type": "https://api.topcalls.ai/errors/insufficient_quota",
      "title": "Insufficient Quota",
      "status": 402,
      "detail": "You need 5 minutes but have 3.5 remaining"
    }

    ```
  version: 1.0.0
  contact:
    name: TopCalls Support
    url: https://topcalls.ai
  license:
    name: Proprietary
servers:
  - url: https://api.topcalls.ai
    description: Production
security: []
tags:
  - name: Calls
    description: Create and manage phone calls
  - name: Phone Numbers
    description: Manage phone numbers and carriers
  - name: Account
    description: Account information and usage
  - name: Webhooks
    description: Webhook configuration and events
  - name: Configuration
    description: Available AI models, voices, and platform capabilities
paths:
  /v1/campaigns:
    post:
      tags:
        - Campaigns
      summary: Create a campaign
      description: |
        Create a campaign. It is always created with status `draft`; use
        `POST /v1/campaigns/{id}/start` to launch it. Optionally attach lead
        lists at creation time via `lead_list_ids`; one `campaign_lead_lists`
        row is created per id.
      operationId: createCampaign
      parameters:
        - $ref: '#/components/parameters/IdempotencyKeyHeader'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateCampaignRequest'
            examples:
              simple:
                summary: Minimal campaign
                value:
                  name: Spring outreach
              with_lead_lists_and_config:
                summary: Campaign with lead lists and call configuration
                value:
                  name: Spring outreach
                  timezone: Europe/Bucharest
                  dispatch_hours_start: '09:00'
                  dispatch_hours_end: '18:00'
                  dispatch_weekdays:
                    - 1
                    - 2
                    - 3
                    - 4
                    - 5
                  lead_list_ids:
                    - 564d4fd4-03bc-400a-abe0-05540fbeff88
                  config:
                    instructions: You are Rachel, a friendly appointment coordinator...
                    voice: rachel
                    mode: legacy
                    max_duration: 10
                    webhook_url: https://your-app.com/webhooks/call-complete
      responses:
        '201':
          description: Campaign created
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/Campaign'
                  - type: object
                    properties:
                      lead_list_ids:
                        type: array
                        items:
                          type: string
                          format: uuid
        '400':
          description: >-
            Invalid request body, or phone_number_ids/lead_list_ids not owned by
            your account
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
      security:
        - bearerAuth: []
components:
  parameters:
    IdempotencyKeyHeader:
      name: Idempotency-Key
      in: header
      required: false
      description: |
        Optional client-supplied idempotency key. When present, the gateway
        caches the response for 24 hours and returns the same response on
        retried requests with the same key (account-scoped). Safe for
        retries on network blips. Format: 8-255 ASCII characters from
        `[A-Za-z0-9_-]`.
      schema:
        type: string
        minLength: 8
        maxLength: 255
        pattern: ^[A-Za-z0-9_-]+$
        example: a1b2c3d4-e5f6-7890-abcd-ef0123456789
  schemas:
    CreateCampaignRequest:
      type: object
      required:
        - name
      description: |
        Request body for creating a campaign. The campaign is always created
        with status `draft`; use the lifecycle endpoints (start/pause/resume/
        stop) to change its status.
      properties:
        name:
          type: string
          minLength: 1
        description:
          type: string
        timezone:
          type: string
          description: >-
            IANA timezone name used to interpret dispatch hours and
            schedule_time.
        dispatch_hours_start:
          type: string
          pattern: ^([01]\d|2[0-3]):[0-5]\d(:[0-5]\d)?$
          description: Local time of day dispatch may begin. Accepts HH:MM or HH:MM:SS.
        dispatch_hours_end:
          type: string
          pattern: ^([01]\d|2[0-3]):[0-5]\d(:[0-5]\d)?$
          description: Local time of day dispatch must stop. Accepts HH:MM or HH:MM:SS.
        dispatch_weekdays:
          type: array
          items:
            type: integer
            minimum: 1
            maximum: 7
          description: Weekdays dispatch is allowed, 1=Monday through 7=Sunday.
        dispatch_hours_overrides:
          type: object
          additionalProperties:
            type: array
            items:
              type: object
              required:
                - start
                - end
              properties:
                start:
                  type: string
                  pattern: ^([01]\d|2[0-3]):[0-5]\d(:[0-5]\d)?$
                end:
                  type: string
                  pattern: ^([01]\d|2[0-3]):[0-5]\d(:[0-5]\d)?$
          description: |
            Per-weekday overrides of the default dispatch hours, keyed by ISO
            weekday string ("1"-"7"). Each value is an array of time windows
            for that day; an empty array marks the day off entirely.
        max_attempts_per_lead:
          type: integer
          minimum: 1
        max_parallel_calls:
          type: integer
          minimum: 1
        schedule_time:
          type: string
          format: date-time
          description: >-
            When set to a future time, the campaign starts as scheduled instead
            of running immediately.
        lead_list_ids:
          type: array
          items:
            type: string
            format: uuid
          description: >-
            Lead lists to attach to this campaign. Every id must belong to your
            account.
        config:
          $ref: '#/components/schemas/CampaignConfig'
    Campaign:
      type: object
      description: |
        Campaign record. Returned by GET /v1/campaigns and
        GET /v1/campaigns/{campaign_id}. Projected to this documented field
        set; additional internal columns are never included.
      additionalProperties: true
      properties:
        id:
          type: string
          format: uuid
        account_id:
          type: string
          format: uuid
        name:
          type: string
        description:
          type: string
          nullable: true
        status:
          type: string
          enum:
            - draft
            - scheduled
            - running
            - paused
            - completed
            - failed
            - cancelled
        timezone:
          type: string
          nullable: true
          description: >-
            IANA timezone name used to interpret dispatch hours and
            schedule_time.
        schedule_time:
          type: string
          format: date-time
          nullable: true
        dispatch_hours_start:
          type: string
          nullable: true
          description: Local time of day dispatch may begin, HH:MM:SS.
        dispatch_hours_end:
          type: string
          nullable: true
          description: Local time of day dispatch must stop, HH:MM:SS.
        dispatch_weekdays:
          type: array
          items:
            type: integer
            minimum: 1
            maximum: 7
          description: Weekdays dispatch is allowed, 1=Monday through 7=Sunday.
        dispatch_hours_overrides:
          type: object
          nullable: true
          additionalProperties: true
          description: Per-weekday overrides of the default dispatch hours.
        max_attempts_per_lead:
          type: integer
        max_parallel_calls:
          type: integer
          nullable: true
        conversion_outcomes:
          type: array
          items:
            type: string
          nullable: true
        outcome_mapping:
          type: object
          nullable: true
          additionalProperties: true
        pause_reason:
          type: string
          nullable: true
        config:
          type: object
          additionalProperties: true
          description: >-
            Call configuration applied to every call dispatched by this
            campaign.
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
          nullable: true
    Problem:
      type: object
      required:
        - status
        - title
      properties:
        type:
          type: string
          format: uri
          description: Error type URI
        title:
          type: string
          description: Error title
        status:
          type: integer
          description: HTTP status code
        detail:
          type: string
          description: Human-readable error detail
        code:
          type: string
          description: >
            Machine-readable error code for programmatic handling. Present on

            errors that carry a stable identifier (e.g. `PROMPT_SAFETY_FRAUD`,

            `job_not_found`, `too_many_ids`, `no_matches`). Distinct from the

            per-field `errors[].code` used for validation failures. Scenario-

            specific — see each endpoint's response examples for the exact
            value.
        instance:
          type: string
          format: uuid
          description: Request instance ID
        errors:
          type: array
          description: Validation errors (for 400 responses)
          items:
            type: object
            properties:
              path:
                type: string
                description: Field path (e.g., "phone_number", "metadata.from_number")
              message:
                type: string
                description: Error message
              code:
                type: string
                description: Error code (e.g., "invalid_string", "custom")
        details:
          type: string
          description: Additional error details (for provider errors)
    CampaignConfig:
      type: object
      additionalProperties: false
      description: |
        Call configuration applied to every call dispatched by this campaign.
        Same shape as the `CreateCallRequest` call-configuration fields,
        applied at the campaign level instead of per-call. Unknown keys are
        rejected.
      properties:
        mode:
          type: string
          enum:
            - realtime
            - legacy
          description: Conversation mode.
        task:
          type: string
          minLength: 10
          description: >-
            Simple prompt describing what the AI should do. Use this OR
            instructions.
        instructions:
          type: string
          minLength: 10
          description: Full system instructions for the AI. Use this OR task.
        model:
          type: string
          minLength: 1
          description: AI model to use for calls dispatched by this campaign.
        voice:
          type: string
          minLength: 1
          description: Voice to use for AI responses.
        temperature:
          type: number
          minimum: 0
          maximum: 1
          description: LLM creativity/temperature (0-1).
        first_sentence:
          type: string
          minLength: 1
          description: The AI's opening line.
        stt_provider:
          type: string
          enum:
            - deepgram
            - gladia
            - speechmatics
            - soniox
          description: STT provider (legacy mode only).
        stt_model:
          type: string
          minLength: 1
          description: STT model (legacy mode only).
        stt_language:
          type: string
          minLength: 2
          maxLength: 35
          description: STT language code (legacy mode only).
        stt_languages:
          type: array
          items:
            type: string
            minLength: 2
          minItems: 1
          maxItems: 10
          description: >-
            Restricted multi-language detection (supported on select
            transcription engines).
        stt_vocabulary:
          type: array
          minItems: 1
          maxItems: 100
          description: Custom STT vocabulary (multi-language provider only).
          items:
            oneOf:
              - type: string
                minLength: 1
              - type: object
                required:
                  - value
                properties:
                  value:
                    type: string
                    minLength: 1
                  language:
                    type: string
                    minLength: 2
        stt_endpoint_sensitivity:
          type: number
          minimum: 0.01
          maximum: 3
          description: Endpoint delay in seconds (provider-dependent effective range).
        stt_endpoint_eagerness:
          type: number
          minimum: -1
          maximum: 1
          default: -0.3
          description: |
            Semantic endpoint-sensitivity bias (-1 to 1). Negative values wait
            longer before ending the turn; positive values end turns more
            eagerly. Only honoured when `stt_provider=soniox`.
        stt_interrupt_sensitivity:
          type: number
          minimum: 0
          maximum: 1
          description: >-
            STT interrupt/speech detection sensitivity (multi-language provider
            only).
        stt_max_delay:
          type: number
          minimum: 0.7
          maximum: 4
          description: >-
            Max wait in seconds before finalizing a transcript (supported on
            select transcription engines).
        transcript_correction_vocabulary:
          type: array
          minItems: 1
          maxItems: 100
          description: Domain terms for LLM-based STT error correction (legacy mode only).
          items:
            oneOf:
              - type: string
                minLength: 1
              - type: object
                required:
                  - correct
                properties:
                  correct:
                    type: string
                    minLength: 1
                  sounds_like:
                    type: array
                    items:
                      type: string
                      minLength: 1
                    maxItems: 10
                  context:
                    type: string
                    minLength: 1
                    maxLength: 50
        tts_provider:
          type: string
          enum:
            - deepgram
            - elevenlabs
            - cartesia
          description: TTS provider (legacy mode only).
        tts_model:
          type: string
          minLength: 1
          description: TTS model (legacy mode only).
        tts_stability:
          type: number
          minimum: 0
          maximum: 1
          description: Voice stability (legacy mode).
        tts_similarity_boost:
          type: number
          minimum: 0
          maximum: 1
          description: Voice similarity boost (legacy mode).
        tts_speed:
          type: number
          minimum: 0.7
          maximum: 1.2
          description: Speech speed (legacy mode).
        tts_style:
          type: number
          minimum: 0
          maximum: 1
          description: |
            Style exaggeration for TTS (legacy mode). 0 is neutral, 1 is
            maximum expressiveness. Only effective on eleven_multilingual_v2;
            when omitted, the TTS provider default applies.
        background_audio:
          type: string
          enum:
            - office
            - none
          description: Background audio preset to play during calls.
        background_audio_gain:
          type: string
          enum:
            - low
            - medium
            - high
          description: Volume level for background audio relative to speech.
        filler_enabled:
          type: boolean
          description: >-
            Enable brief filler acknowledgments before the main response (legacy
            mode only).
        emotion_enabled:
          type: boolean
          description: >-
            Enable expressive-speech markup (prosody + native interjections) for
            expressive-capable voices (legacy mode only; applies when
            `tts_provider=cartesia`).
        block_interruption:
          type: boolean
          description: >-
            Continue TTS even if the caller speaks, buffering their speech for
            later (legacy mode only).
        bot_protection_enabled:
          type: boolean
          default: true
          description: >-
            Detect automated or non-responsive callers and end such calls
            automatically (legacy mode only).
        max_duration:
          type: integer
          minimum: 1
          maximum: 60
          description: Maximum call duration in minutes.
        from_number:
          type: string
          pattern: ^\+[1-9]\d{1,14}$
          description: >-
            Caller ID in E.164 format used for calls dispatched by this
            campaign.
        webhook_url:
          type: string
          format: uri
          description: Webhook URL to receive call completion/failure notifications.
        webhook_call_status_filter:
          type: array
          items:
            type: string
            minLength: 1
          minItems: 1
          maxItems: 20
          description: |
            Restrict webhook delivery to calls matching one of these
            call_status values. When omitted, all call statuses are delivered.
        analysis_schema:
          type: object
          additionalProperties:
            oneOf:
              - type: string
                enum:
                  - boolean
                  - string
                  - text
                  - number
                  - date
              - type: object
                required:
                  - type
                  - description
                properties:
                  type:
                    type: string
                    enum:
                      - boolean
                      - string
                      - text
                      - number
                      - date
                  description:
                    type: string
                    minLength: 1
          description: >-
            Schema for post-call AI analysis, applied to every call dispatched
            by this campaign.
        mcp_tool_allowlist:
          type: array
          items:
            type: string
            minLength: 1
          maxItems: 100
          description: |
            Names of tools from connected automation workflows that the AI is
            allowed to invoke during calls dispatched by this campaign. When
            absent or empty, no such tools are attached.
        summary_prompt:
          type: string
          minLength: 1
          maxLength: 4000
          description: >-
            Custom prompt used to generate the post-call summary for this
            campaign's calls.
        phone_number_ids:
          type: array
          items:
            type: string
            format: uuid
          minItems: 1
          description: |
            Phone numbers this campaign may dial from, chosen at random per
            call. Every id must belong to your account.
        knowledge_base_ids:
          type: array
          items:
            type: string
            format: uuid
          description: |
            Knowledge base entry ids attached to this campaign. Every id must
            belong to your account. On save this set is reconciled: the
            attachment becomes exactly the ids supplied, an empty array
            detaches all, and omitting the field leaves the attachment
            unchanged. The attached entries are the content the campaign's
            calls load.
        crew:
          $ref: '#/components/schemas/CrewConfig'
    CrewConfig:
      type: object
      required:
        - members
      description: |
        Configuration for multiple specialised agents on a single call, with
        controlled handoffs between them. The first member answers the call;
        later members take over when their conditions are met. Availability
        is rolling out gradually.
      properties:
        members:
          type: array
          minItems: 2
          maxItems: 5
          description: 2-5 members. Unique ids. The first member is the entry member.
          items:
            $ref: '#/components/schemas/CrewMember'
        max_handoffs:
          type: integer
          minimum: 1
          maximum: 10
          default: 3
          description: Hard cap on handoffs per call.
    CrewMember:
      type: object
      required:
        - id
        - name
        - instructions
      properties:
        id:
          type: string
          minLength: 1
          description: Slug id, unique within the crew.
        name:
          type: string
          minLength: 1
          description: Display name (e.g. "Alex").
        instructions:
          type: string
          minLength: 1
          maxLength: 8000
          description: Member-specific instructions.
        use_knowledge_base:
          type: boolean
          description: When true, the knowledge base is appended to this member's prompt.
        knowledge_base_ids:
          type: array
          items:
            type: string
            format: uuid
          description: |
            Optional subset of this campaign's attached knowledge base entry ids
            visible to this member. When absent, `use_knowledge_base` controls
            all-or-none knowledge base access. An empty array gives this member
            no knowledge base entries.
        mcp_tool_allowlist:
          type: array
          items:
            type: string
            minLength: 1
          description: >
            Optional subset of the campaign-level `mcp_tool_allowlist` available

            to this member. When absent, the member inherits the campaign-level

            tool allowlist. An empty array gives this member no remote MCP
            tools.
        handoffs:
          type: array
          maxItems: 300
          description: Outbound handoff edges. Empty or absent means a terminal member.
          items:
            type: object
            required:
              - to
              - when
            properties:
              to:
                type: string
                minLength: 1
                description: >-
                  Destination member id. Must reference another member in the
                  same crew.
              when:
                type: string
                minLength: 1
                maxLength: 300
                description: >-
                  Free-form condition describing when to hand off to this
                  member.
  responses:
    Unauthorized:
      description: Unauthorized (missing or invalid API key)
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/Problem'
          example:
            status: 401
            title: Unauthorized
            detail: Invalid or missing API key
    Forbidden:
      description: Forbidden (missing required scope)
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/Problem'
          example:
            status: 403
            title: Forbidden
            detail: 'Missing required scope: calls:write'
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: |
        Use `Authorization: Bearer tc_live_xxxxx`

````