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

# Catalogs

> Product, job, store and offer feeds: supported formats, versions, transforms and activation.

A **catalog** is a feed of items (products, jobs, stores, offers) that belongs to an advertiser.
Semi reads it on a schedule, keeps a version each time the items change, and can fan it out into
campaigns, creative and seller feeds.

## Supported formats

| Format                     | What we read                                                                                    |
| -------------------------- | ----------------------------------------------------------------------------------------------- |
| JSON                       | An array of items, or an object with `items`, `products`, `entries`, `data`, `jobs` or `stores` |
| CSV / TSV                  | A header row, then one item per line                                                            |
| RSS / Atom XML             | Each `<item>` or `<entry>`                                                                      |
| Google Merchant Center XML | `<item>` elements with `g:` fields (`g:id`, `g:title`, `g:price`, …)                            |

Every item needs an id. The first of `id`, `sku`, `offer_id`, `item_id`, `product_id`, `job_id`,
`store_id` or `guid` is used. Field names are normalized to `snake_case` and the `g:` prefix is
dropped. A feed can hold up to 5,000 items and 20 MB.

## Connecting a feed

Ask Semi to connect a feed URL, or call `sync_catalogs`:

```json theme={null}
{
  "advertiserId": 201,
  "catalogs": [
    {
      "name": "Product feed",
      "type": "product",
      "url": "https://example.com/feed.json",
      "updateFrequency": "daily"
    }
  ]
}
```

The feed is fetched right away. Each fetch is a **refresh run** (status, HTTP status, item count).
When the items changed, a new **version** is stored with its change summary (added, updated,
removed, unchanged). Inline items (`items: [...]`) work the same way without a URL.

A feed is **stale** once twice its update frequency has passed without a successful refresh.

## Transform and activation

A **transform** says how to fan the catalog out:

* `groupBy`: item fields that split items into campaign groups (for example `category`)
* `creativePrompt`: the creative brief per group; `{field}` placeholders take the group's values
* `budgetPerGroup`: the budget each campaign group starts with, in the advertiser's currency

`preview_catalog_activation_plan` shows the campaign groups, creative assets and seller targets.
`execute_catalog_activation_plan` creates one **draft** campaign per group (nothing is booked or
spent), queues creative generation, and shares the catalog over AdCP `sync_catalogs` with the
catalog-driven sellers you buy from. Sellers that take assembled creative wait for the creative;
sellers without a catalog or creative handoff are skipped.

## REST

| Method | Path                                                                          |
| ------ | ----------------------------------------------------------------------------- |
| GET    | `/api/v2/buyer/advertisers/{id}/catalogs`                                     |
| POST   | `/api/v2/buyer/advertisers/{id}/catalogs/sync`                                |
| PUT    | `/api/v2/buyer/advertisers/{id}/catalogs/{catalogId}/transform`               |
| POST   | `/api/v2/buyer/advertisers/{id}/catalogs/{catalogId}/activation-plan/preview` |
| POST   | `/api/v2/buyer/advertisers/{id}/catalogs/{catalogId}/refresh`                 |
| POST   | `/api/v2/buyer/advertisers/{id}/catalogs/{catalogId}/activation-plan/execute` |
