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

# Duplicate a campaign

> Creates a draft copy of a campaign with every setting (assistant, sequence, number pool, calling windows, holidays, channel configuration), but without contacts, launch confirmation, schedule or run history. Use it to change the sequence of a campaign that was already started. The copy counts against the plan's campaign limit, and a copy with a sequence or number pool needs a plan that includes Campaign sequences. **Required scope:** `campaigns:write` (keys without scope restrictions have full access).



## OpenAPI

````yaml /api-reference/openapi.json post /campaigns/{id}/duplicate
openapi: 3.1.0
info:
  title: Famulor API
  version: 1.0.0
  description: >-
    REST API for Famulor. Authenticate with an API key (`fam_...`, created under
    **Settings → API Keys**) or an OAuth 2.0 access token (`fam_at_...`) as a
    Bearer token.


    Every response uses a consistent envelope: `{ "data": ... , "meta": { ... }
    }` on success and `{ "error": { "code", "message" } }` on failure. List
    endpoints paginate with `?limit=` (default 50, max 200) and `?offset=`;
    `meta.pagination.total` carries the total match count.


    REST operations require API Access through the workspace plan or a recurring
    add-on. Without it, regular operations return `403 api_access_required`. The
    invoice-payment and billing-portal operations remain available with a valid
    `billing:write` credential after a failed plan payment so an authorized
    owner, admin, or billing member can recover billing.


    The same customer-facing capabilities are available as MCP tools at
    `https://app.famulor.io/mcp` (Model Context Protocol, streamable HTTP) using
    the same credentials, scopes, and workspace access. MCP availability is
    controlled separately by Connect AI / MCP, not by API Access.
servers:
  - url: https://app.famulor.io/api/v1
    description: Hosted platform.
  - url: https://{domain}/api/v1
    description: White-label tenant domain — same paths, tenant branding.
    variables:
      domain:
        default: app.famulor.io
        description: Your white-label tenant domain.
security:
  - bearerAuth: []
tags:
  - name: Account
    description: Self-inspection of the calling credential.
  - name: Migrations
    description: Preview and import data from supported legacy platforms.
  - name: Assistants
    description: Create and manage voice assistants.
  - name: Tools
    description: >-
      Reusable tools (HTTP APIs, external MCP servers and actions of connected
      apps) assistants can call mid-conversation.
  - name: Voices
    description: Browse the text-to-speech voice library.
  - name: Calls
    description: Start outbound calls and read call history, transcripts and recordings.
  - name: History
    description: Unified conversation history across calls, messaging and assistant emails.
  - name: Campaigns
    description: Outbound calling campaigns with a compliant power dialer.
  - name: Leads
    description: Manage Audience contacts across campaigns, channels and Call QA metrics.
  - name: Segments
    description: >-
      Saved, dynamic lead filters — reusable audience definitions used for
      Audience search and campaign lead assignment.
  - name: Suppression
    description: Cross-channel marketing opt-outs and active workspace suppression records.
  - name: Callbacks
    description: >-
      Scheduled callbacks booked by the Schedule callback tool across voice,
      chat, and email.
  - name: Phone Numbers
    description: Marketplace numbers and customer-provided numbers.
  - name: Famulor Loop
    description: >-
      Personal business-phone access, directory, presence, devices, and Loop
      call recents.
  - name: SIP Trunks
    description: Bring your own SIP provider and numbers.
  - name: Carrier Connections
    description: Connect a supported carrier account and import its existing phone numbers.
  - name: Knowledge Bases
    description: RAG knowledge bases and documents for assistants.
  - name: Settings
    description: Workspace-level settings such as caller-memory defaults.
  - name: Billing
    description: Balance and transaction ledger of the API key's workspace.
  - name: Automations
    description: >-
      Native workspace automations — list, create, update, trigger. Requires
      Automations in the workspace plan.
  - name: Milian Missions
    description: Recurring jobs that Milian runs unattended on schedule.
  - name: Integrations
    description: >-
      Calendar integrations (Cal.com, Calendly, Acuity Scheduling, Google
      Calendar, Outlook, native booking engine). Assign them to assistants to
      provide availability and booking tools, plus provider-supported
      appointment lookup, cancellation, and rescheduling.
  - name: Bookings
    description: >-
      Native booking engine — event types with weekly availability, public
      booking pages at /book/{workspace}/{slug}, and the bookings they produce.
  - name: Dashboards
    description: >-
      Custom analytics dashboards, reusable widgets, and tenant-scoped
      performance analytics. Requires Custom dashboards in the workspace plan.
  - name: Catalog
    description: >-
      Read-only platform catalogs — available models, supported assistant
      languages, and prompt templates.
  - name: Simulations
    description: Assistant simulation tests (plan-gated).
  - name: Versions
    description: Assistant configuration version history.
  - name: Caller IDs
    description: Outbound caller ID verification.
  - name: Widgets
    description: Web widget connectors.
  - name: Messaging
    description: >-
      Telegram, Slack, and Messenger text bots linked to assistants (Chat SDK).
      Includes conversation delay, inactivity end, and conversation-ended
      webhooks.
  - name: QA
    description: Cohort AI Quality Assurance runs over call transcripts.
  - name: White Label
    description: >-
      Manage white-label customer accounts, defaults, credit transfers and
      customer plan offers. Each endpoint documents its required scope and
      workspace eligibility.
  - name: API Keys
    description: >-
      Self-service API keys for the calling workspace or a same-brand workspace
      where the credential's user is owner/admin. A key can only mint further
      keys with a scope subset of its own.
  - name: Workspaces
    description: >-
      List visible workspaces, create an additional workspace for the key owner,
      and mint a dedicated credential for a selected owner/admin workspace.
  - name: SMS
    description: Outbound SMS from workspace phone numbers.
  - name: Milian
    description: >-
      Ask Milian, the AI co-worker in your workspace, and start voice sessions
      with it.
  - name: Translation
    description: >-
      Live translation sessions that interpret a conversation between two
      languages.
  - name: Shopify
    description: Native Shopify app store connections, assistant tools and activity.
  - name: Avatars
    description: Private custom avatars and widget avatar selection.
  - name: Webhook Subscriptions
    description: >-
      Signed workspace event subscriptions, independent of existing
      destinations.
