From abbdd8973343367ca4cd1f50658448f635942c12 Mon Sep 17 00:00:00 2001 From: Bosko Milekic Date: Fri, 5 Dec 2025 10:28:37 -0500 Subject: [PATCH 1/2] Implements the Deals Protocol (renamed from Curation Protocol). The Deals Protocol enables buyer agents to discover and activate pre-packaged and bespoke signal-enriched inventory deal packages from SSPs and curation platforms. The Deals Protocol provides an alternative to the Media Buy Protocol for package-based buying, enabling: - Natural language deal discovery - Activation on SSP platforms (Magnite, Pubmatic, OpenX, Index Exchange, Microsoft Curate, etc.) - Support for PMP and Curated deal types - Integration with Signals Protocol for audience-targeted inventory packages --- .changeset/deals-protocol.md | 33 ++ README.md | 4 +- docs.json | 12 +- docs/curation/coming-soon.mdx | 39 --- docs/deals/overview.mdx | 279 ++++++++++++++++ docs/deals/specification.mdx | 279 ++++++++++++++++ docs/deals/tasks/activate_deal.mdx | 314 ++++++++++++++++++ docs/deals/tasks/get_deals.mdx | 272 +++++++++++++++ docs/intro.mdx | 6 +- static/schemas/source/core/deal-pricing.json | 74 +++++ .../schemas/source/core/deal-targeting.json | 53 +++ static/schemas/source/core/deal.json | 91 +++++ .../source/deals/activate-deal-request.json | 28 ++ .../source/deals/activate-deal-response.json | 56 ++++ .../source/deals/get-deals-request.json | 25 ++ .../source/deals/get-deals-response.json | 30 ++ static/schemas/source/index.json | 37 +++ 17 files changed, 1586 insertions(+), 46 deletions(-) create mode 100644 .changeset/deals-protocol.md delete mode 100644 docs/curation/coming-soon.mdx create mode 100644 docs/deals/overview.mdx create mode 100644 docs/deals/specification.mdx create mode 100644 docs/deals/tasks/activate_deal.mdx create mode 100644 docs/deals/tasks/get_deals.mdx create mode 100644 static/schemas/source/core/deal-pricing.json create mode 100644 static/schemas/source/core/deal-targeting.json create mode 100644 static/schemas/source/core/deal.json create mode 100644 static/schemas/source/deals/activate-deal-request.json create mode 100644 static/schemas/source/deals/activate-deal-response.json create mode 100644 static/schemas/source/deals/get-deals-request.json create mode 100644 static/schemas/source/deals/get-deals-response.json diff --git a/.changeset/deals-protocol.md b/.changeset/deals-protocol.md new file mode 100644 index 00000000..e6bba36d --- /dev/null +++ b/.changeset/deals-protocol.md @@ -0,0 +1,33 @@ +--- +"adcontextprotocol": major +--- + +Add Deals Protocol for inventory package discovery and activation. + +**New Protocol:** +- Deals Protocol enables buyer agents to discover and activate pre-packaged and ad-hoc inventory deal packages from SSPs and curation platforms +- Alternative to Media Buy Protocol for package-based buying + +**Tasks:** +- `get_deals`: Discover deal packages using natural language descriptions +- `activate_deal`: Activate deals on SSP platforms + +**Core Schemas:** +- `deal.json`: Deal package with pricing, targeting, and platform availability +- `deal-pricing.json`: Pricing configuration with Floor, Fixed, and Market types, plus optional margins for curated deals +- `deal-targeting.json`: Targeting parameters including geo, devices, allow/block lists, and segments + +**Deal Types:** +- **PMP (Private Marketplace)**: Direct deals with fixed or floor pricing +- **Curated**: Enhanced inventory packages with margin-based pricing + +**Architecture:** +- Deals Agents integrate with Signals Agents (using Signals Protocol) to include audience targeting +- Buyer Agents interact with Deals Agents (using Deals Protocol) without directly accessing Signals Agents +- Parallel architecture to Media Buy Protocol's Sales Agent integration + +**Documentation:** +- Protocol overview and specification +- Task reference documentation +- Integration examples with Signals Protocol +- Renamed from Curation Protocol to Deals Protocol diff --git a/README.md b/README.md index 89ca3897..c2e582f5 100644 --- a/README.md +++ b/README.md @@ -46,8 +46,8 @@ Discover and activate data signals using natural language. - **Transparent Pricing**: CPM and revenue share models - **Real-time Status**: Track activation and deployment progress -### πŸ“ Curation Protocol - Coming Soon -Curate media inventory based on context and brand safety requirements. +### πŸ“ Deals Protocol - RFC/v0.1 +Discover and activate pre-packaged and ad-hoc inventory deals. ### πŸ’° Media Buy Protocol - RFC/v0.1 Execute and optimize media buys programmatically across platforms. diff --git a/docs.json b/docs.json index 6b1aa412..20f585fe 100644 --- a/docs.json +++ b/docs.json @@ -90,9 +90,17 @@ ] }, { - "group": "Curation Protocol", + "group": "Deals Protocol", "pages": [ - "docs/curation/coming-soon" + "docs/deals/overview", + "docs/deals/specification", + { + "group": "Tasks", + "pages": [ + "docs/deals/tasks/get_deals", + "docs/deals/tasks/activate_deal" + ] + } ] }, { diff --git a/docs/curation/coming-soon.mdx b/docs/curation/coming-soon.mdx deleted file mode 100644 index 60068bd9..00000000 --- a/docs/curation/coming-soon.mdx +++ /dev/null @@ -1,39 +0,0 @@ ---- -sidebar_position: 1 -title: Coming Soon ---- - - -The Curation Protocol will enable AI assistants to discover and package media inventory based on campaign objectives, context, and brand safety requirements. - -## Planned Features - -### Inventory Discovery -- Natural language description of desired inventory -- Contextual category matching -- Cross-platform inventory packaging - -### Brand Safety -- Keyword exclusions -- Category blocks -- Custom safety profiles -- Third-party verification integration - -### Package Creation -- Multi-publisher deals -- Audience + inventory bundles -- Preferred pricing tiers - -## Expected Timeline - -- **Coming Soon**: Initial specification draft and reference implementation - -## Get Involved - -Want to help shape the Curation Protocol? - -- Join our [working group](https://join.slack.com/t/agenticads/shared_invite/zt-3c5sxvdjk-x0rVmLB3OFHVUp~WutVWZg) -- Share your use cases -- Review early drafts - -Subscribe to updates: announcements@adcontextprotocol.org \ No newline at end of file diff --git a/docs/deals/overview.mdx b/docs/deals/overview.mdx new file mode 100644 index 00000000..ba5cb433 --- /dev/null +++ b/docs/deals/overview.mdx @@ -0,0 +1,279 @@ +--- +sidebar_position: 1 +title: Overview +--- + +# Deals Protocol Overview + +The Deals Protocol enables AI assistants to discover and activate pre-packaged and ad-hoc inventory deal packages from publishers and ad decisioning platforms through natural languageβ€”simplifying the complex landscape of programmatic deal buying. + +## The Challenge: Navigating Deal Marketplaces + +Modern programmatic advertising offers numerous deal opportunities across publishers and SSPs. While this provides access to premium inventory, it creates challenges: +- **Fragmented discovery**: Deals scattered across multiple SSPs and sellers +- **Varying deal structures**: PMPs, curated packages, guaranteed deals with different terms +- **Complex targeting**: Deals may include pre-applied audiences, context, or brand safety +- **Pricing opacity**: Floor vs. fixed pricing, margins, and package costs vary +- **Manual activation**: Setting up deals across SSPs is time-intensive + +## How AI Assistants Transform Deal Discovery + +### Current Approach +``` +Human β†’ Navigate multiple SSP UIs β†’ Evaluate deal terms β†’ Manual setup across platforms +``` +- **Challenges**: Time-intensive, miss opportunities, requires platform expertise + +### With Deals Protocol +``` +Human describes objectives β†’ AI discovers matching deals β†’ Streamlined activation +``` +- **Benefits**: Comprehensive discovery, transparent comparison, efficient activation + +## The Power of AI-Assisted Deal Discovery + +### AI Can Process and Compare Deals at Scale + +``` +Human: I need premium video inventory for automotive brand with + guaranteed viewability and brand-safe context + +AI: Analyzing 143 video deals across 8 publishers and 5 SSPs... + +Best match: AutoMedia Network's "Premium Automotive Bundle" +- Deal Type: Curated package +- SSP: Magnite +- Inventory: Top 15 automotive content sites +- Ad Format: Video (pre-roll and mid-roll) +- Pricing: $18 CPM fixed + 15% curation margin +- Targeting: Automotive context + auto intender audiences (optional) +- Brand Safety: IAS verification, blocked competitor categories +- Availability: Q1 2026, 50M impressions reserved +- Viewability: 85% guaranteed or make-good + +Alternatives with trade-offs: +- CarContent Direct PMP: Lower cost ($15 CPM) but single publisher +- PremiumVideo Curator: Higher viewability (90%) but $22 CPM +``` + +### Flexible Deal Structures + +The Deals Protocol supports diverse deal types: + +#### Private Marketplace (PMP) Deals +Direct relationships with fixed or floor pricing: +``` +"Sports Publisher Premium Video PMP" +- Deal Type: PMP +- SSP: Pubmatic +- Pricing: $12 CPM floor +- Inventory: All premium sports video inventory +- Bidding: Open auction above floor +``` + +#### Curated Deals +Enhanced packages with added targeting and safety: +``` +"Contextual Curator - Tech Enthusiast Video Package" +- Deal Type: Curated +- SSP: Index Exchange +- Base Cost: $10 CPM +- Margin: 20% ($2 CPM curator fee) +- Enhancement: AI-powered contextual selection + viewability optimization +- Audience: Tech enthusiast targeting included +- Brand Safety: Category blocks and verification +``` + +## From Fragmented Platforms to Unified Discovery + +### Traditional Approach: Multi-Platform Navigation +- Log into multiple SSP platforms individually +- Manually search deal catalogs in each system +- Compare terms across different interfaces +- Set up deals individually on each SSP +- Track performance separately per platform + +### Enhanced with Deals Protocol: AI-Powered Unified Access + +``` +Human: Find video inventory deals targeting parents, ensure kid-safe content + +AI: Found 5 matching deals across 3 SSPs: + +1. FamilyContent Network - "Parent-Targeted Video Bundle" + SSP: OpenX + Type: Curated + Pricing: $14 CPM + 12% margin + Safety: COPPA-compliant, family-safe categories only + Audience: Parents with children under 12 + Scale: 30M impressions/month + +2. KidSafe Curator - "Family-Friendly Premium Video" + SSP: Magnite + Type: Curated + Pricing: $16 CPM + 15% margin + Safety: AI verification + manual review for kid-safe context + Audience: Optional parent targeting + Scale: 45M impressions/month + +3. PremiumFamily Sites - "Direct Parent Deal" + SSP: Pubmatic + Type: PMP + Pricing: $10 CPM floor + Safety: Category-based blocks + Audience: None (reach all visitors) + Scale: 20M impressions/month + +Select deals to activate on SSPs? +``` + +## Deal Discovery with Natural Language + +### Describing Deal Objectives + +The AI assistant helps translate campaign objectives into deal criteria: + +**Objective**: "I need high-impact display placements for luxury brand awareness" + +**AI Translation**: +- Ad Type: Display (likely high-impact formats) +- Targeting: Affluent audiences, premium contexts +- Brand Alignment: Luxury-appropriate environments +- Deal Types: Likely curated packages with quality guarantees + +**Objective**: "Cost-efficient video scale for product launch" + +**AI Translation**: +- Ad Type: Video +- Pricing: Floor pricing or market-rate deals preferred +- Scale: Large impression volumes +- Deal Types: PMP deals or broad curation packages + +### Intelligent Filtering and Recommendations + +The AI assistant can: +- **Filter by constraints**: Budget, scale requirements, timing +- **Compare pricing models**: Floor vs. fixed, with/without margins +- **Evaluate targeting fit**: Match deal targeting to campaign objectives +- **Assess brand safety**: Verify appropriate controls are in place +- **Recommend combinations**: Multiple deals to achieve scale or coverage + +## Integration with Signals Protocol + +**Integration Architecture**: The Deals Agent integrates with Signals Agents behind the scenes. The Buyer Agent interacts only with the Deals Agentβ€”not directly with Signals Agents. + +``` +Buyer Agent β†’ Deals Agent β†’ Signals Agent + (Deals Protocol) (Signals Protocol) +``` + +This is parallel to how the Media Buy Protocol works with Sales Agents. + +### How Deals Agents Leverage Signals + +When the Buyer Agent requests deals, the Deals Agent can: +- Discover relevant audience signals from integrated Signals Agents +- Include those signals in the targeting of returned deals +- Bundle audience targeting with inventory in curated packages +- Provide deals with pre-selected segments for brand safety or performance + +### Signals-Enhanced Deals + +``` +Human (to Buyer Agent): Find video deals for luxury automotive brand + +Buyer Agent β†’ Deals Agent: get_deals request with automotive specifications + +Deals Agent workflow: +1. Searches available video inventory deals +2. Queries integrated Signals Agents for relevant automotive audiences +3. Matches signals with appropriate inventory packages + +Deals Agent β†’ Buyer Agent: Returns deals including: + β†’ "Premium Video Curator - Auto Context" on Magnite + β†’ Includes automotive content + "Luxury Auto Intenders" segment + β†’ Targeting pre-configured with signal IDs from Signals Agent + +Result: Buyer Agent receives deals with inventory + audience targeting combined +``` + +### Deals with Included Targeting + +Deals can return targeting that includes: +- **Context-based signals**: Automotive content, premium publishers +- **Audience signals**: Segments obtained from Signals Agents (referenced by signal IDs) +- **Brand safety**: Block lists and allow lists for appropriate content +- **Geographic targeting**: Regional or local inventory packages + +The Buyer Agent doesn't need to know how the Deals Agent obtained the signalsβ€”it just receives deals with targeting ready to use. + +## Activation and Deployment + +Once deals are discovered, activation is streamlined: + +### Single-Platform Activation +``` +Activate "Premium Video Bundle" on Magnite +β†’ Deal ID configured in SSP +β†’ Ready for buyers to access +``` + +### Multi-Platform Deployment +``` +Activate "Cross-Publisher PMP" on: +- Pubmatic (seller account: publisher_abc) +- Index Exchange (seller account: publisher_abc) +β†’ Same deal available across both SSPs +β†’ Unified reporting and management +``` + +### Asynchronous Activation +Large or complex deals may require asynchronous activation: +``` +Activate deal β†’ Receive operation_id +β†’ Webhook notification when ready +β†’ Or poll for activation status +β†’ Use deal once deployed +``` + +## Use Cases + +### Premium Brand Campaigns +- Discover high-quality inventory packages +- Ensure brand-safe environments +- Access guaranteed viewability or performance +- Activate across multiple premium SSPs + +### Performance Marketing at Scale +- Find floor-priced PMPs for efficient buying +- Access large-scale deal inventory +- Combine multiple deals for reach +- Optimize spend with market-rate opportunities + +### Contextual Targeting Campaigns +- Discover context-aligned deal packages +- Access curated inventory with AI-powered selection +- Combine contextual deals with audience signals +- Ensure content relevance to campaign messaging + +### Retail Media and Commerce +- Access retailer-specific deal inventory +- Combine first-party audience data with publisher deals +- Leverage commerce-focused curation packages +- Target high-intent shoppers in relevant contexts + +## Next Steps + +- **[Protocol Specification](/docs/deals/specification)**: Technical details, data models, and complete task reference +- **[Signals Protocol](/docs/signals/overview)**: Combine deals with audience targeting + +## Get Involved + +Want to help shape the Deals Protocol? + +- Join our [working group](https://join.slack.com/t/agenticads/shared_invite/zt-3c5sxvdjk-x0rVmLB3OFHVUp~WutVWZg) (discussion in the #pmp-protocol channel) +- Share your use cases +- Review early drafts +- Implement the protocol + +Subscribe to updates: announcements@adcontextprotocol.org diff --git a/docs/deals/specification.mdx b/docs/deals/specification.mdx new file mode 100644 index 00000000..4e47e744 --- /dev/null +++ b/docs/deals/specification.mdx @@ -0,0 +1,279 @@ +--- +sidebar_position: 2 +title: Protocol Specification +--- + +# Deals Protocol RFC + +**Status**: Request for Comments +**Last Updated**: November 18, 2025 + +## Abstract + +The Deals Protocol defines a standard Model Context Protocol (MCP) interface for AI-powered deal discovery and activation systems. This protocol enables AI assistants to help buyers discover and activate pre-packaged and ad-hoc deal packages from publishers and ad decisioning platforms through natural language interactions. + +## Overview + +The Deals Protocol provides: + +- Natural language deal discovery based on campaign objectives +- Pre-packaged and ad-hoc deal packages from publishers and decisioning platforms +- Deal activation for specific platforms and accounts +- Transparent pricing with Floor, Fixed, and Market pricing models +- Support for PMP (Private Marketplace) and Curated deals +- Flexible targeting including context, audiences, and brand safety + +## Core Concepts + +### Agent Integration + +The Deals Protocol operates within the broader [AdCP Ecosystem Layers](/docs/intro#the-adcp-ecosystem-layers), enabling deals agents to facilitate buyer-seller transactions for inventory packages. + +**Direct Integration Model**: Deals agents act as intermediaries between buyers and sellers, providing discovery and activation of inventory packages with optional audience targeting, contextual selection, and brand safety controls. + +### Request Roles and Relationships + +Every deal discovery request involves two key roles: + +#### Orchestrator +The platform or system making the API request to the deals agent: +- **Examples**: Trading desk platform, campaign management tool, AI assistant +- **Responsibilities**: Makes API calls, handles authentication, manages the technical interaction +- **Account**: Has technical credentials and API access to the deals platform + +#### Principal +The entity on whose behalf the request is being made: +- **Examples**: Advertiser (Nike), agency (Omnicom), brand team, media buyer +- **Responsibilities**: Owns the campaign objectives, budget, and business relationship +- **Pricing**: May have negotiated rates, contract terms, or access to private deal packages + +#### How This Works in Practice + +1. **Request Flow**: Orchestrator β†’ Deals Agent (on behalf of Principal) β†’ Decisioning Platform +2. **Authentication**: Orchestrator authenticates with technical credentials +3. **Authorization**: Principal's identity determines available deals and pricing +4. **Activation**: Deals are activated for Principal's account on the decisioning platform +5. **Billing**: Principal is responsible for usage costs and campaign spend + +### Deal Types + +#### Private Marketplace (PMP) Deals +Fixed-price or floor-price deals between specific buyers and sellers: +- **Pricing**: Fixed CPM or floor CPM with market bidding above the floor +- **Access**: Available to specific advertisers based on relationships +- **Inventory**: Guaranteed access to premium inventory +- **Use Case**: Direct relationships between buyers and sellers + +#### Curated Deals +Inventory packages assembled and enhanced by curators with added value: +- **Pricing**: Includes margin (percentage or CPM) on top of media costs +- **Access**: May be marketplace or bespoke +- **Enhancement**: May include audience targeting, brand safety, contextual selection +- **Use Case**: Simplified buying with added curation services + +### Deal Agent Types + +#### Publisher Deal Agents +Agents owned by publishers offering their inventory directly: +- **Examples**: Premium publisher direct deals, content network packages +- **Business Model**: Direct deals with floor or fixed pricing +- **Inventory**: First-party publisher inventory + +#### Curation Platform Agents +Platforms that assemble and curate inventory packages: +- **Examples**: SSP curation products, independent curation platforms +- **Business Model**: Curated deals with margin on media costs +- **Inventory**: Multi-publisher packages with targeting and safety controls + +#### DSP Deal Agents +DSPs offering packaged deal inventory to their buyers: +- **Examples**: Major DSPs with curated marketplace deals +- **Business Model**: Both PMP and Curated deal types +- **Inventory**: Cross-publisher inventory accessible through the DSP + +## Protocol Tasks + +The Deals Protocol defines the following tasks that agents can perform: + +### [get_deals](/docs/deals/tasks/get_deals) + +Discover deal packages based on natural language description. The Deals Agent returns deals across all supported SSP platforms with pricing, targeting, and platform availability details. + +### [activate_deal](/docs/deals/tasks/activate_deal) + +Activate a discovered deal on one or more SSP platforms. This task handles the activation request and returns deployment status for each platform. + +## Data Models + +### Deal + +Represents a deal package with inventory, pricing, targeting, and platform availability. + +**Required Fields:** +- `deal_id`: Unique identifier +- `name`: Human-readable deal name +- `advertiser`: Advertiser for whom this deal is available +- `start_date`: Deal start date (YYYY-MM-DD) +- `end_date`: Deal end date (YYYY-MM-DD) +- `deal_type`: Either "PMP" or "Curated" +- `ad_type`: Ad format type ("Banner", "Video", or "Native") +- `platforms`: Array of SSP platform identifiers where this deal can be activated (minimum 1) +- `pricing`: Pricing configuration object +- `status`: Deal status ("draft", "active", or "inactive") + +**Optional Fields:** +- `targeting`: Targeting parameters (geo, devices, allow/block lists, segments) + +### Pricing + +Pricing configuration for a deal. + +**Fields:** +- `type` (required): Pricing type ("Floor", "Fixed", or "Market") +- `cpm` (conditional): CPM price in USD (required for Floor and Fixed types) +- `margin` (conditional): Margin configuration (required for Curated deals) + - `type`: Either "Percentage" or "CPM" + - `percentage`: Margin as percentage (0-100) + - `cpm`: Margin as CPM value + +**Pricing Type Semantics:** +- **Floor**: Minimum CPM with market bidding above the floor +- **Fixed**: Exact CPM price, no bidding +- **Market**: Market-rate pricing determined at impression time + +### Targeting + +Optional targeting parameters for a deal. Omitting the targeting object or specific fields implies targeting all available inventory for those dimensions. + +**Fields (all optional):** +- `geo`: Array of geographic targets (countries, regions, cities, postal codes, metro codes) +- `devices`: Array of device types ("Desktop", "Tablet", "Mobile", "CTV") +- `allow_lists`: Array of included domain/app list IDs in the decisioning platform +- `block_lists`: Array of excluded domain/app list IDs in the decisioning platform +- `include_segments`: Array of included segment IDs (can reference Signal IDs from Signals Protocol) +- `exclude_segments`: Array of excluded segment IDs + +## Integration with Other Protocols + +### Signals Protocol Integration + +**Integration Architecture**: The Deals Agent integrates with Signals Agents using the Signals Protocol. The Buyer Agent interacts with the Deals Agent using the Deals Protocol. The Buyer Agent does not directly call Signals Agents. + +``` +Buyer Agent β†’ Deals Agent β†’ Signals Agent + (Deals Protocol) (Signals Protocol) +``` + +This is parallel to the Media Buy Protocol architecture: +``` +Buyer Agent β†’ Sales Agent β†’ Signals Agent + (Media Buy Protocol) (Signals Protocol) +``` + +**How It Works:** +- The Deals Agent integrates with Signals Agents to discover and access audience segments +- When the Buyer Agent calls `get_deals`, the Deals Agent returns deals that may include targeting with signals obtained from Signals Agents +- Deal targeting `include_segments` and `exclude_segments` can reference `signal_agent_segment_id` values +- Curated deals can bundle pre-selected audience segments with inventory + +**Example Integration Flow:** +1. Deals Agent integrates with Signals Agents (using Signals Protocol) +2. Buyer Agent calls `get_deals` on Deals Agent (using Deals Protocol) +3. Deals Agent returns deals with targeting that includes signal IDs obtained from Signals Agents +4. Buyer Agent activates selected deal, which includes inventory + audience targeting + +### Relationship to Media Buy Protocol + +The Deals Protocol is an **alternative** to the Media Buy Protocol, not complementary: +- **Media Buy Protocol**: Direct campaign execution with publishers via Sales Agents +- **Deals Protocol**: Package-based buying through Deals Agents (typically SSPs or curators) +- **Use Case Separation**: Choose one approach per campaign based on buying strategy +- **Similar Architecture**: Both protocols enable Sales/Deals Agents to integrate with Signals Agents + +## Security and Authentication + +### Principal Authentication + +Deals agents must authenticate both the orchestrator (technical credentials) and the principal (on whose behalf the request is made): +- Orchestrator credentials validate API access +- Principal identity determines available deals and pricing +- Deal activation requires principal authorization on the destination platform + +### Authorization Model + +Deal discovery and activation follow a permission hierarchy: +1. **Orchestrator** must have API access to the deals agent +2. **Principal** must be authorized for the specific deals returned +3. **Destination platform** must accept deal activations from the deals agent +4. **Principal** must have an account on the destination platform + +## Asynchronous Operations + +Deal activation may be asynchronous: +- Initial response includes `operation_id` for tracking +- Status updates delivered via webhooks (if configured) +- Poll for status using the operation tracking endpoint +- Final status indicates successful deployment or error + +## Error Handling + +### Discovery Errors + +Errors during deal discovery (`get_deals`): +- Invalid destination platforms +- No deals matching criteria +- Pricing or availability lookup failures +- Authorization issues + +### Activation Errors + +Errors during deal activation (`activate_deal`): +- Deal no longer available +- Principal not authorized for the deal +- Destination platform connectivity issues +- Deal configuration errors + +## Best Practices + +### Deal Discovery + +1. **Use Natural Language**: Describe campaign objectives clearly in `deal_spec` +2. **Filter Appropriately**: Use filters to refine results, but don't over-constrain +3. **Check Pricing**: Verify pricing models match budget expectations +4. **Review Targeting**: Understand what targeting is pre-applied to the deal + +### Deal Activation + +1. **Verify Availability**: Check deal status before attempting activation +2. **Handle Asynchronous Operations**: Use webhooks or polling for activation status +3. **Error Recovery**: Implement retry logic for transient failures +4. **Track Deployments**: Store deployment IDs for reporting and reconciliation + +### Signal Integration + +1. **Activate Signals First**: Complete signal activation before discovering deals +2. **Reference Signal IDs**: Include activated signal IDs in deal discovery requests +3. **Coordinate Timing**: Ensure signal and deal activation timeframes align + +## Versioning and Compatibility + +The Deals Protocol follows AdCP versioning principles: +- **Path-based versioning**: Version in URL path (`/schemas/v1/deals/`) +- **Semantic versioning**: Major.Minor.Patch version numbers +- **Backward compatibility**: Minor versions maintain compatibility +- **Breaking changes**: Require major version increment + +## Future Enhancements + +Potential future additions to the Deals Protocol: +- **Dynamic pricing**: Real-time pricing based on market conditions +- **Deal recommendations**: AI-powered deal suggestions based on campaign objectives +- **Performance guarantees**: Deals with guaranteed delivery or performance metrics +- **Multi-format deals**: Single deal ID covering multiple ad formats +- **Deal analytics**: Reporting and insights on deal performance + +## References + +- [Signals Protocol Specification](/docs/signals/specification) +- [Media Buy Protocol](/docs/media-buy/) +- [AdCP Core Concepts](/docs/intro) diff --git a/docs/deals/tasks/activate_deal.mdx b/docs/deals/tasks/activate_deal.mdx new file mode 100644 index 00000000..1cfc26f9 --- /dev/null +++ b/docs/deals/tasks/activate_deal.mdx @@ -0,0 +1,314 @@ +--- +sidebar_position: 2 +title: activate_deal +--- + +# activate_deal + +**Task**: Activate a deal on a specific SSP platform. + +**Response Time**: Seconds to minutes (typically fast, may be asynchronous for complex deals) + +**Request Schema**: [`https://adcontextprotocol.org/schemas/v1/deals/activate-deal-request.json`](https://adcontextprotocol.org/schemas/v1/deals/activate-deal-request.json) +**Response Schema**: [`https://adcontextprotocol.org/schemas/v1/deals/activate-deal-response.json`](https://adcontextprotocol.org/schemas/v1/deals/activate-deal-response.json) + +The `activate_deal` task activates a discovered deal on one or more SSP platforms, making it available for use in campaigns. + +## Request Parameters + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `deal_id` | string | Yes | The unique identifier for the deal to activate (from `get_deals` response) | +| `destinations` | Destination[] | Yes | Target SSP platform(s) for activation (see Destination Object below) | +| `context` | object | No | Initiator-provided context for correlation tracking | + +### Destination Object + +Each destination uses a `type` field to discriminate between platform-based and agent-based destinations: + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `type` | string | Yes | Discriminator: "platform" for SSPs, "agent" for other agents | +| `platform_id` | string | Conditional* | Platform identifier (e.g., 'magnite', 'pubmatic', 'openx'). Required when type="platform" | +| `agent_url` | string (URI) | Conditional* | URL identifying the agent. Required when type="agent" | +| `account_id` | string | No | Account identifier on the platform or agent | + +*`platform_id` is required when `type="platform"`, `agent_url` is required when `type="agent"`. + +**Important**: The destination platform must be in the deal's `platforms` array (from `get_deals` response). Attempting to activate on an unsupported platform will result in an error. + +## Response Structure + +The response uses an **atomic** pattern - it returns either success data OR error information, never both: + +### Success Response + +```json +{ + "deployments": [ + { + "type": "platform", + "platform_id": "string", + "account_id": "string", + "deal_id": "string", + "status": "activated", + "activated_at": "string" + } + ], + "context": {} +} +``` + +### Error Response + +```json +{ + "errors": [ + { + "code": "string", + "message": "string", + "field": "string", + "suggestion": "string", + "details": {} + } + ], + "context": {} +} +``` + +## Field Descriptions + +### Deployment Object (Success) + +| Field | Type | Description | +|-------|------|-------------| +| `type` | string | "platform" or "agent" | +| `platform_id` | string | SSP platform identifier (when type="platform") | +| `agent_url` | string | Agent URL (when type="agent") | +| `account_id` | string | Account identifier if applicable | +| `deal_id` | string | The activated deal identifier | +| `status` | string | "activated" when successful | +| `activated_at` | string | ISO 8601 timestamp when activation completed | + +### Error Object + +| Field | Type | Description | +|-------|------|-------------| +| `code` | string | Error code (see Error Codes below) | +| `message` | string | Human-readable error description | +| `field` | string | Field that caused the error (if applicable) | +| `suggestion` | string | Suggested resolution | +| `details` | object | Additional error context | + +## Example Request + +```json +{ + "deal_id": "deal_auto_premium_001", + "destinations": [ + { + "type": "platform", + "platform_id": "magnite", + "account_id": "seller_acme123" + } + ] +} +``` + +## Example Success Response + +```json +{ + "deployments": [ + { + "type": "platform", + "platform_id": "magnite", + "account_id": "seller_acme123", + "deal_id": "deal_auto_premium_001", + "status": "activated", + "activated_at": "2025-11-18T20:45:00Z" + } + ], + "context": { + "request_id": "req_12345" + } +} +``` + +## Example Error Response + +```json +{ + "errors": [ + { + "code": "PLATFORM_NOT_SUPPORTED", + "message": "Deal 'deal_auto_premium_001' is not available on platform 'openx'", + "field": "destinations[0].platform_id", + "suggestion": "This deal is only available on platforms: ['magnite', 'pubmatic']. Use one of these platforms instead.", + "details": { + "deal_id": "deal_auto_premium_001", + "requested_platform": "openx", + "available_platforms": ["magnite", "pubmatic"] + } + } + ], + "context": { + "request_id": "req_12345" + } +} +``` + +## Multi-Platform Activation + +You can activate the same deal on multiple platforms if it's available on all of them: + +```json +{ + "deal_id": "deal_auto_premium_001", + "destinations": [ + { + "type": "platform", + "platform_id": "magnite", + "account_id": "seller_acme123" + }, + { + "type": "platform", + "platform_id": "pubmatic", + "account_id": "seller_acme456" + } + ] +} +``` + +**Success Response** (all platforms activated): +```json +{ + "deployments": [ + { + "type": "platform", + "platform_id": "magnite", + "account_id": "seller_acme123", + "deal_id": "deal_auto_premium_001", + "status": "activated", + "activated_at": "2025-11-18T20:45:00Z" + }, + { + "type": "platform", + "platform_id": "pubmatic", + "account_id": "seller_acme456", + "deal_id": "deal_auto_premium_001", + "status": "activated", + "activated_at": "2025-11-18T20:45:02Z" + } + ] +} +``` + +## Error Codes + +### Activation Errors + +- **DEAL_NOT_FOUND**: The specified deal_id doesn't exist or is not accessible +- **DEAL_INACTIVE**: Deal status is "inactive" and cannot be activated +- **PLATFORM_NOT_SUPPORTED**: Requested platform is not in the deal's platforms array +- **ACCOUNT_NOT_AUTHORIZED**: The principal is not authorized for the specified account +- **DEAL_EXPIRED**: Deal end_date has passed +- **DEAL_NOT_STARTED**: Deal start_date is in the future +- **ACTIVATION_FAILED**: Platform connectivity or configuration issue prevented activation + +### Authorization Errors + +- **PRINCIPAL_NOT_AUTHORIZED**: Principal does not have access to this deal +- **ADVERTISER_MISMATCH**: Deal advertiser doesn't match the authenticated principal + +## Asynchronous Activation + +For complex deals, activation may be asynchronous: + +### Initial Response + +```json +{ + "operation_id": "op_abc123", + "status": "pending", + "estimated_duration_minutes": 5, + "context": { + "request_id": "req_12345" + } +} +``` + +### Status Tracking + +Use the `operation_id` to poll for status or configure webhooks for updates: + +```json +{ + "operation_id": "op_abc123", + "status": "completed", + "deployments": [ + { + "type": "platform", + "platform_id": "magnite", + "deal_id": "deal_auto_premium_001", + "status": "activated", + "activated_at": "2025-11-18T20:50:00Z" + } + ] +} +``` + +## Best Practices + +1. **Verify Platform Availability**: Check the deal's `platforms` array before calling `activate_deal` +2. **Handle Atomic Responses**: Check for either `deployments` (success) or `errors` (failure) +3. **Check Deal Status**: Only activate deals with status "draft" or "active" +4. **Verify Dates**: Ensure current date is between deal `start_date` and `end_date` +5. **Account Identifiers**: Provide `account_id` when activating for specific accounts +6. **Error Recovery**: Implement retry logic for transient failures (e.g., ACTIVATION_FAILED) +7. **Multi-Platform Strategy**: Activate on all available platforms for maximum reach, or choose specific platforms based on your strategy + +## Workflow Integration + +### Typical Flow + +1. **Discover deals** using `get_deals` +2. **Review deal details**: pricing, targeting, platform availability +3. **Select deal and platform(s)** from the `platforms` array +4. **Activate deal** using `activate_deal` on chosen platform(s) +5. **Use activated deal** in your campaign setup + +### Example Complete Workflow + +```javascript +// Step 1: Discover deals +const dealsResponse = await get_deals({ + deal_spec: "Premium video for automotive, US, max $25 CPM" +}); + +// Step 2: Select a deal +const selectedDeal = dealsResponse.deals[0]; +console.log(`Selected: ${selectedDeal.name}`); +console.log(`Available on: ${selectedDeal.platforms.join(', ')}`); + +// Step 3: Activate on preferred platform +const activationResponse = await activate_deal({ + deal_id: selectedDeal.deal_id, + destinations: [{ + type: "platform", + platform_id: "magnite", + account_id: "my_seller_account" + }] +}); + +if (activationResponse.deployments) { + console.log(`Deal activated on ${activationResponse.deployments[0].platform_id}`); + // Proceed with campaign setup +} else { + console.error(`Activation failed: ${activationResponse.errors[0].message}`); +} +``` + +## Next Steps + +After activating a deal, use the deal_id in your campaign setup on the SSP platform to start serving ads through the deal. diff --git a/docs/deals/tasks/get_deals.mdx b/docs/deals/tasks/get_deals.mdx new file mode 100644 index 00000000..ecbd7fb9 --- /dev/null +++ b/docs/deals/tasks/get_deals.mdx @@ -0,0 +1,272 @@ +--- +sidebar_position: 1 +title: get_deals +--- + +# get_deals + +**Task**: Discover deal packages based on natural language description. + +**Response Time**: ~30 seconds (discovery with back-end systems) + +**Request Schema**: [`https://adcontextprotocol.org/schemas/v1/deals/get-deals-request.json`](https://adcontextprotocol.org/schemas/v1/deals/get-deals-request.json) +**Response Schema**: [`https://adcontextprotocol.org/schemas/v1/deals/get-deals-response.json`](https://adcontextprotocol.org/schemas/v1/deals/get-deals-response.json) + +The `get_deals` task returns available deal packages with pricing, targeting, and platform availability information, allowing buyer agents to evaluate options and select deals for activation. + +## Request Parameters + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `deal_spec` | string | Yes | Natural language description of desired deal package, including filtering criteria (deal type, ad format, pricing, dates, etc.) | +| `max_results` | number | No | Maximum number of results to return | +| `context` | object | No | Initiator-provided context for correlation tracking | + +## Response Structure + +```json +{ + "deals": [ + { + "deal_id": "string", + "name": "string", + "advertiser": "string", + "start_date": "YYYY-MM-DD", + "end_date": "YYYY-MM-DD", + "deal_type": "PMP" | "Curated", + "ad_type": "Banner" | "Video" | "Native", + "platforms": ["string"], + "pricing": { ... }, + "targeting": { ... }, + "status": "draft" | "active" | "inactive" + } + ], + "errors": [], + "context": {} +} +``` + +### Deal Object Fields + +| Field | Type | Description | +|-------|------|-------------| +| `deal_id` | string | Unique identifier for the deal | +| `name` | string | Human-readable deal name | +| `advertiser` | string | Advertiser for whom this deal is available | +| `start_date` | string | Deal start date (YYYY-MM-DD) | +| `end_date` | string | Deal end date (YYYY-MM-DD) | +| `deal_type` | string | "PMP" (Private Marketplace) or "Curated" | +| `ad_type` | string | "Banner", "Video", or "Native" | +| `platforms` | string[] | SSP platform identifiers where this deal can be activated (minimum 1) | +| `pricing` | object | Pricing configuration (see below) | +| `targeting` | object | Targeting parameters (optional, see below) | +| `status` | string | "draft", "active", or "inactive" | + +### Pricing Object + +| Field | Type | Description | +|-------|------|-------------| +| `type` | string | "Floor", "Fixed", or "Market" | +| `cpm` | number | CPM price in USD (required for Floor and Fixed types) | +| `margin` | object | Margin configuration (required for Curated deals) | + +**Margin Object** (for Curated deals): +- `type`: "Percentage" or "CPM" +- `percentage`: Margin as percentage (0-100) when type is "Percentage" +- `cpm`: Margin as CPM value when type is "CPM" + +### Targeting Object (Optional) + +All fields are optional. Omitting fields implies no restrictions for those dimensions. + +| Field | Type | Description | +|-------|------|-------------| +| `geo` | string[] | Geographic targeting (countries, regions, cities, postal codes, metro codes) | +| `devices` | string[] | Device types: "Desktop", "Tablet", "Mobile", "CTV" | +| `allow_lists` | string[] | Included domain/app list IDs in the ad decisioning platform | +| `block_lists` | string[] | Excluded domain/app list IDs in the ad decisioning platform | +| `include_segments` | string[] | Included segment IDs (can reference signal IDs from Signals Protocol) | +| `exclude_segments` | string[] | Excluded segment IDs | + +## Example Request + +```json +{ + "deal_spec": "Premium video inventory for automotive brand in the US with viewability guarantee, maximum $25 CPM", + "max_results": 10 +} +``` + +## Example Response + +```json +{ + "deals": [ + { + "deal_id": "deal_auto_premium_001", + "name": "Premium Automotive Video Bundle", + "advertiser": "luxury_auto_brand", + "start_date": "2026-01-01", + "end_date": "2026-03-31", + "deal_type": "Curated", + "ad_type": "Video", + "platforms": ["magnite", "pubmatic"], + "pricing": { + "type": "Fixed", + "cpm": 18.0, + "margin": { + "type": "Percentage", + "percentage": 15.0 + } + }, + "targeting": { + "geo": ["US"], + "devices": ["CTV", "Desktop"], + "include_segments": ["luxury_auto_intenders_v2"], + "block_lists": ["competitor_automotive_brands"] + }, + "status": "draft" + }, + { + "deal_id": "deal_auto_direct_002", + "name": "CarContent Direct Video PMP", + "advertiser": "luxury_auto_brand", + "start_date": "2026-01-15", + "end_date": "2026-06-30", + "deal_type": "PMP", + "ad_type": "Video", + "platforms": ["openx", "index-exchange"], + "pricing": { + "type": "Floor", + "cpm": 12.0 + }, + "targeting": { + "geo": ["US"], + "devices": ["CTV", "Desktop", "Mobile"] + }, + "status": "draft" + } + ], + "context": { + "request_id": "req_12345" + } +} +``` + +## Understanding the Response + +### Platform Availability + +Each deal includes a `platforms` array listing the SSP platforms where it can be activated: +- Deals must be available on at least one platform +- Use the `activate_deal` task to activate the deal on your chosen platform(s) +- Same deal can be activated on multiple platforms if listed + +### Deal Status + +- **"draft"**: Deal is proposed but not yet activated (typical for newly discovered deals) +- **"active"**: Deal is activated and ready to serve +- **"inactive"**: Deal is no longer available or has been deactivated + +### Pricing Types + +**Floor Pricing** (`type: "Floor"`): +- Minimum CPM price +- Buyers can bid above the floor in auctions +- Common in PMP deals with competitive bidding + +**Fixed Pricing** (`type: "Fixed"`): +- Exact CPM price, no bidding +- Predictable costs, guaranteed rate +- Common in guaranteed deals + +**Market Pricing** (`type: "Market"`): +- Market-rate pricing determined at impression time +- Dynamic pricing based on demand +- No fixed CPM in response + +### Curated Deal Margins + +Curated deals include a margin on top of media costs: +- **Percentage margin**: Applied as percentage of media cost (e.g., 15% on $15 CPM = $17.25 total) +- **CPM margin**: Fixed CPM added to media cost (e.g., $2 CPM margin on $15 CPM = $17 total) + +## Integration with Signals Protocol + +### Signal-Enhanced Targeting + +The `include_segments` and `exclude_segments` fields can reference signal IDs obtained by the Deals Agent from Signals Agents: + +```json +{ + "targeting": { + "include_segments": [ + "luxury_auto_intenders_v2", // Signal ID from Signals Agent + "high_income_households" // Another signal ID + ], + "exclude_segments": [ + "competitor_customers" // Exclusion signal + ] + } +} +``` + +**Important**: The Buyer Agent does not directly interact with Signals Agents. The Deals Agent integrates with Signals Agents behind the scenes and includes signal-based targeting in returned deals. + +## Use Cases + +### Discovery by Objectives + +```json +{ + "deal_spec": "High-impact display placements for luxury brand awareness in premium environments" +} +``` + +The Deals Agent interprets the objectives and returns appropriate deals (likely curated packages with quality guarantees). + +### Discovery with Constraints + +```json +{ + "deal_spec": "Cost-efficient video scale for product launch, maximum $15 CPM, Q1 2026 availability" +} +``` + +Natural language spec includes all filtering criteria - no separate filters object needed. + +### Discovery with Signal Integration + +```json +{ + "deal_spec": "Premium video deals for automotive with luxury car intender audiences, US only" +} +``` + +The Deals Agent queries Signals Agents for relevant audiences and returns deals with those segments pre-configured in targeting. + +## Error Handling + +### Common Errors + +- **DEAL_NOT_FOUND**: No deals match the specified criteria +- **INVALID_ADVERTISER**: Advertiser identifier not recognized or not authorized +- **DATE_CONFLICT**: Requested dates don't align with available deal inventory + +### Warnings + +- **PARTIAL_AVAILABILITY**: Some deals have limited inventory remaining +- **PRICING_UNAVAILABLE**: Pricing data temporarily unavailable for some deals + +## Best Practices + +1. **Use Descriptive Specifications**: Clear natural language descriptions help the agent find the most relevant deals +2. **Check Platform Availability**: Verify the deal is available on platforms you can access +3. **Review Targeting**: Understand what targeting is pre-applied before activation +4. **Verify Dates**: Ensure deal dates align with your campaign timing +5. **Compare Pricing**: Evaluate pricing types and margins across multiple deals +6. **Check Status**: Only "draft" or "active" deals can typically be activated + +## Next Steps + +After discovering deals, use the [`activate_deal`](/docs/deals/tasks/activate_deal) task to activate your selected deal on the appropriate SSP platform(s). diff --git a/docs/intro.mdx b/docs/intro.mdx index 1211d973..89a5391e 100644 --- a/docs/intro.mdx +++ b/docs/intro.mdx @@ -137,7 +137,7 @@ Each AdCP protocol operates within this ecosystem: - **Integration**: Direct integration between signal agents and decisioning platforms (DSPs, injective platforms) - **Workflow**: Find signals β†’ Direct activation on target platform β†’ Ready for campaign use -### πŸ“ Curation Protocol (Coming Soon) +### πŸ“ Deals Protocol - **Scope**: Works with **decisioning platforms** and **supply-side platforms** - **Integration**: Curates inventory that will be targeted with activated signals - **Workflow**: Define requirements β†’ Find inventory β†’ Package with signals @@ -207,8 +207,8 @@ The AI assistant will: Discover and activate data signals (audiences, contextual, geographical, temporal) using natural language. -### πŸ“ Curation Protocol -**Status**: Coming Soon +### πŸ“ Deals Protocol +**Status**: RFC/v0.1 Curate media inventory based on context and brand safety. diff --git a/static/schemas/source/core/deal-pricing.json b/static/schemas/source/core/deal-pricing.json new file mode 100644 index 00000000..2e0b844c --- /dev/null +++ b/static/schemas/source/core/deal-pricing.json @@ -0,0 +1,74 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "/schemas/core/deal-pricing.json", + "title": "Deal Pricing", + "description": "Pricing information for a deal, including pricing type and optional margin for curated deals", + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Pricing type for the deal", + "enum": ["Floor", "Fixed", "Market"] + }, + "cpm": { + "type": "number", + "description": "CPM price in USD. Required for Floor and Fixed pricing types. For Floor, represents the minimum CPM. For Fixed, represents the exact CPM price.", + "minimum": 0 + }, + "margin": { + "type": "object", + "description": "Margin configuration for curated deals. Required when deal_type is Curated.", + "oneOf": [ + { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "Percentage" + }, + "percentage": { + "type": "number", + "description": "Margin as a percentage", + "minimum": 0, + "maximum": 100 + } + }, + "required": ["type", "percentage"], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "CPM" + }, + "cpm": { + "type": "number", + "description": "Margin as a CPM value in USD", + "minimum": 0 + } + }, + "required": ["type", "cpm"], + "additionalProperties": false + } + ] + } + }, + "required": ["type"], + "allOf": [ + { + "if": { + "properties": { + "type": { + "enum": ["Floor", "Fixed"] + } + } + }, + "then": { + "required": ["cpm"] + } + } + ], + "additionalProperties": false +} diff --git a/static/schemas/source/core/deal-targeting.json b/static/schemas/source/core/deal-targeting.json new file mode 100644 index 00000000..1427c0d1 --- /dev/null +++ b/static/schemas/source/core/deal-targeting.json @@ -0,0 +1,53 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "/schemas/core/deal-targeting.json", + "title": "Deal Targeting", + "description": "Targeting parameters for a deal. All fields are optional. Omitting this object or specific fields implies targeting all available inventory for those dimensions.", + "type": "object", + "properties": { + "geo": { + "type": "array", + "description": "Geographic targeting. Values can encode countries, regions, cities, postal codes, or metro codes. Omitting implies target all geographies.", + "items": { + "type": "string" + } + }, + "devices": { + "type": "array", + "description": "Device types to target. Omitting implies target all devices.", + "items": { + "type": "string", + "enum": ["Desktop", "Tablet", "Mobile", "CTV"] + } + }, + "allow_lists": { + "type": "array", + "description": "Included domain or app list IDs in the ad decisioning platform. Omitting implies allow everything.", + "items": { + "type": "string" + } + }, + "block_lists": { + "type": "array", + "description": "Excluded domain or app list IDs in the ad decisioning platform", + "items": { + "type": "string" + } + }, + "include_segments": { + "type": "array", + "description": "Included segment IDs in the ad decisioning platform. Can reference signal IDs from the Signals Protocol.", + "items": { + "type": "string" + } + }, + "exclude_segments": { + "type": "array", + "description": "Excluded segment IDs in the ad decisioning platform", + "items": { + "type": "string" + } + } + }, + "additionalProperties": false +} diff --git a/static/schemas/source/core/deal.json b/static/schemas/source/core/deal.json new file mode 100644 index 00000000..0ad6a5f3 --- /dev/null +++ b/static/schemas/source/core/deal.json @@ -0,0 +1,91 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "/schemas/core/deal.json", + "title": "Deal", + "description": "A deal package representing pre-packaged or ad-hoc inventory from publishers or ad decisioning platforms", + "type": "object", + "properties": { + "deal_id": { + "type": "string", + "description": "Unique identifier for the deal" + }, + "name": { + "type": "string", + "description": "Human-readable name for the deal" + }, + "advertiser": { + "type": "string", + "description": "Advertiser name or identifier for whom this deal is available" + }, + "start_date": { + "type": "string", + "format": "date", + "description": "Start date of the deal in YYYY-MM-DD format" + }, + "end_date": { + "type": "string", + "format": "date", + "description": "End date of the deal in YYYY-MM-DD format" + }, + "deal_type": { + "type": "string", + "description": "Type of deal", + "enum": ["PMP", "Curated"] + }, + "ad_type": { + "type": "string", + "description": "Type of ad format for this deal", + "enum": ["Banner", "Video", "Native"] + }, + "platforms": { + "type": "array", + "description": "List of SSP platform identifiers where this deal can be activated. Each deal must be available on at least one platform.", + "items": { + "type": "string" + }, + "minItems": 1 + }, + "pricing": { + "$ref": "/schemas/core/deal-pricing.json" + }, + "targeting": { + "$ref": "/schemas/core/deal-targeting.json" + }, + "status": { + "type": "string", + "description": "Current status of the deal", + "enum": ["draft", "active", "inactive"] + } + }, + "required": [ + "deal_id", + "name", + "advertiser", + "start_date", + "end_date", + "deal_type", + "ad_type", + "platforms", + "pricing", + "status" + ], + "allOf": [ + { + "if": { + "properties": { + "deal_type": { + "const": "Curated" + } + } + }, + "then": { + "properties": { + "pricing": { + "required": ["margin"] + } + } + } + } + ], + "additionalProperties": false +} diff --git a/static/schemas/source/deals/activate-deal-request.json b/static/schemas/source/deals/activate-deal-request.json new file mode 100644 index 00000000..75e1d80d --- /dev/null +++ b/static/schemas/source/deals/activate-deal-request.json @@ -0,0 +1,28 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "/schemas/deals/activate-deal-request.json", + "title": "Activate Deal Request", + "description": "Request parameters for activating a deal on a specific destination platform", + "type": "object", + "properties": { + "deal_id": { + "type": "string", + "description": "The unique identifier for the deal to activate" + }, + "destinations": { + "type": "array", + "description": "Target destination platform(s) for activation. If the authenticated caller matches one of these destinations, activation keys will be included in the response.", + "items": { + "$ref": "/schemas/core/destination.json" + }, + "minItems": 1 + }, + "context": { + "type": "object", + "description": "Initiator-provided context included in the request payload. Agents must echo this value back unchanged in responses and webhooks. Use for UI/session hints, correlation tokens, or tracking metadata.", + "additionalProperties": true + } + }, + "required": ["deal_id", "destinations"], + "additionalProperties": false +} diff --git a/static/schemas/source/deals/activate-deal-response.json b/static/schemas/source/deals/activate-deal-response.json new file mode 100644 index 00000000..7db86b07 --- /dev/null +++ b/static/schemas/source/deals/activate-deal-response.json @@ -0,0 +1,56 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "/schemas/deals/activate-deal-response.json", + "title": "Activate Deal Response", + "description": "Response payload for activate_deal task. Returns either complete success data OR error information, never both. This enforces atomic operation semantics - the deal is either fully activated or not activated at all.", + "type": "object", + "oneOf": [ + { + "description": "Success response - deal activated successfully to one or more destinations", + "type": "object", + "properties": { + "deployments": { + "type": "array", + "description": "Array of deployment results for each destination", + "items": { + "$ref": "/schemas/core/deployment.json" + } + }, + "context": { + "type": "object", + "description": "Initiator-provided context echoed inside the task payload. Opaque metadata such as UI/session hints, correlation tokens, or tracking identifiers.", + "additionalProperties": true + } + }, + "required": ["deployments"], + "additionalProperties": false, + "not": { + "required": ["errors"] + } + }, + { + "description": "Error response - operation failed, deal not activated", + "type": "object", + "properties": { + "errors": { + "type": "array", + "description": "Array of errors explaining why activation failed (e.g., platform connectivity issues, deal configuration problems, authentication failures)", + "items": { + "$ref": "/schemas/core/error.json" + }, + "minItems": 1 + }, + "context": { + "type": "object", + "description": "Initiator-provided context echoed inside the task payload. Opaque metadata such as UI/session hints, correlation tokens, or tracking identifiers.", + "additionalProperties": true + } + }, + "required": ["errors"], + "additionalProperties": false, + "not": { + "required": ["deployments"] + } + } + ] +} diff --git a/static/schemas/source/deals/get-deals-request.json b/static/schemas/source/deals/get-deals-request.json new file mode 100644 index 00000000..17917de3 --- /dev/null +++ b/static/schemas/source/deals/get-deals-request.json @@ -0,0 +1,25 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "/schemas/deals/get-deals-request.json", + "title": "Get Deals Request", + "description": "Request parameters for discovering deal packages based on natural language description", + "type": "object", + "properties": { + "deal_spec": { + "type": "string", + "description": "Natural language description of the desired deal package, including any filtering criteria (deal type, ad format, pricing constraints, dates, etc.)" + }, + "max_results": { + "type": "integer", + "description": "Maximum number of results to return", + "minimum": 1 + }, + "context": { + "type": "object", + "description": "Initiator-provided context included in the request payload. Agents must echo this value back unchanged in responses and webhooks. Use for UI/session hints, correlation tokens, or tracking metadata.", + "additionalProperties": true + } + }, + "required": ["deal_spec"], + "additionalProperties": false +} diff --git a/static/schemas/source/deals/get-deals-response.json b/static/schemas/source/deals/get-deals-response.json new file mode 100644 index 00000000..1f5785e1 --- /dev/null +++ b/static/schemas/source/deals/get-deals-response.json @@ -0,0 +1,30 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "/schemas/deals/get-deals-response.json", + "title": "Get Deals Response", + "description": "Response payload for get_deals task", + "type": "object", + "properties": { + "deals": { + "type": "array", + "description": "Array of matching deal packages", + "items": { + "$ref": "/schemas/core/deal.json" + } + }, + "errors": { + "type": "array", + "description": "Task-specific errors and warnings (e.g., deal discovery or pricing issues)", + "items": { + "$ref": "/schemas/core/error.json" + } + }, + "context": { + "type": "object", + "description": "Initiator-provided context echoed inside the task payload. Opaque metadata such as UI/session hints, correlation tokens, or tracking identifiers.", + "additionalProperties": true + } + }, + "required": ["deals"], + "additionalProperties": false +} diff --git a/static/schemas/source/index.json b/static/schemas/source/index.json index 641737e5..be9a52ad 100644 --- a/static/schemas/source/index.json +++ b/static/schemas/source/index.json @@ -168,6 +168,18 @@ "property-tag": { "$ref": "/schemas/core/property-tag.json", "description": "Tag for categorizing publisher properties - lowercase alphanumeric with underscores only" + }, + "deal": { + "$ref": "/schemas/core/deal.json", + "description": "A deal package representing pre-packaged or ad-hoc inventory from publishers or ad decisioning platforms" + }, + "deal-pricing": { + "$ref": "/schemas/core/deal-pricing.json", + "description": "Pricing information for a deal, including pricing type and optional margin for curated deals" + }, + "deal-targeting": { + "$ref": "/schemas/core/deal-targeting.json", + "description": "Targeting parameters for a deal (geo, devices, allow/block lists, segments)" } } }, @@ -562,6 +574,31 @@ } } }, + "deals": { + "description": "Deals protocol task request/response schemas", + "tasks": { + "get-deals": { + "request": { + "$ref": "/schemas/deals/get-deals-request.json", + "description": "Request parameters for discovering deal packages based on description and filters" + }, + "response": { + "$ref": "/schemas/deals/get-deals-response.json", + "description": "Response payload for get_deals task" + } + }, + "activate-deal": { + "request": { + "$ref": "/schemas/deals/activate-deal-request.json", + "description": "Request parameters for activating a deal on a specific destination platform" + }, + "response": { + "$ref": "/schemas/deals/activate-deal-response.json", + "description": "Response payload for activate_deal task" + } + } + } + }, "adagents": { "description": "Authorized sales agents file format specification", "$ref": "/schemas/adagents.json", From c776474eec7813839d2f538f8d3c598b050a96d7 Mon Sep 17 00:00:00 2001 From: Bosko Milekic Date: Sat, 13 Dec 2025 21:09:26 -0500 Subject: [PATCH 2/2] Align Deals Protocol with Media Buy Protocol patterns MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Updates the Deals Protocol schemas and documentation to match the established patterns used in the Media Buy Protocol, improving consistency across AdCP. Key changes: - Rename deal_spec β†’ brief to match get_products pattern - Add structured filters support via new deal-filters.json schema - Add brand_manifest support (inline or URL reference) - Add ext field for platform-specific extensions - Update context/ext to use $ref to core schemas throughout This improves developer experience by providing consistent request/response patterns across protocols while maintaining backward compatibility via changesets. πŸ€– Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .changeset/deals-protocol-consistency.md | 40 +++++++++ docs/deals/specification.mdx | 9 +- docs/deals/tasks/activate_deal.mdx | 15 ++-- docs/deals/tasks/get_deals.mdx | 83 +++++++++++++++++-- static/schemas/source/core/deal-filters.json | 67 +++++++++++++++ .../source/deals/activate-deal-request.json | 7 +- .../source/deals/activate-deal-response.json | 14 ++-- .../source/deals/get-deals-request.json | 20 +++-- .../source/deals/get-deals-response.json | 7 +- 9 files changed, 227 insertions(+), 35 deletions(-) create mode 100644 .changeset/deals-protocol-consistency.md create mode 100644 static/schemas/source/core/deal-filters.json diff --git a/.changeset/deals-protocol-consistency.md b/.changeset/deals-protocol-consistency.md new file mode 100644 index 00000000..63ac8628 --- /dev/null +++ b/.changeset/deals-protocol-consistency.md @@ -0,0 +1,40 @@ +--- +"adcontextprotocol": minor +--- + +Align Deals Protocol with Media Buy Protocol patterns for consistency across AdCP. + +**New features:** +- Added `deal-filters.json` schema with structured filtering capabilities (deal_type, ad_type, platforms, date ranges, status, countries, devices) +- Added `brand_manifest` support to `get_deals` request (optional, inline or URL reference) +- Added `ext` extension field support to all Deals protocol requests and responses +- Added `filters` parameter to `get_deals` for structured deal discovery + +**Breaking changes:** +- Renamed `deal_spec` to `brief` in `get_deals` request to match `get_products` pattern +- Made all `get_deals` request fields optional (removed `required: ["deal_spec"]`) + +**Improvements:** +- Updated all `context` fields to use `$ref` to `/schemas/core/context.json` instead of inline definitions +- Added `ext` field references to both success and error variants in discriminated union responses +- Improved schema consistency across all Deals protocol tasks + +**Migration guide:** +```javascript +// Before +await client.getDeals({ deal_spec: "Premium video deals" }); + +// After +await client.getDeals({ brief: "Premium video deals" }); + +// New capabilities +await client.getDeals({ + brief: "Premium video deals", + filters: { + deal_type: ["Curated"], + ad_type: ["Video"], + countries: ["US", "CA"] + }, + brand_manifest: "https://example.com/brand.json" +}); +``` diff --git a/docs/deals/specification.mdx b/docs/deals/specification.mdx index 4e47e744..3916a930 100644 --- a/docs/deals/specification.mdx +++ b/docs/deals/specification.mdx @@ -237,10 +237,11 @@ Errors during deal activation (`activate_deal`): ### Deal Discovery -1. **Use Natural Language**: Describe campaign objectives clearly in `deal_spec` -2. **Filter Appropriately**: Use filters to refine results, but don't over-constrain -3. **Check Pricing**: Verify pricing models match budget expectations -4. **Review Targeting**: Understand what targeting is pre-applied to the deal +1. **Use Natural Language**: Describe campaign objectives clearly in the `brief` parameter +2. **Filter Appropriately**: Use structured `filters` to refine results, or combine with natural language for maximum flexibility +3. **Provide Brand Context**: Include `brand_manifest` when available to help agents match deals to your brand requirements +4. **Check Pricing**: Verify pricing models match budget expectations +5. **Review Targeting**: Understand what targeting is pre-applied to the deal ### Deal Activation diff --git a/docs/deals/tasks/activate_deal.mdx b/docs/deals/tasks/activate_deal.mdx index 1cfc26f9..605d8adc 100644 --- a/docs/deals/tasks/activate_deal.mdx +++ b/docs/deals/tasks/activate_deal.mdx @@ -21,6 +21,7 @@ The `activate_deal` task activates a discovered deal on one or more SSP platform | `deal_id` | string | Yes | The unique identifier for the deal to activate (from `get_deals` response) | | `destinations` | Destination[] | Yes | Target SSP platform(s) for activation (see Destination Object below) | | `context` | object | No | Initiator-provided context for correlation tracking | +| `ext` | object | No | Extension object for platform-specific or vendor-namespaced parameters | ### Destination Object @@ -55,7 +56,8 @@ The response uses an **atomic** pattern - it returns either success data OR erro "activated_at": "string" } ], - "context": {} + "context": {}, + "ext": {} } ``` @@ -72,7 +74,8 @@ The response uses an **atomic** pattern - it returns either success data OR erro "details": {} } ], - "context": {} + "context": {}, + "ext": {} } ``` @@ -131,7 +134,8 @@ The response uses an **atomic** pattern - it returns either success data OR erro ], "context": { "request_id": "req_12345" - } + }, + "ext": {} } ``` @@ -154,7 +158,8 @@ The response uses an **atomic** pattern - it returns either success data OR erro ], "context": { "request_id": "req_12345" - } + }, + "ext": {} } ``` @@ -283,7 +288,7 @@ Use the `operation_id` to poll for status or configure webhooks for updates: ```javascript // Step 1: Discover deals const dealsResponse = await get_deals({ - deal_spec: "Premium video for automotive, US, max $25 CPM" + brief: "Premium video for automotive, US, max $25 CPM" }); // Step 2: Select a deal diff --git a/docs/deals/tasks/get_deals.mdx b/docs/deals/tasks/get_deals.mdx index ecbd7fb9..8307b9cb 100644 --- a/docs/deals/tasks/get_deals.mdx +++ b/docs/deals/tasks/get_deals.mdx @@ -18,9 +18,29 @@ The `get_deals` task returns available deal packages with pricing, targeting, an | Parameter | Type | Required | Description | |-----------|------|----------|-------------| -| `deal_spec` | string | Yes | Natural language description of desired deal package, including filtering criteria (deal type, ad format, pricing, dates, etc.) | +| `brief` | string | No | Natural language description of desired deal package, including filtering criteria (deal type, ad format, pricing, dates, etc.) | +| `brand_manifest` | object or string (URI) | No | Brand information manifest providing brand context, assets, and product catalog. Can be provided inline or as a URL reference to a hosted manifest. | +| `filters` | object | No | Structured filters for deal discovery (see Filters Object below) | | `max_results` | number | No | Maximum number of results to return | | `context` | object | No | Initiator-provided context for correlation tracking | +| `ext` | object | No | Extension object for platform-specific or vendor-namespaced parameters | + +### Filters Object + +The `filters` parameter allows structured filtering of deals: + +| Field | Type | Description | +|-------|------|-------------| +| `deal_type` | string[] | Filter by deal types: "PMP", "Curated" | +| `ad_type` | string[] | Filter by ad format types: "Banner", "Video", "Native" | +| `platforms` | string[] | Filter by SSP platform identifiers | +| `start_date` | string | Filter deals available on or after this date (YYYY-MM-DD) | +| `end_date` | string | Filter deals available on or before this date (YYYY-MM-DD) | +| `status` | string[] | Filter by deal status: "draft", "active", "inactive" | +| `countries` | string[] | Filter by target countries (ISO 3166-1 alpha-2 codes, e.g., ["US", "CA", "GB"]) | +| `devices` | string[] | Filter by device types: "Desktop", "Tablet", "Mobile", "CTV" | + +All filter fields are optional and can be used in combination. ## Response Structure @@ -42,7 +62,8 @@ The `get_deals` task returns available deal packages with pricing, targeting, an } ], "errors": [], - "context": {} + "context": {}, + "ext": {} } ``` @@ -90,13 +111,43 @@ All fields are optional. Omitting fields implies no restrictions for those dimen ## Example Request +### Using Natural Language Brief + ```json { - "deal_spec": "Premium video inventory for automotive brand in the US with viewability guarantee, maximum $25 CPM", + "brief": "Premium video inventory for automotive brand in the US with viewability guarantee, maximum $25 CPM", "max_results": 10 } ``` +### Using Structured Filters + +```json +{ + "brief": "Premium video inventory for automotive brand with viewability guarantee", + "filters": { + "ad_type": ["Video"], + "deal_type": ["Curated"], + "countries": ["US"], + "status": ["draft", "active"] + }, + "max_results": 10 +} +``` + +### With Brand Manifest + +```json +{ + "brief": "Premium video deals matching our brand", + "brand_manifest": "https://example.com/brand-manifest.json", + "filters": { + "ad_type": ["Video"], + "countries": ["US"] + } +} +``` + ## Example Response ```json @@ -149,7 +200,8 @@ All fields are optional. Omitting fields implies no restrictions for those dimen ], "context": { "request_id": "req_12345" - } + }, + "ext": {} } ``` @@ -219,7 +271,7 @@ The `include_segments` and `exclude_segments` fields can reference signal IDs ob ```json { - "deal_spec": "High-impact display placements for luxury brand awareness in premium environments" + "brief": "High-impact display placements for luxury brand awareness in premium environments" } ``` @@ -227,19 +279,34 @@ The Deals Agent interprets the objectives and returns appropriate deals (likely ### Discovery with Constraints +You can use natural language in the `brief` field, structured `filters`, or both: + +**Natural language approach:** ```json { - "deal_spec": "Cost-efficient video scale for product launch, maximum $15 CPM, Q1 2026 availability" + "brief": "Cost-efficient video scale for product launch, maximum $15 CPM, Q1 2026 availability" +} +``` + +**Structured filters approach:** +```json +{ + "brief": "Cost-efficient video scale for product launch", + "filters": { + "ad_type": ["Video"], + "start_date": "2026-01-01", + "end_date": "2026-03-31" + } } ``` -Natural language spec includes all filtering criteria - no separate filters object needed. +Both approaches are supported, and you can combine them for maximum flexibility. ### Discovery with Signal Integration ```json { - "deal_spec": "Premium video deals for automotive with luxury car intender audiences, US only" + "brief": "Premium video deals for automotive with luxury car intender audiences, US only" } ``` diff --git a/static/schemas/source/core/deal-filters.json b/static/schemas/source/core/deal-filters.json new file mode 100644 index 00000000..a7f076c3 --- /dev/null +++ b/static/schemas/source/core/deal-filters.json @@ -0,0 +1,67 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "/schemas/core/deal-filters.json", + "title": "Deal Filters", + "description": "Structured filters for deal discovery", + "type": "object", + "properties": { + "deal_type": { + "type": "array", + "description": "Filter by deal types", + "items": { + "type": "string", + "enum": ["PMP", "Curated"] + } + }, + "ad_type": { + "type": "array", + "description": "Filter by ad format types", + "items": { + "type": "string", + "enum": ["Banner", "Video", "Native"] + } + }, + "platforms": { + "type": "array", + "description": "Filter by SSP platform identifiers", + "items": { + "type": "string" + } + }, + "start_date": { + "type": "string", + "format": "date", + "description": "Filter deals available on or after this start date (ISO 8601 date format: YYYY-MM-DD)" + }, + "end_date": { + "type": "string", + "format": "date", + "description": "Filter deals available on or before this end date (ISO 8601 date format: YYYY-MM-DD)" + }, + "status": { + "type": "array", + "description": "Filter by deal status", + "items": { + "type": "string", + "enum": ["draft", "active", "inactive"] + } + }, + "countries": { + "type": "array", + "description": "Filter by target countries using ISO 3166-1 alpha-2 country codes (e.g., ['US', 'CA', 'GB'])", + "items": { + "type": "string", + "pattern": "^[A-Z]{2}$" + } + }, + "devices": { + "type": "array", + "description": "Filter by device types in deal targeting", + "items": { + "type": "string", + "enum": ["Desktop", "Tablet", "Mobile", "CTV"] + } + } + }, + "additionalProperties": false +} diff --git a/static/schemas/source/deals/activate-deal-request.json b/static/schemas/source/deals/activate-deal-request.json index 75e1d80d..6c45b8e1 100644 --- a/static/schemas/source/deals/activate-deal-request.json +++ b/static/schemas/source/deals/activate-deal-request.json @@ -18,9 +18,10 @@ "minItems": 1 }, "context": { - "type": "object", - "description": "Initiator-provided context included in the request payload. Agents must echo this value back unchanged in responses and webhooks. Use for UI/session hints, correlation tokens, or tracking metadata.", - "additionalProperties": true + "$ref": "/schemas/core/context.json" + }, + "ext": { + "$ref": "/schemas/core/ext.json" } }, "required": ["deal_id", "destinations"], diff --git a/static/schemas/source/deals/activate-deal-response.json b/static/schemas/source/deals/activate-deal-response.json index 7db86b07..14dca8ee 100644 --- a/static/schemas/source/deals/activate-deal-response.json +++ b/static/schemas/source/deals/activate-deal-response.json @@ -17,9 +17,10 @@ } }, "context": { - "type": "object", - "description": "Initiator-provided context echoed inside the task payload. Opaque metadata such as UI/session hints, correlation tokens, or tracking identifiers.", - "additionalProperties": true + "$ref": "/schemas/core/context.json" + }, + "ext": { + "$ref": "/schemas/core/ext.json" } }, "required": ["deployments"], @@ -41,9 +42,10 @@ "minItems": 1 }, "context": { - "type": "object", - "description": "Initiator-provided context echoed inside the task payload. Opaque metadata such as UI/session hints, correlation tokens, or tracking identifiers.", - "additionalProperties": true + "$ref": "/schemas/core/context.json" + }, + "ext": { + "$ref": "/schemas/core/ext.json" } }, "required": ["errors"], diff --git a/static/schemas/source/deals/get-deals-request.json b/static/schemas/source/deals/get-deals-request.json index 17917de3..97a9e2b9 100644 --- a/static/schemas/source/deals/get-deals-request.json +++ b/static/schemas/source/deals/get-deals-request.json @@ -2,24 +2,32 @@ "$schema": "http://json-schema.org/draft-07/schema#", "$id": "/schemas/deals/get-deals-request.json", "title": "Get Deals Request", - "description": "Request parameters for discovering deal packages based on natural language description", + "description": "Request parameters for discovering deal packages", "type": "object", "properties": { - "deal_spec": { + "brief": { "type": "string", "description": "Natural language description of the desired deal package, including any filtering criteria (deal type, ad format, pricing constraints, dates, etc.)" }, + "brand_manifest": { + "$ref": "/schemas/core/brand-manifest-ref.json", + "description": "Brand information manifest providing brand context, assets, and product catalog. Can be provided inline or as a URL reference to a hosted manifest." + }, + "filters": { + "$ref": "/schemas/core/deal-filters.json" + }, "max_results": { "type": "integer", "description": "Maximum number of results to return", "minimum": 1 }, "context": { - "type": "object", - "description": "Initiator-provided context included in the request payload. Agents must echo this value back unchanged in responses and webhooks. Use for UI/session hints, correlation tokens, or tracking metadata.", - "additionalProperties": true + "$ref": "/schemas/core/context.json" + }, + "ext": { + "$ref": "/schemas/core/ext.json" } }, - "required": ["deal_spec"], + "required": [], "additionalProperties": false } diff --git a/static/schemas/source/deals/get-deals-response.json b/static/schemas/source/deals/get-deals-response.json index 1f5785e1..89f4793f 100644 --- a/static/schemas/source/deals/get-deals-response.json +++ b/static/schemas/source/deals/get-deals-response.json @@ -20,9 +20,10 @@ } }, "context": { - "type": "object", - "description": "Initiator-provided context echoed inside the task payload. Opaque metadata such as UI/session hints, correlation tokens, or tracking identifiers.", - "additionalProperties": true + "$ref": "/schemas/core/context.json" + }, + "ext": { + "$ref": "/schemas/core/ext.json" } }, "required": ["deals"],