diff --git a/.changeset/release-relaxed-schemas.md b/.changeset/release-relaxed-schemas.md new file mode 100644 index 0000000000..fb0609cfce --- /dev/null +++ b/.changeset/release-relaxed-schemas.md @@ -0,0 +1,9 @@ +--- +"adcontextprotocol": patch +--- + +Release schemas with `additionalProperties: true` for forward compatibility + +This releases `dist/schemas/2.5.2/` containing the relaxed schema validation +introduced in #646. Clients can now safely ignore unknown fields when parsing +API responses, allowing the API to evolve without breaking existing integrations. diff --git a/dist/schemas/2.5.2/adagents.json b/dist/schemas/2.5.2/adagents.json new file mode 100644 index 0000000000..2babff1b0b --- /dev/null +++ b/dist/schemas/2.5.2/adagents.json @@ -0,0 +1,494 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "/schemas/2.5.2/adagents.json", + "title": "Authorized Sales Agents", + "description": "Declaration of authorized sales agents for advertising inventory. Hosted at /.well-known/adagents.json on publisher domains. Can either contain the full structure inline or reference an authoritative URL.", + "oneOf": [ + { + "type": "object", + "description": "URL reference variant - points to the authoritative location of the adagents.json file", + "properties": { + "$schema": { + "type": "string", + "description": "JSON Schema identifier for this adagents.json file" + }, + "authoritative_location": { + "type": "string", + "format": "uri", + "pattern": "^https://", + "description": "HTTPS URL of the authoritative adagents.json file. When present, this file is a reference and the authoritative location contains the actual agent authorization data." + }, + "last_updated": { + "type": "string", + "format": "date-time", + "description": "ISO 8601 timestamp indicating when this reference was last updated" + } + }, + "required": [ + "authoritative_location" + ], + "additionalProperties": true + }, + { + "type": "object", + "description": "Inline structure variant - contains full agent authorization data", + "properties": { + "$schema": { + "type": "string", + "description": "JSON Schema identifier for this adagents.json file" + }, + "contact": { + "type": "object", + "description": "Contact information for the entity managing this adagents.json file (may be publisher or third-party operator)", + "properties": { + "name": { + "type": "string", + "description": "Name of the entity managing this file (e.g., 'Meta Advertising Operations', 'Clear Channel Digital')", + "minLength": 1, + "maxLength": 255 + }, + "email": { + "type": "string", + "format": "email", + "description": "Contact email for questions or issues with this authorization file", + "minLength": 1, + "maxLength": 255 + }, + "domain": { + "type": "string", + "description": "Primary domain of the entity managing this file", + "pattern": "^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$" + }, + "seller_id": { + "type": "string", + "description": "Seller ID from IAB Tech Lab sellers.json (if applicable)", + "minLength": 1, + "maxLength": 255 + }, + "tag_id": { + "type": "string", + "description": "TAG Certified Against Fraud ID for verification (if applicable)", + "minLength": 1, + "maxLength": 100 + } + }, + "required": [ + "name" + ], + "additionalProperties": true + }, + "properties": { + "type": "array", + "description": "Array of all properties covered by this adagents.json file. Defines the canonical property list that authorized agents reference.", + "items": { + "$ref": "/schemas/2.5.2/core/property.json" + }, + "minItems": 1 + }, + "tags": { + "type": "object", + "description": "Metadata for each tag referenced by properties. Provides human-readable context for property tag values.", + "additionalProperties": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Human-readable name for this tag" + }, + "description": { + "type": "string", + "description": "Description of what this tag represents" + } + }, + "required": [ + "name", + "description" + ], + "additionalProperties": true + } + }, + "authorized_agents": { + "type": "array", + "description": "Array of sales agents authorized to sell inventory for properties in this file", + "items": { + "oneOf": [ + { + "type": "object", + "properties": { + "url": { + "type": "string", + "format": "uri", + "description": "The authorized agent's API endpoint URL" + }, + "authorized_for": { + "type": "string", + "description": "Human-readable description of what this agent is authorized to sell", + "minLength": 1, + "maxLength": 500 + }, + "authorization_type": { + "type": "string", + "const": "property_ids", + "description": "Discriminator indicating authorization by specific property IDs" + }, + "property_ids": { + "type": "array", + "description": "Property IDs this agent is authorized for. Resolved against the top-level properties array in this file", + "items": { + "$ref": "/schemas/2.5.2/core/property-id.json" + }, + "minItems": 1 + } + }, + "required": [ + "url", + "authorized_for", + "authorization_type", + "property_ids" + ], + "additionalProperties": true + }, + { + "type": "object", + "properties": { + "url": { + "type": "string", + "format": "uri", + "description": "The authorized agent's API endpoint URL" + }, + "authorized_for": { + "type": "string", + "description": "Human-readable description of what this agent is authorized to sell", + "minLength": 1, + "maxLength": 500 + }, + "authorization_type": { + "type": "string", + "const": "property_tags", + "description": "Discriminator indicating authorization by property tags" + }, + "property_tags": { + "type": "array", + "description": "Tags identifying which properties this agent is authorized for. Resolved against the top-level properties array in this file using tag matching", + "items": { + "$ref": "/schemas/2.5.2/core/property-tag.json" + }, + "minItems": 1 + } + }, + "required": [ + "url", + "authorized_for", + "authorization_type", + "property_tags" + ], + "additionalProperties": true + }, + { + "type": "object", + "properties": { + "url": { + "type": "string", + "format": "uri", + "description": "The authorized agent's API endpoint URL" + }, + "authorized_for": { + "type": "string", + "description": "Human-readable description of what this agent is authorized to sell", + "minLength": 1, + "maxLength": 500 + }, + "authorization_type": { + "type": "string", + "const": "inline_properties", + "description": "Discriminator indicating authorization by inline property definitions" + }, + "properties": { + "type": "array", + "description": "Specific properties this agent is authorized for (alternative to property_ids/property_tags)", + "items": { + "$ref": "/schemas/2.5.2/core/property.json" + }, + "minItems": 1 + } + }, + "required": [ + "url", + "authorized_for", + "authorization_type", + "properties" + ], + "additionalProperties": true + }, + { + "type": "object", + "properties": { + "url": { + "type": "string", + "format": "uri", + "description": "The authorized agent's API endpoint URL" + }, + "authorized_for": { + "type": "string", + "description": "Human-readable description of what this agent is authorized to sell", + "minLength": 1, + "maxLength": 500 + }, + "authorization_type": { + "type": "string", + "const": "publisher_properties", + "description": "Discriminator indicating authorization for properties from other publisher domains" + }, + "publisher_properties": { + "type": "array", + "description": "Properties from other publisher domains this agent is authorized for. Each entry specifies a publisher domain and which of their properties this agent can sell", + "items": { + "$ref": "/schemas/2.5.2/core/publisher-property-selector.json" + }, + "minItems": 1 + } + }, + "required": [ + "url", + "authorized_for", + "authorization_type", + "publisher_properties" + ], + "additionalProperties": true + } + ] + }, + "minItems": 1 + }, + "last_updated": { + "type": "string", + "format": "date-time", + "description": "ISO 8601 timestamp indicating when this file was last updated" + } + }, + "required": [ + "authorized_agents" + ], + "additionalProperties": true + } + ], + "examples": [ + { + "$schema": "/schemas/2.5.2/adagents.json", + "authoritative_location": "https://cdn.example.com/adagents/v2/adagents.json", + "last_updated": "2025-01-15T10:00:00Z" + }, + { + "$schema": "/schemas/2.5.2/adagents.json", + "properties": [ + { + "property_type": "website", + "name": "Example Site", + "identifiers": [ + { + "type": "domain", + "value": "example.com" + } + ], + "publisher_domain": "example.com" + } + ], + "authorized_agents": [ + { + "url": "https://agent.example.com", + "authorized_for": "Official sales agent", + "authorization_type": "property_tags", + "property_tags": [ + "all" + ] + } + ], + "tags": { + "all": { + "name": "All Properties", + "description": "All properties in this file" + } + }, + "last_updated": "2025-01-10T12:00:00Z" + }, + { + "$schema": "/schemas/2.5.2/adagents.json", + "contact": { + "name": "Meta Advertising Operations", + "email": "adops@meta.com", + "domain": "meta.com", + "seller_id": "pub-meta-12345", + "tag_id": "12345" + }, + "properties": [ + { + "property_type": "mobile_app", + "name": "Instagram", + "identifiers": [ + { + "type": "ios_bundle", + "value": "com.burbn.instagram" + }, + { + "type": "android_package", + "value": "com.instagram.android" + } + ], + "tags": [ + "meta_network", + "social_media" + ], + "publisher_domain": "instagram.com" + }, + { + "property_type": "mobile_app", + "name": "Facebook", + "identifiers": [ + { + "type": "ios_bundle", + "value": "com.facebook.Facebook" + }, + { + "type": "android_package", + "value": "com.facebook.katana" + } + ], + "tags": [ + "meta_network", + "social_media" + ], + "publisher_domain": "facebook.com" + }, + { + "property_type": "mobile_app", + "name": "WhatsApp", + "identifiers": [ + { + "type": "ios_bundle", + "value": "net.whatsapp.WhatsApp" + }, + { + "type": "android_package", + "value": "com.whatsapp" + } + ], + "tags": [ + "meta_network", + "messaging" + ], + "publisher_domain": "whatsapp.com" + } + ], + "tags": { + "meta_network": { + "name": "Meta Network", + "description": "All Meta-owned properties" + }, + "social_media": { + "name": "Social Media Apps", + "description": "Social networking applications" + }, + "messaging": { + "name": "Messaging Apps", + "description": "Messaging and communication apps" + } + }, + "authorized_agents": [ + { + "url": "https://meta-ads.com", + "authorized_for": "All Meta properties", + "authorization_type": "property_tags", + "property_tags": [ + "meta_network" + ] + } + ], + "last_updated": "2025-01-10T15:30:00Z" + }, + { + "$schema": "/schemas/2.5.2/adagents.json", + "contact": { + "name": "Tumblr Advertising" + }, + "properties": [ + { + "property_type": "website", + "name": "Tumblr Corporate", + "identifiers": [ + { + "type": "domain", + "value": "tumblr.com" + } + ], + "tags": [ + "corporate" + ], + "publisher_domain": "tumblr.com" + } + ], + "tags": { + "corporate": { + "name": "Corporate Properties", + "description": "Tumblr-owned corporate properties (not user blogs)" + } + }, + "authorized_agents": [ + { + "url": "https://tumblr-sales.com", + "authorized_for": "Tumblr corporate properties only", + "authorization_type": "property_tags", + "property_tags": [ + "corporate" + ] + } + ], + "last_updated": "2025-01-10T16:00:00Z" + }, + { + "$schema": "/schemas/2.5.2/adagents.json", + "contact": { + "name": "Example Third-Party Sales Agent", + "email": "sales@agent.example", + "domain": "agent.example" + }, + "authorized_agents": [ + { + "url": "https://agent.example/api", + "authorized_for": "CNN CTV properties via publisher authorization", + "authorization_type": "publisher_properties", + "publisher_properties": [ + { + "publisher_domain": "cnn.com", + "selection_type": "by_id", + "property_ids": [ + "cnn_ctv_app" + ] + } + ] + }, + { + "url": "https://agent.example/api", + "authorized_for": "All CTV properties from multiple publishers", + "authorization_type": "publisher_properties", + "publisher_properties": [ + { + "publisher_domain": "cnn.com", + "selection_type": "by_tag", + "property_tags": [ + "ctv" + ] + }, + { + "publisher_domain": "espn.com", + "selection_type": "by_tag", + "property_tags": [ + "ctv" + ] + } + ] + } + ], + "last_updated": "2025-01-10T17:00:00Z" + } + ] +} diff --git a/dist/schemas/2.5.2/bundled/media-buy/build-creative-request.json b/dist/schemas/2.5.2/bundled/media-buy/build-creative-request.json new file mode 100644 index 0000000000..794531b8ec --- /dev/null +++ b/dist/schemas/2.5.2/bundled/media-buy/build-creative-request.json @@ -0,0 +1,1349 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "/schemas/2.5.2/bundled/media-buy/build-creative-request.json", + "title": "Build Creative Request", + "description": "Request to transform or generate a creative manifest. Takes a source manifest (which may be minimal for pure generation) and produces a target manifest in the specified format. The source manifest should include all assets required by the target format (e.g., promoted_offerings for generative formats).", + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "Natural language instructions for the transformation or generation. For pure generation, this is the creative brief. For transformation, this provides guidance on how to adapt the creative." + }, + "creative_manifest": { + "title": "Creative Manifest", + "description": "Creative manifest to transform or generate from. For pure generation, this should include the target format_id and any required input assets (e.g., promoted_offerings for generative formats). For transformation (e.g., resizing, reformatting), this is the complete creative to adapt.", + "type": "object", + "properties": { + "format_id": { + "title": "Format ID", + "description": "Format identifier this manifest is for. Can be a template format (id only) or a deterministic format (id + dimensions/duration). For dimension-specific creatives, include width/height/unit in the format_id to create a unique identifier (e.g., {id: 'display_static', width: 300, height: 250, unit: 'px'}).", + "type": "object", + "properties": { + "agent_url": { + "type": "string", + "format": "uri", + "description": "URL of the agent that defines this format (e.g., 'https://creatives.adcontextprotocol.org' for standard formats, or 'https://publisher.com/.well-known/adcp/sales' for custom formats)" + }, + "id": { + "type": "string", + "pattern": "^[a-zA-Z0-9_-]+$", + "description": "Format identifier within the agent's namespace (e.g., 'display_static', 'video_hosted', 'audio_standard'). When used alone, references a template format. When combined with dimension/duration fields, creates a parameterized format ID for a specific variant." + }, + "width": { + "type": "integer", + "minimum": 1, + "description": "Width in pixels for visual formats. When specified, height must also be specified. Both fields together create a parameterized format ID for dimension-specific variants." + }, + "height": { + "type": "integer", + "minimum": 1, + "description": "Height in pixels for visual formats. When specified, width must also be specified. Both fields together create a parameterized format ID for dimension-specific variants." + }, + "duration_ms": { + "type": "number", + "minimum": 1, + "description": "Duration in milliseconds for time-based formats (video, audio). When specified, creates a parameterized format ID. Omit to reference a template format without parameters." + } + }, + "required": [ + "agent_url", + "id" + ], + "additionalProperties": true, + "dependencies": { + "width": [ + "height" + ], + "height": [ + "width" + ] + } + }, + "promoted_offering": { + "type": "string", + "description": "Product name or offering being advertised. Maps to promoted_offerings in create_media_buy request to associate creative with the product being promoted." + }, + "assets": { + "type": "object", + "description": "Map of asset IDs to actual asset content. Each key MUST match an asset_id from the format's assets_required array (e.g., 'banner_image', 'clickthrough_url', 'video_file', 'vast_tag'). The asset_id is the technical identifier used to match assets to format requirements.\n\nIMPORTANT: Creative manifest validation MUST be performed in the context of the format specification. The format defines what type each asset_id should be, which eliminates any validation ambiguity.", + "patternProperties": { + "^[a-z0-9_]+$": { + "oneOf": [ + { + "title": "Image Asset", + "description": "Image asset with URL and dimensions", + "type": "object", + "properties": { + "url": { + "type": "string", + "format": "uri", + "description": "URL to the image asset" + }, + "width": { + "type": "integer", + "minimum": 1, + "description": "Width in pixels" + }, + "height": { + "type": "integer", + "minimum": 1, + "description": "Height in pixels" + }, + "format": { + "type": "string", + "description": "Image file format (jpg, png, gif, webp, etc.)" + }, + "alt_text": { + "type": "string", + "description": "Alternative text for accessibility" + } + }, + "required": [ + "url", + "width", + "height" + ], + "additionalProperties": true + }, + { + "title": "Video Asset", + "description": "Video asset with URL and specifications", + "type": "object", + "properties": { + "url": { + "type": "string", + "format": "uri", + "description": "URL to the video asset" + }, + "width": { + "type": "integer", + "minimum": 1, + "description": "Width in pixels" + }, + "height": { + "type": "integer", + "minimum": 1, + "description": "Height in pixels" + }, + "duration_ms": { + "type": "integer", + "description": "Video duration in milliseconds", + "minimum": 1 + }, + "format": { + "type": "string", + "description": "Video file format (mp4, webm, mov, etc.)" + }, + "bitrate_kbps": { + "type": "integer", + "description": "Video bitrate in kilobits per second", + "minimum": 1 + } + }, + "required": [ + "url", + "width", + "height" + ], + "additionalProperties": true + }, + { + "title": "Audio Asset", + "description": "Audio asset with URL and specifications", + "type": "object", + "properties": { + "url": { + "type": "string", + "format": "uri", + "description": "URL to the audio asset" + }, + "duration_ms": { + "type": "integer", + "description": "Audio duration in milliseconds", + "minimum": 0 + }, + "format": { + "type": "string", + "description": "Audio file format (mp3, wav, aac, etc.)" + }, + "bitrate_kbps": { + "type": "integer", + "description": "Audio bitrate in kilobits per second", + "minimum": 1 + } + }, + "required": [ + "url" + ], + "additionalProperties": true + }, + { + "title": "VAST Asset", + "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving", + "oneOf": [ + { + "type": "object", + "properties": { + "delivery_type": { + "type": "string", + "const": "url", + "description": "Discriminator indicating VAST is delivered via URL endpoint" + }, + "url": { + "type": "string", + "format": "uri", + "description": "URL endpoint that returns VAST XML" + }, + "vast_version": { + "title": "VAST Version", + "description": "VAST specification version", + "type": "string", + "enum": [ + "2.0", + "3.0", + "4.0", + "4.1", + "4.2" + ] + }, + "vpaid_enabled": { + "type": "boolean", + "description": "Whether VPAID (Video Player-Ad Interface Definition) is supported" + }, + "duration_ms": { + "type": "integer", + "description": "Expected video duration in milliseconds (if known)", + "minimum": 0 + }, + "tracking_events": { + "type": "array", + "items": { + "title": "VAST Tracking Event", + "description": "Standard VAST tracking events for video ad playback and interaction", + "type": "string", + "enum": [ + "start", + "firstQuartile", + "midpoint", + "thirdQuartile", + "complete", + "impression", + "click", + "pause", + "resume", + "skip", + "mute", + "unmute", + "fullscreen", + "exitFullscreen", + "playerExpand", + "playerCollapse" + ] + }, + "description": "Tracking events supported by this VAST tag" + } + }, + "required": [ + "delivery_type", + "url" + ], + "additionalProperties": true + }, + { + "type": "object", + "properties": { + "delivery_type": { + "type": "string", + "const": "inline", + "description": "Discriminator indicating VAST is delivered as inline XML content" + }, + "content": { + "type": "string", + "description": "Inline VAST XML content" + }, + "vast_version": { + "title": "VAST Version", + "description": "VAST specification version", + "type": "string", + "enum": [ + "2.0", + "3.0", + "4.0", + "4.1", + "4.2" + ] + }, + "vpaid_enabled": { + "type": "boolean", + "description": "Whether VPAID (Video Player-Ad Interface Definition) is supported" + }, + "duration_ms": { + "type": "integer", + "description": "Expected video duration in milliseconds (if known)", + "minimum": 0 + }, + "tracking_events": { + "type": "array", + "items": { + "title": "VAST Tracking Event", + "description": "Standard VAST tracking events for video ad playback and interaction", + "type": "string", + "enum": [ + "start", + "firstQuartile", + "midpoint", + "thirdQuartile", + "complete", + "impression", + "click", + "pause", + "resume", + "skip", + "mute", + "unmute", + "fullscreen", + "exitFullscreen", + "playerExpand", + "playerCollapse" + ] + }, + "description": "Tracking events supported by this VAST tag" + } + }, + "required": [ + "delivery_type", + "content" + ], + "additionalProperties": true + } + ] + }, + { + "title": "Text Asset", + "description": "Text content asset", + "type": "object", + "properties": { + "content": { + "type": "string", + "description": "Text content" + }, + "language": { + "type": "string", + "description": "Language code (e.g., 'en', 'es', 'fr')" + } + }, + "required": [ + "content" + ], + "additionalProperties": true + }, + { + "title": "URL Asset", + "description": "URL reference asset", + "type": "object", + "properties": { + "url": { + "type": "string", + "format": "uri", + "description": "URL reference" + }, + "url_type": { + "title": "URL Asset Type", + "description": "Type of URL asset: 'clickthrough' for user click destination (landing page), 'tracker_pixel' for impression/event tracking via HTTP request (fires GET, expects pixel/204 response), 'tracker_script' for measurement SDKs that must load as