> ## Documentation Index
> Fetch the complete documentation index at: https://agenticadvertisingorg-feature-feedback.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Collection List Management

> Collection list tasks in AdCP create, update, get, list, and delete inclusion and exclusion lists for content programs, combining explicit program references with dynamic genre and content rating filters.

# Collection list management

Collection lists are managed, cacheable artifacts that express "these collections, filtered by these criteria." They parallel [property lists](/docs/governance/property/tasks/property_lists) but operate on content programs (shows, series, podcasts) rather than technical surfaces (domains, apps).

## Architecture

```
SETUP TIME                          BID TIME                    REFRESH
─────────────                       ────────                    ───────
Buyer creates list ──► Governance    Seller uses cached ◄── Webhook notifies
  base_collections      agent          collection list        seller to
  + filters             resolves                              re-fetch
                        & caches
```

Collection lists are **setup-time resources**. They are resolved once by the governance agent, cached by sellers, and used in delivery decisions without runtime calls back to the governance agent.

## Tasks overview

| Task                     | Purpose                              | Response time    |
| ------------------------ | ------------------------------------ | ---------------- |
| `create_collection_list` | Create a new collection list         | Seconds          |
| `get_collection_list`    | Fetch list with resolved collections | Seconds (cached) |
| `update_collection_list` | Modify base collections or filters   | Seconds          |
| `list_collection_lists`  | List collection lists for an account | Seconds          |
| `delete_collection_list` | Remove a collection list             | Seconds          |

## Base collection sources

Collection lists start with a base set of collections selected through three patterns:

### distribution\_ids

Select collections by platform-independent identifiers. The primary mechanism for cross-publisher exclusion — an IMDb ID identifies a program regardless of which CTV platform carries it.

```json theme={null}
{
  "selection_type": "distribution_ids",
  "identifiers": [
    { "type": "imdb_id", "value": "tt9999901" },
    { "type": "gracenote_id", "value": "SH000001" },
    { "type": "eidr_id", "value": "10.5240/XXXX-XXXX-XXXX-XXXX-XXXX-C" }
  ]
}
```

### publisher\_collections

Select specific collections within a publisher's `adagents.json` by collection ID. Use when the publisher's internal identifiers are known.

```json theme={null}
{
  "selection_type": "publisher_collections",
  "publisher_domain": "titanstreaming.com",
  "collection_ids": ["danger_zone", "wild_nights"]
}
```

### publisher\_genres

Select all collections from a publisher matching genre criteria. Use when excluding entire content categories from a specific publisher.

```json theme={null}
{
  "selection_type": "publisher_genres",
  "publisher_domain": "streamhaus.com",
  "genres": ["news"],
  "genre_taxonomy": "iab_content_3.0"
}
```

When `base_collections` is omitted, the list applies filters against the governance agent's entire collection database.

## Filters

Filters narrow the resolved list after base collection selection:

| Filter                     | Type              | Logic | Description                                                               |
| -------------------------- | ----------------- | ----- | ------------------------------------------------------------------------- |
| `content_ratings_exclude`  | ContentRating\[]  | OR    | Exclude collections with any of these ratings                             |
| `content_ratings_include`  | ContentRating\[]  | OR    | Include only collections with these ratings                               |
| `genres_exclude`           | string\[]         | OR    | Exclude collections tagged with any genre                                 |
| `genres_include`           | string\[]         | OR    | Include only collections with any genre                                   |
| `genre_taxonomy`           | string            | —     | Taxonomy for genre filter values                                          |
| `kinds`                    | string\[]         | OR    | Filter to collection kinds (series, publication, event\_series, rotation) |
| `exclude_distribution_ids` | DistributionId\[] | OR    | Always exclude these specific collections                                 |
| `production_quality`       | string\[]         | OR    | Filter by production quality tier                                         |

**Include vs. exclude**: include filters are allowlists, exclude filters are blocklists. When both are present for the same dimension, include is applied first, then exclude narrows further.