paths:
  /campaigns/{id}/duplicate:
    parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          format: uuid
        description: Campaign ID.
    post:
      tags:
        - Campaigns
      summary: Duplicate a campaign
      description: >-
        Creates a draft copy of a campaign with every setting (assistant,
        sequence, number pool, calling windows, holidays, channel
        configuration), but without contacts, launch confirmation, schedule or
        run history. Use it to change the sequence of a campaign that was
        already started. The copy counts against the plan's campaign limit, and
        a copy with a sequence or number pool needs a plan that includes
        Campaign sequences. **Required scope:** `campaigns:write` (keys without
        scope restrictions have full access).
      operationId: duplicateCampaign
      requestBody:
        required: false
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                  minLength: 1
                  maxLength: 128
                  description: >-
                    Name of the copy. Defaults to the original name followed by
                    ` (copy)`.
            example:
              name: July outreach, second wave
      responses:
        '201':
          description: The draft copy.
          content:
            application/json:
              schema:
                type: object
                required:
                  - data
                properties:
                  data:
                    $ref: '#/components/schemas/Campaign'
              example:
                data:
                  id: ca1b2c3d-0000-4000-8000-000000000031
                  name: July outreach, second wave
                  status: draft
                  assistant_id: a1b2c3d4-0000-4000-8000-000000000001
                  concurrency: 3
                  contact_timezone_mode: campaign
                  double_dial: false
                  launch_attestation: null
                  started_at: null
                  completed_at: null
                  created_at: '2026-07-02T08:00:00Z'
                  updated_at: '2026-07-02T08:00:00Z'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/RateLimited'
        '503':
          $ref: '#/components/responses/CampaignOrProtectionUnavailable'
