These workflows require an enrolled Buyer account or the integrated
own-supply sandbox capability on a Media Company. Call
get_status first.
An integrated Media Company stays in the same account and never uses
switch_account for campaign work.Buyer workflow at a glance
- Confirm buyer operator readiness.
- Create or select an advertiser.
- Create a campaign with its brief, flight, and budget.
- Request proposals from ready sellers.
- Accept a quoted proposal or stage returned products.
- Inspect the staged media buys and resolve any draft issues.
- Launch the campaign explicitly.
- Query bounded campaign delivery.
0. Confirm buyer operator readiness
Callget_status before creating buying work. When
operatorIdentity.usableForBuying is false, new discovery and buying calls are
blocked with BUYER_SETUP_REQUIRED. An account administrator must call
save_buyer_operator with the buyer’s real non-platform domain and choose
whether this account represents the whole_operator or a specific_unit with
a stable operatorUnitId.
scopeStatus is unclassified, and locked is
false, reuse that domain and choose its scope before new AdCP 3.2 provisioning.
Existing buying remains available during that scope migration. If the identity
is locked, follow the support action from get_status instead.
Confirming the commercial operator does not add users, change membership, or
change the login organization. See
Buyer setup and go-live for scope selection and
identity-locking rules.
1. Create an advertiser
Creating requiresname and brand. primaryCurrency defaults to 'USD'
when omitted; pass any ISO 4217 code to override, or update it later while the
advertiser is unlocked. When name or brand is missing the tool returns a
neutral needs_input result naming the missing fields. A needs_input result
is a question, not a failure; nothing is saved until the tool is called again
with the answer.
The currency stays editable until the first campaign or seller binding locks
it. To change it, send advertiserId with the new primaryCurrency as an
ordinary update; you never need to archive and recreate the advertiser.
sandbox is immutable after creation.
advertiserId. To update, send it with only the fields to
change. Do not send sandbox on an update.
2. Create a campaign
Creation requiresadvertiserId, name, flight, budget, and an
idempotencyKey. Write the brief from the buyer’s stated goal, audience, and
what is being promoted.
campaignId and revision.
3. Request proposals from eligible sellers
get_status reports how many destinations are currently ready and includes a
bounded readyDestinations sample for explanation. A fresh
request_proposals call rechecks the complete marketplace server-side and
contacts every active seller whose buyer-specific readiness has canBuy: true.
The caller does not select or cap the seller cohort.
For an active sponsored buyer using a sandbox advertiser, the server instead
confines the cohort to that buyer’s sponsoring storefront and applies the
sandbox transaction path. The sponsoring storefront does not need to be open
to the public marketplace for this no-spend workflow.
expectedSellerId is an optional fail-closed precondition for automation that
must remain confined to one seller. A fresh round fails if the buyer’s current
server-side authority does not resolve exclusively to that seller. The value
can narrow an already-authorized scope; it cannot authorize a seller or reduce
a normal marketplace buyer’s complete eligible cohort. Omit it when broad
marketplace discovery is intentional.
For a fresh round, the call durably schedules complete eligibility enumeration
and returns running; the frozen seller count may therefore be zero on the
first response while discovery is pending. Each background seller attempt has a
30-second bound. Retry the exact same idempotency key until the result becomes
complete, partial, or failed. The execution
stores the resolved seller cohort, so retries never silently add, remove, or
duplicate sellers. Each seller may return:
quotedwith qualified Proposal IDs;productswith aproductQueryId; orfailedwith a bounded error.
page.nextCursor. perSeller
contains at most 50 outcomes on the current page, while product-heavy outcomes
may continue for the same seller on the next cursor. Product details are
bounded for transport; detailsTruncated: true marks a bounded field projection.
The productId remains the selection key. Meanwhile,
summary.sellersRequested always counts the full frozen cohort.
4. Stage a media buy
Accept a quoted proposal
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’sproductQueryId as the idempotency key:
inventorySourceId,
salesAgentId, and pricingOptionId distinguish the exact Product route and
price selected from the returned catalog.
When a returned Product advertises signal_targeting_options, select an
eligible Signal through that Product’s targetingOverlay. Preserve its
signal_ref, value type, bounds or values, activation handle, and pricing
identity exactly as returned; the Seller validates eligibility at launch.
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:sellerId plus
sellerName), and the buy’s gross budget. 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.
Read one buy’s execution tree with get:
campaignId, sellerId, sellerName, budget,
flight, and the why-visibility fields (pendingReason, errorCode,
forwardedAt, buyerReference). Includes add:
Any other include is echoed in
unavailableIncludes with the reason. The
content[0].text of every read mirrors these facts — seller names, budgets,
line items, packages, and format labels — so an agent reading only text sees
the same buy a structured-first host does. Proposal reads and
request_proposals outcomes name their sellers the same way.
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.
5a. Review the draft before going live
When the host renders MCP Apps,open_campaign_receipt opens Review & go
live for one draft campaign: its budget and flight, the staged media buys
with their budget split, why each buy is not live yet, and the readiness
blockers still standing between the draft and launch (a creative that is not
ready, or no media buys staged). The tool returns the shared MCP App directive,
a compact text summary of the same facts, and the projected receipt in
structuredContent.receipt. It reads only: going live remains the explicit
save_campaign step below.
open_campaigns_page with the same campaignId opens its record
instead. The headless equivalent is
get({kind: "campaign", id, include: ["mediaBuys"]}), whose mode: "review"
workspace carries the same readiness.blockers.
6. Launch explicitly
Launch is an update to an existing campaign, not part of campaign creation:7. Query campaign delivery
Useget_delivery with report: "campaign_delivery". Supply an explicit UTC
date range of at most 90 inclusive days and choose only the metrics and
dimensions needed by the caller:
advertiserId, campaignId, mediaBuyId, or packageId. An
integrated Media Company must name at least an advertiser, campaign, or media
buy; the server re-proves that scope against its sandbox advertiser and exact
own Storefront before querying. Advertiser-wide integrated queries also fail
closed if any current buy under that advertiser has wider supply.
Rows preserve the Buyer reporting denomination: spend, ecpm, cpc, and
cpa are gross and fee-inclusive where the underlying buy has pinned terms.
The response names its currency and reports numeric zero as available. A null
derived rate remains unavailable when its denominator or conversion signal is
absent.
This projection is seller-reported delivery viewed through the Buyer hierarchy;
it is not Buyer measurement. The V2 compatibility source does not expose
ordered revision evidence, so V3 does not infer SNAPSHOT or OFFICIAL
finality or billing eligibility. Follow nextCursor without changing the
query when page.truncated is true.
Interactive buyer Pages
Three buyer Pages have fixed v3 owners. Each owner binds one MCP App resource in its tool descriptor, so a host that renders MCP Apps opens the same Page from Murph, Claude, or ChatGPT; a host that does not render them receives the text summary. The Pages self-fetch their data, so none of these launchers puts the list into model context — usesearch and get for text answers.
The compatibility
open_page enum never lists these Pages; the owner tool is
their portable contract. Task pages:
Open Advertisers,
Open Campaigns, and
Open Review & go live.
Lifecycle operations
isPaused: truepauses an active campaign;falsereactivates it.isArchived: truearchives 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.
autonomyfields are accepted for forward compatibility but are not persisted yet.