**Example:** A list with `genres_include: ["drama", "comedy"]` and `genres_exclude: ["crime"]` first includes only drama and comedy collections, then removes any tagged as crime. A collection tagged `["drama", "crime"]` is excluded — the exclude filter wins. A collection tagged `["sports"]` is excluded by the include filter (not in the allowed set).

**Content ratings are metadata filters, not content evaluation.** `content_ratings_exclude: [{ system: "tv_parental", rating: "TV-MA" }]` excludes all collections *declared* as TV-MA. It doesn't evaluate individual episodes — that's [content standards](/docs/governance/content-standards/index).

**Genre taxonomy** normalizes genre matching between buyers and sellers. Supported taxonomies: `iab_content_3.0`, `iab_content_2.2`, `gracenote`, `eidr`, `apple_genres`, `google_genres`, `roku`, `amazon_genres`, `custom`. The `custom` value is an escape hatch for publisher-defined taxonomies — buyer and seller negotiate the vocabulary out of band.

## create\_collection\_list

Create a new collection list on a governance agent.

**Request:**

```json theme={null}
{
  "$schema": "https://adcontextprotocol.org/schemas/v3/collection/create-collection-list-request.json",
  "idempotency_key": "c5d6e7f8-a9b0-4123-c456-123456789012",
  "name": "Nova Motors CTV Do Not Air — 2026",
  "description": "Programs excluded from Nova Motors CTV advertising",
  "base_collections": [
    {
      "selection_type": "distribution_ids",
      "identifiers": [
        { "type": "imdb_id", "value": "tt9999901" },
        { "type": "imdb_id", "value": "tt9999902" }
      ]
    },
    {
      "selection_type": "publisher_genres",
      "publisher_domain": "streamhaus.com",
      "genres": ["news", "crime"],
      "genre_taxonomy": "iab_content_3.0"
    }
  ],
  "filters": {
    "content_ratings_exclude": [
      { "system": "tv_parental", "rating": "TV-MA" },
      { "system": "bbfc", "rating": "18" }
    ],
    "genres_exclude": ["news"],
    "genre_taxonomy": "iab_content_3.0",
    "kinds": ["series"]
  },
  "brand": { "domain": "novamotors.com" }
}
```

**Response:**

```json theme={null}
{
  "$schema": "https://adcontextprotocol.org/schemas/v3/collection/create-collection-list-response.json",
  "status": "completed",
  "list": {
    "list_id": "cl_novamotors_dna_2026",
    "name": "Nova Motors CTV Do Not Air — 2026",
    "collection_count": 247,
    "created_at": "2026-04-07T12:00:00Z",
    "updated_at": "2026-04-07T12:00:00Z"
  },
  "auth_token": "tok_example_store_this_securely"
}
```

The `auth_token` is only returned at creation time. Store it — it authorizes sellers to fetch this list.

## get\_collection\_list

Retrieve a collection list with resolved collections. Sellers call this to fetch and cache the list.

**Request:**

```json theme={null}
{
  "$schema": "https://adcontextprotocol.org/schemas/v3/collection/get-collection-list-request.json",
  "list_id": "cl_novamotors_dna_2026",
  "resolve": true,
  "pagination": {
    "max_results": 1000
  }
}
```

**Response:**

```json theme={null}
{
  "$schema": "https://adcontextprotocol.org/schemas/v3/collection/get-collection-list-response.json",
  "status": "completed",
  "list": {
    "list_id": "cl_novamotors_dna_2026",
    "name": "Nova Motors CTV Do Not Air — 2026",
    "collection_count": 247
  },
  "collections": [
    {
      "collection_rid": "019abc12-3d4e-7f5a-ab6c-7d8e9f0a1b2c",
      "name": "Danger Zone",
      "distribution_ids": [
        { "type": "imdb_id", "value": "tt9999901" }
      ],
      "content_rating": { "system": "tv_parental", "rating": "TV-MA" },
      "genre": ["comedy", "animation"],
      "genre_taxonomy": "iab_content_3.0",
      "kind": "series"
    }
  ],
  "pagination": { "has_more": false },
  "resolved_at": "2026-04-07T14:00:00Z",
  "cache_valid_until": "2026-04-14T14:00:00Z",
  "coverage_gaps": {
    "genre": [
      { "type": "imdb_id", "value": "tt9999905" }
    ]
  }
}
```

