---
title: campaign_plan_create
description: 'Write down what you intend to run — on which channels, for whom, for how much, over what period.'
---

Creates a **Campaign Plan**: a statement of intent you can sum, execute, and later compare against what actually ran.

:::warning[A Campaign Plan is not a provider campaign]

It is AdCrunch's own planning document — written before anything is bought, and possibly executed into several campaigns, or none. For campaigns that exist on Meta or Google, use [`list_entities`](/mcp/tools/list-entities) and [`get_entity`](/mcp/tools/get-entity).

:::

## Input

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `name` | `string` | yes | Display name, e.g. `"Q4 Acquisition"`. |
| `description` | `string` | yes | One-line summary used to pick this plan from a list. |
| `currency` | `string` | yes | ISO 4217. Changeable until a Line Item carries a budget. |
| `slug` | `string` | no | Explicit handle; normalized to kebab-case. Defaults to one derived from the name. |
| `brand_name` | `string` | no | The brand this plan is for. A plan may precede its brand, or cover several. |
| `total_budget` | `number` | no | The envelope, in **whole units** of the currency. Omit for "no declared constraint". |
| `start_date` / `end_date` | `YYYY-MM-DD` | no | Either may be omitted. No end date means always-on. |
| `rationale` | `string` | no | The argument for the split — what a reviewer approves. |
| `measurement` | `string` | no | How success will be judged. |

## Example

```ts
campaign_plan_create({
  name: 'Q4 Acquisition',
  description: 'Prospecting across Meta and TikTok, Oct–Dec.',
  currency: 'EUR',
  total_budget: 100_000, // €100,000.00
  start_date: '2026-10-01',
  end_date: '2026-12-31',
  rationale: 'Meta carries the proven CPA; TikTok is a 30% test we can cut.',
});
// → { campaignPlan: { slug: 'q4-acquisition', status: 'draft', revision: 1, … } }
```

:::warning[Amounts are whole units]

Send `40.5` for €40.50, never `4050`. An amount with more decimals than the currency has is refused rather than rounded: `40.505` in euros, or `50.5` in yen.

:::

:::tip[Almost everything is optional]

A plan is authored incrementally. The window, the budget and the brand can all arrive later — only the currency is required up front, because every amount written afterwards is read through it.

:::

Requires the `campaign_plan:write` scope.

## Reference

Create a Campaign Plan: what this organization intends to run, on which channels, for whom, for how much, over what period. Only a name, a description and a currency are required — the window, the budget envelope and the brand are all authored incrementally. Amounts are whole units of the plan’s currency: send 40.5 for €40.50, never 4050. The plan starts as a draft. A Campaign Plan is AdCrunch's own planning document — it is **not** a campaign on Meta or Google. For those, use list_entities and get_entity.

### Input

| Argument | Type | Required | Description |
| --- | --- | --- | --- |
| `brand_name` | string | no | The slug of the brand this plan is for. Optional and changeable later — a plan may precede its brand, or cover several. |
| `currency` | string, 3 characters | yes | ISO 4217, e.g. EUR. Changeable until a Line Item carries a budget, frozen after that. |
| `description` | string | yes | One-line summary used to pick this plan from a list. |
| `end_date` | string | no | Omit for an always-on plan. Line Items inherit this when they set no end of their own — and a line with no effective end reads as a daily rate. |
| `measurement` | string | no | How success will be judged. |
| `name` | string | yes | Display name, e.g. "Q4 Acquisition". |
| `rationale` | string | no | The argument for the split — why this money goes to these channels. It is what a reviewer approves. |
| `slug` | string | no | Optional explicit slug handle; normalized to kebab-case. Defaults to one derived from the name. |
| `start_date` | string | no |  |
| `total_budget` | number, at least 0 | no | The envelope: what you have, in whole units of the plan currency (40.5 is 40.50). Omit for "no declared constraint" — which is not the same as zero. |

### Failure codes

A failed call has `isError` set, and `structuredContent.error` holds one of these codes. [Errors](/mcp/errors) describes the shape of a failed call.

- `not_found`
- `invalid_slug`
- `invalid_currency`
- `invalid_amount`
- `invalid_window`
- `slug_conflict`
- `forbidden`
- `invalid_request`
- `internal_error`

### Scope

The token must hold `campaign_plan:write`. [Auth & scopes](/mcp/auth) lists each scope.

### Annotations

A client reads these hints. A hint that the tool does not declare has the default value of the MCP specification.

- **Writes.** The tool can change data.
- **Destructive.** The tool can make a change that you cannot undo. A client can ask you to confirm before it calls the tool.
- **Not idempotent.** A second call with the same arguments can change more.
- **Closed world.** The tool reads and writes the data of AdCrunch only.
