From a8723be98e4b9f57f3d1dc26a5a44fd93799ba29 Mon Sep 17 00:00:00 2001 From: BaiyuScope3 Date: Wed, 24 Dec 2025 17:02:14 -0500 Subject: [PATCH 01/10] feat: add unified assets field for better asset discovery - Add new 'assets' array to format schema with 'required' boolean per asset - Deprecate 'assets_required' (still supported for backward compatibility) - Enables full asset discovery for buyers and AI agents - Update server to include both fields in format responses - Update documentation across creative and media-buy docs - Bump version to 2.6.0 --- CHANGELOG.md | 39 +++++++ docs/creative/asset-types.mdx | 20 +++- docs/creative/formats.mdx | 51 ++++++++- .../creative/implementing-creative-agents.mdx | 4 +- .../task-reference/list_creative_formats.mdx | 4 +- package-lock.json | 4 +- package.json | 2 +- server/src/http.ts | 29 +++-- static/schemas/source/core/format.json | 107 +++++++++++++++++- static/schemas/source/index.json | 2 +- 10 files changed, 237 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7ac14daf..156ba372 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,44 @@ # Changelog +## 2.6.0 + +### Minor Changes + +- Add unified `assets` field to format schema for better asset discovery + + **Schema Changes:** + + - **format.json**: Add new `assets` array field that includes both required and optional assets + - **format.json**: Deprecate `assets_required` (still supported for backward compatibility) + + **Rationale:** + + Previously, buyers and AI agents could only see required assets via `assets_required`. There was no way to discover optional assets that enhance creatives (companion banners, third-party tracking pixels, etc.). + + Since each asset already has a `required` boolean field, we introduced a unified `assets` array where: + - `required: true` - Asset MUST be provided for a valid creative + - `required: false` - Asset is optional, enhances the creative when provided + + This enables: + - **Full asset discovery**: Buyers and AI agents can see ALL assets a format supports + - **Richer creatives**: Optional assets like impression trackers can now be discovered and used + - **Cleaner schema**: Single array instead of two separate arrays + + **Example:** + + ```json + { + "format_id": { "agent_url": "https://creative.adcontextprotocol.org", "id": "video_30s" }, + "assets": [ + { "item_type": "individual", "asset_id": "video_file", "asset_type": "video", "required": true }, + { "item_type": "individual", "asset_id": "end_card", "asset_type": "image", "required": false }, + { "item_type": "individual", "asset_id": "impression_tracker", "asset_type": "tracking_pixel", "required": false } + ] + } + ``` + + **Migration:** Non-breaking change. `assets_required` is deprecated but still supported. New implementations should use `assets`. + ## 2.5.1 ### Patch Changes diff --git a/docs/creative/asset-types.mdx b/docs/creative/asset-types.mdx index c3d58aa6..7d669e1a 100644 --- a/docs/creative/asset-types.mdx +++ b/docs/creative/asset-types.mdx @@ -338,7 +338,9 @@ The keys in the assets object correspond to the `asset_id` values defined in the ## Usage in Creative Formats -Creative formats specify their required assets using `assets_required` (an array): +Creative formats specify their assets using the `assets` array. Each asset has a `required` boolean: +- **`required: true`** - Asset MUST be provided for a valid creative +- **`required: false`** - Asset is optional, enhances the creative (e.g., companion banners, third-party tracking pixels) ```json { @@ -346,7 +348,7 @@ Creative formats specify their required assets using `assets_required` (an array "agent_url": "https://creative.adcontextprotocol.org", "id": "video_15s_hosted" }, - "assets_required": [ + "assets": [ { "item_type": "individual", "asset_id": "video_file", @@ -359,11 +361,25 @@ Creative formats specify their required assets using `assets_required` (an array "acceptable_resolutions": ["1920x1080", "1280x720"], "max_file_size_mb": 30 } + }, + { + "item_type": "individual", + "asset_id": "impression_tracker", + "asset_type": "tracking_pixel", + "required": false, + "requirements": { + "format": ["url"], + "description": "Third-party impression tracking pixel URL" + } } ] } ``` + +**Backward Compatibility**: The deprecated `assets_required` field is still supported. New implementations should use `assets`. + + ## Repeatable Asset Groups For formats with asset sequences (like carousels, slideshows, stories), see the [Carousel & Multi-Asset Formats guide](/docs/creative/channels/carousels) for complete documentation on repeatable asset group patterns. diff --git a/docs/creative/formats.mdx b/docs/creative/formats.mdx index 882fe962..be40371c 100644 --- a/docs/creative/formats.mdx +++ b/docs/creative/formats.mdx @@ -216,8 +216,9 @@ Formats are JSON objects with the following key fields: }, "name": "30-Second Hosted Video", "type": "video", - "assets_required": [ + "assets": [ { + "item_type": "individual", "asset_id": "video_file", "asset_type": "video", "asset_role": "hero_video", @@ -227,6 +228,39 @@ Formats are JSON objects with the following key fields: "format": ["MP4"], "resolution": ["1920x1080", "1280x720"] } + }, + { + "item_type": "individual", + "asset_id": "end_card_image", + "asset_type": "image", + "asset_role": "end_card", + "required": false, + "requirements": { + "dimensions": "1920x1080", + "format": ["PNG", "JPG"] + } + }, + { + "item_type": "individual", + "asset_id": "companion_banner", + "asset_type": "image", + "asset_role": "companion", + "required": false, + "requirements": { + "dimensions": "300x250", + "format": ["PNG", "JPG", "GIF"] + } + }, + { + "item_type": "individual", + "asset_id": "impression_tracker", + "asset_type": "tracking_pixel", + "asset_role": "third_party_tracking", + "required": false, + "requirements": { + "format": ["url"], + "description": "Third-party impression tracking pixel URL" + } } ] } @@ -236,10 +270,23 @@ Formats are JSON objects with the following key fields: - **format_id**: Unique identifier (may be namespaced with `domain:id`) - **agent_url**: The creative agent authoritative for this format - **type**: Category (video, display, audio, native, dooh, rich_media) -- **assets_required**: Array of asset specifications +- **assets**: Array of all asset specifications with `required` boolean indicating mandatory vs optional - **asset_role**: Identifies asset purpose (hero_image, logo, cta_button, etc.) - **renders**: Array of rendered outputs with dimensions - see below +### Asset Discovery + +The `assets` array enables comprehensive asset discovery. Each asset has a `required` boolean: + +- **`required: true`** - Asset MUST be provided for a valid creative +- **`required: false`** - Asset is optional, enhances the creative when provided (e.g., companion banners, third-party tracking pixels) + +This unified approach helps creative tools and AI agents understand the full capabilities of a format, enabling richer creative experiences when optional assets are available while clearly indicating minimum requirements. + + +**Backward Compatibility**: The deprecated `assets_required` field is still supported for existing implementations. New implementations should use `assets` with the `required` boolean on each asset. + + ### Rendered Outputs and Dimensions Formats specify their rendered outputs via the `renders` array. Most formats produce a single render, but some (companion ads, adaptive formats, multi-placement) produce multiple renders: diff --git a/docs/creative/implementing-creative-agents.mdx b/docs/creative/implementing-creative-agents.mdx index 98671f1e..dea73b14 100644 --- a/docs/creative/implementing-creative-agents.mdx +++ b/docs/creative/implementing-creative-agents.mdx @@ -100,7 +100,7 @@ Creative agents must implement these two tasks: Return all formats your agent defines. This is how buyers discover what creative formats you support. **Key responsibilities:** -- Return complete format definitions with all `assets_required` +- Return complete format definitions with all `assets` (both required and optional) - Include your `agent_url` in each format - Use proper namespacing for `format_id` values @@ -169,7 +169,7 @@ When validating manifests: When updating format definitions: -- **Additive changes** (new optional assets) are safe +- **Additive changes** (new optional assets in `assets_optional`) are safe - **Breaking changes** (removing assets, changing requirements) require new format_id - Consider versioning: `youragency.com:format_name_v2` - Maintain backward compatibility when possible diff --git a/docs/media-buy/task-reference/list_creative_formats.mdx b/docs/media-buy/task-reference/list_creative_formats.mdx index f5f7ed11..30c4ba1b 100644 --- a/docs/media-buy/task-reference/list_creative_formats.mdx +++ b/docs/media-buy/task-reference/list_creative_formats.mdx @@ -40,7 +40,7 @@ Formats may produce multiple rendered pieces (e.g., video + companion banner). D | Field | Description | |-------|-------------| -| `formats` | Array of full format definitions (format_id, name, type, requirements, assets_required, renders) | +| `formats` | Array of full format definitions (format_id, name, type, requirements, assets, renders) | | `creative_agents` | Optional array of other creative agents providing additional formats | See [Format schema](https://adcontextprotocol.org/schemas/v2/core/format.json) for complete format object structure. @@ -405,7 +405,7 @@ Each format includes: | `name` | Human-readable format name | | `type` | Format type (audio, video, display, dooh) | | `requirements` | Technical requirements (duration, file types, bitrate, etc.) | -| `assets_required` | Array of required assets with specifications | +| `assets` | Array of all assets with `required` boolean indicating mandatory vs optional | | `renders` | Array of rendered output pieces (dimensions, role) | ### Asset Roles diff --git a/package-lock.json b/package-lock.json index db95e222..31742dbf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "adcontextprotocol", - "version": "2.5.0", + "version": "2.5.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "adcontextprotocol", - "version": "2.5.0", + "version": "2.5.2", "dependencies": { "@adcp/client": "^3.4.0", "@modelcontextprotocol/sdk": "^1.24.3", diff --git a/package.json b/package.json index 0ec58a95..91ded87e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "adcontextprotocol", - "version": "2.5.1", + "version": "2.6.0", "private": true, "scripts": { "start": "bash -c 'source <(grep CONDUCTOR_PORT .env.local | sed \"s/^/export /\") && DOTENV_CONFIG_PATH=.env.local PORT=${CONDUCTOR_PORT:-3000} tsx watch server/src/index.ts'", diff --git a/server/src/http.ts b/server/src/http.ts index 3b9718d9..fbcbe426 100644 --- a/server/src/http.ts +++ b/server/src/http.ts @@ -8334,18 +8334,23 @@ Disallow: /api/admin/ return res.json({ success: true, - formats: formats.map(format => ({ - format_id: format.format_id, - name: format.name, - type: format.type, - description: format.description, - preview_image: format.preview_image, - example_url: format.example_url, - renders: format.renders, - assets_required: format.assets_required, - output_format_ids: format.output_format_ids, - agent_url: format.agent_url, - })), + formats: formats.map(format => { + // Cast to allow 'assets' field (added in schema v2.5.2, @adcp/client may not have it yet) + const formatWithAssets = format as typeof format & { assets?: unknown }; + return { + format_id: format.format_id, + name: format.name, + type: format.type, + description: format.description, + preview_image: format.preview_image, + example_url: format.example_url, + renders: format.renders, + assets_required: format.assets_required, // deprecated but kept for backward compatibility + assets: formatWithAssets.assets, // new unified field + output_format_ids: format.output_format_ids, + agent_url: format.agent_url, + }; + }), }); } catch (error) { logger.error({ err: error, url }, 'Agent formats fetch error'); diff --git a/static/schemas/source/core/format.json b/static/schemas/source/core/format.json index d778d5de..b399d24c 100644 --- a/static/schemas/source/core/format.json +++ b/static/schemas/source/core/format.json @@ -121,7 +121,7 @@ }, "assets_required": { "type": "array", - "description": "Array of required assets or asset groups for this format. Each asset is identified by its asset_id, which must be used as the key in creative manifests. Can contain individual assets or repeatable asset sequences (e.g., carousel products, slideshow frames).", + "description": "DEPRECATED: Use 'assets' instead. Array of required assets or asset groups for this format. Each asset is identified by its asset_id, which must be used as the key in creative manifests. Can contain individual assets or repeatable asset sequences (e.g., carousel products, slideshow frames). This field is maintained for backward compatibility; new implementations should use 'assets' with the 'required' boolean on each asset.", "items": { "oneOf": [ { @@ -217,6 +217,111 @@ ] } }, + "assets": { + "type": "array", + "description": "Array of all assets supported for this format. Each asset is identified by its asset_id, which must be used as the key in creative manifests. Use the 'required' boolean on each asset to indicate whether it's mandatory. This field replaces the deprecated 'assets_required' and enables full asset discovery for buyers and AI agents.", + "items": { + "oneOf": [ + { + "description": "Individual asset specification", + "type": "object", + "properties": { + "item_type": { + "type": "string", + "const": "individual", + "description": "Discriminator indicating this is an individual asset" + }, + "asset_id": { + "type": "string", + "description": "Unique identifier for this asset. Creative manifests MUST use this exact value as the key in the assets object." + }, + "asset_type": { + "$ref": "/schemas/enums/asset-content-type.json", + "description": "Type of asset" + }, + "asset_role": { + "type": "string", + "description": "Optional descriptive label for this asset's purpose (e.g., 'hero_image', 'logo', 'third_party_tracking'). Not used for referencing assets in manifests—use asset_id instead. This field is for human-readable documentation and UI display only." + }, + "required": { + "type": "boolean", + "description": "Whether this asset is required (true) or optional (false). Required assets must be provided for a valid creative. Optional assets enhance the creative but are not mandatory.", + "default": false + }, + "requirements": { + "type": "object", + "description": "Technical requirements for this asset (dimensions, file size, duration, etc.). For template formats, use parameters_from_format_id: true to indicate asset parameters must match the format_id parameters (width/height/unit and/or duration_ms).", + "additionalProperties": true + } + }, + "required": ["item_type", "asset_id", "asset_type"] + }, + { + "description": "Repeatable asset group (for carousels, slideshows, playlists, etc.)", + "type": "object", + "properties": { + "item_type": { + "type": "string", + "const": "repeatable_group", + "description": "Discriminator indicating this is a repeatable asset group" + }, + "asset_group_id": { + "type": "string", + "description": "Identifier for this asset group (e.g., 'product', 'slide', 'card')" + }, + "required": { + "type": "boolean", + "description": "Whether this asset group is required. If true, at least min_count repetitions must be provided.", + "default": false + }, + "min_count": { + "type": "integer", + "description": "Minimum number of repetitions required (if group is required) or allowed (if optional)", + "minimum": 0 + }, + "max_count": { + "type": "integer", + "description": "Maximum number of repetitions allowed", + "minimum": 1 + }, + "assets": { + "type": "array", + "description": "Assets within each repetition of this group", + "items": { + "type": "object", + "properties": { + "asset_id": { + "type": "string", + "description": "Identifier for this asset within the group" + }, + "asset_type": { + "$ref": "/schemas/enums/asset-content-type.json", + "description": "Type of asset" + }, + "asset_role": { + "type": "string", + "description": "Optional descriptive label for this asset's purpose. Not used for referencing assets in manifests—use asset_id instead. This field is for human-readable documentation and UI display only." + }, + "required": { + "type": "boolean", + "description": "Whether this asset is required within each repetition of the group", + "default": false + }, + "requirements": { + "type": "object", + "description": "Technical requirements for this asset. For template formats, use parameters_from_format_id: true to indicate asset parameters must match the format_id parameters (width/height/unit and/or duration_ms).", + "additionalProperties": true + } + }, + "required": ["asset_id", "asset_type"] + } + } + }, + "required": ["item_type", "asset_group_id", "min_count", "max_count", "assets"] + } + ] + } + }, "delivery": { "type": "object", "description": "Delivery method specifications (e.g., hosted, VAST, third-party tags)", diff --git a/static/schemas/source/index.json b/static/schemas/source/index.json index 2056c90c..6ea9e42a 100644 --- a/static/schemas/source/index.json +++ b/static/schemas/source/index.json @@ -4,7 +4,7 @@ "title": "AdCP Schema Registry v1", "version": "1.0.0", "description": "Registry of all AdCP JSON schemas for validation and discovery", - "adcp_version": "2.5.1", + "adcp_version": "2.6.0", "standard_formats_version": "2.0.0", "versioning": { "note": "AdCP uses path-based versioning. The schema URL path (/schemas/) indicates the version. Individual request/response schemas do NOT include adcp_version fields. Compatibility follows semantic versioning rules." From e2b0b62364f4fd9dfc7894d14cf7bb52eeb74243 Mon Sep 17 00:00:00 2001 From: BaiyuScope3 Date: Fri, 2 Jan 2026 14:57:17 -0500 Subject: [PATCH 02/10] Add changeset for assets field feature --- .changeset/assets-discovery.md | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 .changeset/assets-discovery.md diff --git a/.changeset/assets-discovery.md b/.changeset/assets-discovery.md new file mode 100644 index 00000000..43d94fd6 --- /dev/null +++ b/.changeset/assets-discovery.md @@ -0,0 +1,11 @@ +--- +"adcontextprotocol": minor +--- + +Add unified `assets` field to format schema for better asset discovery + +- Add new `assets` array to format schema with `required` boolean per asset +- Deprecate `assets_required` (still supported for backward compatibility) +- Enables full asset discovery for buyers and AI agents to see all supported assets +- Optional assets like impression trackers can now be discovered and used + From e4ed83965e62060ed3231f2f6cfa2e88061fa373 Mon Sep 17 00:00:00 2001 From: BaiyuScope3 Date: Fri, 2 Jan 2026 15:02:11 -0500 Subject: [PATCH 03/10] fix: update CI to use .cjs extension for check-testable-snippets --- .github/workflows/check-testable-snippets.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/check-testable-snippets.yml b/.github/workflows/check-testable-snippets.yml index 7dea6c92..e3ef8c27 100644 --- a/.github/workflows/check-testable-snippets.yml +++ b/.github/workflows/check-testable-snippets.yml @@ -26,7 +26,7 @@ jobs: if [ -s changed_files.txt ]; then echo "📋 Checking documentation changes for testable snippets..." - node scripts/check-testable-snippets.js + node scripts/check-testable-snippets.cjs else echo "✓ No documentation files changed" fi From e7bbaac17bdf2813a028b89c776e2b99bbbd8e02 Mon Sep 17 00:00:00 2001 From: BaiyuScope3 Date: Fri, 2 Jan 2026 15:15:54 -0500 Subject: [PATCH 04/10] fix: update docs to reference assets field instead of assets_optional --- docs/creative/implementing-creative-agents.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/creative/implementing-creative-agents.mdx b/docs/creative/implementing-creative-agents.mdx index dea73b14..abb86bb5 100644 --- a/docs/creative/implementing-creative-agents.mdx +++ b/docs/creative/implementing-creative-agents.mdx @@ -169,7 +169,7 @@ When validating manifests: When updating format definitions: -- **Additive changes** (new optional assets in `assets_optional`) are safe +- **Additive changes** (new optional assets with `required: false` in `assets`) are safe - **Breaking changes** (removing assets, changing requirements) require new format_id - Consider versioning: `youragency.com:format_name_v2` - Maintain backward compatibility when possible From 619ca3e7f3492a55189e7ca49a6602973db5130b Mon Sep 17 00:00:00 2001 From: BaiyuScope3 Date: Fri, 2 Jan 2026 16:36:52 -0500 Subject: [PATCH 05/10] docs: keep assets_required as deprecated alongside new assets field --- docs/creative/asset-types.mdx | 2 +- docs/creative/formats.mdx | 3 ++- docs/creative/task-reference/list_creative_formats.mdx | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/creative/asset-types.mdx b/docs/creative/asset-types.mdx index b4a4cdba..32ba29a2 100644 --- a/docs/creative/asset-types.mdx +++ b/docs/creative/asset-types.mdx @@ -377,7 +377,7 @@ Creative formats specify their assets using the `assets` array. Each asset has a ``` -**Backward Compatibility**: The deprecated `assets_required` field is still supported. New implementations should use `assets`. +**Backward Compatibility**: The `assets_required` field is deprecated but still supported. Existing implementations can continue using `assets_required` for required assets only. New implementations should use `assets` with the `required` boolean for full asset discovery. ## Repeatable Asset Groups diff --git a/docs/creative/formats.mdx b/docs/creative/formats.mdx index 15470c3b..d3fb2071 100644 --- a/docs/creative/formats.mdx +++ b/docs/creative/formats.mdx @@ -276,6 +276,7 @@ Formats are JSON objects with the following key fields: - **agent_url**: The creative agent authoritative for this format - **type**: Category (video, display, audio, native, dooh, rich_media) - **assets**: Array of all asset specifications with `required` boolean indicating mandatory vs optional +- **assets_required**: *(Deprecated)* Array of required asset specifications - use `assets` instead - **asset_role**: Identifies asset purpose (hero_image, logo, cta_button, etc.) - **renders**: Array of rendered outputs with dimensions - see below @@ -289,7 +290,7 @@ The `assets` array enables comprehensive asset discovery. Each asset has a `requ This unified approach helps creative tools and AI agents understand the full capabilities of a format, enabling richer creative experiences when optional assets are available while clearly indicating minimum requirements. -**Backward Compatibility**: The deprecated `assets_required` field is still supported for existing implementations. New implementations should use `assets` with the `required` boolean on each asset. +**Backward Compatibility**: The `assets_required` field is deprecated but still supported. Existing implementations can continue using `assets_required` for required assets only. New implementations should use `assets` with the `required` boolean on each asset for full asset discovery. ### Rendered Outputs and Dimensions diff --git a/docs/creative/task-reference/list_creative_formats.mdx b/docs/creative/task-reference/list_creative_formats.mdx index cc22e2b2..af0348f7 100644 --- a/docs/creative/task-reference/list_creative_formats.mdx +++ b/docs/creative/task-reference/list_creative_formats.mdx @@ -56,7 +56,7 @@ Formats may produce multiple rendered pieces (e.g., video + companion banner). D | Field | Description | |-------|-------------| -| `formats` | Array of full format definitions (format_id, name, type, requirements, assets, renders) | +| `formats` | Array of full format definitions (format_id, name, type, requirements, assets, assets_required, renders) | | `creative_agents` | Optional array of other creative agents providing additional formats | See [Format schema](https://adcontextprotocol.org/schemas/v2/core/format.json) for complete format object structure. @@ -422,6 +422,7 @@ Each format includes: | `type` | Format type (audio, video, display, dooh) | | `requirements` | Technical requirements (duration, file types, bitrate, etc.) | | `assets` | Array of all assets with `required` boolean indicating mandatory vs optional | +| `assets_required` | *(Deprecated)* Array of required assets - use `assets` instead | | `renders` | Array of rendered output pieces (dimensions, role) | ### Asset Roles From 7681bfb4982908d97ed44ad4ec48133503371f1c Mon Sep 17 00:00:00 2001 From: BaiyuScope3 Date: Fri, 2 Jan 2026 16:38:27 -0500 Subject: [PATCH 06/10] schema: add formal deprecated: true to assets_required field --- static/schemas/source/core/format.json | 1 + 1 file changed, 1 insertion(+) diff --git a/static/schemas/source/core/format.json b/static/schemas/source/core/format.json index b399d24c..9ab38f74 100644 --- a/static/schemas/source/core/format.json +++ b/static/schemas/source/core/format.json @@ -121,6 +121,7 @@ }, "assets_required": { "type": "array", + "deprecated": true, "description": "DEPRECATED: Use 'assets' instead. Array of required assets or asset groups for this format. Each asset is identified by its asset_id, which must be used as the key in creative manifests. Can contain individual assets or repeatable asset sequences (e.g., carousel products, slideshow frames). This field is maintained for backward compatibility; new implementations should use 'assets' with the 'required' boolean on each asset.", "items": { "oneOf": [ From 0bbdf287021976be9ea577d1d28683529ee504c8 Mon Sep 17 00:00:00 2001 From: BaiyuScope3 Date: Fri, 2 Jan 2026 16:42:08 -0500 Subject: [PATCH 07/10] schema: make 'required' field mandatory in assets array --- static/schemas/source/core/format.json | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/static/schemas/source/core/format.json b/static/schemas/source/core/format.json index 9ab38f74..5e633074 100644 --- a/static/schemas/source/core/format.json +++ b/static/schemas/source/core/format.json @@ -246,8 +246,7 @@ }, "required": { "type": "boolean", - "description": "Whether this asset is required (true) or optional (false). Required assets must be provided for a valid creative. Optional assets enhance the creative but are not mandatory.", - "default": false + "description": "Whether this asset is required (true) or optional (false). Required assets must be provided for a valid creative. Optional assets enhance the creative but are not mandatory." }, "requirements": { "type": "object", @@ -255,7 +254,7 @@ "additionalProperties": true } }, - "required": ["item_type", "asset_id", "asset_type"] + "required": ["item_type", "asset_id", "asset_type", "required"] }, { "description": "Repeatable asset group (for carousels, slideshows, playlists, etc.)", @@ -272,8 +271,7 @@ }, "required": { "type": "boolean", - "description": "Whether this asset group is required. If true, at least min_count repetitions must be provided.", - "default": false + "description": "Whether this asset group is required. If true, at least min_count repetitions must be provided." }, "min_count": { "type": "integer", @@ -318,7 +316,7 @@ } } }, - "required": ["item_type", "asset_group_id", "min_count", "max_count", "assets"] + "required": ["item_type", "asset_group_id", "required", "min_count", "max_count", "assets"] } ] } From c8a4487b1af8b8e4162cd35d8e33857c778cb50c Mon Sep 17 00:00:00 2001 From: BaiyuScope3 Date: Fri, 2 Jan 2026 16:45:36 -0500 Subject: [PATCH 08/10] schema: make 'required' field mandatory in nested repeatable_group assets --- static/schemas/source/core/format.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/static/schemas/source/core/format.json b/static/schemas/source/core/format.json index 5e633074..a018252d 100644 --- a/static/schemas/source/core/format.json +++ b/static/schemas/source/core/format.json @@ -312,7 +312,7 @@ "additionalProperties": true } }, - "required": ["asset_id", "asset_type"] + "required": ["asset_id", "asset_type", "required"] } } }, From 8261125d9e20c954c24c26b451f5fb8cf6d92f89 Mon Sep 17 00:00:00 2001 From: BaiyuScope3 Date: Fri, 2 Jan 2026 17:24:34 -0500 Subject: [PATCH 09/10] docs: add deprecated assets_required examples with deprecation comments --- docs/creative/asset-types.mdx | 16 ++++++++++++++++ docs/creative/formats.mdx | 15 +++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/docs/creative/asset-types.mdx b/docs/creative/asset-types.mdx index 32ba29a2..927fbedf 100644 --- a/docs/creative/asset-types.mdx +++ b/docs/creative/asset-types.mdx @@ -372,6 +372,22 @@ Creative formats specify their assets using the `assets` array. Each asset has a "description": "Third-party impression tracking pixel URL" } } + ], + + // DEPRECATED: Use "assets" above instead. Kept for backward compatibility. + "assets_required": [ + { + "item_type": "individual", + "asset_id": "video_file", + "asset_type": "video", + "requirements": { + "duration_seconds": 15, + "acceptable_formats": ["mp4"], + "acceptable_codecs": ["h264"], + "acceptable_resolutions": ["1920x1080", "1280x720"], + "max_file_size_mb": 30 + } + } ] } ``` diff --git a/docs/creative/formats.mdx b/docs/creative/formats.mdx index d3fb2071..ba6b100d 100644 --- a/docs/creative/formats.mdx +++ b/docs/creative/formats.mdx @@ -267,6 +267,21 @@ Formats are JSON objects with the following key fields: "description": "Third-party impression tracking pixel URL" } } + ], + + // DEPRECATED: Use "assets" above instead. Kept for backward compatibility. + "assets_required": [ + { + "item_type": "individual", + "asset_id": "video_file", + "asset_type": "video", + "asset_role": "hero_video", + "requirements": { + "duration": "30s", + "format": ["MP4"], + "resolution": ["1920x1080", "1280x720"] + } + } ] } ``` From 7c9c9f9b5ac55b9116e9de525dfaf9427472d682 Mon Sep 17 00:00:00 2001 From: BaiyuScope3 Date: Fri, 2 Jan 2026 17:30:32 -0500 Subject: [PATCH 10/10] ci: add 2.6.x branch to all workflows --- .github/workflows/broken-links.yml | 4 ++-- .github/workflows/changeset-check.yml | 2 +- .github/workflows/check-testable-snippets.yml | 1 + .github/workflows/release.yml | 1 + .github/workflows/schema-validation.yml | 4 ++-- 5 files changed, 7 insertions(+), 5 deletions(-) diff --git a/.github/workflows/broken-links.yml b/.github/workflows/broken-links.yml index b8b2bce7..8b3045af 100644 --- a/.github/workflows/broken-links.yml +++ b/.github/workflows/broken-links.yml @@ -2,9 +2,9 @@ name: Check for Broken Links on: push: - branches: [ main, develop ] + branches: [ main, develop, '2.6.x' ] pull_request: - branches: [ main, develop ] + branches: [ main, develop, '2.6.x' ] jobs: broken-links: diff --git a/.github/workflows/changeset-check.yml b/.github/workflows/changeset-check.yml index 346ed620..267de5f1 100644 --- a/.github/workflows/changeset-check.yml +++ b/.github/workflows/changeset-check.yml @@ -2,7 +2,7 @@ name: Changeset Check on: pull_request: - branches: [main] + branches: [main, '2.6.x'] jobs: check: diff --git a/.github/workflows/check-testable-snippets.yml b/.github/workflows/check-testable-snippets.yml index e3ef8c27..f28614b7 100644 --- a/.github/workflows/check-testable-snippets.yml +++ b/.github/workflows/check-testable-snippets.yml @@ -2,6 +2,7 @@ name: Check Testable Snippets on: pull_request: + branches: [main, '2.6.x'] paths: - 'docs/**/*.md' - 'docs/**/*.mdx' diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c5665ce6..176da7a2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -4,6 +4,7 @@ on: push: branches: - main + - '2.6.x' concurrency: ${{ github.workflow }}-${{ github.ref }} diff --git a/.github/workflows/schema-validation.yml b/.github/workflows/schema-validation.yml index 7d772503..a599e1ad 100644 --- a/.github/workflows/schema-validation.yml +++ b/.github/workflows/schema-validation.yml @@ -2,9 +2,9 @@ name: JSON Schema Validation on: push: - branches: [ main, develop ] + branches: [ main, develop, '2.6.x' ] pull_request: - branches: [ main, develop ] + branches: [ main, develop, '2.6.x' ] jobs: schema-validation: