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

# Buyer Workflows

> Use v3 to create buyer objects, request seller proposals, stage media buys, and launch a campaign.

<Note>
  These workflows require an enrolled Buyer account. Call `get_status` first
  and use `switch_account` if the active account is a Seller or organisation.
</Note>

## Buyer workflow at a glance

1. Create or select an advertiser.
2. Create a campaign with its brief, flight, and budget.
3. Request proposals from ready sellers.
4. Accept a quoted proposal or stage returned products.
5. Inspect the staged media buys and resolve any draft issues.
6. Launch the campaign explicitly.

## 1. Create an advertiser

Creating requires `name` and `brand`. Choose the primary currency deliberately:
it defaults to USD when omitted and becomes locked after the first campaign or
seller binding. `sandbox` is also immutable after creation.

```json theme={null}
{
  "name": "Acme Europe",
  "brand": "acme.example",
  "primaryCurrency": "EUR",
  "sandbox": true
}
```

Retain the returned `advertiserId`. To update, send it with only the fields to
change. Do not send `sandbox` on an update.

## 2. Create a campaign

Creation requires `advertiserId`, `name`, `flight`, `budget`, and an
`idempotencyKey`. Write the brief from the buyer's stated goal, audience, and
what is being promoted.

```json theme={null}
{
  "advertiserId": "ADVERTISER_ID",
  "name": "Autumn launch",
  "brief": "Reach sustainability leaders in the Netherlands with Acme's autumn product launch.",
  "flight": {
    "startAt": "2026-09-01T00:00:00Z",
    "endAt": "2026-09-30T23:59:59Z"
  },
  "budget": {
    "total": 50000,
    "currency": "EUR",
    "pacing": "even"
  },
  "idempotencyKey": "acme-autumn-create-v1"
}
```

Creation does not launch. Retain the returned `campaignId` and `revision`.

## 3. Choose sellers and request proposals

`get_status` returns `readyDestinations` with the seller IDs accepted by
`request_proposals`. These are seller/storefront IDs, not account IDs.

```json theme={null}
{
  "campaignId": "CAMPAIGN_ID",
  "expectedCampaignRevision": 1,
  "sellerIds": ["10", "24"],
  "evaluation": {
    "instructions": "Prefer contextual relevance and transparent fixed pricing."
  },
  "idempotencyKey": "acme-autumn-proposals-v1"
}
```

For a fresh round, the call waits up to 30 seconds per seller and ordinarily
returns a terminal `complete`, `partial`, or `failed` result. A concurrent call
using the same idempotency key may instead see `running`; retry that same key
until it becomes terminal. Each seller may return:

* `quoted` with qualified Proposal IDs;
* `products` with a `productQueryId`; or
* `failed` with a bounded error.

Repeating the same idempotency key returns the same proposal round. Use a new
key only when intentionally asking sellers for a fresh round. Evaluation
instructions are recorded but are not yet applied to ranking; review the
returned results yourself.

## 4. Stage a media buy

### Accept a quoted proposal

```json theme={null}
{
  "fromProposalId": "sfp1:QUALIFIED_PROPOSAL_ID",
  "idempotencyKey": "acme-autumn-accept-proposal-v1"
}
```

The proposal version must still be current and belong to the campaign. The
result is a draft media buy; accepting a proposal does not launch it. The
current schema requires `idempotencyKey` on every call, although proposal
acceptance derives retry safety from the qualified proposal version and does
not consume the supplied key.

### Stage returned products

For a seller that returned products without a Proposal, preserve every returned
identity field and use that seller's `productQueryId` as the idempotency key:

```json theme={null}
{
  "campaignId": "CAMPAIGN_ID",
  "sellerId": "10",
  "products": [
    {
      "productId": "QUALIFIED_PRODUCT_ID",
      "inventorySourceId": "200",
      "salesAgentId": "SELLER_AGENT_ID",
      "budget": 5000
    }
  ],
  "idempotencyKey": "PRODUCT_QUERY_ID"
}
```

Do not reconstruct qualified IDs. `inventorySourceId` and `salesAgentId`
distinguish products that may otherwise look identical across seller routes.

Creation-time `flight` and top-level `budget` are not supported by
`save_media_buy`; allocate with `products[].budget`, then update the draft's
flight in a separate call using `mediaBuyId`.

## 5. Inspect staged work

List media buys under the campaign:

```json theme={null}
{ "kind": "media_buy", "filter": { "campaignId": "CAMPAIGN_ID" } }
```

The Buyer projection reports phase, pause state, and flight. It does not retain
Proposal evidence after the acceptance response, so preserve the
`proposalSource` fields returned by `save_media_buy` when that audit link
matters. There is no cross-campaign Buyer media-buy list; select a campaign
first.

Buyer reads currently project `isArchived: false` because the underlying read
does not expose media-buy archive state. Do not use that field or an
`isArchived: true` search as proof that no archived buy exists.

There is no separate confirmation call in v3. At this step, inspect each draft,
apply any supported correction with `save_media_buy({ mediaBuyId: ... })`, and
continue only when the staged set is the one you intend to launch.

## 6. Launch explicitly

Launch is an update to an existing campaign, not part of campaign creation:

```json theme={null}
{
  "campaignId": "CAMPAIGN_ID",
  "expectedRevision": 1,
  "desiredPhase": "active",
  "idempotencyKey": "acme-autumn-launch-v1"
}
```

Do not combine launch with pause or archive in the same call. A launch can
partially write downstream execution state even when no media buy activates;
read the structured error, fix the cause, re-read the campaign revision, and
retry deliberately.

## Lifecycle operations

* `isPaused: true` pauses an active campaign; `false` reactivates it.
* `isArchived: true` archives it.
* `desiredPhase: "canceled"` and unarchive are not implemented in v3; use v2.
* A tracked campaign is read-only until it is adopted or duplicated through
  the existing v2 workflow.
* `autonomy` fields are accepted for forward compatibility but are not
  persisted yet.

See [Preview limitations](/v2/setup/v3/limitations) before replacing a v2 buyer
integration.
