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

# Create campaign

> Open a platform-managed draft or a separately gated directed media buy

`POST /api/v2/buyer/campaigns`

For `discovery` and `performance`, creates a campaign in `DRAFT` status for the
given advertiser. You set flight dates and budget up front; products, creatives,
and audiences attach afterward. The legacy `routingType` field is not a
campaign input; it is derived per media buy as compatibility metadata for the
current execution path and is independent of campaign mode, BYOA, protocol
connectivity, and settlement. Execute the campaign later to turn it into live
media buys.

For the separately enrolled directed-write alpha, the same endpoint forwards one
explicit AdCP media buy to a mapped, subscribed connection and projects the result
as a `directed` campaign. A directed campaign has no DRAFT planning or execute step.
Its create uses `decisionMode: "raw"` for buyer-authored pass-through (and
defaults to raw when omitted), or `decisionMode: "assisted"` plus an accepted
decision-plan reference. See [Plan a directed campaign](/v2/buyer/campaigns/tasks/plan-directed-campaign).

Every campaign budget is **GROSS**: `budget.total` is the all-in amount the buyer pays, with the Interchange fee inside it. Every budget downstream is gross too — media buy and package budgets allocate against `budget.total` directly, and the media/fee split is derived per media buy at the fee terms locked when that buy is created (readable via its `budget_breakdown` — see [Budgets and fees](/v2/concepts/budgets-and-fees)). There is no fee-model input at creation — the campaign object has no `feeType` field.

## Request

<CodeGroup>
  ```bash curl theme={null}
  curl -X POST https://api.interchange.io/api/v2/buyer/campaigns \
    -H "Authorization: Bearer $SCOPE3_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "advertiserId": 12345,
      "name": "Q2 2026 Tech Launch",
      "flightDates": { "startDate": "2026-05-15T00:00:00Z", "endDate": "2026-07-15T23:59:59Z" },
      "budget": { "total": 100000, "currency": "USD", "pacing": "EVEN" },
      "brief": "Premium video for tech-savvy professionals",
      "constraints": {
        "channels": ["ctv", "video"],
        "geo_countries": ["US", "CA"],
        "geo_metros": [{ "system": "nielsen_dma", "values": ["501", "803"] }],
        "language": ["en"]
      }
    }'
  ```

  ```json With pacing periods theme={null}
  {
    "advertiserId": 12345,
    "name": "Holiday Heavy-Up",
    "flightDates": { "startDate": "2026-11-01T00:00:00Z", "endDate": "2026-12-31T23:59:59Z" },
    "budget": { "total": 250000, "currency": "USD" },
    "pacingPeriods": {
      "mode": "weight",
      "periods": [
        { "label": "Pre-Black Friday", "start": "2026-11-01T00:00:00Z", "end": "2026-11-26T23:59:59Z", "weight": 1.0 },
        { "label": "Black Friday / Cyber Monday", "start": "2026-11-27T00:00:00Z", "end": "2026-12-02T23:59:59Z", "weight": 3.0 },
        { "label": "Holiday push", "start": "2026-12-03T00:00:00Z", "end": "2026-12-31T23:59:59Z", "weight": 1.5 }
      ]
    }
  }
  ```
</CodeGroup>

## Parameters

