---
title: "Change a campaign's settings"
method: PATCH
path: "/api/v1/campaigns/{id}"
---

# Change a campaign's settings

`PATCH /api/v1/campaigns/{id}`

## Request

- Base URL: `https://www.easeclaw.com`
- URL: `https://www.easeclaw.com/api/v1/campaigns/{id}`
- Auth: HTTP bearer

Its targeting, pacing, handoff, booking link, or who approves. Message text and the waits between steps are NOT settings. They belong to the campaign's playbook, whose single writer is the playbook builder, so invite_note_mode, invite_note_template, first_message_template and accept_wait_days are refused here. The campaign's status, project and source are not editable here either. Use the stop endpoint to stop it. A finished campaign answers 409: its settings are the record of what it ran with. Rate-limited to 60/hour per account, shared with the dashboard. Requires an outreach-scope API key (Pro plan or higher).

## Path parameters

- `id` string, uuid, required

## Request body

- object
  - `name` string
  - `mode` 'autopilot' | 'copilot': Who approves what goes out: autopilot: the agent approves inside the owner's limits; copilot: every batch waits for the owner. Neither mode is reachable from this API: it decides who approves, and this surface is not either of them.
  - `followup_wait_days` integer
  - `withdraw_after_days` integer, nullable: Withdraw invitations unanswered this long. null turns auto-withdraw off.
  - `email_handoff_enabled` boolean
  - `email_handoff_campaign_id` string, nullable
  - `meeting_link` string, uri, nullable
  - `signal_min_score` integer
  - `icp` object, nullable: null resets targeting to the project's ICP
  - `goal` 'meeting' | 'reply' | 'share_link' | 'null', nullable: What the AI writes toward. null = not set.
  - `tone` 'friendly' | 'professional' | 'direct' | 'casual' | 'null', nullable: null = not set.
  - `language` 'en-US' | 'en-GB' | 'fr' | 'de' | 'es' | 'nl' | 'null', nullable: The language the AI writes in. null = follow the prospect's own language.
  - `exclude_first_degree` boolean: Skip people you're already connected with on LinkedIn.
  - `split_messages` boolean: Stored only. Not acted on yet.
  - `email_fallback_days` integer, nullable: Stored only. null = off. The playbook's waits decide when an email step runs.

## Response `200`

The campaign as it now stands

- object
  - `campaign` Campaign
    - `id` string, uuid
    - `project_id` string, uuid
    - `name` string
    - `source_type` 'competitor_harvest' | 'signal' | 'profile_urls' | 'csv' | 'basic_search' | 'sales_navigator' | 'recruiter' | 'my_network': Where a campaign's people come from. Defaults to competitor_harvest.
    - `source_ref` string, nullable: What this campaign sources from, per source_type. Null for signal campaigns (their source is the project) and for the multi-ref kinds, where provenance is recorded per person instead.
    - `source_params` object, nullable: basic_search only: the search descriptor it re-runs from
    - `signal_min_score` integer, nullable
    - `icp` object, nullable: This campaign's own targeting; null means it inherits the project's ICP
    - `status` 'draft' | 'sourcing' | 'review' | 'active' | 'paused' | 'done' | 'stopped'
    - `mode` 'autopilot' | 'copilot': Who approves what goes out: autopilot: the agent approves inside the owner's limits; copilot: every batch waits for the owner. Neither mode is reachable from this API: it decides who approves, and this surface is not either of them.
    - `invite_note_mode` 'none' | 'custom'
    - `invite_note_template` string, nullable
    - `first_message_template` string, nullable
    - `accept_wait_days` integer
    - `followup_wait_days` integer
    - `withdraw_after_days` integer, nullable: null = auto-withdraw off
    - `email_handoff_enabled` boolean
    - `email_handoff_campaign_id` string, nullable
    - `meeting_link` string, uri, nullable
    - `goal` 'meeting' | 'reply' | 'share_link' | 'null', nullable
    - `tone` 'friendly' | 'professional' | 'direct' | 'casual' | 'null', nullable
    - `language` 'en-US' | 'en-GB' | 'fr' | 'de' | 'es' | 'nl' | 'null', nullable
    - `exclude_first_degree` boolean
    - `split_messages` boolean
    - `email_fallback_days` integer, nullable: null = email fallback off
    - `daily_quota` integer, nullable
    - `created_at` string, date-time
    - `updated_at` string, date-time

## Other responses

- `400`: Error
- `401`: Error
- `402`: Error
- `403`: The key is not outreach-scoped (code outreach_scope_required). Campaign paths need a key minted with the outreach scope at https://www.easeclaw.com/leads/api. The scope cannot be widened on an existing key.
- `404`: Error
- `409`: Error
- `429`: Rate limited (300/hour per account; drafting also 30/hour + daily AI budget). Retry-After header set when known.
- `500`: Error

---

[API](https://skmtc.dev/easeclaw/apis/easeclaw-api.md) · [All operations](https://skmtc.dev/easeclaw/apis/easeclaw-api/llms.txt) · [OpenAPI document](https://skmtc.dev/easeclaw/apis/easeclaw-api/revisions/79a190b20f61?raw)
