Skip to main content
Manage catalog feeds on a seller account. Sync product feeds, inventory data, store locations, offerings, and industry-vertical catalogs (hotel, flight, job, vehicle, real estate, education, destination). Supports URL-based feeds with scheduled re-fetch, inline item data, and discovery of existing catalogs. Response Time: Instant to days (returns completed for small catalogs, or submitted for large feeds requiring platform review) Request Schema: /schemas/latest/media-buy/sync-catalogs-request.json Response Schema: /schemas/latest/media-buy/sync-catalogs-response.json

Who calls whom

The buyer calls sync_catalogs on the seller to push catalog feeds to the seller’s account. The seller validates items, runs content policy checks, and returns per-item approval status. This task sits between format discovery and creative submission in the account state setup sequence:
  1. list_creative_formats — check catalog asset types in each format’s assets array to know what feeds to sync
  2. sync_catalogs — push the required feeds to the account
  3. sync_creatives — submit creatives that reference synced catalogs by catalog_id
  4. create_media_buy — launch the campaign

Quick start

Sync a product feed:
{
  "account": { "account_id": "acct_acmecorp" },
  "catalogs": [
    {
      "catalog_id": "product-feed",
      "name": "Acme Product Catalog",
      "type": "product",
      "url": "https://feeds.acmecorp.com/products.xml",
      "feed_format": "google_merchant_center",
      "update_frequency": "daily"
    }
  ]
}

Request parameters

ParameterTypeRequiredDescription
accountaccount-refConditionalAccount reference. Pass { "account_id": "..." } or { "brand": {...}, "operator": "..." } if the seller supports implicit resolution. Required when the agent has multiple accounts.
catalogsCatalog[]NoCatalog feeds to sync (max 50). Omit for discovery mode.
catalog_idsstring[]NoLimit sync scope to specific catalog IDs. Others on the account are unaffected.
delete_missingbooleanNoWhen true, buyer-managed catalogs not in this sync are removed. Does not affect seller-managed catalogs. Requires catalogs to be present. Default: false.
dry_runbooleanNoPreview changes without applying. Default: false.
validation_modestringNo"strict" (default) fails entire sync on any error. "lenient" processes valid catalogs and reports errors.
push_notification_configobjectNoWebhook configuration for async completion notification.

Catalog object

Each catalog in the catalogs array is a Catalog object. Key fields:
FieldTypeRequiredDescription
catalog_idstringYesBuyer’s identifier. Used to match existing catalogs for upsert.
typeCatalogTypeYesCatalog type: product, offering, inventory, store, promotion, hotel, flight, job, vehicle, real_estate, education, destination
urluriNoExternal feed URL. Mutually exclusive with items.
feed_formatstringNoFeed format: google_merchant_center, facebook_catalog, shopify, linkedin_jobs, custom
update_frequencystringNoRe-fetch schedule: realtime, hourly, daily, weekly
itemsobject[]NoInline catalog data. Mutually exclusive with url.
conversion_eventsEventType[]NoEvent types representing conversions for items in this catalog

Response

Success response — per-catalog results:
FieldTypeDescription
catalogsobject[]Results for each catalog processed
catalogs[].catalog_idstringCatalog ID from request
catalogs[].actionstringcreated, updated, unchanged, failed, deleted
catalogs[].platform_idstringPlatform-assigned ID
catalogs[].item_countintegerTotal items after sync
catalogs[].items_approvedintegerItems approved by platform
catalogs[].items_pendingintegerItems awaiting review
catalogs[].items_rejectedintegerItems rejected
catalogs[].item_issuesobject[]Per-item rejection reasons
catalogs[].next_fetch_atdatetimeNext scheduled feed fetch (URL-based catalogs)
Error response — operation failed entirely:
FieldTypeDescription
errorsError[]Operation-level errors (auth failure, service unavailable)
Responses use discriminated unions — you get either catalogs or errors, never both.

Example response with item-level review

{
  "catalogs": [
    {
      "catalog_id": "product-feed",
      "action": "created",
      "platform_id": "plat_cat_001",
      "item_count": 1250,
      "items_approved": 1180,
      "items_pending": 45,
      "items_rejected": 25,
      "item_issues": [
        {
          "item_id": "SKU-789",
          "status": "rejected",
          "reasons": ["Missing required field: image_url"]
        }
      ],
      "next_fetch_at": "2025-03-01T06:00:00Z"
    }
  ]
}

Item review lifecycle

