> ## 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.

# Plan a directed campaign (alpha)

> Turn an advertiser brief into reviewable provider-native decisions before any write

<Warning>
  Alpha. This operation requires both the `directed-campaigns` mirror gate and
  the narrower `directed-campaign-writes` gate. It never creates or changes a
  provider campaign, but a ready plan is persisted temporarily so it can be
  accepted and bound to a later assisted create.
</Warning>

Use this planning preflight when a buyer starts with an advertiser brief. It
calls the connected provider's ordinary AdCP `get_products` path, validates its
controlled planning payload, then returns the available products, a typed
decision plan, and a 30-minute proposal reference. Raw directed create remains
brief-free and defaults to `decisionMode: "raw"` when that field is omitted. To claim Scope3-assisted
brief strategy, accept the proposal and reference its exact digests in the
create.

**Named operation:** `plan_directed_campaign`

| Field          | Location | Type           | Required | Description                                                                                                    |
| -------------- | -------- | -------------- | -------- | -------------------------------------------------------------------------------------------------------------- |
| `connectionId` | path     | integer        | Yes      | Active official-adapter connection ID                                                                          |
| `accountId`    | path     | integer        | Yes      | Buyable provider-account row selected from the connection                                                      |
| `advertiserId` | body     | numeric string | Yes      | Advertiser already mapped to this account and subscription                                                     |
| `brief`        | body     | string         | Yes      | Advertiser objective, audience, geography, creative direction, and relevant setup context; 20–4,000 characters |

```bash theme={null}
curl -X POST \
  "https://api.interchange.io/api/v2/buyer/storefront-connections/42/accounts/81/directed-campaigns/plan" \
  -H "Authorization: Bearer $SCOPE3_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "advertiserId": "12345",
    "brief": "Build brand awareness among women aged 25-34 in the US using a 1:1 image."
  }'
```

## Meta decision plan

Meta currently supports this contract. The response is provider-neutral and
top-level; adapter extension fields are validated inside Interchange and are
not passed through to buyers. Controlled fields are intended for review and
exact testing; narrative rationale is not used as a provider enum.

```json theme={null}
{
  "provider": "meta",
  "schema_version": 1,
  "status": "ready",
  "products": [
    {
      "product_id": "meta_awareness_7a31c902",
      "pricing_options": [
        { "pricing_option_id": "meta_awareness_7a31c902_cpm" }
      ]
    }
  ],
  "intent": {
    "goal": "awareness",
    "geo_countries": ["US"],
    "age_ranges": ["25-34"],
    "genders": ["FEMALE"],
    "creative_format": "meta_image_feed"
  },
  "plan": {
    "schema_version": 1,
    "decision_mode": "assisted",
    "provider": "meta",
    "product_id": "meta_awareness",
    "concrete_product_id": "meta_awareness_7a31c902",
    "pricing_option_id": "meta_awareness_7a31c902_cpm",
    "execution_snapshot": {
      "provider": "meta",
      "product_id": "meta_awareness_7a31c902",
      "base_product_id": "meta_awareness",
      "objective": "OUTCOME_AWARENESS",
      "optimization_goal": "REACH",
      "targeting": {
        "geo_countries": ["US"],
        "age_ranges": ["25-34"],
        "genders": ["FEMALE"]
      },
      "pricing": {
        "pricing_option_id": "meta_awareness_7a31c902_cpm",
        "pricing_model": "cpm",
        "currency": "USD",
        "floor_price": 5
      }
    },
    "outcome": "awareness",
    "objective": "OUTCOME_AWARENESS",
    "optimization_goal": "REACH",
    "targeting": {
      "geo_countries_included": ["US"],
      "geo_countries_excluded": [],
      "resolved_audiences": [],
      "age_ranges": ["25-34"],
      "genders": ["FEMALE"]
    },
    "creative": {
      "format_ids": ["meta_image_feed"],
      "placements": [],
      "identity_refs": [],
      "assets": [],
      "call_to_action": null,
      "landing_page_url": null
    },
    "measurement_prerequisites": [],
    "setup_prerequisites": [
      "facebook_page",
      "hosted_https_asset",
      "https_landing_url"
    ],
    "assumptions": ["account_currency_applies", "paused_launch"],
    "rationale_codes": [
      "objective_from_brief",
      "geo_from_brief",
      "creative_format_from_brief"
    ],
    "clarification_requirements": []
  },
  "plan_ref": {
    "plan_id": "11111111-1111-4111-8111-111111111111",
    "plan_digest": "sha256:...",
    "write_intent_digest": null,
    "expires_at": "2026-07-20T12:00:00Z",
    "acceptance_status": "proposed"
  },
  "clarification_codes": [],
  "assumptions": ["account_currency_applies", "paused_launch"],
  "rationale_codes": [
    "objective_from_brief",
    "geo_from_brief",
    "creative_format_from_brief"
  ],
  "review": {
    "audience_description": "Women aged 25-34 in the US",
    "confidence": "high"
  }
}
```