components:
  schemas:
    Campaign:
      type: object
      properties:
        id:
          type: string
          format: uuid
        name:
          type: string
        status:
          type: string
          enum:
            - draft
            - scheduled
            - running
            - paused
            - completed
            - archived
        channel:
          type: string
          enum:
            - phone_call
            - whatsapp_template
            - whatsapp_call
            - sms
          default: phone_call
        channel_config:
          type: object
          additionalProperties: true
          description: >-
            Sender and message of the channel. `sms`: `from_number_id` (a
            workspace number) or `rcs_sender_id` (a company name, RCS), exactly
            one, plus `message` and `variable_mapping`. `whatsapp_template`:
            `connector_id`, `template_id`, `variable_mapping`.
        follow_up_config:
          type: object
          additionalProperties: true
          description: >-
            Optional voice follow-up after retries are exhausted. `channel` is
            `off` | `whatsapp_template` | `sms` | `email`. An `sms` follow-up
            names its sender with exactly one of `from_number_id` (a workspace
            number) or `rcs_sender_id` (a company name, RCS). Email is follow-up
            only and uses `subject`, `message`, and `variable_mapping`; it sends
            from the campaign assistant address. A campaign with a `sequence`
            takes no follow-up: any channel other than `off` is rejected with
            400 (use message steps in the sequence instead), also when the
            request adds a sequence to a campaign whose stored follow-up is on
            and does not turn it off.
        scheduled_start_at:
          type:
            - string
            - 'null'
          format: date-time
        assistant_id:
          type:
            - string
            - 'null'
          format: uuid
          description: Assistant that runs the campaign calls.
        concurrency:
          type: integer
          minimum: 1
          maximum: 2147483647
          description: >-
            Maximum parallel voice calls for this campaign. Must fit the
            workspace's effective Concurrent Lines allowance, including add-ons.
            Calls across campaigns share that workspace allowance.
        retry_max:
          type: integer
          description: Max retry attempts per lead. Ignored when `sequence` is set.
        retry_delay_minutes:
          type: integer
          description: Minutes between retries. Ignored when `sequence` is set.
        calling_windows:
          $ref: '#/components/schemas/CallingWindows'
        timezone:
          type: string
          description: IANA timezone the calling windows are evaluated in.
        amd_enabled:
          type: boolean
          description: Answering-machine detection at call start.
        voicemail_action:
          type: string
          enum:
            - hangup
            - drop_message
        voicemail_message:
          type:
            - string
            - 'null'
          description: >-
            TTS text spoken to voicemail when `voicemail_action` is
            `drop_message`.
        started_at:
          type:
            - string
            - 'null'
          format: date-time
        completed_at:
          type:
            - string
            - 'null'
          format: date-time
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
        amd_mode:
          type: string
          enum:
            - conservative
            - aggressive
          description: Answering-machine detection sensitivity when AMD is enabled.
        ivr_navigation:
          type: boolean
          description: >-
            Allow navigating phone menus. Enabling requires workspace Beta
            features.
        external_audience:
          anyOf:
            - $ref: '#/components/schemas/CampaignExternalAudience'
            - type: 'null'
          description: >-
            Opt-in external beta audience. Phone calls only with follow-up off.
            Null selects existing local leads. Current membership, scenario and
            explicit voice permission are checked before every attempt; no
            profile mirror. Cannot change after execution starts.
        retry_on_voicemail:
          type: boolean
          description: >-
            Retry leads whose call reached a voicemail or an unavailable
            mailbox, within `retry_max`. When `false`, a completed call counts
            as reached even if a voicemail answered. Ignored when `sequence` is
            set.
        retry_until_goal:
          type: boolean
          description: >-
            Mark a lead completed only when `goal_variable` evaluates to true
            after the call; otherwise schedule another attempt, within
            `retry_max`. Ignored when `sequence` is set.
        goal_variable:
          type:
            - string
            - 'null'
          description: >-
            Yes/no post-call analysis field of the assistant, or the built-in
            `success` result, that decides whether a lead's goal was reached.
            Used by `retry_until_goal` and by the conversion count of classic
            campaigns. `null` clears it. Retries ignore it when `sequence` is
            set.
        mark_complete_when_no_leads:
          type: boolean
          description: >-
            Mark the campaign `completed` automatically when no lead is left to
            call. When `false`, the campaign stays open for leads added later.
        outbound_ringing_timeout_sec:
          type:
            - integer
            - 'null'
          minimum: 15
          maximum: 80
          description: >-
            Seconds an outbound call may ring before it counts as unanswered (15
            to 80). `null` uses the platform default.
        sequence:
          anyOf:
            - $ref: '#/components/schemas/CampaignSequence'
            - type: 'null'
          description: >-
            Sequence of call and message steps with outcomes and per-step
            attempts. `null` keeps the classic retry settings (`retry_max`,
            `retry_delay_minutes`). Campaigns created without it stay classic.
            Phone call campaigns only; not with an external audience. Draft and
            paused campaigns can change it, also after they were started (see
            `updateCampaign`); a running campaign is paused first, a scheduled
            one cancels its schedule first, a completed one is duplicated.
        sequence_hash:
          type:
            - string
            - 'null'
          readOnly: true
          description: >-
            Opaque change token of `sequence`; `null` for a campaign without a
            sequence. Pass it unchanged as `sequence_hash` to `launchCampaign`
            to be sure the sequence has not changed since you read it. Do not
            compute it yourself.
        number_pool:
          anyOf:
            - $ref: '#/components/schemas/CampaignNumberPool'
            - type: 'null'
          description: >-
            Caller numbers to dial from. `null` uses the assistant's outbound
            number. Needs a `sequence` (400 without one); phone call campaigns
            only; not with an external audience. Removing the sequence resets it
            to `null`.
        contact_timezone_mode:
          type: string
          enum:
            - campaign
            - contact
          default: campaign
          description: >-
            Which time zone the calling windows follow. `campaign`: the
            campaign's `timezone`. `contact`: each contact's own local time,
            derived from the phone number; needs a `sequence` (400 without one),
            because only sequence campaigns apply it.
        holidays:
          allOf:
            - $ref: '#/components/schemas/CampaignHolidays'
          description: >-
            Days without calls. Defaults to no public holidays and no custom
            dates. Non-default values need a `sequence` (400 without one),
            because only sequence campaigns apply them.
        double_dial:
          type: boolean
          default: false
          description: >-
            Redial once immediately when a call ends unanswered or busy. Off by
            default; `true` needs a `sequence` (400 without one), because only
            sequence campaigns redial; repeated immediate calls can be an
            unreasonable nuisance under EU law, so check the countries you call
            before turning it on.
        launch_attestation:
          anyOf:
            - $ref: '#/components/schemas/CampaignLaunchAttestation'
            - type: 'null'
          readOnly: true
          description: >-
            Who confirmed that the campaign is lawful and when. Set by
            `launchCampaign`, or by `startCampaign` or `resumeCampaign` with
            `compliance_attestation`. `null` until then;
            `cancelCampaignSchedule` clears it, and so does a changed sequence.
      required:
        - id
        - name
        - status
        - created_at
        - updated_at
    CallingWindows:
      type: object
      description: >-
        Allowed calling windows per weekday, local to the campaign `timezone`.
        Keys: `mon`–`sun`; each value is an array of `["HH:MM", "HH:MM"]`
        start/end pairs (24h). An empty array or missing key blocks the whole
        day.
      propertyNames:
        enum:
          - mon
          - tue
          - wed
          - thu
          - fri
          - sat
          - sun
      additionalProperties:
        type: array
        items:
          type: array
          items:
            type: string
            pattern: ^([01][0-9]|2[0-3]):[0-5][0-9]$
          minItems: 2
          maxItems: 2
    CampaignExternalAudience:
      type: object
      properties:
        provider:
          type: string
          description: Connected audience source.
          enum:
            - shopify
            - klaviyo
        connection_id:
          type: string
          description: Workspace connection returned by audience discovery.
          format: uuid
        segment_id:
          type: string
          description: Source-owned segment returned by segment discovery.
          minLength: 1
          maxLength: 200
        scenario:
          type: string
          description: >-
            Klaviyo supports selected_segment only. Win-back and replenishment
            require older order access. Failed payment covers supported unpaid
            existing orders with proven failed transactions, not subscriptions
            or unsaved checkouts.
          enum:
            - selected_segment
            - winback
            - replenishment
            - abandoned_checkout
            - failed_payment
        eligibility:
          type: object
          properties:
            inactivity_days:
              type: integer
              description: Required win-back inactivity threshold in days.
              minimum: 1
              maximum: 3650
            product_id:
              type: string
              description: Exact Shopify product selected for replenishment.
              pattern: ^gid://shopify/Product/[0-9]+$
            interval_days:
              type: integer
              description: Required merchant-selected replenishment interval.
              minimum: 1
              maximum: 3650
          required: []
        consent_mapping:
          type: object
          properties:
            namespace:
              type: string
              description: Required Shopify customer permission metafield namespace.
            key:
              type: string
              description: >-
                Authoritative JSON permission property/metafield key. Record
                must contain current subject_ref and phone, channel:voice,
                purpose:marketing, granted:true, revoked:false, granted_at,
                evidence_ref and source_revision. Email/SMS consent is
                insufficient.
            semantics:
              type: string
              description: Explicit voice marketing permission contract.
              enum:
                - voice_marketing_permission_v1
          required:
            - key
            - semantics
      required:
        - provider
        - connection_id
        - segment_id
        - scenario
        - eligibility
        - consent_mapping
    CampaignSequence:
      type: object
      description: >-
        A sequence of steps: a small directed acyclic graph of call steps and
        message steps (SMS, WhatsApp template, email). A call step dials with
        its own assistant and attempt schedule; after an answered call, its
        outcomes decide where the contact goes next. A message step sends one
        message, optionally waits for a reply, and moves the contact on. When a
        sequence is set, the classic `retry_max`, `retry_delay_minutes`,
        `retry_on_voicemail`, `retry_until_goal` and `goal_variable` settings
        are ignored. Available for phone call campaigns with their own contact
        list, on plans that include Campaign sequences. A sequence that starts
        with a message step also needs a plan that includes multi-channel
        campaigns; later message steps need nothing extra. A started campaign
        can change its sequence while it is paused, as long as the contacts that
        wait on a step keep that step (see `updateCampaign`).
      required:
        - version
        - start_node_id
        - nodes
      additionalProperties: false
      properties:
        version:
          type: integer
          const: 1
          description: Sequence format version. Always `1`.
        start_node_id:
          type: string
          pattern: ^[a-z0-9][a-z0-9_-]{0,39}$
          description: >-
            Id of the step every contact starts with. Every other step must be
            reachable from it. The start step can be a message step.
        nodes:
          type: array
          minItems: 1
          maxItems: 10
          items:
            $ref: '#/components/schemas/CampaignSequenceStep'
          description: The steps of the sequence (1 to 10), call steps and message steps.
        global_outcomes:
          type: array
          maxItems: 10
          items:
            $ref: '#/components/schemas/CampaignSequenceGlobalOutcome'
          description: >-
            Outcomes checked for every node after the node's own outcomes (0 to
            10). They can only end the sequence.
      example:
        version: 1
        start_node_id: call
        nodes:
          - id: call
            name: Call
            assistant_id: null
            attempts:
              - delay_minutes: 0
              - delay_minutes: 1440
              - delay_minutes: 1440
            outcomes:
              - id: not_interested
                label: Not interested
                condition:
                  type: prompt
                  description: The contact says they are not interested.
                destination:
                  type: end
                  successful: false
            no_response:
              destination:
                type: node
                node_id: sms_reminder
            other:
              destination:
                type: retry
          - id: sms_reminder
            name: SMS reminder
            channel: sms
            assistant_id: null
            message:
              config:
                from_number_id: 6f2c1a52-8d3b-4c47-9a3e-1b7d5e0c9a11
                message: >-
                  Hi {{name}}, we tried to reach you. Reply to this message and
                  we will call you back.
                variable_mapping: {}
              wait_minutes: 1440
              next:
                type: end
                successful: false
              replied:
                type: end
                successful: true
              failed:
                type: end
                successful: false
        global_outcomes: []
    CampaignNumberPool:
      type: object
      description: >-
        Caller numbers a campaign dials from. Every contact keeps the same
        caller number on every attempt. `null` on the campaign means the
        assistant's outbound number. Available for phone call campaigns on plans
        that include Campaign sequences; after the campaign has been started,
        the numbers stay editable but the mode does not.
      required:
        - mode
        - phone_number_ids
      additionalProperties: false
      properties:
        mode:
          type: string
          enum:
            - local_presence
            - round_robin
          description: >-
            `local_presence`: the caller number matches the contact's own area
            code or country where the pool has one. `round_robin`: numbers
            rotate evenly.
        phone_number_ids:
          type: array
          minItems: 1
          maxItems: 500
          uniqueItems: true
          items:
            type: string
            format: uuid
          description: >-
            Phone numbers of the pool (1 to 500, no duplicates). Each must be an
            active number of the workspace with outbound calling and a trunk; a
            caller ID must be verified.
        default_phone_number_id:
          type:
            - string
            - 'null'
          format: uuid
          description: >-
            Number used when no pool number fits a contact. `null` or one of
            `phone_number_ids`.
    CampaignHolidays:
      type: object
      description: Days without calls, judged in the contact's local time zone.
      required:
        - public
        - custom_dates
      additionalProperties: false
      properties:
        public:
          type: boolean
          description: >-
            Skip national public holidays of the contact's country. Known for
            AT, BE, CA, CH, DE, ES, FR, GB (England and Wales), IE, IT, NL and
            US; contacts in other countries are not affected. Regional holidays
            are not included.
        custom_dates:
          type: array
          maxItems: 100
          uniqueItems: true
          items:
            type: string
            pattern: ^\d{4}-\d{2}-\d{2}$
            format: date
          description: >-
            Local dates (`YYYY-MM-DD`) without calls, for example a company
            holiday (at most 100).
    CampaignLaunchAttestation:
      type: object
      description: Who confirmed that the campaign is lawful, when and from which surface.
      required:
        - attested_at
        - actor_type
        - actor_id
        - surface
        - text_version
        - locale
      properties:
        attested_at:
          type: string
          format: date-time
          description: When the confirmation was given.
        actor_type:
          type: string
          enum:
            - user
            - api_key
            - service_account
          description: Kind of credential that confirmed.
        actor_id:
          type:
            - string
            - 'null'
          description: Id of that user, API key or service account.
        surface:
          type: string
          enum:
            - web
            - api
            - mcp
            - cli
          description: Where the confirmation was given.
        text_version:
          type: string
          description: Version of the confirmation wording, for example `2026-11-09`.
        locale:
          type: string
          enum:
            - en
            - de
            - fr
            - es
          description: Language of the confirmation wording.
    ErrorEnvelope:
      type: object
      description: Error envelope returned by every /api/v1 endpoint on failure.
      required:
        - error
      properties:
        error:
          type: object
          required:
            - code
            - message
          properties:
            code:
              type: string
              enum:
                - unauthorized
                - forbidden
                - api_access_required
                - not_found
                - invalid_request
                - rate_limited
                - conflict
                - telephony_configuration_error
                - telephony_unavailable
                - destination_forbidden
                - internal_error
                - service_unavailable
                - verification_address_required
                - bundle_address_missing
              description: >-
                Stable, machine-readable error code. `service_unavailable` is
                returned by POST /bookings and GET
                /booking-event-types/{id}/slots specifically when the
                availability engine could not be reached (see
                AvailabilityOrProtectionUnavailable).
                `verification_address_required` and `bundle_address_missing` are
                returned by POST /phone-numbers when the verification behind the
                number has no address (see the operation description).
            message:
              type: string
              description: Human-readable description of the error.
            reason:
              type: string
              description: >-
                Optional, more specific and stable reason for this error, for
                example `plan_required`, `read_only_role` or `missing_scope`.
                Branch on `code` first: `reason` is only present on some errors,
                and new values may be added. Campaign operations use
                `attestation_required` (400, `compliance_attestation` missing on
                launch), `launch_required` (400, a sequence campaign was never
                launched; launch it or start it with `compliance_attestation`),
                `sequence_changed` (409, the sequence changed after
                `sequence_hash` was taken), `campaign_sequences_unavailable`
                (403, the plan does not include Campaign sequences),
                `campaign_extension_unavailable` (503 `service_unavailable`, the
                campaign feature is not available yet) and `analytics_timeout`
                (504 `service_unavailable`, the campaign analytics took too
                long; choose a shorter period).
            hint:
              type: string
              description: >-
                Optional recovery advice that is safe to show to the end user,
                for example which settings page to open.
    CampaignSequenceStep:
      description: >-
        One step of a sequence: a call step or a message step. A step with
        `channel` `sms`, `whatsapp_template` or `email` and a `message` is a
        message step; every other step is a call step.
      oneOf:
        - $ref: '#/components/schemas/CampaignSequenceNode'
        - $ref: '#/components/schemas/CampaignSequenceMessageNode'
    CampaignSequenceGlobalOutcome:
      type: object
      description: >-
        An outcome checked for every node after the node's own outcomes. It can
        only end the sequence.
      required:
        - id
        - label
        - condition
        - destination
      additionalProperties: false
      properties:
        id:
          type: string
          pattern: ^[a-z0-9][a-z0-9_-]{0,39}$
          description: >-
            Unique id across every node and outcome of the sequence. Not
            `do_not_call`, `no_response`, `other`, `sent`, `replied` or
            `not_sent`: the platform produces those itself.
        label:
          type: string
          minLength: 1
          maxLength: 60
          description: Name shown in the contact list and the analytics.
        condition:
          $ref: '#/components/schemas/CampaignSequenceCondition'
        destination:
          $ref: '#/components/schemas/CampaignSequenceEndDestination'
          description: >-
            Where the contact goes: global outcomes can only end the sequence
            (`type: end`).
        save_to_field:
          anyOf:
            - type: object
              required:
                - key
                - value
              additionalProperties: false
              properties:
                key:
                  type: string
                  pattern: ^[a-z][a-z0-9_]{0,63}$
                  description: >-
                    Custom field key of the contact (lowercase letters, digits
                    and `_`, at most 64 characters).
                value:
                  type:
                    - string
                    - number
                    - boolean
                  description: Fixed value written to that field.
            - type: 'null'
          description: >-
            Fixed value written to a custom field of the contact when this
            outcome applies. Available through the API only.
    CampaignSequenceNode:
      type: object
      description: >-
        A call step: its own assistant, attempt schedule and outcomes. A step
        without `channel` is a call step.
      required:
        - id
        - name
        - attempts
        - no_response
        - other
      additionalProperties: false
      properties:
        id:
          type: string
          pattern: ^[a-z0-9][a-z0-9_-]{0,39}$
          description: Unique id across every node and outcome of the sequence.
        name:
          type: string
          minLength: 1
          maxLength: 60
          description: Name shown in the web app and the analytics.
        channel:
          type: string
          const: phone_call
          description: '`phone_call`, or absent: this step dials the contact.'
        assistant_id:
          type:
            - string
            - 'null'
          format: uuid
          description: >-
            Assistant that dials this node. Must belong to your workspace and be
            enabled. `null` or absent uses the campaign's assistant.
        attempts:
          type: array
          minItems: 1
          maxItems: 10
          items:
            $ref: '#/components/schemas/CampaignSequenceAttempt'
          description: Call attempts of this node (1 to 10).
        outcomes:
          type: array
          maxItems: 10
          items:
            $ref: '#/components/schemas/CampaignSequenceOutcome'
          description: >-
            Outcomes evaluated after an answered call, in order (0 to 10). Do
            not call is detected automatically and takes priority.
        no_response:
          type: object
          required:
            - destination
          additionalProperties: false
          description: Every attempt went unanswered or reached a voicemail.
          properties:
            destination:
              oneOf:
                - $ref: '#/components/schemas/CampaignSequenceNodeDestination'
                - $ref: '#/components/schemas/CampaignSequenceEndDestination'
              description: Another node or the end. It can never be `retry`.
        other:
          type: object
          required:
            - destination
          additionalProperties: false
          description: The call was answered but none of the outcomes matched.
          properties:
            destination:
              $ref: '#/components/schemas/CampaignSequenceDestination'
              description: Another node, a retry or the end.
    CampaignSequenceMessageNode:
      type: object
      description: >-
        A message step: sends one SMS, WhatsApp template or email, optionally
        waits for a reply, and moves the contact on.
      required:
        - id
        - name
        - channel
        - message
      additionalProperties: false
      properties:
        id:
          type: string
          pattern: ^[a-z0-9][a-z0-9_-]{0,39}$
          description: Unique id across every node and outcome of the sequence.
        name:
          type: string
          minLength: 1
          maxLength: 60
          description: Name shown in the web app and the analytics.
        channel:
          type: string
          enum:
            - sms
            - whatsapp_template
            - email
          description: What the step sends.
        assistant_id:
          type:
            - string
            - 'null'
          format: uuid
          description: >-
            Only used by `email` steps: the email leaves from this assistant's
            verified address. Must belong to your workspace and be enabled.
            `null` or absent uses the campaign's assistant.
        message:
          $ref: '#/components/schemas/CampaignSequenceMessage'
      example:
        id: sms_reminder
        name: SMS reminder
        channel: sms
        assistant_id: null
        message:
          config:
            from_number_id: 6f2c1a52-8d3b-4c47-9a3e-1b7d5e0c9a11
            message: >-
              Hi {{name}}, we tried to reach you. Reply to this message and we
              will call you back.
            variable_mapping: {}
          wait_minutes: 1440
          next:
            type: end
            successful: false
          replied:
            type: end
            successful: true
          failed:
            type: end
            successful: false
    CampaignSequenceCondition:
      description: >-
        When an outcome applies: an AI judgement of the transcript (`prompt`) or
        preset rules on call data (`rules`).
      oneOf:
        - $ref: '#/components/schemas/CampaignSequencePromptCondition'
        - $ref: '#/components/schemas/CampaignSequenceRulesCondition'
    CampaignSequenceEndDestination:
      type: object
      description: Finish the sequence for this contact.
      required:
        - type
        - successful
      additionalProperties: false
      properties:
        type:
          type: string
          const: end
          description: Destination kind.
        successful:
          type: boolean
          description: '`true` counts the contact as converted in the analytics.'
    CampaignSequenceAttempt:
      type: object
      description: One call attempt of a node.
      required:
        - delay_minutes
      additionalProperties: false
      properties:
        delay_minutes:
          type: integer
          minimum: 0
          maximum: 43200
          description: >-
            The first attempt must be `0` (immediately). Later attempts start
            this many minutes (at least 1, at most 43200) after the previous
            attempt started.
        voicemail:
          anyOf:
            - $ref: '#/components/schemas/CampaignSequenceVoicemail'
            - type: 'null'
          description: >-
            Voicemail handling for this attempt. `null` or absent uses the
            campaign's voicemail settings.
    CampaignSequenceOutcome:
      type: object
      description: A result of an answered call and where the contact goes next.
      required:
        - id
        - label
        - condition
        - destination
      additionalProperties: false
      properties:
        id:
          type: string
          pattern: ^[a-z0-9][a-z0-9_-]{0,39}$
          description: >-
            Unique id across every node and outcome of the sequence. Not
            `do_not_call`, `no_response`, `other`, `sent`, `replied` or
            `not_sent`: the platform produces those itself.
        label:
          type: string
          minLength: 1
          maxLength: 60
          description: Name shown in the contact list and the analytics.
        condition:
          $ref: '#/components/schemas/CampaignSequenceCondition'
        destination:
          $ref: '#/components/schemas/CampaignSequenceDestination'
          description: Where the contact goes when this outcome applies.
        save_to_field:
          anyOf:
            - type: object
              required:
                - key
                - value
              additionalProperties: false
              properties:
                key:
                  type: string
                  pattern: ^[a-z][a-z0-9_]{0,63}$
                  description: >-
                    Custom field key of the contact (lowercase letters, digits
                    and `_`, at most 64 characters).
                value:
                  type:
                    - string
                    - number
                    - boolean
                  description: Fixed value written to that field.
            - type: 'null'
          description: >-
            Fixed value written to a custom field of the contact when this
            outcome applies. Available through the API only.
        delay_minutes:
          type: integer
          minimum: 0
          maximum: 43200
          description: >-
            Minutes before the first attempt of the next node. Only with a
            `node` destination. After an answered call the dialer waits at least
            5 minutes. At most 43200 (30 days).
    CampaignSequenceNodeDestination:
      type: object
      description: Continue with another node of the sequence.
      required:
        - type
        - node_id
      additionalProperties: false
      properties:
        type:
          type: string
          const: node
          description: Destination kind.
        node_id:
          type: string
          pattern: ^[a-z0-9][a-z0-9_-]{0,39}$
          description: >-
            Id of an existing node. A node can never lead back to itself or to
            an earlier node.
    CampaignSequenceDestination:
      description: >-
        Where a contact goes next: another node, the next attempt of the same
        node, or the end.
      oneOf:
        - $ref: '#/components/schemas/CampaignSequenceNodeDestination'
        - $ref: '#/components/schemas/CampaignSequenceRetryDestination'
        - $ref: '#/components/schemas/CampaignSequenceEndDestination'
    CampaignSequenceMessage:
      type: object
      description: What a message step sends and where the contact goes afterwards.
      required:
        - config
        - wait_minutes
        - next
        - failed
      additionalProperties: false
      properties:
        config:
          oneOf:
            - $ref: '#/components/schemas/CampaignSequenceSmsConfig'
            - $ref: '#/components/schemas/CampaignSequenceSmsCompanySenderConfig'
            - $ref: '#/components/schemas/CampaignSequenceWhatsAppConfig'
            - $ref: '#/components/schemas/CampaignSequenceEmailConfig'
          description: >-
            The message. Its shape follows the `channel` of the step: `sms` (a
            workspace number or a company sender), `whatsapp_template` or
            `email`.
        wait_minutes:
          type: integer
          minimum: 0
          maximum: 43200
          description: >-
            Minutes to wait after the message went out before the contact moves
            on (0 to 43200). `0` moves on right away.
        next:
          $ref: '#/components/schemas/CampaignSequenceRouteDestination'
          description: >-
            Where the contact goes when the wait is over and no reply was seen.
            Another node or the end; it can never be `retry`.
        replied:
          anyOf:
            - $ref: '#/components/schemas/CampaignSequenceRouteDestination'
            - type: 'null'
          description: >-
            Optional. Where the contact goes when it answered on this channel
            during the wait. Needs a `wait_minutes` of at least 1. `null` or
            absent: replies are not watched. A contact that opted out is never
            counted as replied.
        failed:
          $ref: '#/components/schemas/CampaignSequenceRouteDestination'
          description: >-
            Where the contact goes when the message could not be sent: no
            address on file, opted out of the channel, or the provider rejected
            it. Another node or the end.
    CampaignSequencePromptCondition:
      type: object
      description: >-
        An AI reads the call transcript and decides whether this description
        fits best.
      required:
        - type
        - description
      additionalProperties: false
      properties:
        type:
          type: string
          const: prompt
          description: Condition kind.
        description:
          type: string
          minLength: 1
          maxLength: 500
          description: >-
            What the contact said or did, for example "The contact is open to
            the offer but wants to think it over".
    CampaignSequenceRulesCondition:
      type: object
      description: Preset rules checked against call data without AI.
      required:
        - type
        - match
        - rules
      additionalProperties: false
      properties:
        type:
          type: string
          const: rules
          description: Condition kind.
        match:
          type: string
          enum:
            - all
            - any
          description: '`all`: every rule must hold. `any`: one rule is enough.'
        rules:
          type: array
          minItems: 1
          maxItems: 10
          items:
            $ref: '#/components/schemas/CampaignSequenceRule'
          description: The rules to check (1 to 10).
    CampaignSequenceVoicemail:
      type: object
      description: What an attempt does when it reaches a voicemail.
      required:
        - action
      additionalProperties: false
      properties:
        action:
          type: string
          enum:
            - hangup
            - drop_message
          description: Hang up, or speak `message` to the voicemail.
        message:
          type:
            - string
            - 'null'
          minLength: 1
          maxLength: 1000
          description: >-
            Text spoken to the voicemail. Required with `drop_message` (1 to
            1000 characters); dynamic `{{variables}}` are allowed.
    CampaignSequenceRetryDestination:
      type: object
      description: >-
        Run the next attempt of the same node. When no attempt is left, the
        node's `no_response` destination applies.
      required:
        - type
      additionalProperties: false
      properties:
        type:
          type: string
          const: retry
          description: Destination kind.
    CampaignSequenceSmsConfig:
      type: object
      description: >-
        What an SMS step sends from a workspace number. To send under a company
        name (RCS) use `CampaignSequenceSmsCompanySenderConfig` instead.
      required:
        - from_number_id
        - message
      additionalProperties: false
      properties:
        from_number_id:
          type: string
          format: uuid
          description: >-
            Phone number the SMS is sent from. It must belong to your workspace
            and be an SMS-capable number with outbound SMS enabled.
        rcs_sender_id:
          anyOf:
            - type: 'null'
            - type: string
              pattern: ^\s*$
          description: >-
            Not used by a step that sends from a number: leave it out, or send
            `null` or an empty string.
        message:
          type: string
          minLength: 1
          maxLength: 1600
          description: >-
            Text of the SMS (1 to 1,600 characters). Dynamic `{{variables}}` are
            filled from the contact.
        variable_mapping:
          type: object
          additionalProperties:
            type: string
          description: Maps a `{{placeholder}}` of the message to a contact variable.
      example:
        from_number_id: 6f2c1a52-8d3b-4c47-9a3e-1b7d5e0c9a11
        message: >-
          Hi {{name}}, we tried to reach you. Reply to this message and we will
          call you back.
        variable_mapping: {}
    CampaignSequenceSmsCompanySenderConfig:
      type: object
      description: >-
        What an SMS step sends under a company name (RCS sender). Give
        `rcs_sender_id` or `from_number_id`, never both. The sender must be
        approved and ready to send, and the plan must include RCS; a recipient
        the sender cannot reach (country, number) counts as not sent.
      required:
        - rcs_sender_id
        - message
      additionalProperties: false
      properties:
        rcs_sender_id:
          type: string
          format: uuid
          description: >-
            Company sender (RCS) of your workspace, as listed under Settings >
            Channels > SMS & RCS. It must be approved and ready to send.
        from_number_id:
          anyOf:
            - type: 'null'
            - type: string
              pattern: ^\s*$
          description: >-
            Not used by a step that sends under a company name: leave it out, or
            send `null` or an empty string. A number as well as a company name
            is refused.
        message:
          type: string
          minLength: 1
          maxLength: 1600
          description: >-
            Text of the message (1 to 1,600 characters). Dynamic `{{variables}}`
            are filled from the contact.
        variable_mapping:
          type: object
          additionalProperties:
            type: string
          description: Maps a `{{placeholder}}` of the message to a contact variable.
      example:
        rcs_sender_id: 3d9a7c10-6b4e-4f58-b2a7-9e1c5d8f0a42
        message: >-
          Hi {{name}}, we tried to reach you. Reply to this message and we will
          call you back.
        variable_mapping: {}
    CampaignSequenceWhatsAppConfig:
      type: object
      description: What a WhatsApp step sends.
      required:
        - connector_id
        - template_id
      additionalProperties: false
      properties:
        connector_id:
          type: string
          format: uuid
          description: >-
            The WhatsApp sender (messaging connector) of your workspace. It must
            be active.
        template_id:
          type: string
          format: uuid
          description: >-
            An approved text template of that sender. Templates that need media,
            a dynamic button link or a copy code cannot be sent.
        variable_mapping:
          type: object
          additionalProperties:
            type: string
          description: >-
            Maps each `{{placeholder}}` of the template to a contact variable.
            Every placeholder needs a mapping.
      example:
        connector_id: 0b5e8f0e-3c52-4a9f-8f7a-2d4c6b1e9a30
        template_id: a41d9c77-52e0-4d8b-b8a1-7c3f0e5d2b64
        variable_mapping:
          '1': name
    CampaignSequenceEmailConfig:
      type: object
      description: >-
        What an email step sends. The email leaves from the verified address of
        the step's assistant (or the campaign's assistant).
      required:
        - subject
        - message
      additionalProperties: false
      properties:
        subject:
          type: string
          minLength: 1
          maxLength: 200
          description: >-
            Subject line (1 to 200 characters). Dynamic `{{variables}}` are
            filled from the contact.
        message:
          type: string
          minLength: 1
          maxLength: 10000
          description: >-
            Body of the email (1 to 10,000 characters). Dynamic `{{variables}}`
            are filled from the contact.
        variable_mapping:
          type: object
          additionalProperties:
            type: string
          description: >-
            Maps a `{{placeholder}}` of the subject or message to a contact
            variable.
      example:
        subject: Your appointment
        message: Hi {{name}}, here is a short summary of our call.
        variable_mapping: {}
    CampaignSequenceRouteDestination:
      description: >-
        Where a contact goes after a message step: another node or the end.
        Never `retry`.
      oneOf:
        - $ref: '#/components/schemas/CampaignSequenceNodeDestination'
        - $ref: '#/components/schemas/CampaignSequenceEndDestination'
    CampaignSequenceRule:
      type: object
      description: One comparison against call data, evaluated in code (no AI).
      required:
        - variable
        - operator
      additionalProperties: false
      properties:
        variable:
          type: string
          minLength: 1
          maxLength: 80
          description: >-
            A built-in variable (`call_status`, `answered`, `amd_result`,
            `duration_sec`, `success`, `sentiment`, `engagement_outcome`,
            `transfer_completed`, `callback_scheduled`, `attempt`), the name of
            a post-call analysis field, or `contact.<field_key>` for a custom
            field of the contact (lowercase letters, digits and `_`).
        operator:
          type: string
          enum:
            - eq
            - neq
            - gt
            - gte
            - lt
            - lte
            - contains
            - not_contains
            - exists
            - not_exists
          description: >-
            Comparison. `gt`, `gte`, `lt` and `lte` need a number as `value`;
            `exists` and `not_exists` take no `value`.
        value:
          type:
            - string
            - number
            - boolean
          maxLength: 200
          description: >-
            Value to compare with. Required for every operator except `exists`
            and `not_exists`. Text is 1 to 200 characters.
  responses:
    BadRequest:
      description: Invalid request body or parameters.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
          example:
            error:
              code: invalid_request
              message: '"to_number" is required (E.164 format, e.g. +4930123456).'
    Unauthorized:
      description: Missing, invalid, expired or revoked API key / access token.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
          example:
            error:
              code: unauthorized
              message: Invalid API key.
    Forbidden:
      description: >-
        The credential lacks the required scope or role, or the workspace does
        not have the required capability.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
          examples:
            scopeDenied:
              summary: Required scope is missing
              value:
                error:
                  code: forbidden
                  message: >-
                    This API key is missing the required scope
                    "assistants:write".
            apiAccessRequired:
              summary: API Access is not available
              value:
                error:
                  code: api_access_required
                  message: >-
                    API Access is not available for this workspace. Review
                    Settings → Plan.
    NotFound:
      description: Resource not found (or it belongs to another workspace).
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
          example:
            error:
              code: not_found
              message: Assistant not found
    RateLimited:
      description: Too many requests. Retry after the indicated delay.
      headers:
        Retry-After:
          description: Seconds to wait before retrying.
          schema:
            type: integer
            minimum: 1
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
          example:
            error:
              code: rate_limited
              message: Too many requests. Retry after the indicated delay.
    CampaignOrProtectionUnavailable:
      description: >-
        Either request protection is temporarily unavailable (code
        `internal_error`), or the campaign dialer feature is not available yet
        (code `service_unavailable`; write operations add the reason
        `campaign_extension_unavailable`). Retry after a short delay in both
        cases.
      headers:
        Retry-After:
          description: Seconds to wait before retrying.
          schema:
            type: integer
            minimum: 1
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
          examples:
            requestProtectionUnavailable:
              summary: Request protection unavailable
              value:
                error:
                  code: internal_error
                  message: Request protection is temporarily unavailable.
            campaignFeatureUnavailable:
              summary: Campaign dialer not available yet
              value:
                error:
                  code: service_unavailable
                  message: This campaign feature is not available yet.
                  reason: campaign_extension_unavailable
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: API key
      description: >-
        API key (`fam_...`, created under **Settings → API Keys**) or an OAuth
        2.0 access token (`fam_at_...`). REST operations also require API Access
        for the credential's workspace. Keys can be restricted to scopes such as
        `assistants:read`, `calls:write`, `campaigns:write`, `automations:read`,
        `dashboards:read`, `dashboards:write`, `leads:write`, `segments:write`,
        `loop:read`, `loop:write`, `phone_numbers:write`, `sip_trunks:write`,
        `knowledge:write`, `voices:read`, `billing:read`, `billing:write`,
        `settings:write`, `platform:read`, `platform:write`; a `*:write` scope
        implies the matching `*:read`. Automation and dashboard endpoints also
        accept the legacy `calls:*` scope. Keys without scope restrictions have
        full access within the workspace's available capabilities.

````

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