**Coverage gaps** report collections included in the list despite missing metadata for a filtered dimension. In this example, `tt9999905` was included but has no genre metadata — the governance agent couldn't confirm it matches the genre filter.

**Caching**: sellers should cache the resolved collections and re-fetch after `cache_valid_until`. The default cache duration is 168 hours (one week) because collection metadata changes less frequently than property metadata.

## update\_collection\_list

Modify an existing collection list. `base_collections` and `filters` are complete replacements, not patches.

```json theme={null}
{
  "$schema": "https://adcontextprotocol.org/schemas/v3/collection/update-collection-list-request.json",
  "idempotency_key": "d6e7f8a9-b0c1-4234-d567-234567890123",
  "list_id": "cl_novamotors_dna_2026",
  "base_collections": [
    {
      "selection_type": "distribution_ids",
      "identifiers": [
        { "type": "imdb_id", "value": "tt9999901" },
        { "type": "imdb_id", "value": "tt9999902" },
        { "type": "imdb_id", "value": "tt9999903" }
      ]
    }
  ],
  "filters": {
    "content_ratings_exclude": [
      { "system": "tv_parental", "rating": "TV-MA" }
    ]
  },
  "webhook_url": "https://governance.pinnacleagency.com/webhooks/collection-lists"
}
```

## list\_collection\_lists

List collection lists for an account. Returns metadata only, not resolved collections.

```json theme={null}
{
  "$schema": "https://adcontextprotocol.org/schemas/v3/collection/list-collection-lists-request.json",
  "account": { "brand": { "domain": "novamotors.com" }, "operator": "pinnacleagency.com" },
  "pagination": { "max_results": 50 }
}
```

## delete\_collection\_list

Remove a collection list. Sellers with cached copies will stop receiving webhook updates.

```json theme={null}
{
  "$schema": "https://adcontextprotocol.org/schemas/v3/collection/delete-collection-list-request.json",
  "idempotency_key": "e7f8a9b0-c1d2-4345-e678-345678901234",
  "list_id": "cl_novamotors_dna_2026"
}
```

## Webhooks

When a collection list's resolved collections change (new programs matched, ratings updated, programs removed), the governance agent sends a webhook notification:

```json theme={null}
{
  "idempotency_key": "clch_01HW9DEPJ5MN8Q2R4T6V8X0Z2B",
  "event": "collection_list_changed",
  "list_id": "cl_novamotors_dna_2026",
  "list_name": "Nova Motors CTV Do Not Air — 2026",
  "change_summary": {
    "collections_added": 3,
    "collections_removed": 1,
    "total_collections": 249
  },
  "resolved_at": "2026-04-08T10:00:00Z",
  "cache_valid_until": "2026-04-15T10:00:00Z",
  "signature": "..."
}
```

Webhooks contain a summary only — recipients must call `get_collection_list` for the updated entries. Recipients MUST verify the `signature` before processing and MUST dedupe by `idempotency_key` so retried deliveries of the same change event are ignored.

## Live sports

Live sports is one of the largest CTV brand safety concerns. Collection lists handle it through the `event_series` kind:

```json theme={null}
{
  "$schema": "https://adcontextprotocol.org/schemas/v3/collection/create-collection-list-request.json",
  "idempotency_key": "f8a9b0c1-d2e3-4456-f789-456789012345",
  "name": "Acme Outdoor — Excluded Sports Events",
  "base_collections": [
    {
      "selection_type": "distribution_ids",
      "identifiers": [
        { "type": "gracenote_id", "value": "SP000001" },
        { "type": "gracenote_id", "value": "SP000002" }
      ]
    }
  ],
  "filters": {
    "kinds": ["event_series"],
    "genres_exclude": ["combat_sports"],
    "genre_taxonomy": "gracenote"
  },
  "brand": { "domain": "acmeoutdoor.com" }
}
```