The table below describes platform-managed creation. See
[Directed campaigns](/v2/buyer/campaigns/directed-campaigns#create-and-update-through-the-connection)
for the strict `mode: "directed"` branch.

| Field           | Type   | Required | Notes                                                                                                                                                                                                                                                                                                                                                                                                        |
| --------------- | ------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `advertiserId`  | number | Yes      | Owning advertiser                                                                                                                                                                                                                                                                                                                                                                                            |
| `name`          | string | Yes      | Campaign name (max 255)                                                                                                                                                                                                                                                                                                                                                                                      |
| `flightDates`   | object | Yes      | `{ startDate, endDate }`, ISO 8601 dates                                                                                                                                                                                                                                                                                                                                                                     |
| `budget`        | object | Yes      | `{ total, currency?, dailyCap?, pacing? }`. `currency` defaults to the advertiser's primary currency when omitted. `pacing` is `EVEN`, `ASAP`, or `FRONTLOADED`                                                                                                                                                                                                                                              |
| `brief`         | string | No       | Free-text plan brief used to guide product selection                                                                                                                                                                                                                                                                                                                                                         |
| `constraints`   | object | No       | `channels` filter plus AdCP targeting overlay: `geo_countries`, `geo_metros`, `language`. Send only metro codes in `geo_metros`; use `resolve_targeting_dimension` when the buyer provides a name such as "LA DMA", and request `fields=geo_metro_names` on campaign reads when display labels are needed. Included labels return in `geo_metro_names`; excluded labels return in `geo_metro_names_exclude`. |
| `pacingPeriods` | object | No       | Time-windowed pacing. `mode` is `weight` or `budget`; `periods[]` each carry `label`, `start`, `end`, and `weight` (weight mode)                                                                                                                                                                                                                                                                             |

### Directed request (alpha)

A directed create requires `mode`, `advertiserId`, `connectionId`, `accountId`,
`name`, a 16–255 character root `idempotencyKey`, root `currency`, and an
explicit `mediaBuy`. The subscription must carry matching currency and
per-buy/account governance caps, and the customer must have both directed read
and write flags. `brief`, `flightDates`, campaign-level `budget`, and nested
`account`/`idempotency_key` fields are validation errors.

If the buyer starts with a brief, first call
[`plan_directed_campaign`](/v2/buyer/campaigns/tasks/plan-directed-campaign).
Review its controlled decisions or resolve its clarification codes, then put
only the approved explicit fields in this create request.
Murph and other typed-tool hosts expose the bounded assisted branch as the
`create_directed_campaign` named operation so plan, accept, and create all stay
within provider schema budgets.

TikTok's first write canary requires `mediaBuy.paused: true` and rejects creative
assignments or inline creatives. Use future dates as an additional precaution.
The media buy contains the AdCP `brand`, `total_budget`, and explicit
`packages`; use only product and pricing-option IDs returned by
[`list_directed_campaign_products`](/v2/buyer/campaigns/tasks/list-directed-campaign-products)
for this connected account. See the directed-campaign guide for a complete request.
TikTok packages may also carry canonical `catalogs[]` entries of type `offering`
or `job`; unsupported catalog types fail before provider dispatch.

## Response

```json theme={null}
{
  "campaign": {
    "campaignId": "cmp_987654321",
    "advertiserId": "12345",
    "name": "Q2 2026 Tech Launch",
    "status": "DRAFT",
    "flightDates": { "startDate": "2026-05-15T00:00:00Z", "endDate": "2026-07-15T23:59:59Z" },
    "budget": { "total": 100000, "currency": "USD", "pacing": "EVEN" },
    "optimizationApplyMode": "MANUAL",
    "createdAt": "2026-05-01T09:00:00Z",
    "updatedAt": "2026-05-01T09:00:00Z"
  }
}
```

The campaign is created in `status: "DRAFT"`. `campaign.campaignId` is the stable identifier you pass to every sibling operation. Routing is decided per media buy at execution time — a campaign has no routing type of its own. When the request included a `discoveryId`, the response also carries `productGroups`, `budgetContext`, and `summary` from the discovery session.

For a directed create that reconciles synchronously, the response is
`{ campaign, directedWrite }`; `directedWrite.status` is `CONFIRMED` and the
campaign is the provider-backed projection, not a DRAFT shell. If provider
enumeration has not proved the new object yet, the endpoint returns `202
Accepted` with the raw directed write result and
`status: "AWAITING_CONFIRMATION"`.

## Errors

* `400 VALIDATION_ERROR` — missing required field, malformed `flightDates`, or non-positive `budget.total`.
* `403 FEATURE_NOT_ENABLED` — directed mirror or the narrower directed-write alpha is not enabled for this customer.
* `409 CONFLICT` — a directed idempotency key was reused with a different payload, the expected revision is stale, or governance currency/caps reject the write.
* `404 NOT_FOUND` — `advertiserId` does not exist or is not visible to the authenticated account.

See [Errors](/v2/reference/errors) for the full error contract.

## Related

<CardGroup cols={2}>
  <Card title="Campaign tasks" href="/v2/buyer/campaigns/tasks" icon="list-check">
    All campaign operations
  </Card>

  <Card title="Campaign overview" href="/v2/object-guides/campaign" icon="rocket">
    Fields, lifecycle, and concepts
  </Card>

  <Card title="Auto-select products" href="/v2/buyer/campaigns/tasks/auto-select-products" icon="wand-magic-sparkles">
    Populate a campaign from decisioned inventory
  </Card>

  <Card title="Execute campaign" href="/v2/buyer/campaigns/tasks/execute-campaign" icon="rocket">
    Launch into media buys
  </Card>
</CardGroup>
