> ## Documentation Index
> Fetch the complete documentation index at: https://docs.apostra.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Manage advertiser creative collections

> Group an advertiser's saved creatives into named, non-executable collections and keep them current with a revision check

An **advertiser creative collection** is a named group of saved creatives that
belongs to an advertiser rather than to a campaign. It is non-executable: it
does not attach to a campaign, carry a role or sync policy, or deliver anything
on its own. Use it to organise the advertiser's library, for example a brand
kit, an approved set, or a seasonal shelf. To make a collection's creatives
available to a campaign, attach the collection from that campaign with
`POST /api/v2/buyer/campaigns/{campaignId}/creative-collections/{collectionId}/attach`.

Campaign-scoped collections under `/campaigns/{campaignId}/creative-collections`
keep their existing behaviour and are not described here.

## Operations

All paths are under `/api/v2/buyer/advertisers/{advertiserId}`. The advertiser
must belong to the authenticated customer; otherwise the request returns
`NOT_FOUND`.

| Method and path                                       | What it does                                                                                |
| ----------------------------------------------------- | ------------------------------------------------------------------------------------------- |
| `GET /creative-collections`                           | List the advertiser's collections. Accepts `search`, `include_members`, `take`, and `skip`. |
| `POST /creative-collections`                          | Create a collection. `name` is required; `description` and `parent_id` are optional.        |
| `GET /creative-collections/{collectionId}`            | Read one collection with its creative members.                                              |
| `PUT /creative-collections/{collectionId}`            | Rename, re-describe, or move a collection with `parent_id`. Requires `expected_updated_at`. |
| `DELETE /creative-collections/{collectionId}`         | Archive a collection. Requires `expected_updated_at`.                                       |
| `POST /creative-collections/{collectionId}/members`   | Add saved creatives. Body: `member_ids` and `expected_updated_at`.                          |
| `DELETE /creative-collections/{collectionId}/members` | Remove saved creatives. Body: `member_ids` and `expected_updated_at`.                       |

Every response that changes a collection returns the collection as it stands
after the change, read inside the same transaction, and member changes also
return `added_count` or `removed_count`.

## The revision check

Each collection carries `updated_at`. Update and member operations require you
to send that value back as `expected_updated_at`. If the collection changed
since you read it, the request returns `409 CONFLICT` and nothing changes; read
the collection again and retry with the new value. This keeps two people or
agents from silently overwriting each other's work.

## Members

Members are saved creatives owned by the same advertiser. Every id in
`member_ids` must name an active creative of that advertiser; if any id does not,
the request returns `400 VALIDATION_ERROR` and no members are added. Adding a
creative that is already a member is a no-op, and removing an id that is not a
member is a no-op that leaves `updated_at` unchanged. A creative can belong to a
collection whether or not it is assigned to a campaign.

## Clearing a description

Send `"description": null` on the update to clear it. Omitting `description`
leaves it as it is.

## Nesting collections

Set `parent_id` when creating or updating a collection to place it beneath
another active collection owned by the same advertiser. Send `"parent_id":
null` on an update to move it back to the top level. Reads and list results
include `parent_id` and `descendant_member_count`; the latter counts each saved
creative once across the collection and all active descendants.

You cannot make a collection its own parent, move it under one of its
descendants, cross advertiser or customer boundaries, or create a hierarchy
deeper than 16 levels. Archive children first: a collection with active children
cannot be archived.

## In the Creative Library

Collections appear as a navigable tree. Nested collections show their full
path, and a parent count includes distinct saved creatives in child
collections. You can drag a creative onto any collection to add it; the
Library immediately offers Undo for the members it added.

## From an agent

In the v3 tool surface the same operations are `search` and `get` with
`kind: "creative_collection"` and an `advertiserId`, and
`save_creative_collection` with `advertiserId`, the `collectionId`, and the
returned `updatedAt` as `expectedUpdatedAt`. Advertiser writes accept `name`,
`description` (`null` clears it), `parentId` (`null` clears it), and one
`addMemberIds` or `removeMemberIds` list per call. Send `isArchived: true` to
archive a collection after its children are archived. Send `isArchived: false`
with the archive response's `expectedUpdatedAt` to restore it. A restore
requires that its parent, if any, is active and belongs to the same advertiser.
Campaign-only fields such as `role`, `syncPolicy`, and `attachToCampaign` are
refused for advertiser collections.
