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

# Campaign

> The unit of media planning: a brief, a flight, a budget, and the media buys that carry them out.

A **campaign** is where a buyer's plan lives. It holds the brief sellers read, the flight dates and
budget, any targeting, the creatives that run, and the media buys placed with each seller. Every
campaign belongs to exactly one [advertiser](/help/glossary#advertiser) and inherits its currency.

A campaign starts as a `DRAFT`. The draft is your **cart**: you add proposals and products to it and
stage media buys against it without contacting any seller. Launching turns the staged buys into real
AdCP transactions, one per seller.

## Key fields

<ResponseField name="campaignId" type="string" required>
  Stable id with the `cmp_` prefix.
</ResponseField>

<ResponseField name="advertiserId" type="integer" required>
  The advertiser that owns the campaign. The budget currency must match the advertiser's primary
  currency.
</ResponseField>

<ResponseField name="name" type="string" required>
  Display name, 1 to 200 characters.
</ResponseField>

<ResponseField name="brief" type="string">
  The plain-language description sellers read: goals, audience, channels, must-haves and
  constraints. Up to 20,000 characters. The better the brief, the better the proposals.
</ResponseField>

<ResponseField name="status" type="enum">
  `DRAFT`, `ACTIVE`, `PAUSED`, `COMPLETED`, `CANCELED` or `ARCHIVED`. See [lifecycle](#lifecycle).
</ResponseField>

<ResponseField name="management" type="enum">
  `managed` when Semicola places and runs the buys; `tracked` when the campaign mirrors buys placed
  elsewhere.
</ResponseField>

<ResponseField name="flight" type="object">
  `startAt` and `endAt`, both ISO 8601 date-times with an offset.
</ResponseField>

<ResponseField name="budget" type="object">
  `total` (decimal), `currency` (ISO 4217), `pacing` (`EVEN`, `ASAP` or `FRONTLOADED`) and an
  optional `dailyCap`.
</ResponseField>

<ResponseField name="allocatedBudget / unallocatedBudget" type="decimal string">
  How much of the total is committed to staged or live media buys, and how much is left. Allocated
  budget can never exceed the total.
</ResponseField>

<ResponseField name="targeting" type="object">
  Structured intent sent with the brief: `countries`, `channels`, `ageRange` (`min` 13 or more,
  `max` 99 or less), `audience` (free text) and `geoMetros`. Sellers that cannot honor part of it
  say so in their proposal.
</ResponseField>

<ResponseField name="autonomy" type="object">
  How much the agent may do without asking: `inventorySelection` and `rebriefing`, each `manual`,
  `propose` or `automatic`. Defaults come from the advertiser.
</ResponseField>

<ResponseField name="creativeFormats" type="object">
  Format coverage for launch: `required`, `covered` and `missing`.
</ResponseField>

<ResponseField name="mediaBuys" type="array">
  The campaign's media buys, one per seller (and settlement currency). See [media buys and
  packages](#media-buys-and-packages).
</ResponseField>

<ResponseField name="revision" type="integer" required>
  Increments on every change. Writes that modify a campaign send `expectedRevision`; a stale value
  fails with `REVISION_CONFLICT` so two agents never overwrite each other.
</ResponseField>

## Lifecycle

```text theme={null}
DRAFT --launch (confirmed)--> ACTIVE --pause--> PAUSED --reactivate--> ACTIVE
DRAFT | ACTIVE | PAUSED --cancel--> CANCELED
ACTIVE --flight over and every buy finished--> COMPLETED
any finished state --archive--> ARCHIVED
```

Pausing a campaign pauses every media buy on it. Reactivating is the only way back from `PAUSED`.

### Launch preconditions

A draft can launch when all of these hold:

* the advertiser is active and the budget currency matches its primary currency;
* at least one media buy is staged;
* allocated budget does not exceed the total;
* the required creative formats are covered, or you accept that some buys will wait for creatives;
* the account is allowed to buy live (otherwise only sandbox launches are possible).

The **Review & go live** widget (`open_campaign_receipt`) shows each of these as a checklist with any
blockers.

## Common operations

### Create a draft

<CodeGroup>
  ```json MCP (save_campaign) theme={null}
  {
    "advertiserId": 12,
    "name": "Holiday Wrenfield Push",
    "brief": "Reach gift shoppers aged 30 to 55 in the US with CTV, audio and display.",
    "flight": { "startAt": "2026-11-15T00:00:00-05:00", "endAt": "2026-12-31T23:59:59-05:00" },
    "budget": { "total": 50000, "currency": "USD", "pacing": "EVEN" },
    "targeting": { "countries": ["US"], "channels": ["ctv", "streaming_audio", "display"] },
    "idempotencyKey": "wrenfield-holiday-2026-create-01"
  }
  ```

  ```bash REST theme={null}
  curl -X POST https://api.semicola.com/api/v2/buyer/campaigns \
    -H "Authorization: Bearer $SEMICOLA_API_KEY" \
    -H "X-Account-Id: $ACCOUNT_ID" \
    -H "Idempotency-Key: wrenfield-holiday-2026-create-01" \
    -H "Content-Type: application/json" \
    -d '{"advertiserId": 12, "name": "Holiday Wrenfield Push", "budget": {"total": "50000", "currency": "USD"}}'
  ```
</CodeGroup>

If a required fact is missing (most often the currency), the tool answers with `needs_input` and a
question instead of guessing. Ask the person, then call again.

### Collect proposals and stage buys

1. `request_proposals` with `campaignId` and `expectedCampaignRevision` sends the brief to every
   eligible seller and returns an execution id straight away. Only one execution runs per buyer at a
   time.
2. Poll with `get` (`kind: "proposal"`) or watch the Proposals widget as sellers answer.
3. `refine_proposal` asks one seller for a revised version.
4. `save_media_buy` with `fromProposalId` stages the proposal's products as a draft media buy.

### Launch

Launching is deliberately two calls so a person can see the spend before it happens.

<Steps>
  <Step title="Ask to go live">
    Call `save_campaign` with `campaignId`, `expectedRevision` and `desiredPhase: "active"`. The
    result is `pending_confirmation`, with a summary of spend per seller and an expiry.
  </Step>

  <Step title="Get the person's approval">
    Show the summary. In the Semicola app and in MCP Apps hosts, a confirmation card does this for
    you.
  </Step>

  <Step title="Confirm">
    Call `save_campaign` again with `confirmLaunch: true` and the same `expectedRevision`. Semicola
    dispatches one AdCP `create_media_buy` per seller, each with its own idempotency key.
  </Step>
</Steps>

<Warning>
  A brief, a budget or a staged buy is never authority to spend. Agents must not set `confirmLaunch`
  without an explicit approval from the person they act for.
</Warning>

The launch result reports `mediaBuysExecuted` and a list of `errors`, one per failed buy, with a
`recovery` of `transient`, `correctable` or `terminal` and a `retrySafe` flag. Launching again
resubmits only the failed draft buys.

### Pause, reactivate, cancel, archive

Send `isPaused`, `desiredPhase: "canceled"` or `isArchived` to `save_campaign` with
`expectedRevision`. Over REST, use `POST /api/v2/buyer/campaigns/{id}/pause` and
`/reactivate`.

## Media buys and packages

A **media buy** is one AdCP transaction with one seller in one settlement currency. Its id starts
with `mb_`. A **package** (`pkg_`) is one product inside a media buy, with its own budget, pacing
(`even`, `asap` or `front_loaded`), optional bid price, flight and creatives.

| Media buy status       | Meaning                                                                                           |
| ---------------------- | ------------------------------------------------------------------------------------------------- |
| `DRAFT`                | Staged in the cart. No seller has seen it.                                                        |
| `PENDING_APPROVAL`     | Sent; the seller is reviewing it. `pendingAt` says whether the storefront or its source holds it. |
| `INPUT_REQUIRED`       | The seller needs something from you before it can continue.                                       |
| `ACTIVE`               | Accepted. It may still be waiting to start or waiting for creatives.                              |
| `PAUSED`               | Paused by you or by the campaign.                                                                 |
| `COMPLETED`            | The flight ended or the budget ran out.                                                           |
| `REJECTED`             | The seller declined it. The seller's reason is attached.                                          |
| `FAILED`               | Dispatch failed. Safe failures return to `DRAFT` on the next launch.                              |
| `CANCELED`, `ARCHIVED` | Stopped or filed away.                                                                            |

The campaign's **operational status** is the most restrictive status across its buys: one of
`no_media_buys`, `draft`, `pending_creatives`, `pending_start`, `active`, `paused`, `completed` or
`attention_required`. Read it from `GET /api/v2/buyer/campaigns/{id}/media-buy-status` or the campaign
workspace.

## Related

<CardGroup cols={2}>
  <Card title="Buying overview" icon="bullhorn" href="/buy/overview">
    The whole loop from brief to delivery.
  </Card>

  <Card title="v3 Tool Catalog" icon="toolbox" href="/v3/tool-catalog">
    Exact inputs for `save_campaign`, `request_proposals` and `save_media_buy`.
  </Card>

  <Card title="Errors" icon="triangle-exclamation" href="/v3/errors">
    Revision conflicts, `needs_input` and partial launches.
  </Card>

  <Card title="Glossary" icon="book" href="/help/glossary">
    Every term on this page, defined.
  </Card>
</CardGroup>
