Overview
UsebusinessProfile.publisherDomains to tell Interchange which publisher
domains your storefront is authorized to sell. This is the canonical publisher
domain set for a managed storefront.
operatorDomain is separate: it identifies the company or domain operating the
storefront. For network sellers, the operator domain is often not the same as
the publisher domains being sold. A third domain — the one your account is
registered under — decides whether your operator domain can be verified at all.
See Which domain is which if any two of them differ.
The top-level
publisherDomain field on POST /storefront and
PUT /storefront is legacy metadata. Keep using operatorDomain for the
storefront identity and businessProfile.publisherDomains for the publisher
domains the storefront can sell.Set publisher domains
Send the full current domain set on the storefront business profile:The REST
PUT below replaces the supplied business profile, so send its full
current value. MCP clients can instead call update_business_profile with only
publisherDomains; fields omitted from the profile state read for that call
are preserved. Overlapping patch calls use last-writer-wins behavior.Managed sales-agent sync
For a storefront backed by an Interchange-managed sales agent,businessProfile.publisherDomains is also synchronized to that managed sales
agent as the authoritative publisher-domain set.
When the set changes:
- Added domains are registered with the managed sales agent.
- Removed domains are cleared from the managed sales agent’s authorization projection.
- Current domains are rechecked against AAO and
adagents.jsonso their authorization status stays fresh.
Authorization status in setup
Storefront setup lists each configured publisher domain separately. A domain can be:
The underlying
adagentsStatus separates “there is no file” from “there is a
file and we cannot read it”, because the fix is different:
Declaring a domain (
POST /api/v2/storefront/publishers, or a business-profile
update) kicks off its adagents.json resolution immediately — you do not wait
for a background sweep. The result usually lands within seconds; re-read the
publisher list to see it. A failed immediate resolve is retried by the sweep.
Re-declaring a domain you already configured re-checks it the same way,
subject to a short cooldown (currently 10 minutes) since its last completed
sync — so if you just fixed your adagents.json, re-declaring the domain (or
resending it in a PUT of the full set) gets you a fresh answer immediately
instead of waiting for the sweep. Re-declaring inside the cooldown is a no-op:
it does not reset the domain to “Checking” or trigger another fetch.
Why a domain is not authorized
Every resolved domain also carries a machine-readableauthorizationReason
naming the exact outcome, so you know what to fix rather than seeing a bare
“not authorized”:
The reason appears on
GET /api/v2/storefront/publishers items and on each
domain in the readiness checklist, which also summarizes the most common fix
(for example, “2 domains need an adagents.json upgrade to typed
authorizations”).
Publisher-domain declaration is a go-live readiness check. Setup remains
incomplete until at least one publisher domain is configured. Product mapping
to the configured set is shown as a rollout warning while older catalogs are
backfilled. Authorization is shown separately as advisory provenance and does
not block transactions.
The status also shows the number of resolved properties when available. That
count describes what the current publisher document contains; it does not prove
that a network’s document includes every site the network represents. Network
sellers should compare it with their own managed-site roster before enabling
buyer-visible coverage — the roster’s propertyCount is the number to compare
against, and it agrees with this one.
If the managed sales agent cannot accept the replacement set, Interchange keeps
the prior local publisher-domain sync state instead of deleting rows first. That
lets the update retry without losing the previous authorization projection.
Adding or removing one domain
Two routes change exactly one domain and leave every other one alone:
Prefer these over
PUT /api/v2/storefront/publishers (or a business-profile
update) whenever you are changing one domain. The PUT replaces the entire
declared set: any domain you declared that is missing from the body is deleted,
and it has no conditional-write check, so a set you assembled from an earlier
read can also discard a change someone else made in between. The single-domain
routes have neither problem, because they never send a set.
The PUT applies as a diff, so it is safe to resend a set you already have. A
domain that is in both your current set and the body keeps its row and
everything resolved under it — its properties, collections, creative formats,
your own property claims, and its authorization verdict. Only the declared
domains you left out are deleted, and only domains that were not there before
are created (those start at pending, since nothing has resolved them yet).
Only domains you declared are yours to remove, whichever route you use. DELETE
returns 409 when the domain exists but its provenance is not declared — a
domain we discovered or crawled for you follows its own source, and nothing is
changed. The PUT behaves consistently rather than silently: it replaces your
declarations only, so a discovered domain left out of the body stays on the list.
Leaving one out is not a way to delete it.
Empty or missing values
An empty array means “clear the publisher-domain set” for the storefront:publisherDomains means the authorized domains are unknown or have not
been captured yet. It does not authorize the storefront to sell every domain.
Setting businessProfile to null clears the business profile and clears the
publisher-domain set for managed sales-agent sync.
Buyer visibility
Updating the publisher-domain set does not by itself change the storefront name, operator identity, or buyer-facing seller profile. Buyers may see publisher domain coverage on products when those products exposepublisher_properties; see Publisher properties and coverage.
Authorization is necessary but does not by itself enable buyer disclosure. The
storefront’s resolved property coverage must also be synchronized and its
coverage-disclosure rollout enabled.
The property roster
Every declared publisher domain is resolved through two deliberately separate reads. AAO’s publisher lookup supplies creative format declarations, including AAO registry declarations for platforms that do not publish their own file. The live publisher-originadagents.json read supplies authorization and
continues to fail closed. The property roster is the canonical seller view
of the result: each domain’s declared properties[] (with their identifiers,
types, and tags), its collections[] (canonical identity
{publisher_domain, collection_id}), its canonical creative formats[], and
the authorization outcome.
Fetch it with GET /api/v2/storefront/property-roster, the
get_property_roster operation, or by asking your agent to open the Property
Roster page (the open_property_roster tool in any MCP host).
Each publisher in the roster carries:
authorizationStatus—authorized,unauthorized, orunknown.authorizationReason— the distinct resolution outcome behind that status:no_file(no adagents.json found),file_invalid(the file could not be read),agent_not_listed(the file does not list your sales agent),agent_untyped(your agent is listed in the pre-3.x format without a typed authorization mapping),agent_not_property_bound(typed entries exist but none map your agent to this publisher’s properties), orauthorized.nullmeans the domain has not yet been resolved under the reason contract.properties[]andcollections[]— persisted from the most recent successful resolution. Entries a newer document no longer declares are removed from the live roster (history is retained internally). A publisher that stops serving an adagents.json entirely has its declared identity removed from the live roster until the file returns.formats[]— canonical, URL-freeformatKind+paramsdeclarations from the AAO publisher lookup. Each entry retains its publisher property-id/tag scope, the live roster properties that scope matches, and provenance:publisher_adagentsfor publisher-origin declarations oraao_registryfor an AAO registry declaration. If an AAO lookup fails, the roster preserves the last successful catalog instead of treating the failure as an empty catalog.formatCatalogSyncedAt— when AAO last returned a definitive format catalog for this publisher. This timestamp is independent oflastSyncedAt, which describes the live-origin authorization and identity check. Use the catalog timestamp to judge the freshness of preserved formats.propertyCount,collectionCount, andformatCount— how many the domain actually has. For a large network these can be bigger than the corresponding arrays are long, because a single roster read is size-bounded. Read the counts, not the array lengths, when you want to know what a domain covers.
totals for the whole storefront and a truncated
object:
totals always describes the storefront, never the response. When any
truncated flag is true, the response left rows out — so an absence in
properties[] is not evidence a property is missing. Look the specific
property up, or open the Property Roster page, rather than concluding a site
is not covered.
Whether one property is authorized
Every property carries its ownauthorization:
grain before acting on status. Authorization is granted by the
publisher domain’s adagents.json, and that is where we resolve it, so:
unauthorizedis definite. The domain does not authorize your agent, so nothing under it can be sold — however many properties the file declares.authorizedis inherited from the domain (grain: "domain"), not proven against the specific selector mapped to your agent. Under AdCP 3.x a file can map an agent to a subset of the properties it declares.unknownmeans no publisher-origin declaration backs this property — most often a property you declared yourself, which stays on your roster but cannot read as authorized until the publisher’s file declares it.
Storefronts where coverage does not apply
The response also carriescoverageApplies. It is false for a storefront that
sells through a platform account connection (Meta, Google, TikTok and the like):
selling rights come from that connection, no adagents.json will ever resolve,
and the authorization verdict is not something to fix. Do not read those
verdicts as a problem, and do not publish a file to change them.
The header totals include the number of discovered formats, and each publisher
card can expand its format list. An unscoped declaration applies to every
property under that publisher; a scoped declaration matches a property when
either its propertyId is listed or one of its tags overlaps.
Discovered publisher formats describe capacity — what the publisher says its
inventory accepts. A product’s format_options[] is the closed executable set
that a buyer can actually purchase from that sales agent, so it may be
narrower. AAO registry provenance never authorizes a sales agent.
In Property Roster, Create product opens Create a product
with that publisher format already selected. Choose an Ad server,
select the exact inventory to package, and choose one or more Delivery
formats reported by that source. Select Review product, then Create
draft product after validation succeeds. The format stays in the task instead
of being sent back through chat.
Review property mapping means the complete publisher roster was checked and
the format did not match a current property. Mapping not shown and Check
inventory mapping mean the roster view was size-bounded, so it does not
contain enough properties to prove whether the format matches. Use the check
action to inspect the mapping instead of treating the format as unavailable.
Format IDs, sources, and the complete creative parameter object remain under
Technical details.
When a product uses a publisher-catalog option, copy its format_option_id,
publisher_domain, format_kind, and params into the product’s
format_options[]. Product validation compares that identity and canonical
kind with the connected roster and warns when the option is unknown, uses a
different kind, or applies to none of the product’s selected publisher
properties. The product may narrow the catalog option’s parameters. These are
authoring advisories: a catalog read failure does not block a product write or
change the sales agent’s own validation verdict. Product validation does not
yet check placement-specific format availability.
The roster only reflects what publishers declare — Interchange never invents
property identity. To appear authorized, the publisher’s adagents.json must
list your sales agent URL with a typed authorization mapping
(authorization_type plus the matching selector, e.g. property_ids);
listing the URL alone is not authorization under AdCP 3.x. See
adagents.json for the file
format and deployment guidance.
Declaring properties before the publisher does
A seller can record properties conversationally — through their agent or viaPOST /api/v2/storefront/property-roster/properties (the
declare_roster_property operation) — before the publisher’s adagents.json
declares them. Declared entries carry provenance: seller_declared and are
visibly distinct from publisher-origin identity:
- A declared property needs at least a
propertyId, an identifier, or a name. The roster never invents identity. - When the publisher’s adagents.json later declares the same property, the
publisher-origin record supersedes the declared one (declaring it again
returns
outcome: already_resolved). Your claim is retained either way: if the publisher later stops declaring the property, it returns to the roster as your declaration instead of disappearing. - adagents.json changes never remove seller-declared entries; remove one with
DELETE /api/v2/storefront/property-roster/properties/{domain}/{propertyKey}(remove_declared_roster_property). Publisher-origin entries cannot be removed this way — they follow the publisher’s file.