Catalog items follow a simple review cycle: items enter pending on sync, and the platform reviews them asynchronously. Items are either approved, rejected (with reasons), or approved with warning (serving but with fixable issues). Rejection is not terminal — fix the issue in the source catalog and re-sync. Re-syncing an item resets it to pending for re-review. The item_issues array on the response identifies per-item rejection reasons.

Discovery mode

Omit catalogs to list all catalogs on the account without modification:
{
  "account": { "account_id": "acct_acmecorp" }
}
This matters because sellers may already have brand data from other sources — a retailer might have the brand’s product catalog from their commerce platform. Discovery lets the buyer build on existing state rather than re-uploading everything.

Async approval workflow

Large feeds or feeds requiring content policy review return status: "submitted" with a task_id. The seller reviews items asynchronously and notifies the buyer via webhook when done. Async response states:
  • working — platform is processing the feed (fetching URL, validating items)
  • input-required — platform needs buyer action (fix validation errors, provide missing fields)
  • submitted — review complete, final per-catalog results available
Configure push_notification_config on the request to receive webhook notifications for state transitions.

Common scenarios

Retail media (product + inventory + store)

{
  "account": { "account_id": "acct_acmecorp" },
  "catalogs": [
    {
      "catalog_id": "product-feed",
      "type": "product",
      "url": "https://feeds.acmecorp.com/products.xml",
      "feed_format": "google_merchant_center",
      "update_frequency": "daily"
    },
    {
      "catalog_id": "inventory-feed",
      "type": "inventory",
      "url": "https://feeds.acmecorp.com/inventory.json",
      "feed_format": "custom",
      "update_frequency": "hourly"
    },
    {
      "catalog_id": "store-locations",
      "type": "store",
      "url": "https://feeds.acmecorp.com/stores.json",
      "feed_format": "custom",
      "update_frequency": "weekly"
    }
  ]
}

Recruitment (inline job offerings)

{
  "account": { "account_id": "acct_restaurants" },
  "catalogs": [
    {
      "catalog_id": "chef-vacancies",
      "type": "offering",
      "items": [
        {
          "offering_id": "chef-amsterdam-42",
          "name": "Head Chef - Amsterdam",
          "landing_url": "https://jobs.acme-restaurants.com/chef-amsterdam-42",
          "geo_targets": {
            "countries": ["NL"],
            "regions": ["NL-NH"]
          }
        }
      ]
    }
  ]
}

Dry run validation

{
  "account": { "account_id": "acct_acmecorp" },
  "dry_run": true,
  "catalogs": [
    {
      "catalog_id": "product-feed",
      "type": "product",
      "url": "https://feeds.acmecorp.com/products.xml",
      "feed_format": "google_merchant_center"
    }
  ]
}

Error handling

ErrorDescriptionResolution
CATALOG_NOT_FOUNDReferenced catalog_id doesn’t exist (when using catalog_ids filter)Verify catalog IDs from a previous sync or discovery call
FEED_FETCH_FAILEDPlatform couldn’t fetch the feed URLCheck URL accessibility, authentication, and feed format
INVALID_FEED_FORMATFeed doesn’t match declared feed_formatVerify feed content matches the format (XML for google_merchant_center, etc.)
ITEM_VALIDATION_FAILEDItems failed schema validationCheck item_issues for per-item rejection reasons
CATALOG_LIMIT_EXCEEDEDAccount has reached maximum catalog countRemove unused catalogs or contact seller

Best practices

  1. Check format requirements first — Call list_creative_formats and check catalog asset types in each format’s assets array before syncing. This tells you what catalog types to sync and what fields each item needs.
  2. Use discovery mode — Before syncing, call without catalogs to see what the seller already has. The seller may have brand data from other sources.
  3. Set update_frequency — For URL-based feeds, always set update_frequency so the platform knows how often to re-fetch. Stale feeds lead to ads showing out-of-stock products.
  4. Declare conversion_events — Connect catalogs to the conversion tracking system by declaring which event types represent conversions for catalog items.
  5. Use dry_run for large feeds — Validate before committing, especially for first-time syncs with thousands of items.
  6. Handle per-item failures — In lenient mode, valid items are processed even when others fail. Check item_issues on the response to fix rejected items.

Next steps

  • Catalogs — Complete documentation on catalog types, sourcing, and format requirements
  • Account state — How catalogs fit into the account setup sequence
  • sync_creatives — Submit creatives that reference synced catalogs
  • list_creative_formats — Discover format catalog requirements