list_collections reads the sales agent’s catalog of collection cards: the shows, creators, series and podcasts it sells, with their pictures, samples, links and follower counts. One task covers two jobs: looking up specific collections by key, and browsing the catalog with filters and pages. It returns collections only, never products, pricing or availability. It is side-effect free and never provisions an account.
It is not list_collection_lists, which lists buyer-owned collection targeting lists on a governance agent.
Experimental.
list_collections and the collection_card.updated, collection_card.removed and collection_catalog.bulk_change webhooks are experimental in AdCP 3.3 under the feature id media_buy.collection_catalog (#8183). A seller that implements any of them lists media_buy.collection_catalog in experimental_features, and also lists media_buy.collection_cards, because the response carries card fields. The shape may change between 3.x releases with notice; see experimental status.core/response-collection.json copies that include_collections adds to product and proposal reads, under the same authority rules. Account-level webhooks push card changes to buyer mirrors, with list_collections as the bootstrap and repair read.
When to use it
Request
Request schema:/schemas/3.3.0-beta.0/media-buy/list-collections-request.json
The request rejects unknown fields. Values within one filter are alternatives (OR); different filters combine with AND. The seller applies selectors and filters before pagination. A seller that cannot apply a filter it receives fails the request with
VALIDATION_ERROR and never returns a broader result. More than 100 collection IDs is also a VALIDATION_ERROR.
Order is seller-defined and stable within one collections_version. There is no sort parameter, and in particular no sort by follower count: followers must not be summed or compared across distribution entries.
A key lookup that refreshes two cards, with the first selector copied from a product’s collections:
genre, status, talent or kind) is a discovery hint. Before relying on those fields for suitability, buyers check them against the publisher’s adagents.json, exactly as they do for a response copy from include_collections.
Response
Response schema:/schemas/3.3.0-beta.0/media-buy/list-collections-response.json
- One entry per key. A response has at most one entry per
(publisher_domain, collection_id). If a key appears more than once, that collection is unresolvable from the response and the buyer falls back toadagents.json, the same duplicate rule as forinclude_collections. - Silent omission. A selector key that is unknown, or not visible to the caller, is omitted with no per-key error. “Doesn’t exist” and “not yours” look the same, as with the uniform response rule behind
REFERENCE_NOT_FOUND. Buyers detect omissions by comparing their selectors with the returned entries, as they already do forinclude_collections. - What is returned. The seller returns only collections it represents and can sell to the caller, meaning collections that its products offered to that caller can reference. Ended and upcoming collections are allowed, with their
status. It SHOULD return only collections whose publisher’sadagents.jsonauthorizes it, directly or through a collection-scoped selector. Card fields are public display data: the response carries no pricing, availability or account terms.
Authority
Alist_collections entry is a response copy, and the rules in Collections in responses apply unchanged: adagents.json is authoritative, the copy wins only on its closed list of display fields, a copy is never authorization evidence, an unverified copy (of an undeclared collection, or from an agent adagents.json does not authorize) is display-only and never feeds carriage verification, and definition pins hash adagents.json, never the copy. This page does not restate that list.
Consistency with include_collections. Both reads serve the same copy. For the same key, account and moment, a seller MUST return the same copy from list_collections as from a product or proposal read with include_collections: true, and the same copy it pushes in collection_card.updated.
Versioning and caching
collections_version and if_collections_version are this task’s own conditional-fetch tokens. When if_collections_version matches, the seller returns outcome: "unchanged" without collections:
- Scope. The version is scoped to the agent, the canonicalized
collectionsselectors and the canonicalizedfilters, plus account identity whencache_scopeisaccount. Arrays have set semantics.pagination.cursoris outside the scope. A token presented with different selectors or filters is a mismatch and gets a fulllistedresponse. - What moves it. The version changes when any copy the selection would return changes, or when the set of collections it selects changes. A follower refresh that leaves a count’s
lower_bound,upper_boundandprecisionunchanged is not a change: it moves no version and keeps the earlieras_of(see follower counts). - Pages. If a later page arrives with a different
collections_version, the catalog changed mid-walk: restart from the first page, as with wholesale feed versioning. - Independent of product feeds.
collections_versionis not theinclude_collectionsscope offeed_versionorwholesale_feed_version. A change to one says nothing about the others, so card churn never forces a product mirror to refetch. cache_scope. A request withoutaccountgetspublic. A request withaccountgetspublicoraccount, as the seller declares, with the same downgrade semantics as wholesale feeds: a laterpublicon a conditional request that wasaccountmeans the account no longer has its own visible set. Only the set of visible collections may vary by account. The content of a copy for a given key never does: there is one card per collection per seller.
updated_since). Push goes through webhooks.
Collection card webhooks
Registrycollection.* events report the publisher’s authoritative adagents.json declaration. A seller’s card fields (images, sample_content, url, description, season, cadence, distribution[].followers) never reach the registry, so three account-level events push them to buyer mirrors, the way product.* events push products.
Registration
Subscriptions are account-level and durable, throughsync_accounts.accounts[].notification_configs[], exactly like product.* and wholesale_feed.bulk_change. A list_collections call never creates one: the request takes no push_notification_config. A seller that emits these events lists them in wholesale_feed_webhooks.event_types on get_adcp_capabilities. Buyers register only types the seller lists, and sellers reject undeclared types. Subscribing requires an account; buyers browsing without one poll.
Events
The names are not
collection.*, which registry events use for the publisher’s declaration: a buyer dispatching both feeds on the type string must never read a seller’s display copy as the publisher’s declaration. The bulk event is separate from wholesale_feed.bulk_change, so existing product and signal subscribers never receive it.
Envelope
The events reuse the wholesale feed webhook envelope (core/wholesale-feed-webhook.json) unchanged, with one receiver, one signing profile and one set of delivery rules:
notification_idequalsevent.event_id, andnotification_typeequalsevent.event_type.account_idis required, andcache_scopeequalsevent.payload.applies_to.scope.product_payload_viewis omitted.wholesale_feed_versioncarries the post-changecollections_versionof the unfiltered catalog, the same way thelist_productsfeed_versiontravels in that field.event.entity_typeiscollectionfor card events andfeedfor the bulk event.entity_idis opaque: receivers key the mirror on the payload’s(publisher_domain, collection_id), never onentity_id.- Delivery follows the persistent webhook contract unchanged: at least once, deduped on
idempotency_key, no ordering guarantee, and RFC 9421 signing (webhook_signing.supportedistrueoncewholesale_feed_webhooks.supportedis).
Volume
- Per-card
collection_card.updatedis for an editorial change to one card (a new thumbnail, a new sample, a description orseasonedit, a status change) and for one card entering the catalog.collection_card.removedis for one card leaving it. - A seller SHOULD send one
collection_catalog.bulk_changeinstead of per-card events when one operation touches more than 5% of the catalog or more than 100 cards, whichever is smaller. This is the wholesale feed threshold. A scheduled sweep that refreshes follower counts is the typical case and SHOULD always go out as one bulk event, never as a stream of per-card events. - A refresh that leaves a count’s bounds and
precisionunchanged is not a card change: it fires nothing and produces no new version, and the earlieras_ofstays.
Versions and repair
These follow the wholesale feed rules, applied tolist_collections:
- Bootstrap from an unfiltered
list_collectionsread (no selectors, no filters) of every page, and storecollections_versionandcache_scope. Webhook versions describe the unfiltered catalog for theircache_scope, so tokens from filtered reads cannot be compared with them. - Apply each event, then store the event’s version.
- On a gap (
previous_wholesale_feed_versiondoesn’t match the stored version), a failed signature, or a stale version, repair withlist_collectionsandif_collections_versionset to the last applied version. The webhook’s version is never the conditional token for a stale mirror. - On
collection_catalog.bulk_change, or any uncertain state, drop the token and replace the mirror from a complete unfiltered read.
Authority, scope and privacy
- A pushed card is a response copy, and the authority rules apply unchanged.
collection_card.removedmeans only that this seller stopped offering the card. It does not mean the collection was retired or that authorization changed; those facts arrive as registrycollection.removedandauthorization.revoked. - A buyer recomputes its merged view when either feed fires. A card event changes closed-list fields, a registry event changes anchored fields, and neither overrides the other’s fields.
applies_tois required on every event. Because copy content does not vary by account, account-scoped events only move a card into or out of an account’s visible set, and content changes to a public card arepublicevents.- Sellers MUST apply the
list_collectionsvisibility predicate when they emit. A subscriber whose account cannot see a card throughlist_collectionsMUST NOT receive its events.
Capability and version gate
- Feature id.
media_buy.collection_catalogcoverslist_collections, its request and response schemas, and the three webhook event types. A seller that lists it MUST also listmedia_buy.collection_cards. A seller can serve cards in-band throughinclude_collectionswithout running this read, and the two surfaces can graduate separately. - Discovery. The task is not in
media_buy.lifecycle_tools, which lists the product and MediaBuy lifecycle. Buyers see the feature id, and the tool intools/listor the A2A skills. - Webhooks are optional within the feature. A seller can declare the read without push. Listing any
collection_card.*event orcollection_catalog.bulk_changeinwholesale_feed_webhooks.event_typesrequires listingmedia_buy.collection_catalog, becauselist_collectionsis the repair path. - Version gate.
list_collectionsis a 3.3 task. A seller MUST NOT serve it to a caller whoseadcp_versionis below 3.3, and fails such a request withUNSUPPORTED_FEATURE.
Conformance
Thecollection-copies test vectors grade the buyer’s merged view of a copy and adagents.json, seller responses, webhook payloads, and mirror application, before any agent emits these events. Storyboards follow once the training agent supports the task.