> ## 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.

# Sync catalogs

> Push catalog feeds and items to an advertiser

`POST /api/v2/buyer/advertisers/{advertiserId}/catalogs/sync`

Inbound ADCP `sync_catalogs` endpoint. Buyers call this to sync catalog feeds and items onto the advertiser. Provide either a remote feed `url` or inline `items` per catalog — not both.

For an agent on the account-resolved V3 MCP surface, use `save_catalog`
instead. It saves exactly one catalog per request and requires an idempotency
key, so a retry returns the original outcome rather than applying another
update. Its request is one flat catalog object, not a `catalog` wrapper. A URL
is re-fetched on each save; archive through the same tool with `isArchived:
true` and the catalog identity instead of looking for a separate delete
operation:

```json theme={null}
{
  "catalogId": "summer-sale-2026",
  "advertiserId": "12345",
  "name": "Summer Sale 2026",
  "type": "product",
  "url": "https://feeds.acme.com/products.xml",
  "feedFormat": "google_merchant_center",
  "updateFrequency": "daily",
  "idempotencyKey": "save-summer-sale-2026-0001"
}
```

The Catalogs Page uses this operation directly. Choose **Add feed** to connect a
hosted URL or upload a CSV, TSV, XLS, XLSX, or JSON file. For an existing
uploaded feed, choose **Replace file**. The Page keeps progress, validation
errors, approval counts, rejected rows, and field-level issues beside the feed;
it does not copy a generated instruction into chat. If you give Murph an exact
feed URL or inline item payload, Murph can call the same operation directly.

## Request

```bash curl theme={null}
curl -X POST https://api.apostra.com/api/v2/buyer/advertisers/12345/catalogs/sync \
  -H "Authorization: Bearer $SCOPE3_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "account": { "account_id": "12345" },
    "catalogs": [
      {
        "catalog_id": "summer-sale-2026",
        "type": "product",
        "name": "Summer Sale 2026",
        "url": "https://feeds.acme.com/products.xml",
        "feed_format": "google_merchant_center",
        "update_frequency": "daily",
        "conversion_events": ["purchase", "add_to_cart"]
      }
    ],
    "delete_missing": false,
    "validation_mode": "strict"
  }'
```

## Parameters

| Field | Type | Required | Notes |
| - | - | - | - |
| `advertiserId` | string (path) | Yes | Unique identifier for the advertiser |
| `account.account_id` | string | Yes | Advertiser ID to attach catalogs to |
| `catalogs` | array | Yes | Catalog feeds to sync (1–50 per call) |
| `catalogs[].catalog_id` | string | Yes | Buyer-assigned catalog identifier |
| `catalogs[].type` | enum | Yes | `product`, `offering`, `inventory`, `store`, `promotion`, `hotel`, `flight`, `job`, `vehicle`, `real_estate`, `education`, `destination` |
| `catalogs[].name` | string | No | Display name (1–255 chars) |
| `catalogs[].url` | string | No | Remote feed URL. Provide this **or** `items`, not both |
| `catalogs[].items` | array | No | Inline catalog items (max 10000). Provide this **or** `url`, not both |
| `catalogs[].feed_format` | enum | No | `google_merchant_center`, `facebook_catalog`, `shopify`, `linkedin_jobs`, `custom` |
| `catalogs[].update_frequency` | enum | No | `realtime`, `hourly`, `daily`, `weekly` |
| `catalogs[].conversion_events` | array | No | Conversion event IDs linked to this catalog |
| `catalog_ids` | array | No | Only process these `catalog_id`s from the `catalogs` array |
| `delete_missing` | boolean | No | Archive buyer-managed catalogs not in this request. Default `false` |
| `dry_run` | boolean | No | Preview changes without persisting. Default `false` |
| `validation_mode` | enum | No | `strict` (default) or `lenient` item validation |

## Response

```json theme={null}
{
  "catalogs": [
    {
      "catalog_id": "summer-sale-2026",
      "action": "created",
      "platform_id": "cat_abc123",
      "item_count": 1840,
      "items_approved": 1832,
      "items_pending": 0,
      "items_rejected": 8,
      "item_issues": [
        { "item_id": "sku_4471", "field": "image_link", "issue": "unreachable URL", "severity": "error" }
      ],
      "last_synced_at": "2026-06-07T12:00:00Z",
      "next_fetch_at": "2026-06-08T12:00:00Z"
    }
  ],
  "dry_run": false
}
```

Each result carries an `action` of `created`, `updated`, `unchanged`, `failed`, or `deleted`. Item-level problems appear in `item_issues` with `severity` `error` or `warning`. When `dry_run` was `true`, nothing is persisted.

## Errors

* `400 VALIDATION_ERROR` — a catalog supplies both `url` and `items`, exceeds 50 catalogs, or fails `strict` item validation.
* `404 NOT_FOUND` — `advertiserId` does not exist or is not visible to the authenticated account.

See [Errors](/v2/reference/errors) for the full error contract.

## Related

<CardGroup cols={2}>
  <Card title="Advertiser tasks" href="/v2/buyer/advertisers/tasks" icon="list-check">
    All advertiser operations
  </Card>

  <Card title="Advertiser overview" href="/v2/object-guides/advertiser" icon="user-tie">
    Fields, lifecycle, and concepts
  </Card>

  <Card title="List catalogs" href="/v2/buyer/advertisers/tasks/list-catalogs" icon="list-ul">
    See synced catalogs
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.