This excludes specific sports programs by Gracenote ID (SP-prefixed for sports) and structurally excludes all combat sports event series. The `event_series` kind filter ensures the list targets live event programming, not documentary series about sports.

## Security considerations

Collection lists gate delivery decisions, so the `auth_token` and webhook callbacks need explicit lifecycle rules. General controls in [Security](/docs/building/by-layer/L1/security) apply; the collection-list-specific rules:

**`auth_token` scope, revocation, and log hygiene.** Each token authorizes exactly one `list_id`; do not reuse a token across lists. Governance agents MUST issue a distinct token per seller that receives the list — shared tokens cannot be revoked per relationship and make list-wide rotation the only response to a single compromise. Tokens MUST NOT be written to logs, cache keys, or metric labels, and error responses from `get_collection_list` MUST NOT echo the presented token.

`delete_collection_list` and per-seller revocation differ:

* **Normal deletion or end-of-relationship**: the token MUST fail subsequent `get_collection_list` calls immediately, but sellers with a cached resolution MAY continue serving from cache until `cache_valid_until`. A natural relationship end is not a compromise.
* **Compromise-driven revocation**: the governance agent MUST signal cache invalidation. Either return a reduced `cache_valid_until` (at or before `now`) on the next poll that the seller still has access to complete, or emit a `collection_list_changed` webhook whose `change_summary` conveys that the list version has been invalidated so cached copies are discarded. Leaving compromised content in seller caches until the scheduled TTL is not acceptable.

**Webhook URL validation.** The `webhook_url` on `update_collection_list` is SSRF-equivalent to any other buyer-provided callback URL. Apply the canonical [Webhook URL validation (SSRF)](/docs/building/by-layer/L1/security#webhook-url-validation-ssrf) rules — HTTPS only, validated IP ranges (IPv4 and IPv6 including `::ffff:0:0/96`), connection pinning (not just DNS re-resolution), no redirect following, size and timeout caps.

**Webhook signature algorithm.** The webhook signature MUST follow the [standard webhook signing rules](/docs/building/by-layer/L1/security#webhook-security). By default, the RFC 9421 [webhook callbacks profile](/docs/building/by-layer/L1/security#webhook-callbacks) applies: the governance agent signs with its `adcp_use: "request-signing"` key published at the `jwks_uri` of its `agents[]` entry in its own brand.json; deprecated `webhook-signing` keys remain accepted during the compatibility window. The subscribing seller verifies covered components `@method`, `@target-uri`, `@authority`, `content-type`, `content-digest`, with `tag="adcp/webhook-signing/v1"`. The deprecated HMAC-SHA256 fallback applies only when the subscribing seller populates `authentication.credentials` on the webhook registration; that path follows the [Legacy HMAC-SHA256 fallback](/docs/building/by-layer/L1/security#legacy-hmac-sha256-fallback-deprecated-removed-in-40) rules, and any body `signature` field under that path is a convenience copy — recipients MUST verify against the headers and MUST NOT trust the body value.

**Distribution-ID inputs.** Governance agents SHOULD validate identifier format before persisting (IMDb: `^tt\d+$`, EIDR: `10.5240/...`, Gracenote: vendor-prefixed) and SHOULD enforce per-account rate limits on list mutations to prevent list-bloat DoS. Surface unresolved identifiers in `coverage_gaps` rather than silently dropping them.

## Sharing collection lists with sellers

The pattern matches [property list sharing](/docs/governance/property/index#sharing-property-lists-with-sellers):

1. Create the collection list on a governance agent
2. Store the `auth_token` from the creation response
3. Pass `collection_list` or `collection_list_exclude` in targeting overlays
4. Sellers fetch and cache the resolved list using the auth token
5. Webhooks notify sellers when the list changes