The plan's `product_id` is the stable family and `concrete_product_id` is the
only product accepted by an assisted create. Accept the proposal before it
expires; proposal and acceptance are bound to the authenticated principal,
customer, advertiser, selected account subscription, and provider.
The execution snapshot is part of the plan digest. Meta prices the concrete
product in the selected ad account's authoritative currency. For non-USD
accounts, `floor_price: 0` means no account-currency floor was inferred; Meta
omits USD-only proposal and forecast guidance instead of assuming an exchange
rate. Meta rejects a missing or changed stored product or currency before
mutation and executes from this accepted snapshot.
Plan audit rows remain reviewable for at least 30 days, then become eligible for
bounded best-effort cleanup on later planning traffic; this is not a hard
deletion SLA, and the independent write journal retains replay provenance.

```bash theme={null}
curl -X POST \
  "https://api.interchange.io/api/v2/buyer/storefront-connections/42/accounts/81/directed-campaigns/plans/11111111-1111-4111-8111-111111111111/accept" \
  -H "Authorization: Bearer $SCOPE3_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "advertiserId": "12345",
    "plan_digest": "sha256:...",
    "write_intent": {
      "name": "US awareness campaign",
      "currency": "USD",
      "mediaBuy": {
        "brand": { "domain": "example.com" },
        "total_budget": { "amount": 2500, "currency": "USD" },
        "start_time": "2026-08-01T00:00:00Z",
        "end_time": "2026-08-31T23:59:59Z",
        "paused": true,
        "packages": [{
          "product_id": "meta_awareness_7a31c902",
          "pricing_option_id": "meta_awareness_7a31c902_cpm",
          "budget": 2500,
          "targeting_overlay": { "geo_countries": ["US"] }
        }]
      }
    }
  }'
```

The later create uses `decisionMode: "assisted"` and passes the accepted
`planId`, `planDigest`, and `writeIntentDigest`. Interchange verifies those
values, the planned product/pricing/geography, and the exact accepted create
intent before reserving budget or calling Meta. One accepted plan authorizes
one create; idempotent retries reuse the original create key.
Version 1 accepts only a paused, single-package write with the planned product,
pricing option, budget, and country targeting. Inline creative, actor, format,
catalog, CTA, landing-page, extension, or other package execution fields are
rejected until the plan contract can map them. Creative attachment remains
unavailable for assisted v1 until the separate sync/assignment workflow lands.

Controlled Meta brief planning currently supports contiguous age buckets from
18–24 through 65+; non-bucket or disjoint age language requires clarification
instead of being broadened. Separate account readback may preserve
provider-authored ages from 13 upward. That read compatibility does not mean
Scope3 controlled writes support under-18 targeting; on readback, `age_max: 65`
represents Meta's 65+ bucket and an empty gender list means all genders.

Explicit composite ranges that align exactly to those contiguous buckets are
also supported. For example, `25-54` resolves to `25-34`, `35-44`, and `45-54`
without broadening the requested audience. Explicit country names such as
`Australia` and uppercase ISO codes such as `AU` are grounded deterministically,
so a complete objective/geography/creative brief does not depend on the optional
model interpreter being available.

Conversion, app-install, and lead briefs currently return
`execution_setup_unavailable` because the directed write contract cannot yet
carry the promoted-object setup those objectives require. Planning does not
pretend those campaigns are executable.

## Clarification is a successful planning result

If the brief is ambiguous, omits geography or objective, contains instruction
conflicts, requests unresolved interest or exclusion targeting, or asks for an
unverified creative/localization path, Meta returns
`status: "clarification_required"`, `plan: null`, `plan_ref: null`, and no
actionable products.
The current contract models positive targeting only, so exclusions must be
resolved explicitly rather than being reinterpreted as inclusions. Ask the buyer
to resolve the named `clarification_codes`; do not silently choose defaults and
do not proceed to a provider write.

```json theme={null}
{
  "provider": "meta",
  "schema_version": 1,
  "status": "clarification_required",
  "products": [],
  "intent": {
    "goal": null,
    "geo_countries": [],
    "age_ranges": [],
    "genders": [],
    "creative_format": null
  },
  "plan": null,
  "plan_ref": null,
  "clarification_codes": [
    "ambiguous_brief",
    "missing_geography",
    "missing_objective"
  ],
  "assumptions": ["account_currency_applies", "paused_launch"],
  "rationale_codes": [],
  "review": {
    "audience_description": "Unable to interpret brief",
    "confidence": "low"
  }
}
```

Provider adapters that do not yet implement the controlled decision contract
return `CAPABILITY_NOT_SUPPORTED`. They can still list products or accept a raw
directed write when those separate capabilities are enabled.

See [Directed campaigns (alpha)](/v2/buyer/campaigns/directed-campaigns),
[List directed campaign products](/v2/buyer/campaigns/tasks/list-directed-campaign-products),
[Accept a directed campaign plan](/v2/buyer/campaigns/tasks/accept-directed-campaign-plan),
and [Create campaign](/v2/buyer/campaigns/tasks/create-campaign).
