adcp 0.1.2__py3-none-any.whl → 1.0.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- adcp/__init__.py +80 -2
- adcp/__main__.py +284 -0
- adcp/client.py +290 -105
- adcp/config.py +82 -0
- adcp/exceptions.py +121 -0
- adcp/protocols/__init__.py +2 -0
- adcp/protocols/a2a.py +201 -87
- adcp/protocols/base.py +11 -0
- adcp/protocols/mcp.py +185 -25
- adcp/types/__init__.py +4 -0
- adcp/types/core.py +76 -1
- adcp/types/generated.py +615 -0
- adcp/types/tasks.py +281 -0
- adcp/utils/__init__.py +2 -0
- adcp/utils/operation_id.py +2 -0
- {adcp-0.1.2.dist-info → adcp-1.0.2.dist-info}/METADATA +184 -8
- adcp-1.0.2.dist-info/RECORD +21 -0
- adcp-1.0.2.dist-info/entry_points.txt +2 -0
- adcp-0.1.2.dist-info/RECORD +0 -15
- {adcp-0.1.2.dist-info → adcp-1.0.2.dist-info}/WHEEL +0 -0
- {adcp-0.1.2.dist-info → adcp-1.0.2.dist-info}/licenses/LICENSE +0 -0
- {adcp-0.1.2.dist-info → adcp-1.0.2.dist-info}/top_level.txt +0 -0
adcp/types/generated.py
ADDED
|
@@ -0,0 +1,615 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Auto-generated Pydantic models from AdCP JSON schemas.
|
|
3
|
+
|
|
4
|
+
DO NOT EDIT THIS FILE MANUALLY.
|
|
5
|
+
Generated from: https://adcontextprotocol.org/schemas/v1/
|
|
6
|
+
To regenerate:
|
|
7
|
+
python scripts/sync_schemas.py
|
|
8
|
+
python scripts/fix_schema_refs.py
|
|
9
|
+
python scripts/generate_models_simple.py
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
from typing import Any, Literal
|
|
15
|
+
|
|
16
|
+
from pydantic import BaseModel, Field
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
# ============================================================================
|
|
20
|
+
# MISSING SCHEMA TYPES (referenced but not provided by upstream)
|
|
21
|
+
# ============================================================================
|
|
22
|
+
|
|
23
|
+
# These types are referenced in schemas but don't have schema files
|
|
24
|
+
# Defining them as type aliases to maintain type safety
|
|
25
|
+
FormatId = str
|
|
26
|
+
PackageRequest = dict[str, Any]
|
|
27
|
+
PushNotificationConfig = dict[str, Any]
|
|
28
|
+
ReportingCapabilities = dict[str, Any]
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
# ============================================================================
|
|
32
|
+
# CORE DOMAIN TYPES
|
|
33
|
+
# ============================================================================
|
|
34
|
+
|
|
35
|
+
class Product(BaseModel):
|
|
36
|
+
"""Represents available advertising inventory"""
|
|
37
|
+
|
|
38
|
+
product_id: str = Field(description="Unique identifier for the product")
|
|
39
|
+
name: str = Field(description="Human-readable product name")
|
|
40
|
+
description: str = Field(description="Detailed description of the product and its inventory")
|
|
41
|
+
publisher_properties: list[dict[str, Any]] = Field(description="Publisher properties covered by this product. Buyers fetch actual property definitions from each publisher's adagents.json and validate agent authorization.")
|
|
42
|
+
format_ids: list[FormatId] = Field(description="Array of supported creative format IDs - structured format_id objects with agent_url and id")
|
|
43
|
+
placements: list[Placement] | None = Field(None, description="Optional array of specific placements within this product. When provided, buyers can target specific placements when assigning creatives.")
|
|
44
|
+
delivery_type: DeliveryType
|
|
45
|
+
pricing_options: list[PricingOption] = Field(description="Available pricing models for this product")
|
|
46
|
+
estimated_exposures: int | None = Field(None, description="Estimated exposures/impressions for guaranteed products")
|
|
47
|
+
measurement: Measurement | None = None
|
|
48
|
+
delivery_measurement: dict[str, Any] = Field(description="Measurement provider and methodology for delivery metrics. The buyer accepts the declared provider as the source of truth for the buy. REQUIRED for all products.")
|
|
49
|
+
reporting_capabilities: ReportingCapabilities | None = None
|
|
50
|
+
creative_policy: CreativePolicy | None = None
|
|
51
|
+
is_custom: bool | None = Field(None, description="Whether this is a custom product")
|
|
52
|
+
brief_relevance: str | None = Field(None, description="Explanation of why this product matches the brief (only included when brief is provided)")
|
|
53
|
+
expires_at: str | None = Field(None, description="Expiration timestamp for custom products")
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class MediaBuy(BaseModel):
|
|
57
|
+
"""Represents a purchased advertising campaign"""
|
|
58
|
+
|
|
59
|
+
media_buy_id: str = Field(description="Publisher's unique identifier for the media buy")
|
|
60
|
+
buyer_ref: str | None = Field(None, description="Buyer's reference identifier for this media buy")
|
|
61
|
+
status: MediaBuyStatus
|
|
62
|
+
promoted_offering: str = Field(description="Description of advertiser and what is being promoted")
|
|
63
|
+
total_budget: float = Field(description="Total budget amount")
|
|
64
|
+
packages: list[Package] = Field(description="Array of packages within this media buy")
|
|
65
|
+
creative_deadline: str | None = Field(None, description="ISO 8601 timestamp for creative upload deadline")
|
|
66
|
+
created_at: str | None = Field(None, description="Creation timestamp")
|
|
67
|
+
updated_at: str | None = Field(None, description="Last update timestamp")
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
class Package(BaseModel):
|
|
71
|
+
"""A specific product within a media buy (line item)"""
|
|
72
|
+
|
|
73
|
+
package_id: str = Field(description="Publisher's unique identifier for the package")
|
|
74
|
+
buyer_ref: str | None = Field(None, description="Buyer's reference identifier for this package")
|
|
75
|
+
product_id: str | None = Field(None, description="ID of the product this package is based on")
|
|
76
|
+
budget: float | None = Field(None, description="Budget allocation for this package in the currency specified by the pricing option")
|
|
77
|
+
pacing: Pacing | None = None
|
|
78
|
+
pricing_option_id: str | None = Field(None, description="ID of the selected pricing option from the product's pricing_options array")
|
|
79
|
+
bid_price: float | None = Field(None, description="Bid price for auction-based CPM pricing (present if using cpm-auction-option)")
|
|
80
|
+
impressions: float | None = Field(None, description="Impression goal for this package")
|
|
81
|
+
targeting_overlay: Targeting | None = None
|
|
82
|
+
creative_assignments: list[CreativeAssignment] | None = Field(None, description="Creative assets assigned to this package")
|
|
83
|
+
format_ids_to_provide: list[FormatId] | None = Field(None, description="Format IDs that creative assets will be provided for this package")
|
|
84
|
+
status: PackageStatus
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
class CreativeAsset(BaseModel):
|
|
88
|
+
"""Creative asset for upload to library - supports static assets, generative formats, and third-party snippets"""
|
|
89
|
+
|
|
90
|
+
creative_id: str = Field(description="Unique identifier for the creative")
|
|
91
|
+
name: str = Field(description="Human-readable creative name")
|
|
92
|
+
format_id: FormatId = Field(description="Format identifier specifying which format this creative conforms to")
|
|
93
|
+
assets: dict[str, Any] = Field(description="Assets required by the format, keyed by asset_role")
|
|
94
|
+
inputs: list[dict[str, Any]] | None = Field(None, description="Preview contexts for generative formats - defines what scenarios to generate previews for")
|
|
95
|
+
tags: list[str] | None = Field(None, description="User-defined tags for organization and searchability")
|
|
96
|
+
approved: bool | None = Field(None, description="For generative creatives: set to true to approve and finalize, false to request regeneration with updated assets/message. Omit for non-generative creatives.")
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
class CreativeManifest(BaseModel):
|
|
100
|
+
"""Complete specification of a creative with all assets needed for rendering in a specific format. Each asset is typed according to its asset_role from the format specification and contains the actual content/URL that fulfills the format requirements."""
|
|
101
|
+
|
|
102
|
+
format_id: FormatId = Field(description="Format identifier this manifest is for")
|
|
103
|
+
promoted_offering: str | None = Field(None, description="Product name or offering being advertised. Maps to promoted_offerings in create_media_buy request to associate creative with the product being promoted.")
|
|
104
|
+
assets: dict[str, Any] = Field(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. IMPORTANT: 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.")
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
class BrandManifest(BaseModel):
|
|
108
|
+
"""Standardized brand information manifest for creative generation and media buying. Enables low-friction creative workflows by providing brand context that can be easily cached and shared across requests."""
|
|
109
|
+
|
|
110
|
+
url: str | None = Field(None, description="Primary brand URL for context and asset discovery. Creative agents can infer brand information from this URL.")
|
|
111
|
+
name: str | None = Field(None, description="Brand or business name")
|
|
112
|
+
logos: list[dict[str, Any]] | None = Field(None, description="Brand logo assets with semantic tags for different use cases")
|
|
113
|
+
colors: dict[str, Any] | None = Field(None, description="Brand color palette")
|
|
114
|
+
fonts: dict[str, Any] | None = Field(None, description="Brand typography guidelines")
|
|
115
|
+
tone: str | None = Field(None, description="Brand voice and messaging tone (e.g., 'professional', 'casual', 'humorous', 'trustworthy', 'innovative')")
|
|
116
|
+
tagline: str | None = Field(None, description="Brand tagline or slogan")
|
|
117
|
+
assets: list[dict[str, Any]] | None = Field(None, description="Brand asset library with explicit assets and tags. Assets are referenced inline with URLs pointing to CDN-hosted files.")
|
|
118
|
+
product_catalog: dict[str, Any] | None = Field(None, description="Product catalog information for e-commerce advertisers. Enables SKU-level creative generation and product selection.")
|
|
119
|
+
disclaimers: list[dict[str, Any]] | None = Field(None, description="Legal disclaimers or required text that must appear in creatives")
|
|
120
|
+
industry: str | None = Field(None, description="Industry or vertical (e.g., 'retail', 'automotive', 'finance', 'healthcare')")
|
|
121
|
+
target_audience: str | None = Field(None, description="Primary target audience description")
|
|
122
|
+
contact: dict[str, Any] | None = Field(None, description="Brand contact information")
|
|
123
|
+
metadata: dict[str, Any] | None = Field(None, description="Additional brand metadata")
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
# Type alias for Brand Manifest Reference
|
|
127
|
+
# Brand manifest provided either as an inline object or a URL string pointing to a hosted manifest
|
|
128
|
+
BrandManifestRef = Any
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
class Format(BaseModel):
|
|
132
|
+
"""Represents a creative format with its requirements"""
|
|
133
|
+
|
|
134
|
+
format_id: FormatId = Field(description="Structured format identifier with agent URL and format name")
|
|
135
|
+
name: str = Field(description="Human-readable format name")
|
|
136
|
+
description: str | None = Field(None, description="Plain text explanation of what this format does and what assets it requires")
|
|
137
|
+
preview_image: str | None = Field(None, description="Optional preview image URL for format browsing/discovery UI. Should be 400x300px (4:3 aspect ratio) PNG or JPG. Used as thumbnail/card image in format browsers.")
|
|
138
|
+
example_url: str | None = Field(None, description="Optional URL to showcase page with examples and interactive demos of this format")
|
|
139
|
+
type: Literal["audio", "video", "display", "native", "dooh", "rich_media", "universal"] = Field(description="Media type of this format - determines rendering method and asset requirements")
|
|
140
|
+
renders: list[dict[str, Any]] | None = Field(None, description="Specification of rendered pieces for this format. Most formats produce a single render. Companion ad formats (video + banner), adaptive formats, and multi-placement formats produce multiple renders. Each render specifies its role and dimensions.")
|
|
141
|
+
assets_required: list[Any] | None = Field(None, description="Array of required assets or asset groups for this format. Each asset is identified by its asset_id, which must be used as the key in creative manifests. Can contain individual assets or repeatable asset sequences (e.g., carousel products, slideshow frames).")
|
|
142
|
+
delivery: dict[str, Any] | None = Field(None, description="Delivery method specifications (e.g., hosted, VAST, third-party tags)")
|
|
143
|
+
supported_macros: list[str] | None = Field(None, description="List of universal macros supported by this format (e.g., MEDIA_BUY_ID, CACHEBUSTER, DEVICE_ID). Used for validation and developer tooling.")
|
|
144
|
+
output_format_ids: list[FormatId] | None = Field(None, description="For generative formats: array of format IDs that this format can generate. When a format accepts inputs like brand_manifest and message, this specifies what concrete output formats can be produced (e.g., a generative banner format might output standard image banner formats).")
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
class Targeting(BaseModel):
|
|
148
|
+
"""Optional geographic refinements for media buys. Most targeting should be expressed in the brief and handled by the publisher. These fields are primarily for geographic restrictions (RCT testing, regulatory compliance)."""
|
|
149
|
+
|
|
150
|
+
geo_country_any_of: list[str] | None = Field(None, description="Restrict delivery to specific countries (ISO codes). Use for regulatory compliance or RCT testing.")
|
|
151
|
+
geo_region_any_of: list[str] | None = Field(None, description="Restrict delivery to specific regions/states. Use for regulatory compliance or RCT testing.")
|
|
152
|
+
geo_metro_any_of: list[str] | None = Field(None, description="Restrict delivery to specific metro areas (DMA codes). Use for regulatory compliance or RCT testing.")
|
|
153
|
+
geo_postal_code_any_of: list[str] | None = Field(None, description="Restrict delivery to specific postal/ZIP codes. Use for regulatory compliance or RCT testing.")
|
|
154
|
+
frequency_cap: FrequencyCap | None = None
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
class FrequencyCap(BaseModel):
|
|
158
|
+
"""Frequency capping settings for package-level application"""
|
|
159
|
+
|
|
160
|
+
suppress_minutes: float = Field(description="Minutes to suppress after impression")
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
class Measurement(BaseModel):
|
|
164
|
+
"""Measurement capabilities included with a product"""
|
|
165
|
+
|
|
166
|
+
type: str = Field(description="Type of measurement")
|
|
167
|
+
attribution: str = Field(description="Attribution methodology")
|
|
168
|
+
window: str | None = Field(None, description="Attribution window")
|
|
169
|
+
reporting: str = Field(description="Reporting frequency and format")
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
class DeliveryMetrics(BaseModel):
|
|
173
|
+
"""Standard delivery metrics that can be reported at media buy, package, or creative level"""
|
|
174
|
+
|
|
175
|
+
impressions: float | None = Field(None, description="Impressions delivered")
|
|
176
|
+
spend: float | None = Field(None, description="Amount spent")
|
|
177
|
+
clicks: float | None = Field(None, description="Total clicks")
|
|
178
|
+
ctr: float | None = Field(None, description="Click-through rate (clicks/impressions)")
|
|
179
|
+
views: float | None = Field(None, description="Views at threshold (for CPV)")
|
|
180
|
+
completed_views: float | None = Field(None, description="100% completions (for CPCV)")
|
|
181
|
+
completion_rate: float | None = Field(None, description="Completion rate (completed_views/impressions)")
|
|
182
|
+
conversions: float | None = Field(None, description="Conversions (reserved for future CPA pricing support)")
|
|
183
|
+
leads: float | None = Field(None, description="Leads generated (reserved for future CPL pricing support)")
|
|
184
|
+
grps: float | None = Field(None, description="Gross Rating Points delivered (for CPP)")
|
|
185
|
+
reach: float | None = Field(None, description="Unique reach - units depend on measurement provider (e.g., individuals, households, devices, cookies). See delivery_measurement.provider for methodology.")
|
|
186
|
+
frequency: float | None = Field(None, description="Average frequency per individual (typically measured over campaign duration, but can vary by measurement provider)")
|
|
187
|
+
quartile_data: dict[str, Any] | None = Field(None, description="Video quartile completion data")
|
|
188
|
+
dooh_metrics: dict[str, Any] | None = Field(None, description="DOOH-specific metrics (only included for DOOH campaigns)")
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
class Error(BaseModel):
|
|
192
|
+
"""Standard error structure for task-specific errors and warnings"""
|
|
193
|
+
|
|
194
|
+
code: str = Field(description="Error code for programmatic handling")
|
|
195
|
+
message: str = Field(description="Human-readable error message")
|
|
196
|
+
field: str | None = Field(None, description="Field path associated with the error (e.g., 'packages[0].targeting')")
|
|
197
|
+
suggestion: str | None = Field(None, description="Suggested fix for the error")
|
|
198
|
+
retry_after: float | None = Field(None, description="Seconds to wait before retrying the operation")
|
|
199
|
+
details: Any | None = Field(None, description="Additional task-specific error details")
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
class Property(BaseModel):
|
|
203
|
+
"""An advertising property that can be validated via adagents.json"""
|
|
204
|
+
|
|
205
|
+
property_id: str | None = Field(None, description="Unique identifier for this property (optional). Enables referencing properties by ID instead of repeating full objects. Recommended format: lowercase with underscores (e.g., 'cnn_ctv_app', 'instagram_mobile')")
|
|
206
|
+
property_type: Literal["website", "mobile_app", "ctv_app", "dooh", "podcast", "radio", "streaming_audio"] = Field(description="Type of advertising property")
|
|
207
|
+
name: str = Field(description="Human-readable property name")
|
|
208
|
+
identifiers: list[dict[str, Any]] = Field(description="Array of identifiers for this property")
|
|
209
|
+
tags: list[str] | None = Field(None, description="Tags for categorization and grouping (e.g., network membership, content categories)")
|
|
210
|
+
publisher_domain: str | None = Field(None, description="Domain where adagents.json should be checked for authorization validation. Required for list_authorized_properties response. Optional in adagents.json (file location implies domain).")
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
class Placement(BaseModel):
|
|
214
|
+
"""Represents a specific ad placement within a product's inventory"""
|
|
215
|
+
|
|
216
|
+
placement_id: str = Field(description="Unique identifier for the placement within the product")
|
|
217
|
+
name: str = Field(description="Human-readable name for the placement (e.g., 'Homepage Banner', 'Article Sidebar')")
|
|
218
|
+
description: str | None = Field(None, description="Detailed description of where and how the placement appears")
|
|
219
|
+
format_ids: list[FormatId] | None = Field(None, description="Format IDs supported by this specific placement (subset of product's formats)")
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
class CreativePolicy(BaseModel):
|
|
223
|
+
"""Creative requirements and restrictions for a product"""
|
|
224
|
+
|
|
225
|
+
co_branding: Literal["required", "optional", "none"] = Field(description="Co-branding requirement")
|
|
226
|
+
landing_page: Literal["any", "retailer_site_only", "must_include_retailer"] = Field(description="Landing page requirements")
|
|
227
|
+
templates_available: bool = Field(description="Whether creative templates are provided")
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
class CreativeAssignment(BaseModel):
|
|
231
|
+
"""Assignment of a creative asset to a package with optional placement targeting. Used in create_media_buy and update_media_buy requests. Note: sync_creatives does not support placement_ids - use create/update_media_buy for placement-level targeting."""
|
|
232
|
+
|
|
233
|
+
creative_id: str = Field(description="Unique identifier for the creative")
|
|
234
|
+
weight: float | None = Field(None, description="Delivery weight for this creative")
|
|
235
|
+
placement_ids: list[str] | None = Field(None, description="Optional array of placement IDs where this creative should run. When omitted, the creative runs on all placements in the package. References placement_id values from the product's placements array.")
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
class PerformanceFeedback(BaseModel):
|
|
239
|
+
"""Represents performance feedback data for a media buy or package"""
|
|
240
|
+
|
|
241
|
+
feedback_id: str = Field(description="Unique identifier for this performance feedback submission")
|
|
242
|
+
media_buy_id: str = Field(description="Publisher's media buy identifier")
|
|
243
|
+
package_id: str | None = Field(None, description="Specific package within the media buy (if feedback is package-specific)")
|
|
244
|
+
creative_id: str | None = Field(None, description="Specific creative asset (if feedback is creative-specific)")
|
|
245
|
+
measurement_period: dict[str, Any] = Field(description="Time period for performance measurement")
|
|
246
|
+
performance_index: float = Field(description="Normalized performance score (0.0 = no value, 1.0 = expected, >1.0 = above expected)")
|
|
247
|
+
metric_type: Literal["overall_performance", "conversion_rate", "brand_lift", "click_through_rate", "completion_rate", "viewability", "brand_safety", "cost_efficiency"] = Field(description="The business metric being measured")
|
|
248
|
+
feedback_source: Literal["buyer_attribution", "third_party_measurement", "platform_analytics", "verification_partner"] = Field(description="Source of the performance data")
|
|
249
|
+
status: Literal["accepted", "queued", "applied", "rejected"] = Field(description="Processing status of the performance feedback")
|
|
250
|
+
submitted_at: str = Field(description="ISO 8601 timestamp when feedback was submitted")
|
|
251
|
+
applied_at: str | None = Field(None, description="ISO 8601 timestamp when feedback was applied to optimization algorithms")
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
# Type alias for Start Timing
|
|
255
|
+
# Campaign start timing: 'asap' or ISO 8601 date-time
|
|
256
|
+
StartTiming = Any
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
class SubAsset(BaseModel):
|
|
260
|
+
"""Sub-asset for multi-asset creative formats, including carousel images and native ad template variables"""
|
|
261
|
+
|
|
262
|
+
asset_type: str | None = Field(None, description="Type of asset. Common types: headline, body_text, thumbnail_image, product_image, featured_image, logo, cta_text, price_text, sponsor_name, author_name, click_url")
|
|
263
|
+
asset_id: str | None = Field(None, description="Unique identifier for the asset within the creative")
|
|
264
|
+
content_uri: str | None = Field(None, description="URL for media assets (images, videos, etc.)")
|
|
265
|
+
content: Any | None = Field(None, description="Text content for text-based assets like headlines, body text, CTA text, etc.")
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
class WebhookPayload(BaseModel):
|
|
269
|
+
"""Payload structure sent to webhook endpoints when async task status changes. Protocol-level fields are at the top level and the task-specific payload is nested under the 'result' field. This schema represents what your webhook handler will receive when a task transitions from 'submitted' to a terminal or intermediate state."""
|
|
270
|
+
|
|
271
|
+
operation_id: str | None = Field(None, description="Publisher-defined operation identifier correlating a sequence of task updates across webhooks.")
|
|
272
|
+
task_id: str = Field(description="Unique identifier for this task. Use this to correlate webhook notifications with the original task submission.")
|
|
273
|
+
task_type: TaskType = Field(description="Type of AdCP operation that triggered this webhook. Enables webhook handlers to route to appropriate processing logic.")
|
|
274
|
+
domain: Literal["media-buy", "signals"] | None = Field(None, description="AdCP domain this task belongs to. Helps classify the operation type at a high level.")
|
|
275
|
+
status: TaskStatus = Field(description="Current task status. Webhooks are only triggered for status changes after initial submission (e.g., submitted → input-required, submitted → completed, submitted → failed).")
|
|
276
|
+
timestamp: str = Field(description="ISO 8601 timestamp when this webhook was generated.")
|
|
277
|
+
message: str | None = Field(None, description="Human-readable summary of the current task state. Provides context about what happened and what action may be needed.")
|
|
278
|
+
context_id: str | None = Field(None, description="Session/conversation identifier. Use this to continue the conversation if input-required status needs clarification or additional parameters.")
|
|
279
|
+
progress: dict[str, Any] | None = Field(None, description="Progress information for tasks still in 'working' state. Rarely seen in webhooks since 'working' tasks typically complete synchronously, but may appear if a task transitions from 'submitted' to 'working'.")
|
|
280
|
+
result: Any | None = Field(None, description="Task-specific payload for this status update. For 'completed', contains the final result. For 'input-required', may contain approval or clarification context. Optional for non-terminal updates.")
|
|
281
|
+
error: Any | None = Field(None, description="Error message for failed tasks. Only present when status is 'failed'.")
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
class ProtocolEnvelope(BaseModel):
|
|
285
|
+
"""Standard envelope structure for AdCP task responses. This envelope is added by the protocol layer (MCP, A2A, REST) and wraps the task-specific response payload. Task response schemas should NOT include these fields - they are protocol-level concerns."""
|
|
286
|
+
|
|
287
|
+
context_id: str | None = Field(None, description="Session/conversation identifier for tracking related operations across multiple task invocations. Managed by the protocol layer to maintain conversational context.")
|
|
288
|
+
task_id: str | None = Field(None, description="Unique identifier for tracking asynchronous operations. Present when a task requires extended processing time. Used to query task status and retrieve results when complete.")
|
|
289
|
+
status: TaskStatus = Field(description="Current task execution state. Indicates whether the task is completed, in progress (working), submitted for async processing, failed, or requires user input. Managed by the protocol layer.")
|
|
290
|
+
message: str | None = Field(None, description="Human-readable summary of the task result. Provides natural language explanation of what happened, suitable for display to end users or for AI agent comprehension. Generated by the protocol layer based on the task response.")
|
|
291
|
+
timestamp: str | None = Field(None, description="ISO 8601 timestamp when the response was generated. Useful for debugging, logging, cache validation, and tracking async operation progress.")
|
|
292
|
+
push_notification_config: PushNotificationConfig | None = Field(None, description="Push notification configuration for async task updates (A2A and REST protocols). Echoed from the request to confirm webhook settings. Specifies URL, authentication scheme (Bearer or HMAC-SHA256), and credentials. MCP uses progress notifications instead of webhooks.")
|
|
293
|
+
payload: dict[str, Any] = Field(description="The actual task-specific response data. This is the content defined in individual task response schemas (e.g., get-products-response.json, create-media-buy-response.json). Contains only domain-specific data without protocol-level fields.")
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
class Response(BaseModel):
|
|
297
|
+
"""Protocol-level response wrapper (MCP/A2A) - contains AdCP task data plus protocol fields"""
|
|
298
|
+
|
|
299
|
+
message: str = Field(description="Human-readable summary")
|
|
300
|
+
context_id: str | None = Field(None, description="Session continuity identifier")
|
|
301
|
+
data: Any | None = Field(None, description="AdCP task-specific response data (see individual task response schemas)")
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
class PromotedProducts(BaseModel):
|
|
305
|
+
"""Specification of products or offerings being promoted in a campaign. Supports multiple selection methods from the brand manifest that can be combined using UNION (OR) logic. When multiple selection methods are provided, products matching ANY of the criteria are selected (logical OR, not AND)."""
|
|
306
|
+
|
|
307
|
+
manifest_skus: list[str] | None = Field(None, description="Direct product SKU references from the brand manifest product catalog")
|
|
308
|
+
manifest_tags: list[str] | None = Field(None, description="Select products by tags from the brand manifest product catalog (e.g., 'organic', 'sauces', 'holiday')")
|
|
309
|
+
manifest_category: str | None = Field(None, description="Select products from a specific category in the brand manifest product catalog (e.g., 'beverages/soft-drinks', 'food/sauces')")
|
|
310
|
+
manifest_query: str | None = Field(None, description="Natural language query to select products from the brand manifest (e.g., 'all Kraft Heinz pasta sauces', 'organic products under $20')")
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
# Type alias for Advertising Channels
|
|
314
|
+
# Standard advertising channels supported by AdCP
|
|
315
|
+
Channels = Literal["display", "video", "audio", "native", "dooh", "ctv", "podcast", "retail", "social"]
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
# Type alias for Delivery Type
|
|
319
|
+
# Type of inventory delivery
|
|
320
|
+
DeliveryType = Literal["guaranteed", "non_guaranteed"]
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
# Type alias for Pacing
|
|
324
|
+
# Budget pacing strategy
|
|
325
|
+
Pacing = Literal["even", "asap", "front_loaded"]
|
|
326
|
+
|
|
327
|
+
|
|
328
|
+
# Type alias for Package Status
|
|
329
|
+
# Status of a package
|
|
330
|
+
PackageStatus = Literal["draft", "active", "paused", "completed"]
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
# Type alias for Media Buy Status
|
|
334
|
+
# Status of a media buy
|
|
335
|
+
MediaBuyStatus = Literal["pending_activation", "active", "paused", "completed"]
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
# Type alias for Task Type
|
|
339
|
+
# Valid AdCP task types across all domains. These represent the complete set of operations that can be tracked via the task management system.
|
|
340
|
+
TaskType = Literal["create_media_buy", "update_media_buy", "sync_creatives", "activate_signal", "get_signals"]
|
|
341
|
+
|
|
342
|
+
|
|
343
|
+
# Type alias for Task Status
|
|
344
|
+
# Standardized task status values based on A2A TaskState enum. Indicates the current state of any AdCP operation.
|
|
345
|
+
TaskStatus = Literal["submitted", "working", "input-required", "completed", "canceled", "failed", "rejected", "auth-required", "unknown"]
|
|
346
|
+
|
|
347
|
+
|
|
348
|
+
# Type alias for Pricing Model
|
|
349
|
+
# Supported pricing models for advertising products
|
|
350
|
+
PricingModel = Literal["cpm", "vcpm", "cpc", "cpcv", "cpv", "cpp", "flat_rate"]
|
|
351
|
+
|
|
352
|
+
|
|
353
|
+
# Type alias for Pricing Option
|
|
354
|
+
# A pricing model option offered by a publisher for a product. Each pricing model has its own schema with model-specific requirements.
|
|
355
|
+
PricingOption = Any
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
# Type alias for Standard Format IDs
|
|
359
|
+
# Enumeration of all standard creative format identifiers in AdCP
|
|
360
|
+
StandardFormatIds = Literal["display_300x250", "display_728x90", "display_320x50", "display_160x600", "display_970x250", "display_336x280", "display_expandable_300x250", "display_expandable_728x90", "display_interstitial_320x480", "display_interstitial_desktop", "display_dynamic_300x250", "display_responsive", "native_in_feed", "native_content_recommendation", "native_product", "video_skippable_15s", "video_skippable_30s", "video_non_skippable_15s", "video_non_skippable_30s", "video_outstream_autoplay", "video_vertical_story", "video_rewarded_30s", "video_pause_ad", "video_ctv_non_skippable_30s", "audio_standard_15s", "audio_standard_30s", "audio_podcast_host_read", "audio_programmatic", "universal_carousel", "universal_canvas", "universal_takeover", "universal_gallery", "universal_reveal", "dooh_landscape_static", "dooh_portrait_video"]
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
|
|
364
|
+
# ============================================================================
|
|
365
|
+
# TASK REQUEST/RESPONSE TYPES
|
|
366
|
+
# ============================================================================
|
|
367
|
+
|
|
368
|
+
class ActivateSignalRequest(BaseModel):
|
|
369
|
+
"""Request parameters for activating a signal on a specific platform/account"""
|
|
370
|
+
|
|
371
|
+
signal_agent_segment_id: str = Field(description="The universal identifier for the signal to activate")
|
|
372
|
+
platform: str = Field(description="The target platform for activation")
|
|
373
|
+
account: str | None = Field(None, description="Account identifier (required for account-specific activation)")
|
|
374
|
+
|
|
375
|
+
|
|
376
|
+
class BuildCreativeRequest(BaseModel):
|
|
377
|
+
"""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)."""
|
|
378
|
+
|
|
379
|
+
message: str | None = Field(None, 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.")
|
|
380
|
+
creative_manifest: CreativeManifest | None = Field(None, 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.")
|
|
381
|
+
target_format_id: FormatId = Field(description="Format ID to generate. The format definition specifies required input assets and output structure.")
|
|
382
|
+
|
|
383
|
+
|
|
384
|
+
class CreateMediaBuyRequest(BaseModel):
|
|
385
|
+
"""Request parameters for creating a media buy"""
|
|
386
|
+
|
|
387
|
+
buyer_ref: str = Field(description="Buyer's reference identifier for this media buy")
|
|
388
|
+
packages: list[PackageRequest] = Field(description="Array of package configurations")
|
|
389
|
+
brand_manifest: BrandManifestRef = Field(description="Brand information manifest serving as the namespace and identity for this media buy. Provides brand context, assets, and product catalog. Can be provided inline or as a URL reference to a hosted manifest. Can be cached and reused across multiple requests.")
|
|
390
|
+
po_number: str | None = Field(None, description="Purchase order number for tracking")
|
|
391
|
+
start_time: StartTiming
|
|
392
|
+
end_time: str = Field(description="Campaign end date/time in ISO 8601 format")
|
|
393
|
+
reporting_webhook: Any | None = None
|
|
394
|
+
|
|
395
|
+
|
|
396
|
+
class GetMediaBuyDeliveryRequest(BaseModel):
|
|
397
|
+
"""Request parameters for retrieving comprehensive delivery metrics"""
|
|
398
|
+
|
|
399
|
+
media_buy_ids: list[str] | None = Field(None, description="Array of publisher media buy IDs to get delivery data for")
|
|
400
|
+
buyer_refs: list[str] | None = Field(None, description="Array of buyer reference IDs to get delivery data for")
|
|
401
|
+
status_filter: Any | None = Field(None, description="Filter by status. Can be a single status or array of statuses")
|
|
402
|
+
start_date: str | None = Field(None, description="Start date for reporting period (YYYY-MM-DD)")
|
|
403
|
+
end_date: str | None = Field(None, description="End date for reporting period (YYYY-MM-DD)")
|
|
404
|
+
|
|
405
|
+
|
|
406
|
+
class GetProductsRequest(BaseModel):
|
|
407
|
+
"""Request parameters for discovering available advertising products"""
|
|
408
|
+
|
|
409
|
+
brief: str | None = Field(None, description="Natural language description of campaign requirements")
|
|
410
|
+
brand_manifest: BrandManifestRef | None = Field(None, description="Brand information manifest providing brand context, assets, and product catalog. Can be provided inline or as a URL reference to a hosted manifest.")
|
|
411
|
+
filters: dict[str, Any] | None = Field(None, description="Structured filters for product discovery")
|
|
412
|
+
|
|
413
|
+
|
|
414
|
+
class GetSignalsRequest(BaseModel):
|
|
415
|
+
"""Request parameters for discovering signals based on description"""
|
|
416
|
+
|
|
417
|
+
signal_spec: str = Field(description="Natural language description of the desired signals")
|
|
418
|
+
deliver_to: dict[str, Any] = Field(description="Where the signals need to be delivered")
|
|
419
|
+
filters: dict[str, Any] | None = Field(None, description="Filters to refine results")
|
|
420
|
+
max_results: int | None = Field(None, description="Maximum number of results to return")
|
|
421
|
+
|
|
422
|
+
|
|
423
|
+
class ListAuthorizedPropertiesRequest(BaseModel):
|
|
424
|
+
"""Request parameters for discovering which publishers this agent is authorized to represent"""
|
|
425
|
+
|
|
426
|
+
publisher_domains: list[str] | None = Field(None, description="Filter to specific publisher domains (optional). If omitted, returns all publishers this agent represents.")
|
|
427
|
+
|
|
428
|
+
|
|
429
|
+
class ListCreativeFormatsRequest(BaseModel):
|
|
430
|
+
"""Request parameters for discovering creative formats provided by this creative agent"""
|
|
431
|
+
|
|
432
|
+
format_ids: list[FormatId] | None = Field(None, description="Return only these specific format IDs")
|
|
433
|
+
type: Literal["audio", "video", "display", "dooh"] | None = Field(None, description="Filter by format type (technical categories with distinct requirements)")
|
|
434
|
+
asset_types: list[Literal["image", "video", "audio", "text", "html", "javascript", "url"]] | None = Field(None, description="Filter to formats that include these asset types. For third-party tags, search for 'html' or 'javascript'. E.g., ['image', 'text'] returns formats with images and text, ['javascript'] returns formats accepting JavaScript tags.")
|
|
435
|
+
max_width: int | None = Field(None, description="Maximum width in pixels (inclusive). Returns formats with width <= this value. Omit for responsive/fluid formats.")
|
|
436
|
+
max_height: int | None = Field(None, description="Maximum height in pixels (inclusive). Returns formats with height <= this value. Omit for responsive/fluid formats.")
|
|
437
|
+
min_width: int | None = Field(None, description="Minimum width in pixels (inclusive). Returns formats with width >= this value.")
|
|
438
|
+
min_height: int | None = Field(None, description="Minimum height in pixels (inclusive). Returns formats with height >= this value.")
|
|
439
|
+
is_responsive: bool | None = Field(None, description="Filter for responsive formats that adapt to container size. When true, returns formats without fixed dimensions.")
|
|
440
|
+
name_search: str | None = Field(None, description="Search for formats by name (case-insensitive partial match)")
|
|
441
|
+
|
|
442
|
+
|
|
443
|
+
class ListCreativesRequest(BaseModel):
|
|
444
|
+
"""Request parameters for querying creative assets from the centralized library with filtering, sorting, and pagination"""
|
|
445
|
+
|
|
446
|
+
filters: dict[str, Any] | None = Field(None, description="Filter criteria for querying creatives")
|
|
447
|
+
sort: dict[str, Any] | None = Field(None, description="Sorting parameters")
|
|
448
|
+
pagination: dict[str, Any] | None = Field(None, description="Pagination parameters")
|
|
449
|
+
include_assignments: bool | None = Field(None, description="Include package assignment information in response")
|
|
450
|
+
include_performance: bool | None = Field(None, description="Include aggregated performance metrics in response")
|
|
451
|
+
include_sub_assets: bool | None = Field(None, description="Include sub-assets (for carousel/native formats) in response")
|
|
452
|
+
fields: list[Literal["creative_id", "name", "format", "status", "created_date", "updated_date", "tags", "assignments", "performance", "sub_assets"]] | None = Field(None, description="Specific fields to include in response (omit for all fields)")
|
|
453
|
+
|
|
454
|
+
|
|
455
|
+
class PreviewCreativeRequest(BaseModel):
|
|
456
|
+
"""Request to generate a preview of a creative manifest in a specific format. The creative_manifest should include all assets required by the format (e.g., promoted_offerings for generative formats)."""
|
|
457
|
+
|
|
458
|
+
format_id: FormatId = Field(description="Format identifier for rendering the preview")
|
|
459
|
+
creative_manifest: CreativeManifest = Field(description="Complete creative manifest with all required assets (including promoted_offerings if required by the format)")
|
|
460
|
+
inputs: list[dict[str, Any]] | None = Field(None, description="Array of input sets for generating multiple preview variants. Each input set defines macros and context values for one preview rendering. If not provided, creative agent will generate default previews.")
|
|
461
|
+
template_id: str | None = Field(None, description="Specific template ID for custom format rendering")
|
|
462
|
+
|
|
463
|
+
|
|
464
|
+
class ProvidePerformanceFeedbackRequest(BaseModel):
|
|
465
|
+
"""Request payload for provide_performance_feedback task"""
|
|
466
|
+
|
|
467
|
+
media_buy_id: str = Field(description="Publisher's media buy identifier")
|
|
468
|
+
measurement_period: dict[str, Any] = Field(description="Time period for performance measurement")
|
|
469
|
+
performance_index: float = Field(description="Normalized performance score (0.0 = no value, 1.0 = expected, >1.0 = above expected)")
|
|
470
|
+
package_id: str | None = Field(None, description="Specific package within the media buy (if feedback is package-specific)")
|
|
471
|
+
creative_id: str | None = Field(None, description="Specific creative asset (if feedback is creative-specific)")
|
|
472
|
+
metric_type: Literal["overall_performance", "conversion_rate", "brand_lift", "click_through_rate", "completion_rate", "viewability", "brand_safety", "cost_efficiency"] | None = Field(None, description="The business metric being measured")
|
|
473
|
+
feedback_source: Literal["buyer_attribution", "third_party_measurement", "platform_analytics", "verification_partner"] | None = Field(None, description="Source of the performance data")
|
|
474
|
+
|
|
475
|
+
|
|
476
|
+
class SyncCreativesRequest(BaseModel):
|
|
477
|
+
"""Request parameters for syncing creative assets with upsert semantics - supports bulk operations, patch updates, and assignment management"""
|
|
478
|
+
|
|
479
|
+
creatives: list[CreativeAsset] = Field(description="Array of creative assets to sync (create or update)")
|
|
480
|
+
patch: bool | None = Field(None, description="When true, only provided fields are updated (partial update). When false, entire creative is replaced (full upsert).")
|
|
481
|
+
assignments: dict[str, Any] | None = Field(None, description="Optional bulk assignment of creatives to packages")
|
|
482
|
+
delete_missing: bool | None = Field(None, description="When true, creatives not included in this sync will be archived. Use with caution for full library replacement.")
|
|
483
|
+
dry_run: bool | None = Field(None, description="When true, preview changes without applying them. Returns what would be created/updated/deleted.")
|
|
484
|
+
validation_mode: Literal["strict", "lenient"] | None = Field(None, description="Validation strictness. 'strict' fails entire sync on any validation error. 'lenient' processes valid creatives and reports errors.")
|
|
485
|
+
push_notification_config: PushNotificationConfig | None = Field(None, description="Optional webhook configuration for async sync notifications. Publisher will send webhook when sync completes if operation takes longer than immediate response time (typically for large bulk operations or manual approval/HITL).")
|
|
486
|
+
|
|
487
|
+
|
|
488
|
+
class UpdateMediaBuyRequest(BaseModel):
|
|
489
|
+
"""Request parameters for updating campaign and package settings"""
|
|
490
|
+
|
|
491
|
+
media_buy_id: str | None = Field(None, description="Publisher's ID of the media buy to update")
|
|
492
|
+
buyer_ref: str | None = Field(None, description="Buyer's reference for the media buy to update")
|
|
493
|
+
active: bool | None = Field(None, description="Pause/resume the entire media buy")
|
|
494
|
+
start_time: StartTiming | None = None
|
|
495
|
+
end_time: str | None = Field(None, description="New end date/time in ISO 8601 format")
|
|
496
|
+
packages: list[dict[str, Any]] | None = Field(None, description="Package-specific updates")
|
|
497
|
+
push_notification_config: PushNotificationConfig | None = Field(None, description="Optional webhook configuration for async update notifications. Publisher will send webhook when update completes if operation takes longer than immediate response time.")
|
|
498
|
+
|
|
499
|
+
|
|
500
|
+
class ActivateSignalResponse(BaseModel):
|
|
501
|
+
"""Response payload for activate_signal task"""
|
|
502
|
+
|
|
503
|
+
decisioning_platform_segment_id: str | None = Field(None, description="The platform-specific ID to use once activated")
|
|
504
|
+
estimated_activation_duration_minutes: float | None = Field(None, description="Estimated time to complete (optional)")
|
|
505
|
+
deployed_at: str | None = Field(None, description="Timestamp when activation completed (optional)")
|
|
506
|
+
errors: list[Error] | None = Field(None, description="Task-specific errors and warnings (e.g., activation failures, platform issues)")
|
|
507
|
+
|
|
508
|
+
|
|
509
|
+
class BuildCreativeResponse(BaseModel):
|
|
510
|
+
"""Response containing the transformed or generated creative manifest, ready for use with preview_creative or sync_creatives"""
|
|
511
|
+
|
|
512
|
+
creative_manifest: CreativeManifest = Field(description="The generated or transformed creative manifest")
|
|
513
|
+
errors: list[Error] | None = Field(None, description="Task-specific errors and warnings")
|
|
514
|
+
|
|
515
|
+
|
|
516
|
+
class CreateMediaBuyResponse(BaseModel):
|
|
517
|
+
"""Response payload for create_media_buy task"""
|
|
518
|
+
|
|
519
|
+
media_buy_id: str | None = Field(None, description="Publisher's unique identifier for the created media buy")
|
|
520
|
+
buyer_ref: str = Field(description="Buyer's reference identifier for this media buy")
|
|
521
|
+
creative_deadline: str | None = Field(None, description="ISO 8601 timestamp for creative upload deadline")
|
|
522
|
+
packages: list[dict[str, Any]] | None = Field(None, description="Array of created packages")
|
|
523
|
+
errors: list[Error] | None = Field(None, description="Task-specific errors and warnings (e.g., partial package creation failures)")
|
|
524
|
+
|
|
525
|
+
|
|
526
|
+
class GetMediaBuyDeliveryResponse(BaseModel):
|
|
527
|
+
"""Response payload for get_media_buy_delivery task"""
|
|
528
|
+
|
|
529
|
+
notification_type: Literal["scheduled", "final", "delayed", "adjusted"] | None = Field(None, description="Type of webhook notification (only present in webhook deliveries): scheduled = regular periodic update, final = campaign completed, delayed = data not yet available, adjusted = resending period with updated data")
|
|
530
|
+
partial_data: bool | None = Field(None, description="Indicates if any media buys in this webhook have missing/delayed data (only present in webhook deliveries)")
|
|
531
|
+
unavailable_count: int | None = Field(None, description="Number of media buys with reporting_delayed or failed status (only present in webhook deliveries when partial_data is true)")
|
|
532
|
+
sequence_number: int | None = Field(None, description="Sequential notification number (only present in webhook deliveries, starts at 1)")
|
|
533
|
+
next_expected_at: str | None = Field(None, description="ISO 8601 timestamp for next expected notification (only present in webhook deliveries when notification_type is not 'final')")
|
|
534
|
+
reporting_period: dict[str, Any] = Field(description="Date range for the report. All periods use UTC timezone.")
|
|
535
|
+
currency: str = Field(description="ISO 4217 currency code")
|
|
536
|
+
aggregated_totals: dict[str, Any] | None = Field(None, description="Combined metrics across all returned media buys. Only included in API responses (get_media_buy_delivery), not in webhook notifications.")
|
|
537
|
+
media_buy_deliveries: list[dict[str, Any]] = Field(description="Array of delivery data for media buys. When used in webhook notifications, may contain multiple media buys aggregated by publisher. When used in get_media_buy_delivery API responses, typically contains requested media buys.")
|
|
538
|
+
errors: list[Error] | None = Field(None, description="Task-specific errors and warnings (e.g., missing delivery data, reporting platform issues)")
|
|
539
|
+
|
|
540
|
+
|
|
541
|
+
class GetProductsResponse(BaseModel):
|
|
542
|
+
"""Response payload for get_products task"""
|
|
543
|
+
|
|
544
|
+
products: list[Product] = Field(description="Array of matching products")
|
|
545
|
+
errors: list[Error] | None = Field(None, description="Task-specific errors and warnings (e.g., product filtering issues)")
|
|
546
|
+
|
|
547
|
+
|
|
548
|
+
class GetSignalsResponse(BaseModel):
|
|
549
|
+
"""Response payload for get_signals task"""
|
|
550
|
+
|
|
551
|
+
signals: list[dict[str, Any]] = Field(description="Array of matching signals")
|
|
552
|
+
errors: list[Error] | None = Field(None, description="Task-specific errors and warnings (e.g., signal discovery or pricing issues)")
|
|
553
|
+
|
|
554
|
+
|
|
555
|
+
class ListAuthorizedPropertiesResponse(BaseModel):
|
|
556
|
+
"""Response payload for list_authorized_properties task. Lists publisher domains and authorization scope (property_ids or property_tags). Buyers fetch actual property definitions from each publisher's canonical adagents.json file."""
|
|
557
|
+
|
|
558
|
+
publisher_domains: list[str] = Field(description="Publisher domains this agent is authorized to represent. Buyers should fetch each publisher's adagents.json to see property definitions and verify this agent is in their authorized_agents list with authorization scope.")
|
|
559
|
+
primary_channels: list[Channels] | None = Field(None, description="Primary advertising channels represented in this property portfolio. Helps buying agents quickly filter relevance.")
|
|
560
|
+
primary_countries: list[str] | None = Field(None, description="Primary countries (ISO 3166-1 alpha-2 codes) where properties are concentrated. Helps buying agents quickly filter relevance.")
|
|
561
|
+
portfolio_description: str | None = Field(None, description="Markdown-formatted description of the property portfolio, including inventory types, audience characteristics, and special features.")
|
|
562
|
+
advertising_policies: str | None = Field(None, description="Publisher's advertising content policies, restrictions, and guidelines in natural language. May include prohibited categories, blocked advertisers, restricted tactics, brand safety requirements, or links to full policy documentation.")
|
|
563
|
+
last_updated: str | None = Field(None, description="ISO 8601 timestamp of when the agent's publisher authorization list was last updated. Buyers can use this to determine if their cached publisher adagents.json files might be stale.")
|
|
564
|
+
errors: list[Error] | None = Field(None, description="Task-specific errors and warnings (e.g., property availability issues)")
|
|
565
|
+
|
|
566
|
+
|
|
567
|
+
class ListCreativeFormatsResponse(BaseModel):
|
|
568
|
+
"""Response payload for list_creative_formats task from creative agent - returns full format definitions"""
|
|
569
|
+
|
|
570
|
+
formats: list[Format] = Field(description="Full format definitions for all formats this agent supports. Each format's authoritative source is indicated by its agent_url field.")
|
|
571
|
+
creative_agents: list[dict[str, Any]] | None = Field(None, description="Optional: Creative agents that provide additional formats. Buyers can recursively query these agents to discover more formats. No authentication required for list_creative_formats.")
|
|
572
|
+
errors: list[Error] | None = Field(None, description="Task-specific errors and warnings")
|
|
573
|
+
|
|
574
|
+
|
|
575
|
+
class ListCreativesResponse(BaseModel):
|
|
576
|
+
"""Response from creative library query with filtered results, metadata, and optional enriched data"""
|
|
577
|
+
|
|
578
|
+
query_summary: dict[str, Any] = Field(description="Summary of the query that was executed")
|
|
579
|
+
pagination: dict[str, Any] = Field(description="Pagination information for navigating results")
|
|
580
|
+
creatives: list[dict[str, Any]] = Field(description="Array of creative assets matching the query")
|
|
581
|
+
format_summary: dict[str, Any] | None = Field(None, description="Breakdown of creatives by format type")
|
|
582
|
+
status_summary: dict[str, Any] | None = Field(None, description="Breakdown of creatives by status")
|
|
583
|
+
|
|
584
|
+
|
|
585
|
+
class PreviewCreativeResponse(BaseModel):
|
|
586
|
+
"""Response containing preview links for a creative. Each preview URL returns an HTML page that can be embedded in an iframe to display the rendered creative."""
|
|
587
|
+
|
|
588
|
+
previews: list[dict[str, Any]] = Field(description="Array of preview variants. Each preview corresponds to an input set from the request. If no inputs were provided, returns a single default preview.")
|
|
589
|
+
interactive_url: str | None = Field(None, description="Optional URL to an interactive testing page that shows all preview variants with controls to switch between them, modify macro values, and test different scenarios.")
|
|
590
|
+
expires_at: str = Field(description="ISO 8601 timestamp when preview links expire")
|
|
591
|
+
|
|
592
|
+
|
|
593
|
+
class ProvidePerformanceFeedbackResponse(BaseModel):
|
|
594
|
+
"""Response payload for provide_performance_feedback task"""
|
|
595
|
+
|
|
596
|
+
success: bool = Field(description="Whether the performance feedback was successfully received")
|
|
597
|
+
errors: list[Error] | None = Field(None, description="Task-specific errors and warnings (e.g., invalid measurement period, missing campaign data)")
|
|
598
|
+
|
|
599
|
+
|
|
600
|
+
class SyncCreativesResponse(BaseModel):
|
|
601
|
+
"""Response from creative sync operation with results for each creative"""
|
|
602
|
+
|
|
603
|
+
dry_run: bool | None = Field(None, description="Whether this was a dry run (no actual changes made)")
|
|
604
|
+
creatives: list[dict[str, Any]] = Field(description="Results for each creative processed")
|
|
605
|
+
|
|
606
|
+
|
|
607
|
+
class UpdateMediaBuyResponse(BaseModel):
|
|
608
|
+
"""Response payload for update_media_buy task"""
|
|
609
|
+
|
|
610
|
+
media_buy_id: str = Field(description="Publisher's identifier for the media buy")
|
|
611
|
+
buyer_ref: str = Field(description="Buyer's reference identifier for the media buy")
|
|
612
|
+
implementation_date: Any | None = Field(None, description="ISO 8601 timestamp when changes take effect (null if pending approval)")
|
|
613
|
+
affected_packages: list[dict[str, Any]] | None = Field(None, description="Array of packages that were modified")
|
|
614
|
+
errors: list[Error] | None = Field(None, description="Task-specific errors and warnings (e.g., partial update failures)")
|
|
615
|
+
|