merchandising document. Merchandising is what your
storefront does — the Merchandising Agent
selling on your behalf — not a thing you save. Three Pages steer it, split by
what kind of fact each one holds:
The Page names and read tools now use the same three nouns. Selling Terms is retired:
structured prices and floors moved to Playbook, while approval gates moved to
Business Rules. Business Profile is compatibility storage, not a Page and
not a Media Kit. “Media Kit” means Product Marketing material used as an input
to merchandising; that product is not a V3 noun until its backing store exists.
Your saved configuration and version history do not move or reset.
In chat and any MCP Apps host,
get_discovery_card, get_playbook, and
get_business_rules open the portable Pages. The historical media-kit resource
URI continues to render the deprecated legacy Business Profile/Media Kit only
for saved-conversation compatibility; it is not the Discovery Card Page.
/mcp/v3 remains a gated preview. The get and save_* examples below apply
only to that surface; the get_discovery_card, get_playbook, and
get_business_rules Pages are available through the current seller MCP
surface.One fact, one owner
Playbook instruction content cannot duplicate structured Playbook pricing, Buyer Discounts, Discovery Card facts, or Business Rules. It may refer to those facts without restating them. A conflicting version is rejected on save rather than left for the agent to reconcile later. Writing “the Nike house gets 12%” into your guidance is the case this catches: the discount is a structured rule with its own field, not a sentence for the agent to interpret. Business Rules separates three decisions. Brief Acceptance decides whether an otherwise matching brief should receive a response; Creative Policy judges submitted creative; and Approval Mechanics decides whether and where human review runs. WithmediaBuyApproval: manual and no active policy, every media buy is held
for review. Discovery Card channels/countries and Playbook guide what the agent
presents and how it sells; neither controls the review gate.
A managed seller may separately elect to show Brief Acceptance, Creative
Policy, both, or neither as Advertising Policies on the Discovery Card.
This disclosure selector belongs to Business Rules because that is where its
source text is edited. Approval mode, approvers, routing, per-buyer overrides,
and revision notes are never disclosed. For a pass-through storefront, the
read-only disclosure comes from upstream AdCP
media_buy.portfolio.advertising_policies.
External pass-through storefronts do not get local Business Rules or approval
settings. Their channels and countries come from the upstream agent’s
get_adcp_capabilities portfolio; both are read-only. Missing declarations
stay unknown and do not match filtered searches.Reading singleton nouns and the storefront projection
playbook and business_rules are singletons — exactly one per storefront —
so get identifies them by kind alone. Discovery Card is not a noun; request
it as a projection of the storefront:
include: ["versions"] adds the full version history for playbook and
business_rules (an array of { version, isActive, notes, createdAt }); omit
it and get returns only what is currently active. There is no separate
“list versions” tool — version history is an include, the same way source
diagnostics are.
The history is deliberately a summary: it carries no content, because a
storefront with dozens of 50,000-character versions would return an unusable
response. To read one version in full, name it:
selectedVersion with the version’s content, its notes, its
ownershipIssues, and a restorable flag. restorable: false means the
version restates a fact owned by another canonical surface and would be rejected
if you saved it back unchanged; the create-and-activate section below explains why, and
what to do about it.
version is only served for kind: "playbook".
include: ["discounts"] adds the playbook’s brand and operator
house discount rules. If a read
fails, the key is omitted and an unavailableIncludes entry names it —
“no discounts are configured” and “the discount read failed” mean opposite
things for what your buyers are paying, so the response never lets you confuse
them.
include: ["approvalRouting"] on business_rules adds who receives each kind
of review work — see Approval routing.
Discovery Card — what buyers see
save_storefront writes the local description and, for a managed storefront,
the buyer-visible channels and ISO countries. Pass-through storefronts read channels
and countries from get_adcp_capabilities; those fields are read-only locally.
brand.json; link or correct that identity instead of forking it on the
card. Open the Page with:
playbook — how you sell
save_playbook has three independent halves you can send together or apart:
content (posture and packaging guidance, versioned), pricing (your
value-anchor facts), and discounts (your brand and operator rate-card
rules).
ownershipIssues identifies any line in the active guidance that duplicates
structured Playbook pricing, Buyer Discounts, Discovery Card facts, or Business
Rules. pricing.facts replaces the
whole list — a fact you don’t repeat in the request is removed, the same
“whole document” semantics as content.
Discounts are per rule, not a whole list
discounts is the exception, and the difference is deliberate. A
house discount is keyed by
(houseDomain, scope) and changes what a real buyer pays on their next buy,
so a rule you don’t mention is left exactly as it was. Removing one means
naming it:
- A rule for a
(houseDomain, scope)pair that doesn’t exist yet is created; one that does is updated. Sending a rule that already matches is a no-op and says so. - Omitting
noteskeeps the note you already wrote. Sendnullto clear it. removeneeds both halves of the key, becausenike.comcan carry a brand discount and an operator discount at once and they are different rules.- Naming the same pair in
rulesandremoveis rejected rather than resolved for you.
content half of the same call is never rolled back for a discounts
failure, and vice versa: they are separate writes, and the response names what
landed.
Which discount a buyer actually gets
The rules you author and the discount a buy receives are different things.search will resolve one for you:
results is your authored rules, unchanged. resolution is derived: the
corporate chain the domain resolved up (converse.com → nike.com), the
hierarchy coverage, and the nearest rule that keys on each axis. It always
carries caveats, because a real buy resolves its brand and its operator
separately and takes the larger of the two — one domain’s chain cannot
decide it. When the hierarchy can’t be resolved, you get unavailable and
your authored rows rather than a confident “no discount applies”.
business_rules — what you accept
save_business_rules also has independent versioned policy sections and two
approval gates. Structured policy writes always send both sections, so an
omitted field can never erase the other section accidentally.
Turning off human review
MovingcreativeApproval or mediaBuyApproval to auto needs
acknowledgeNoHumanReview: true on the same call:
auto removes human review; it does not remove the product-discovery policy
boundary. A confident policy conflict returns no products, while an
unavailable qualifier fails open. Once a buyer passes discovery,
create_media_buy preserves the established auto-forward contract. With
mediaBuyApproval: manual, the submitted buy is evaluated again: clearly
on-policy buys auto-forward, while uncertain results, evaluator errors, and
deterministic hard findings queue for an operator. Live auto-rejection
requires a separate seller opt-in or versioned rollout.Every save is create-and-activate
playbook.content and business_rules.content are versioned and immutable.
Saving one creates a new version and makes it active in the same call —
the response’s createdVersion and replacedVersion tell you what happened,
and there is no activate flag on the save. A version you save has full
effect immediately; there’s no draft state where it exists but hasn’t taken
effect.
Rolling back: two routes, and the agent only has one of them
There is no activation field oractivate_* tool on /mcp/v3, by design.
An agent rolls back the way it writes anything else — by saving the earlier
content again, which mints a new version carrying it. History stays
append-only, and the restored content is re-checked against the current
ownership rules on the way in.
The Business Rules Page has the other route: it lists every immutable version
and can reactivate one directly, behind a two-step confirmation, without
minting anything. Use it when you want the version count and history left
exactly as they are. Open it with get_business_rules, or on /mcp/v3 with
open_page and page: "business_rules".
Either way, decisions already recorded keep the policy they were made under.
Changing which version is active changes what happens next; it does not
retroactively re-judge a creative or media buy someone already approved.
playbook works the same way: save the earlier content again to roll back.
For the playbook that is a two-step journey, and both steps are reads you can
make:
1
Read the version you want back
get({ kind: "playbook", version: 2 }) returns that version’s full
content plus a restorable flag.2
Save that content again
save_playbook({ content: "…" }) mints a new version carrying it, active
immediately. Your history keeps both — nothing is overwritten.restorable: false is worth reading before you try. Playbook content that
restates a price, a discount, a market, or an acceptance rule is rejected on
save because another canonical surface owns that fact, and an older version
written before that check can still contain one. Re-saving it puts it back through the
current validator, so a flagged version needs editing before it can go live
again. That is not a cost of the re-save route: the older activate call
re-runs the same validator and refuses a flagged version too, so the content
is unacceptable either way. Edit the flagged lines out and save what’s left.
save_playbook and save_business_rules also each take unversioned halves
in the same call — pricing and discounts on the playbook, the approval
gates on business rules. The parts run in a fixed order — content, then
pricing, then discounts — and there is no transaction spanning them.
If a part fails, the response tells you exactly where the call stopped:
- Parts that already succeeded stay applied. A version that was created is
live and is not rolled back, and the error still names
createdVersion(andreplacedVersion) so you know it exists before retrying. - Parts that never ran are listed in
unattempted, and the message names them. Apricingfailure means yourdiscountswere not read, created, changed or removed at all — so the retry guidance says to re-sendpricinganddiscounts, and acontentfailure means neither of the other two was attempted and nothing is half-applied. - Retry only what the response tells you to. Sending
contentagain would mint a second, identical version rather than fixing anything.
Approval routing: who reviews, as opposed to whether anyone reviews
The approval gates decide whether a human reviews. Approval routing decides which human — the named users and roles who receive each kind of review work, the channels they are notified on, and the reminder and escalation clock. It is a third thing, on its own lifecycle: not versioned like the acceptance policy, and not a gate. Read it as an include onbusiness_rules:
policies is not unrouted — it falls back to
the default org-admin audience. An approver shown with eligible: false is
still named in the policy but no longer has an eligible role on the account,
which is worth cleaning up. Reading routing requires a storefront admin; a
non-admin session gets an approvalRouting entry under unavailableIncludes
explaining why, never an empty table that would read as “nobody reviews”.
Routing is changed on the Approvals Page, not by a tool
There is no routing field onsave_business_rules, and passing one returns an
error naming the Page instead. Choosing an approver changes who can act on
your storefront, and that class of change is a human ceremony rather than
something an agent writes — the same rule that keeps credentials, access
grants, and payout destinations off the agent surface. Open the Page with
open_page and page: "approvals"; the routing editor lives there alongside
the queues, and only admins can save it.
Eligible users’ email addresses are deliberately not returned to the agent.
An approver who has never set a name comes back as "name": null rather than
falling back to their address — they are still eligible: true, there is just
no name safe to show. The Page shows the full directory to the human choosing.
Searching version history and discount rules
playbook and business_rules are singletons, so search doesn’t search
them. Discovery Card is a storefront projection rather than a searchable
noun. What is list-shaped is the version history and the playbook’s
discount rules.
business_rules_version works the same way over acceptance-policy history,
and house_discount lists the playbook’s brand and operator rules.
Omit kind and search lists every list-shaped object it knows about,
playbook_version, business_rules_version, and house_discount included —
so a broad question about your setup never silently leaves your discounts out.
v3 Agent Surface
The one-endpoint, noun-shaped surface these tools live on.
Merchandising
The three Pages you use today, and how they map to the platform.
Acceptance policy
How the pre-screen reads your policy, and the three verdicts it returns.
Glossary
Component, Product, and the rest of the vocabulary these nouns build on.