{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "https://adcontextprotocol.org/schemas/3.2.0-beta.0/core/creative-manifest.json",
  "title": "Creative Manifest",
  "description": "Complete specification of a creative: format identification + assets. In 3.2 a manifest uses `format_kind` (the canonical format name it targets), paired with optional `format_option_ref` when a product has multiple declarations sharing that kind. The deprecated `format_id` named-format branch remains only for 3.x wire compatibility. Everything the creative needs — images, text, briefs, catalogs — lives in the assets map declared by the matching format declaration.",
  "type": "object",
  "properties": {
    "format_id": {
      "$ref": "https://adcontextprotocol.org/schemas/3.2.0-beta.0/core/format-id.json",
      "deprecated": true,
      "description": "**DEPRECATED in 3.2.** Legacy named-format path retained for 3.x compatibility. New manifests use canonical `format_kind` and, when product routing requires it, `format_option_ref`. Mutually exclusive with format_kind."
    },
    "format_kind": {
      "$ref": "https://adcontextprotocol.org/schemas/3.2.0-beta.0/core/canonical-format-kind.json",
      "description": "Canonical 3.2 path. The canonical format name this manifest targets (e.g., `image`, `video_hosted`, `audio_daast`, `sponsored_placement`). Selects the contract against which the seller validates the manifest's assets. Mutually exclusive with deprecated `format_id`."
    },
    "format_option_ref": {
      "$ref": "https://adcontextprotocol.org/schemas/3.2.0-beta.0/core/format-option-ref.json",
      "description": "3.1+ format-option path, optional. Structured format option reference matching one of the target product's `format_options[]` declarations. Publisher-catalog-backed options match by `{ scope: \"publisher\", publisher_domain, format_option_id }`; product-local options match by `{ scope: \"product\", format_option_id }`. Required when the target product carries multiple `format_options` entries sharing the same `format_kind`; optional when `format_kind` alone routes the manifest to a single declaration. Product-scoped refs require an enclosing target product/package context."
    },
    "assets": {
      "type": "object",
      "description": "Map of slot keys to actual asset content. Legacy named-format path: each key matches an `asset_id` from the format's `assets` array (e.g., 'banner_image', 'clickthrough_url', 'video_file', 'vast_tag'). 3.1+ canonical-format path: each key matches an `asset_group_id` from the format's `slots` declaration drawn from the canonical vocabulary registry (e.g., 'images_landscape', 'video', 'published_post', 'landing_page_url', 'vast_tag', 'script', 'creative_brief'). Either path produces the same envelope shape; only the slot-key vocabulary differs.\n\nEach slot value is **either** a single asset object (most slots — image, video, published_post, vast_tag, landing_page_url, etc.) **or** an array of asset objects (slots with `min`/`max` counts on the format declaration — `cards` on `image_carousel`, `headlines` / `descriptions` / `images_landscape` on `responsive_creative`, etc.). Single-vs-array shape is governed by the format's `slots[].min` and `slots[].max` parameters: when `max > 1` (or when the slot is conceptually a pool), the value MUST be an array; when the slot is single-valued, the value MUST be a single object. Each asset value (single or array element) carries an `asset_type` discriminator (image, video, audio, vast, daast, text, markdown, url, html, css, webhook, javascript, brief, catalog, published_post, zip, card) that selects the matching asset schema. Validators with OpenAPI-style discriminator support use `asset_type` to report errors against only the selected branch instead of all branches.",
      "patternProperties": {
        "^[a-z0-9_]+$": {
          "oneOf": [
            {
              "$ref": "https://adcontextprotocol.org/schemas/3.2.0-beta.0/core/assets/asset-union.json"
            },
            {
              "type": "array",
              "items": {
                "$ref": "https://adcontextprotocol.org/schemas/3.2.0-beta.0/core/assets/asset-union.json"
              },
              "minItems": 1
            }
          ]
        }
      },
      "additionalProperties": true
    },
    "brand": {
      "$ref": "https://adcontextprotocol.org/schemas/3.2.0-beta.0/core/brand-ref.json",
      "description": "Brand identity reference (BrandRef — `domain` plus optional `brand_id` for house-of-brands; plus optional inline `brand_kit_override` for per-creative tweaks where brand.json is missing/stale). When present, the seller pulls master brand identity (logo, palette, fonts, voice, and visual guidelines) from the brand's brand.json automatically; supported fields present in `brand_kit_override` take precedence, and all other master identity fields continue to come from brand.json. Catalogs supply product or item payload. Catalog item asset groups — including an item-level `logo` for a property or franchise — are item identity selected through format field bindings; they do not override brand.json's master logo or other brand identity fields. v2 formats no longer redeclare brand_logo / brand_colors / brand_voice as explicit slots — brand identity is implicit context."
    },
    "rights": {
      "type": "array",
      "description": "Rights constraints attached to this creative. Buyer-carried fields are informational until a serving party evaluates an issuer-bound attestation reference under its own policy. Only a verified, unexpired, unrevoked, digest-matched evaluation can support serving authorization; verification_url is never authority.",
      "items": {
        "$ref": "https://adcontextprotocol.org/schemas/3.2.0-beta.0/core/rights-constraint.json"
      }
    },
    "industry_identifiers": {
      "type": "array",
      "description": "Industry-standard or market-specific identifiers for this specific manifest (e.g., Ad-ID, ISCI, Clearcast clock number, IDcrea). When present, overrides creative-level identifiers. Use when different format versions of the same source creative have distinct traffic identifiers (e.g., the :15 and :30 cuts, or separate TV and radio versions). Add a PR to extend creative-identifier-type when another shared identifier scheme needs first-class support.",
      "items": {
        "$ref": "https://adcontextprotocol.org/schemas/3.2.0-beta.0/core/industry-identifier.json"
      },
      "uniqueItems": true
    },
    "provenance": {
      "$ref": "https://adcontextprotocol.org/schemas/3.2.0-beta.0/core/provenance.json",
      "description": "Provenance metadata for this creative manifest. Serves as the default provenance for all assets in this manifest. An asset with its own provenance replaces this object entirely (no field-level merging)."
    },
    "ext": {
      "$ref": "https://adcontextprotocol.org/schemas/3.2.0-beta.0/core/ext.json"
    }
  },
  "required": [
    "assets"
  ],
  "not": {
    "anyOf": [
      {
        "required": [
          "capability_id"
        ]
      },
      {
        "required": [
          "capability_ref"
        ]
      }
    ]
  },
  "oneOf": [
    {
      "title": "Named-format manifest",
      "deprecated": true,
      "description": "Deprecated 3.x compatibility branch. Manifest references a named format via the structured format_id object. New 3.2 manifests use format_kind.",
      "required": [
        "format_id"
      ],
      "not": {
        "required": [
          "format_kind"
        ]
      }
    },
    {
      "title": "Canonical-format manifest",
      "description": "Manifest declares which canonical format it targets via `format_kind` (e.g., `image`). This 3.1+ canonical-format path was introduced by RFC #3305.",
      "required": [
        "format_kind"
      ],
      "not": {
        "required": [
          "format_id"
        ]
      }
    }
  ],
  "additionalProperties": true
}
