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

# Update a campaign's settings

> Updates the campaign's shared settings block - name, start date, timezone and sending days, source and exclusion lists, enrollment exclusions, tracking, delegates and the {CTA Link} URL - and returns the campaign as stored. Every field is optional but at least one must be present. Changing `listIds` rewrites the source-list set; it does not by itself enroll a newly added list's contacts into a running campaign. Changing `campaignStartDate` reschedules the first step's still-pending sends, and changing `ctaLink` rewrites queued sends that carry the old link. Only the token owner's own campaigns can be updated: a campaign delegated to you, one shared by your team's visibility settings, and a deleted one all answer 404. Rate limit: 30 requests/minute and 1,000/day per token owner, shared by every campaign, scheduled-send, campaign-template and knowledge-hub endpoint.

Errors:
- `404` `CAMPAIGN_NOT_FOUND` — No campaign with this id exists, it belongs to another account (including a campaign delegated to you or shared by your team's visibility settings), or it has been deleted.
- `409` `CAMPAIGN_INITIALIZING` — listIds was sent while an ai-generated campaign's background initialization is still running, so its channels are not settled yet; poll GET /business/campaigns/{campaignId} until initializationStatus is completed or failed, then retry.
- `422` `LIST_INCOMPATIBLE_WITH_CHANNELS` — The listIds together have no contact usable by the campaign's steps: they are empty, or no contact carries an email address (email/inmail step) or a LinkedIn URL (LinkedIn step).
- `422` `EXCLUDE_COMPANY_LISTS_INVALID` — An excludeCompanyLists entry is not a non-archived company or people list owned by your team.
- `422` `VALIDATION_FAILED` — Empty body, unknown key, an unrecognised timezone, a non-http(s) ctaLink, or a value out of range; `param` names the field.
- `429` `RATE_LIMITED` — More than 30 campaign requests in a minute, or 1,000 in a day, for this token owner (the bucket is shared by every /business/campaigns, /business/scheduled-sends, /business/campaign-templates and /business/knowledge-hubs call).
- `500` `UNEXPECTED_ERROR` — An unhandled failure; the detail stays in our logs and is never returned.

Requires one of the following token scopes: campaigns.



## OpenAPI

````yaml /openapi.json patch /business/campaigns/{campaignId}
openapi: 3.1.0
info:
  title: Fuse Business API
  version: 1.0.0
  description: >-
    External API for lists, campaigns, prospect search and contacts.
    Authenticate with your API token as HTTP Basic. All paths are under /api/v1.
servers:
  - url: https://api.tryfuse.ai/api/v1
    description: Production
security:
  - basicAuth: []
tags:
  - name: Lists
  - name: Custom columns
  - name: Smart columns
  - name: Exports
  - name: Campaigns
  - name: Knowledge hubs
  - name: Analytics
  - name: Website intent
  - name: Account
  - name: Prospect search
  - name: Campaign steps
  - name: Scheduled sends
  - name: Campaign templates
  - name: Agents
  - name: Research
  - name: Company search
  - name: Saved searches
  - name: Folders
  - name: Contacts
paths:
  /business/campaigns/{campaignId}:
    patch:
      tags:
        - Campaigns
      summary: Update a campaign's settings
      description: >-
        Updates the campaign's shared settings block - name, start date,
        timezone and sending days, source and exclusion lists, enrollment
        exclusions, tracking, delegates and the {CTA Link} URL - and returns the
        campaign as stored. Every field is optional but at least one must be
        present. Changing `listIds` rewrites the source-list set; it does not by
        itself enroll a newly added list's contacts into a running campaign.
        Changing `campaignStartDate` reschedules the first step's still-pending
        sends, and changing `ctaLink` rewrites queued sends that carry the old
        link. Only the token owner's own campaigns can be updated: a campaign
        delegated to you, one shared by your team's visibility settings, and a
        deleted one all answer 404. Rate limit: 30 requests/minute and 1,000/day
        per token owner, shared by every campaign, scheduled-send,
        campaign-template and knowledge-hub endpoint.


        Errors:

        - `404` `CAMPAIGN_NOT_FOUND` — No campaign with this id exists, it
        belongs to another account (including a campaign delegated to you or
        shared by your team's visibility settings), or it has been deleted.

        - `409` `CAMPAIGN_INITIALIZING` — listIds was sent while an ai-generated
        campaign's background initialization is still running, so its channels
        are not settled yet; poll GET /business/campaigns/{campaignId} until
        initializationStatus is completed or failed, then retry.

        - `422` `LIST_INCOMPATIBLE_WITH_CHANNELS` — The listIds together have no
        contact usable by the campaign's steps: they are empty, or no contact
        carries an email address (email/inmail step) or a LinkedIn URL (LinkedIn
        step).

        - `422` `EXCLUDE_COMPANY_LISTS_INVALID` — An excludeCompanyLists entry
        is not a non-archived company or people list owned by your team.

        - `422` `VALIDATION_FAILED` — Empty body, unknown key, an unrecognised
        timezone, a non-http(s) ctaLink, or a value out of range; `param` names
        the field.

        - `429` `RATE_LIMITED` — More than 30 campaign requests in a minute, or
        1,000 in a day, for this token owner (the bucket is shared by every
        /business/campaigns, /business/scheduled-sends,
        /business/campaign-templates and /business/knowledge-hubs call).

        - `500` `UNEXPECTED_ERROR` — An unhandled failure; the detail stays in
        our logs and is never returned.


        Requires one of the following token scopes: campaigns.
      operationId: updateCampaign
      parameters:
        - name: campaignId
          in: path
          required: true
          description: >-
            The campaign's id (24-character hex ObjectId), as returned by POST
            /business/campaigns or as the campaignId of a GET
            /business/campaigns row.
          schema:
            type: string
            description: >-
              The campaign's id (24-character hex ObjectId), as returned by POST
              /business/campaigns or as the campaignId of a GET
              /business/campaigns row.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                campaignName:
                  type: string
                  minLength: 1
                  maxLength: 200
                  description: New display name (1-200 characters, trimmed).
                campaignStartDate:
                  type: string
                  description: >-
                    New ISO 8601 start date-time; the first step's still-pending
                    sends are rescheduled to it.
                timezone:
                  type: string
                  description: >-
                    New time zone in which the daily sending window and
                    emailDays are evaluated. Accepted values are IANA time zone
                    names, for example America/New_York, Europe/Berlin,
                    Asia/Kolkata or UTC. Do not send an abbreviation: EST is in
                    the tz database but resolves to a fixed UTC-5 zone that
                    never observes daylight saving, so name the region instead.
                    A name the tz database does not know is rejected rather than
                    silently evaluated as UTC.
                emailDays:
                  type: array
                  items:
                    type: string
                    enum:
                      - Monday
                      - Tuesday
                      - Wednesday
                      - Thursday
                      - Friday
                      - Saturday
                      - Sunday
                    description: >-
                      An English weekday name with a capital first letter
                      (Monday ... Sunday).
                  minItems: 1
                  description: >-
                    Replacement set of weekdays on which sends may go out. One
                    of exactly: Monday, Tuesday, Wednesday, Thursday, Friday,
                    Saturday, Sunday — capitalised English names, nothing else.
                    The days are OR-joined: a send that comes due is pushed
                    forward to the next day named in the set, so a weekday you
                    leave out is never used. 1-7 unique names; naming all seven
                    removes the weekday restriction.
                listIds:
                  type: array
                  items:
                    type: string
                    description: >-
                      A Fuse list id (24-character hex ObjectId), as the `id` of
                      a GET /business/lists row.
                  minItems: 1
                  maxItems: 10
                  description: >-
                    Replacement set of 1-10 source list ids; rewrites the
                    campaign's source-list set but does not by itself enroll a
                    newly added list's contacts into an already running
                    campaign. Take the ids from GET /business/lists with
                    entityType=contactList — a campaign enrolls contacts. The
                    lists are OR-joined into a deduplicated union: they are read
                    in the order given and a contact that sits in two of them is
                    enrolled once, up to the campaign's 10000-contact cap, after
                    which the remaining lists are skipped. This endpoint stores
                    the ids without an ownership check (create answers 404
                    LIST_NOT_FOUND for one it cannot resolve), so an id that is
                    not one of your lists is accepted here and simply
                    contributes nobody. Like create, the lists together must
                    have at least one contact with an enriched professional
                    email for an email step and one with a LinkedIn profile for
                    a LinkedIn step, else 422 LIST_INCOMPATIBLE_WITH_CHANNELS.
                    The check reads the campaign's actual steps, so an
                    ai-generated campaign whose initializationStatus is not yet
                    completed or failed answers 409 CAMPAIGN_INITIALIZING; poll
                    and retry.
                excludeLists:
                  type: array
                  items:
                    type: string
                    description: >-
                      A Fuse list id (24-character hex ObjectId), as the `id` of
                      a GET /business/lists row.
                  maxItems: 10
                  description: >-
                    Replacement set of up to 10 people-list ids whose members
                    are excluded from future enrollment. Take the ids from GET
                    /business/lists with entityType=contactList. The lists are
                    OR-joined: a contact is skipped when it appears in any one
                    of them, matched on contact id, email address
                    (case-insensitively) or LinkedIn URL. These ids are stored
                    without an ownership check, so an id that is not one of your
                    lists is accepted and silently excludes nobody — and a
                    companyList here excludes nobody either, use
                    excludeCompanyLists for that.
                excludeCompanyLists:
                  type: array
                  items:
                    type: string
                    description: >-
                      A Fuse list id (24-character hex ObjectId), as the `id` of
                      a GET /business/lists row.
                  maxItems: 20
                  description: >-
                    Replacement set of up to 20 company or people list ids whose
                    companies' contacts are skipped at enrollment. Take the ids
                    from GET /business/lists — either entityType: a companyList
                    contributes its companies, a contactList contributes the
                    companies its contacts work at. The lists are OR-joined: a
                    contact is skipped when its company appears in any one of
                    them, matched by company id and by the company's web domain
                    (personal-email domains are never used). Unlike excludeLists
                    these ids are checked, so one that is unknown, archived or
                    not your team's answers 422 EXCLUDE_COMPANY_LISTS_INVALID.
                excludeContacted:
                  type: string
                  enum:
                    - none
                    - ever
                    - last_1_month
                    - last_3_months
                    - last_6_months
                    - last_1_year
                  description: >-
                    Skips contacts your campaigns already reached: none keeps
                    them, ever excludes anyone ever messaged, last_1_month /
                    last_3_months / last_6_months / last_1_year exclude those
                    messaged within that window; contacts with a pending send in
                    an active campaign are always excluded. Applies to future
                    enrollment only.
                excludeEngagedContacts:
                  type: boolean
                  description: >-
                    When true, contacts who have already replied to one of your
                    campaigns are excluded from enrollment. Applies to future
                    enrollment only.
                isDynamic:
                  type: boolean
                  description: >-
                    When true, contacts added to the source lists after
                    activation are enrolled automatically by a background
                    refresh.
                useLinkedinPosts:
                  type: boolean
                  description: >-
                    When true, each contact's recent LinkedIn posts are fetched
                    at activation and fed to AI personalization (needs a
                    LinkedIn URL on the contact).
                addUnsubscribeLink:
                  type: boolean
                  description: >-
                    When true, every email step appends a one-click unsubscribe
                    footer (email channel only).
                openRateTrackingEnabledAt:
                  type:
                    - string
                    - 'null'
                  description: >-
                    ISO 8601 timestamp from which the open-tracking pixel is
                    added to outgoing emails, or null to switch open tracking
                    off.
                sendOnlyToValidatedEmailsEnabledAt:
                  type:
                    - string
                    - 'null'
                  description: >-
                    ISO 8601 timestamp from which enrollment only accepts
                    contacts whose email verified as valid (catch-all and
                    never-verified uploaded addresses skipped), or null to also
                    allow both. Applies to future enrollment only.
                delegates:
                  type: array
                  items:
                    type: string
                    description: >-
                      A Fuse user id (24-character hex ObjectId) of a teammate,
                      as the `id` of a GET /business/team/members row.
                  description: >-
                    Replacement list of teammate user ids allowed to view and
                    edit this campaign in the app; [] revokes every delegate.
                    Take each id from the `id` of a GET /business/team/members
                    row (a row whose id is null has no linked user account and
                    cannot be a delegate). Access is OR-joined — any one of the
                    listed users gets it — and there is no cap on how many you
                    list. Nothing checks the ids against your team on the way
                    in, and the app's delegate test is a plain membership check
                    on this array that runs ahead of every team rule, so an id
                    belonging to any real Fuse user — teammate or not — grants
                    that user the access the owner has: opening the campaign,
                    editing its settings and steps, activating it so it sends,
                    and seeing it in their own campaign list. Only a well-formed
                    id that matches no user grants nobody anything. The grant
                    stops at the app: every campaign endpoint here resolves the
                    token owner's own campaigns, so a delegate calling with
                    their own key still gets 404.
                ctaLink:
                  type:
                    - string
                    - 'null'
                  maxLength: 2000
                  description: >-
                    New call-to-action link, or null / an empty string to clear
                    it; queued sends that already carry the old link are
                    rewritten to the new one. Accepted values: one absolute URL
                    whose scheme is http:// or https:// (up to 2000 characters);
                    anything else, a bare domain or a mailto: link included, is
                    rejected. The URL is inserted verbatim wherever a step's
                    text uses {CTA Link} or one of its aliases {Calendar Link},
                    {cta_link}, {calendar_link}, {{calendarLink}}.
      responses:
        '200':
          description: Success
          headers:
            RateLimit-Limit:
              schema:
                type: integer
              description: Requests permitted in the current window.
            RateLimit-Remaining:
              schema:
                type: integer
              description: Requests remaining in the current window.
            RateLimit-Reset:
              schema:
                type: integer
              description: Seconds until the current window resets.
          content:
            application/json:
              schema:
                type: object
                properties:
                  campaign:
                    type: object
                    properties:
                      id:
                        type: string
                        description: The campaign's id.
                      name:
                        type:
                          - string
                          - 'null'
                        description: Display name.
                      type:
                        type:
                          - string
                          - 'null'
                        enum:
                          - manual
                          - ai-generated
                          - null
                        description: Which creation flow the campaign uses.
                      status:
                        type:
                          - string
                          - 'null'
                        enum:
                          - initializing
                          - active
                          - stopped
                          - paused_manual
                          - initialization_failed
                          - null
                        description: Lifecycle status.
                      initializationStatus:
                        type:
                          - string
                          - 'null'
                        enum:
                          - processing
                          - completed
                          - failed
                          - null
                        description: >-
                          Draft-preparation state. A manual campaign is
                          completed from the start; an ai-generated one reaches
                          completed when background topic generation finishes.
                      initializationError:
                        type:
                          - string
                          - 'null'
                        description: >-
                          Our own status text when initializationStatus is
                          failed; null otherwise.
                      listIds:
                        type: array
                        items:
                          type: string
                        description: Ids of the lists the campaign sources contacts from.
                    required:
                      - id
                      - name
                      - type
                      - status
                      - initializationStatus
                      - initializationError
                      - listIds
                required:
                  - campaign
              example:
                campaign:
                  id: 6a8dd1205936d46e458ff40a
                  name: Q3 fintech outreach (US)
                  type: manual
                  status: active
                  initializationStatus: completed
                  initializationError: null
                  listIds:
                    - 6a1edba88936e0fe1b20287c
        '400':
          description: Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '402':
          description: Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '403':
          description: Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '409':
          description: Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '422':
          description: Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '429':
          description: Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '500':
          description: Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
      security:
        - basicAuth: []
components:
  schemas:
    Error:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
            message:
              type: string
            param:
              type:
                - string
                - 'null'
            doc_url:
              type:
                - string
                - 'null'
            request_id:
              type:
                - string
                - 'null'
          required:
            - code
            - message
      required:
        - error
  securitySchemes:
    basicAuth:
      type: http
      scheme: basic
      description: >-
        Your API token (`af_…`) as the Basic-auth username, with an empty
        password.

````