adcp 1.6.0__py3-none-any.whl → 2.0.0__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 +19 -221
- adcp/adagents.py +11 -12
- adcp/client.py +16 -11
- adcp/types/generated.py +540 -1129
- adcp/types/generated_poc/__init__.py +3 -0
- adcp/types/generated_poc/activate_signal_request.py +34 -0
- adcp/types/generated_poc/activate_signal_response.py +57 -0
- adcp/types/generated_poc/activation_key.py +30 -0
- adcp/types/generated_poc/adagents.py +266 -0
- adcp/types/generated_poc/asset_type.py +100 -0
- adcp/types/generated_poc/audio_asset.py +26 -0
- adcp/types/generated_poc/brand_manifest.py +260 -0
- adcp/types/generated_poc/brand_manifest_ref.py +361 -0
- adcp/types/generated_poc/build_creative_request.py +43 -0
- adcp/types/generated_poc/build_creative_response.py +57 -0
- adcp/types/generated_poc/channels.py +19 -0
- adcp/types/generated_poc/cpc_option.py +39 -0
- adcp/types/generated_poc/cpcv_option.py +41 -0
- adcp/types/generated_poc/cpm_auction_option.py +54 -0
- adcp/types/generated_poc/cpm_fixed_option.py +39 -0
- adcp/types/generated_poc/cpp_option.py +60 -0
- adcp/types/generated_poc/cpv_option.py +73 -0
- adcp/types/generated_poc/create_media_buy_request.py +96 -0
- adcp/types/generated_poc/create_media_buy_response.py +66 -0
- adcp/types/generated_poc/creative_asset.py +83 -0
- adcp/types/generated_poc/creative_assignment.py +27 -0
- adcp/types/generated_poc/creative_manifest.py +61 -0
- adcp/types/generated_poc/creative_policy.py +34 -0
- adcp/types/generated_poc/creative_status.py +14 -0
- adcp/types/generated_poc/css_asset.py +20 -0
- adcp/types/generated_poc/daast_asset.py +76 -0
- adcp/types/generated_poc/delivery_metrics.py +111 -0
- adcp/types/generated_poc/delivery_type.py +12 -0
- adcp/types/generated_poc/deployment.py +78 -0
- adcp/types/generated_poc/destination.py +43 -0
- adcp/types/generated_poc/error.py +29 -0
- adcp/types/generated_poc/flat_rate_option.py +93 -0
- adcp/types/generated_poc/format.py +260 -0
- adcp/types/generated_poc/format_id.py +29 -0
- adcp/types/generated_poc/frequency_cap.py +19 -0
- adcp/types/generated_poc/frequency_cap_scope.py +16 -0
- adcp/types/generated_poc/get_media_buy_delivery_request.py +65 -0
- adcp/types/generated_poc/get_media_buy_delivery_response.py +220 -0
- adcp/types/generated_poc/get_products_request.py +83 -0
- adcp/types/generated_poc/get_products_response.py +29 -0
- adcp/types/generated_poc/get_signals_request.py +77 -0
- adcp/types/generated_poc/get_signals_response.py +65 -0
- adcp/types/generated_poc/html_asset.py +18 -0
- adcp/types/generated_poc/identifier_types.py +29 -0
- adcp/types/generated_poc/image_asset.py +23 -0
- adcp/types/generated_poc/index.py +17 -0
- adcp/types/generated_poc/javascript_asset.py +25 -0
- adcp/types/generated_poc/list_authorized_properties_request.py +39 -0
- adcp/types/generated_poc/list_authorized_properties_response.py +85 -0
- adcp/types/generated_poc/list_creative_formats_request.py +93 -0
- adcp/types/generated_poc/list_creative_formats_response.py +63 -0
- adcp/types/generated_poc/list_creatives_request.py +154 -0
- adcp/types/generated_poc/list_creatives_response.py +234 -0
- adcp/types/generated_poc/markdown_asset.py +43 -0
- adcp/types/generated_poc/measurement.py +40 -0
- adcp/types/generated_poc/media_buy.py +37 -0
- adcp/types/generated_poc/media_buy_status.py +14 -0
- adcp/types/generated_poc/pacing.py +13 -0
- adcp/types/generated_poc/package.py +61 -0
- adcp/types/generated_poc/package_request.py +61 -0
- adcp/types/generated_poc/package_status.py +14 -0
- adcp/types/generated_poc/performance_feedback.py +89 -0
- adcp/types/generated_poc/placement.py +37 -0
- adcp/types/generated_poc/preview_creative_request.py +163 -0
- adcp/types/generated_poc/preview_creative_response.py +175 -0
- adcp/types/generated_poc/preview_render.py +144 -0
- adcp/types/generated_poc/pricing_model.py +17 -0
- adcp/types/generated_poc/pricing_option.py +365 -0
- adcp/types/generated_poc/product.py +211 -0
- adcp/types/generated_poc/promoted_offerings.py +102 -0
- adcp/types/generated_poc/promoted_products.py +38 -0
- adcp/types/generated_poc/property.py +79 -0
- adcp/types/generated_poc/protocol_envelope.py +61 -0
- adcp/types/generated_poc/provide_performance_feedback_request.py +85 -0
- adcp/types/generated_poc/provide_performance_feedback_response.py +59 -0
- adcp/types/generated_poc/publisher_identifier_types.py +15 -0
- adcp/types/generated_poc/push_notification_config.py +55 -0
- adcp/types/generated_poc/reporting_capabilities.py +68 -0
- adcp/types/generated_poc/response.py +24 -0
- adcp/types/generated_poc/standard_format_ids.py +45 -0
- adcp/types/generated_poc/start_timing.py +13 -0
- adcp/types/generated_poc/sub_asset.py +55 -0
- adcp/types/generated_poc/sync_creatives_request.py +69 -0
- adcp/types/generated_poc/sync_creatives_response.py +117 -0
- adcp/types/generated_poc/targeting.py +53 -0
- adcp/types/generated_poc/task_status.py +19 -0
- adcp/types/generated_poc/task_type.py +15 -0
- adcp/types/generated_poc/tasks_get_request.py +29 -0
- adcp/types/generated_poc/tasks_get_response.py +112 -0
- adcp/types/generated_poc/tasks_list_request.py +121 -0
- adcp/types/generated_poc/tasks_list_response.py +122 -0
- adcp/types/generated_poc/text_asset.py +20 -0
- adcp/types/generated_poc/update_media_buy_request.py +160 -0
- adcp/types/generated_poc/update_media_buy_response.py +67 -0
- adcp/types/generated_poc/url_asset.py +33 -0
- adcp/types/generated_poc/vast_asset.py +86 -0
- adcp/types/generated_poc/vcpm_auction_option.py +57 -0
- adcp/types/generated_poc/vcpm_fixed_option.py +43 -0
- adcp/types/generated_poc/video_asset.py +28 -0
- adcp/types/generated_poc/webhook_asset.py +65 -0
- adcp/types/generated_poc/webhook_payload.py +102 -0
- adcp/utils/preview_cache.py +57 -39
- adcp/validation.py +172 -0
- {adcp-1.6.0.dist-info → adcp-2.0.0.dist-info}/METADATA +3 -1
- adcp-2.0.0.dist-info/RECORD +130 -0
- adcp/types/tasks.py +0 -511
- adcp-1.6.0.dist-info/RECORD +0 -28
- {adcp-1.6.0.dist-info → adcp-2.0.0.dist-info}/WHEEL +0 -0
- {adcp-1.6.0.dist-info → adcp-2.0.0.dist-info}/entry_points.txt +0 -0
- {adcp-1.6.0.dist-info → adcp-2.0.0.dist-info}/licenses/LICENSE +0 -0
- {adcp-1.6.0.dist-info → adcp-2.0.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
# generated by datamodel-codegen:
|
|
2
|
+
# filename: pricing-option.json
|
|
3
|
+
# timestamp: 2025-11-15T17:41:03+00:00
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
from typing import Literal
|
|
8
|
+
|
|
9
|
+
from adcp.types.base import AdCPBaseModel
|
|
10
|
+
from pydantic import ConfigDict, Field, RootModel
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class CpmFixedOption(AdCPBaseModel):
|
|
14
|
+
model_config = ConfigDict(
|
|
15
|
+
extra="forbid",
|
|
16
|
+
)
|
|
17
|
+
pricing_option_id: str = Field(
|
|
18
|
+
...,
|
|
19
|
+
description="Unique identifier for this pricing option within the product (e.g., 'cpm_usd_guaranteed')",
|
|
20
|
+
)
|
|
21
|
+
pricing_model: Literal["cpm"] = Field(..., description="Cost per 1,000 impressions")
|
|
22
|
+
rate: float = Field(..., description="Fixed CPM rate (cost per 1,000 impressions)", ge=0.0)
|
|
23
|
+
currency: str = Field(
|
|
24
|
+
...,
|
|
25
|
+
description="ISO 4217 currency code",
|
|
26
|
+
examples=["USD", "EUR", "GBP", "JPY"],
|
|
27
|
+
pattern="^[A-Z]{3}$",
|
|
28
|
+
)
|
|
29
|
+
min_spend_per_package: float | None = Field(
|
|
30
|
+
None,
|
|
31
|
+
description="Minimum spend requirement per package using this pricing option, in the specified currency",
|
|
32
|
+
ge=0.0,
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class PriceGuidance(AdCPBaseModel):
|
|
37
|
+
floor: float = Field(
|
|
38
|
+
..., description="Minimum bid price - publisher will reject bids under this value", ge=0.0
|
|
39
|
+
)
|
|
40
|
+
p25: float | None = Field(None, description="25th percentile winning price", ge=0.0)
|
|
41
|
+
p50: float | None = Field(None, description="Median winning price", ge=0.0)
|
|
42
|
+
p75: float | None = Field(None, description="75th percentile winning price", ge=0.0)
|
|
43
|
+
p90: float | None = Field(None, description="90th percentile winning price", ge=0.0)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class CpmAuctionOption(AdCPBaseModel):
|
|
47
|
+
model_config = ConfigDict(
|
|
48
|
+
extra="forbid",
|
|
49
|
+
)
|
|
50
|
+
pricing_option_id: str = Field(
|
|
51
|
+
...,
|
|
52
|
+
description="Unique identifier for this pricing option within the product (e.g., 'cpm_usd_auction')",
|
|
53
|
+
)
|
|
54
|
+
pricing_model: Literal["cpm"] = Field(..., description="Cost per 1,000 impressions")
|
|
55
|
+
currency: str = Field(
|
|
56
|
+
...,
|
|
57
|
+
description="ISO 4217 currency code",
|
|
58
|
+
examples=["USD", "EUR", "GBP", "JPY"],
|
|
59
|
+
pattern="^[A-Z]{3}$",
|
|
60
|
+
)
|
|
61
|
+
price_guidance: PriceGuidance = Field(
|
|
62
|
+
..., description="Pricing guidance for auction-based CPM bidding"
|
|
63
|
+
)
|
|
64
|
+
min_spend_per_package: float | None = Field(
|
|
65
|
+
None,
|
|
66
|
+
description="Minimum spend requirement per package using this pricing option, in the specified currency",
|
|
67
|
+
ge=0.0,
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
class VcpmFixedOption(AdCPBaseModel):
|
|
72
|
+
model_config = ConfigDict(
|
|
73
|
+
extra="forbid",
|
|
74
|
+
)
|
|
75
|
+
pricing_option_id: str = Field(
|
|
76
|
+
...,
|
|
77
|
+
description="Unique identifier for this pricing option within the product (e.g., 'vcpm_usd_guaranteed')",
|
|
78
|
+
)
|
|
79
|
+
pricing_model: Literal["vcpm"] = Field(
|
|
80
|
+
..., description="Cost per 1,000 viewable impressions (MRC standard)"
|
|
81
|
+
)
|
|
82
|
+
rate: float = Field(
|
|
83
|
+
..., description="Fixed vCPM rate (cost per 1,000 viewable impressions)", ge=0.0
|
|
84
|
+
)
|
|
85
|
+
currency: str = Field(
|
|
86
|
+
...,
|
|
87
|
+
description="ISO 4217 currency code",
|
|
88
|
+
examples=["USD", "EUR", "GBP", "JPY"],
|
|
89
|
+
pattern="^[A-Z]{3}$",
|
|
90
|
+
)
|
|
91
|
+
min_spend_per_package: float | None = Field(
|
|
92
|
+
None,
|
|
93
|
+
description="Minimum spend requirement per package using this pricing option, in the specified currency",
|
|
94
|
+
ge=0.0,
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
class PriceGuidance1(AdCPBaseModel):
|
|
99
|
+
floor: float = Field(..., description="Minimum acceptable bid price", ge=0.0)
|
|
100
|
+
p25: float | None = Field(None, description="25th percentile of recent winning bids", ge=0.0)
|
|
101
|
+
p50: float | None = Field(None, description="Median of recent winning bids", ge=0.0)
|
|
102
|
+
p75: float | None = Field(None, description="75th percentile of recent winning bids", ge=0.0)
|
|
103
|
+
p90: float | None = Field(None, description="90th percentile of recent winning bids", ge=0.0)
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
class VcpmAuctionOption(AdCPBaseModel):
|
|
107
|
+
model_config = ConfigDict(
|
|
108
|
+
extra="forbid",
|
|
109
|
+
)
|
|
110
|
+
pricing_option_id: str = Field(
|
|
111
|
+
...,
|
|
112
|
+
description="Unique identifier for this pricing option within the product (e.g., 'vcpm_usd_auction')",
|
|
113
|
+
)
|
|
114
|
+
pricing_model: Literal["vcpm"] = Field(
|
|
115
|
+
..., description="Cost per 1,000 viewable impressions (MRC standard)"
|
|
116
|
+
)
|
|
117
|
+
currency: str = Field(
|
|
118
|
+
...,
|
|
119
|
+
description="ISO 4217 currency code",
|
|
120
|
+
examples=["USD", "EUR", "GBP", "JPY"],
|
|
121
|
+
pattern="^[A-Z]{3}$",
|
|
122
|
+
)
|
|
123
|
+
price_guidance: PriceGuidance1 = Field(
|
|
124
|
+
..., description="Statistical guidance for auction pricing"
|
|
125
|
+
)
|
|
126
|
+
min_spend_per_package: float | None = Field(
|
|
127
|
+
None,
|
|
128
|
+
description="Minimum spend requirement per package using this pricing option, in the specified currency",
|
|
129
|
+
ge=0.0,
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
class CpcOption(AdCPBaseModel):
|
|
134
|
+
model_config = ConfigDict(
|
|
135
|
+
extra="forbid",
|
|
136
|
+
)
|
|
137
|
+
pricing_option_id: str = Field(
|
|
138
|
+
...,
|
|
139
|
+
description="Unique identifier for this pricing option within the product (e.g., 'cpc_usd_fixed')",
|
|
140
|
+
)
|
|
141
|
+
pricing_model: Literal["cpc"] = Field(..., description="Cost per click")
|
|
142
|
+
rate: float = Field(..., description="Fixed CPC rate (cost per click)", ge=0.0)
|
|
143
|
+
currency: str = Field(
|
|
144
|
+
...,
|
|
145
|
+
description="ISO 4217 currency code",
|
|
146
|
+
examples=["USD", "EUR", "GBP", "JPY"],
|
|
147
|
+
pattern="^[A-Z]{3}$",
|
|
148
|
+
)
|
|
149
|
+
min_spend_per_package: float | None = Field(
|
|
150
|
+
None,
|
|
151
|
+
description="Minimum spend requirement per package using this pricing option, in the specified currency",
|
|
152
|
+
ge=0.0,
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
class CpcvOption(AdCPBaseModel):
|
|
157
|
+
model_config = ConfigDict(
|
|
158
|
+
extra="forbid",
|
|
159
|
+
)
|
|
160
|
+
pricing_option_id: str = Field(
|
|
161
|
+
...,
|
|
162
|
+
description="Unique identifier for this pricing option within the product (e.g., 'cpcv_usd_guaranteed')",
|
|
163
|
+
)
|
|
164
|
+
pricing_model: Literal["cpcv"] = Field(
|
|
165
|
+
..., description="Cost per completed view (100% completion)"
|
|
166
|
+
)
|
|
167
|
+
rate: float = Field(..., description="Fixed CPCV rate (cost per 100% completion)", ge=0.0)
|
|
168
|
+
currency: str = Field(
|
|
169
|
+
...,
|
|
170
|
+
description="ISO 4217 currency code",
|
|
171
|
+
examples=["USD", "EUR", "GBP", "JPY"],
|
|
172
|
+
pattern="^[A-Z]{3}$",
|
|
173
|
+
)
|
|
174
|
+
min_spend_per_package: float | None = Field(
|
|
175
|
+
None,
|
|
176
|
+
description="Minimum spend requirement per package using this pricing option, in the specified currency",
|
|
177
|
+
ge=0.0,
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
class ViewThreshold(RootModel[float]):
|
|
182
|
+
root: float = Field(
|
|
183
|
+
...,
|
|
184
|
+
description="Percentage completion threshold for CPV pricing (0.0 to 1.0, e.g., 0.5 = 50% completion)",
|
|
185
|
+
ge=0.0,
|
|
186
|
+
le=1.0,
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
class ViewThreshold1(AdCPBaseModel):
|
|
191
|
+
model_config = ConfigDict(
|
|
192
|
+
extra="forbid",
|
|
193
|
+
)
|
|
194
|
+
duration_seconds: int = Field(
|
|
195
|
+
...,
|
|
196
|
+
description="Seconds of viewing required (e.g., 30 for YouTube-style '30 seconds = view')",
|
|
197
|
+
ge=1,
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
class Parameters(AdCPBaseModel):
|
|
202
|
+
model_config = ConfigDict(
|
|
203
|
+
extra="forbid",
|
|
204
|
+
)
|
|
205
|
+
view_threshold: ViewThreshold | ViewThreshold1
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
class CpvOption(AdCPBaseModel):
|
|
209
|
+
model_config = ConfigDict(
|
|
210
|
+
extra="forbid",
|
|
211
|
+
)
|
|
212
|
+
pricing_option_id: str = Field(
|
|
213
|
+
...,
|
|
214
|
+
description="Unique identifier for this pricing option within the product (e.g., 'cpv_usd_50pct')",
|
|
215
|
+
)
|
|
216
|
+
pricing_model: Literal["cpv"] = Field(..., description="Cost per view at threshold")
|
|
217
|
+
rate: float = Field(..., description="Fixed CPV rate (cost per view)", ge=0.0)
|
|
218
|
+
currency: str = Field(
|
|
219
|
+
...,
|
|
220
|
+
description="ISO 4217 currency code",
|
|
221
|
+
examples=["USD", "EUR", "GBP", "JPY"],
|
|
222
|
+
pattern="^[A-Z]{3}$",
|
|
223
|
+
)
|
|
224
|
+
parameters: Parameters = Field(
|
|
225
|
+
..., description="CPV-specific parameters defining the view threshold"
|
|
226
|
+
)
|
|
227
|
+
min_spend_per_package: float | None = Field(
|
|
228
|
+
None,
|
|
229
|
+
description="Minimum spend requirement per package using this pricing option, in the specified currency",
|
|
230
|
+
ge=0.0,
|
|
231
|
+
)
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
class Parameters1(AdCPBaseModel):
|
|
235
|
+
model_config = ConfigDict(
|
|
236
|
+
extra="forbid",
|
|
237
|
+
)
|
|
238
|
+
demographic: str = Field(
|
|
239
|
+
...,
|
|
240
|
+
description="Target demographic in Nielsen format: P/M/W/A/C + age range. Examples: P18-49 (Persons 18-49), M25-54 (Men 25-54), W35+ (Women 35+), A18-34 (Adults 18-34), C2-11 (Children 2-11)",
|
|
241
|
+
pattern="^[PMWAC][0-9]{2}(-[0-9]{2}|\\+)$",
|
|
242
|
+
)
|
|
243
|
+
min_points: float | None = Field(
|
|
244
|
+
None, description="Minimum GRPs/TRPs required for this pricing option", ge=0.0
|
|
245
|
+
)
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
class CppOption(AdCPBaseModel):
|
|
249
|
+
model_config = ConfigDict(
|
|
250
|
+
extra="forbid",
|
|
251
|
+
)
|
|
252
|
+
pricing_option_id: str = Field(
|
|
253
|
+
...,
|
|
254
|
+
description="Unique identifier for this pricing option within the product (e.g., 'cpp_usd_p18-49')",
|
|
255
|
+
)
|
|
256
|
+
pricing_model: Literal["cpp"] = Field(..., description="Cost per Gross Rating Point")
|
|
257
|
+
rate: float = Field(..., description="Fixed CPP rate (cost per rating point)", ge=0.0)
|
|
258
|
+
currency: str = Field(
|
|
259
|
+
...,
|
|
260
|
+
description="ISO 4217 currency code",
|
|
261
|
+
examples=["USD", "EUR", "GBP", "JPY"],
|
|
262
|
+
pattern="^[A-Z]{3}$",
|
|
263
|
+
)
|
|
264
|
+
parameters: Parameters1 = Field(
|
|
265
|
+
..., description="CPP-specific parameters for demographic targeting and GRP requirements"
|
|
266
|
+
)
|
|
267
|
+
min_spend_per_package: float | None = Field(
|
|
268
|
+
None,
|
|
269
|
+
description="Minimum spend requirement per package using this pricing option, in the specified currency",
|
|
270
|
+
ge=0.0,
|
|
271
|
+
)
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
class Parameters2(AdCPBaseModel):
|
|
275
|
+
model_config = ConfigDict(
|
|
276
|
+
extra="forbid",
|
|
277
|
+
)
|
|
278
|
+
duration_hours: float | None = Field(
|
|
279
|
+
None, description="Duration in hours for time-based flat rate pricing (DOOH)", ge=0.0
|
|
280
|
+
)
|
|
281
|
+
sov_percentage: float | None = Field(
|
|
282
|
+
None, description="Guaranteed share of voice as percentage (DOOH, 0-100)", ge=0.0, le=100.0
|
|
283
|
+
)
|
|
284
|
+
loop_duration_seconds: int | None = Field(
|
|
285
|
+
None, description="Duration of ad loop rotation in seconds (DOOH)", ge=1
|
|
286
|
+
)
|
|
287
|
+
min_plays_per_hour: int | None = Field(
|
|
288
|
+
None,
|
|
289
|
+
description="Minimum number of times ad plays per hour (DOOH frequency guarantee)",
|
|
290
|
+
ge=0,
|
|
291
|
+
)
|
|
292
|
+
venue_package: str | None = Field(
|
|
293
|
+
None,
|
|
294
|
+
description="Named venue package identifier for DOOH (e.g., 'times_square_network', 'airport_terminals')",
|
|
295
|
+
)
|
|
296
|
+
estimated_impressions: int | None = Field(
|
|
297
|
+
None,
|
|
298
|
+
description="Estimated impressions for this flat rate option (informational, commonly used with SOV or time-based DOOH)",
|
|
299
|
+
ge=0,
|
|
300
|
+
)
|
|
301
|
+
daypart: str | None = Field(
|
|
302
|
+
None,
|
|
303
|
+
description="Specific daypart for time-based pricing (e.g., 'morning_commute', 'evening_prime', 'overnight')",
|
|
304
|
+
)
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
class FlatRateOption(AdCPBaseModel):
|
|
308
|
+
model_config = ConfigDict(
|
|
309
|
+
extra="forbid",
|
|
310
|
+
)
|
|
311
|
+
pricing_option_id: str = Field(
|
|
312
|
+
...,
|
|
313
|
+
description="Unique identifier for this pricing option within the product (e.g., 'flat_rate_usd_24h_takeover')",
|
|
314
|
+
)
|
|
315
|
+
pricing_model: Literal["flat_rate"] = Field(
|
|
316
|
+
..., description="Fixed cost regardless of delivery volume"
|
|
317
|
+
)
|
|
318
|
+
rate: float = Field(..., description="Flat rate cost", ge=0.0)
|
|
319
|
+
currency: str = Field(
|
|
320
|
+
...,
|
|
321
|
+
description="ISO 4217 currency code",
|
|
322
|
+
examples=["USD", "EUR", "GBP", "JPY"],
|
|
323
|
+
pattern="^[A-Z]{3}$",
|
|
324
|
+
)
|
|
325
|
+
is_fixed: Literal[True] = Field(
|
|
326
|
+
..., description="Whether this is a fixed rate (true) or auction-based (false)"
|
|
327
|
+
)
|
|
328
|
+
parameters: Parameters2 | None = Field(
|
|
329
|
+
None, description="Flat rate parameters for DOOH and time-based campaigns"
|
|
330
|
+
)
|
|
331
|
+
min_spend_per_package: float | None = Field(
|
|
332
|
+
None,
|
|
333
|
+
description="Minimum spend requirement per package using this pricing option, in the specified currency",
|
|
334
|
+
ge=0.0,
|
|
335
|
+
)
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
class PricingOption(
|
|
339
|
+
RootModel[
|
|
340
|
+
CpmFixedOption
|
|
341
|
+
| CpmAuctionOption
|
|
342
|
+
| VcpmFixedOption
|
|
343
|
+
| VcpmAuctionOption
|
|
344
|
+
| CpcOption
|
|
345
|
+
| CpcvOption
|
|
346
|
+
| CpvOption
|
|
347
|
+
| CppOption
|
|
348
|
+
| FlatRateOption
|
|
349
|
+
]
|
|
350
|
+
):
|
|
351
|
+
root: (
|
|
352
|
+
CpmFixedOption
|
|
353
|
+
| CpmAuctionOption
|
|
354
|
+
| VcpmFixedOption
|
|
355
|
+
| VcpmAuctionOption
|
|
356
|
+
| CpcOption
|
|
357
|
+
| CpcvOption
|
|
358
|
+
| CpvOption
|
|
359
|
+
| CppOption
|
|
360
|
+
| FlatRateOption
|
|
361
|
+
) = Field(
|
|
362
|
+
...,
|
|
363
|
+
description="A pricing model option offered by a publisher for a product. Each pricing model has its own schema with model-specific requirements.",
|
|
364
|
+
title="Pricing Option",
|
|
365
|
+
)
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
# generated by datamodel-codegen:
|
|
2
|
+
# filename: product.json
|
|
3
|
+
# timestamp: 2025-11-15T22:03:55+00:00
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
from typing import Annotated, Any, Literal
|
|
8
|
+
|
|
9
|
+
from adcp.types.base import AdCPBaseModel
|
|
10
|
+
from pydantic import AwareDatetime, ConfigDict, Field, RootModel, model_validator
|
|
11
|
+
|
|
12
|
+
from . import cpc_option, cpcv_option, cpm_auction_option, cpm_fixed_option, cpp_option, cpv_option
|
|
13
|
+
from . import creative_policy as creative_policy_1
|
|
14
|
+
from . import delivery_type as delivery_type_1
|
|
15
|
+
from . import flat_rate_option
|
|
16
|
+
from . import format_id as format_id_1
|
|
17
|
+
from . import measurement as measurement_1
|
|
18
|
+
from . import placement
|
|
19
|
+
from . import reporting_capabilities as reporting_capabilities_1
|
|
20
|
+
from . import vcpm_auction_option, vcpm_fixed_option
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class DeliveryMeasurement(AdCPBaseModel):
|
|
24
|
+
notes: Annotated[
|
|
25
|
+
str | None,
|
|
26
|
+
Field(
|
|
27
|
+
description="Additional details about measurement methodology in plain language (e.g., 'MRC-accredited viewability. 50% in-view for 1s display / 2s video', 'Panel-based demographic measurement updated monthly')"
|
|
28
|
+
),
|
|
29
|
+
] = None
|
|
30
|
+
provider: Annotated[
|
|
31
|
+
str,
|
|
32
|
+
Field(
|
|
33
|
+
description="Measurement provider(s) used for this product (e.g., 'Google Ad Manager with IAS viewability', 'Nielsen DAR', 'Geopath for DOOH impressions')"
|
|
34
|
+
),
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class ProductCard(AdCPBaseModel):
|
|
39
|
+
model_config = ConfigDict(
|
|
40
|
+
extra="forbid",
|
|
41
|
+
)
|
|
42
|
+
format_id: Annotated[
|
|
43
|
+
format_id_1.FormatId,
|
|
44
|
+
Field(
|
|
45
|
+
description="Creative format defining the card layout (typically product_card_standard)"
|
|
46
|
+
),
|
|
47
|
+
]
|
|
48
|
+
manifest: Annotated[
|
|
49
|
+
dict[str, Any],
|
|
50
|
+
Field(description="Asset manifest for rendering the card, structure defined by the format"),
|
|
51
|
+
]
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class ProductCardDetailed(AdCPBaseModel):
|
|
55
|
+
model_config = ConfigDict(
|
|
56
|
+
extra="forbid",
|
|
57
|
+
)
|
|
58
|
+
format_id: Annotated[
|
|
59
|
+
format_id_1.FormatId,
|
|
60
|
+
Field(
|
|
61
|
+
description="Creative format defining the detailed card layout (typically product_card_detailed)"
|
|
62
|
+
),
|
|
63
|
+
]
|
|
64
|
+
manifest: Annotated[
|
|
65
|
+
dict[str, Any],
|
|
66
|
+
Field(
|
|
67
|
+
description="Asset manifest for rendering the detailed card, structure defined by the format"
|
|
68
|
+
),
|
|
69
|
+
]
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class PropertyId(RootModel[str]):
|
|
73
|
+
root: Annotated[str, Field(pattern="^[a-z0-9_]+$")]
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class PublisherProperties(AdCPBaseModel):
|
|
77
|
+
model_config = ConfigDict(
|
|
78
|
+
extra="forbid",
|
|
79
|
+
)
|
|
80
|
+
property_ids: Annotated[
|
|
81
|
+
list[PropertyId],
|
|
82
|
+
Field(description="Specific property IDs from the publisher's adagents.json", min_length=1),
|
|
83
|
+
]
|
|
84
|
+
publisher_domain: Annotated[
|
|
85
|
+
str,
|
|
86
|
+
Field(
|
|
87
|
+
description="Domain where publisher's adagents.json is hosted (e.g., 'cnn.com')",
|
|
88
|
+
pattern="^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$",
|
|
89
|
+
),
|
|
90
|
+
]
|
|
91
|
+
selection_type: Annotated[
|
|
92
|
+
Literal["by_id"],
|
|
93
|
+
Field(description="Discriminator indicating selection by specific property IDs"),
|
|
94
|
+
]
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
class PropertyTag(PropertyId):
|
|
98
|
+
pass
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
class PublisherProperties3(AdCPBaseModel):
|
|
102
|
+
model_config = ConfigDict(
|
|
103
|
+
extra="forbid",
|
|
104
|
+
)
|
|
105
|
+
property_tags: Annotated[
|
|
106
|
+
list[PropertyTag],
|
|
107
|
+
Field(
|
|
108
|
+
description="Property tags from the publisher's adagents.json. Product covers all properties with these tags",
|
|
109
|
+
min_length=1,
|
|
110
|
+
),
|
|
111
|
+
]
|
|
112
|
+
publisher_domain: Annotated[
|
|
113
|
+
str,
|
|
114
|
+
Field(
|
|
115
|
+
description="Domain where publisher's adagents.json is hosted (e.g., 'cnn.com')",
|
|
116
|
+
pattern="^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$",
|
|
117
|
+
),
|
|
118
|
+
]
|
|
119
|
+
selection_type: Annotated[
|
|
120
|
+
Literal["by_tag"], Field(description="Discriminator indicating selection by property tags")
|
|
121
|
+
]
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
class Product(AdCPBaseModel):
|
|
125
|
+
model_config = ConfigDict(
|
|
126
|
+
extra="forbid",
|
|
127
|
+
)
|
|
128
|
+
brief_relevance: Annotated[
|
|
129
|
+
str | None,
|
|
130
|
+
Field(
|
|
131
|
+
description="Explanation of why this product matches the brief (only included when brief is provided)"
|
|
132
|
+
),
|
|
133
|
+
] = None
|
|
134
|
+
creative_policy: creative_policy_1.CreativePolicy | None = None
|
|
135
|
+
delivery_measurement: Annotated[
|
|
136
|
+
DeliveryMeasurement,
|
|
137
|
+
Field(
|
|
138
|
+
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."
|
|
139
|
+
),
|
|
140
|
+
]
|
|
141
|
+
delivery_type: delivery_type_1.DeliveryType
|
|
142
|
+
description: Annotated[
|
|
143
|
+
str, Field(description="Detailed description of the product and its inventory")
|
|
144
|
+
]
|
|
145
|
+
estimated_exposures: Annotated[
|
|
146
|
+
int | None,
|
|
147
|
+
Field(description="Estimated exposures/impressions for guaranteed products", ge=0),
|
|
148
|
+
] = None
|
|
149
|
+
expires_at: Annotated[
|
|
150
|
+
AwareDatetime | None, Field(description="Expiration timestamp for custom products")
|
|
151
|
+
] = None
|
|
152
|
+
format_ids: Annotated[
|
|
153
|
+
list[format_id_1.FormatId],
|
|
154
|
+
Field(
|
|
155
|
+
description="Array of supported creative format IDs - structured format_id objects with agent_url and id"
|
|
156
|
+
),
|
|
157
|
+
]
|
|
158
|
+
is_custom: Annotated[bool | None, Field(description="Whether this is a custom product")] = None
|
|
159
|
+
measurement: measurement_1.Measurement | None = None
|
|
160
|
+
name: Annotated[str, Field(description="Human-readable product name")]
|
|
161
|
+
placements: Annotated[
|
|
162
|
+
list[placement.Placement] | None,
|
|
163
|
+
Field(
|
|
164
|
+
description="Optional array of specific placements within this product. When provided, buyers can target specific placements when assigning creatives.",
|
|
165
|
+
min_length=1,
|
|
166
|
+
),
|
|
167
|
+
] = None
|
|
168
|
+
pricing_options: Annotated[
|
|
169
|
+
list[
|
|
170
|
+
cpm_fixed_option.CpmFixedRatePricingOption
|
|
171
|
+
| cpm_auction_option.CpmAuctionPricingOption
|
|
172
|
+
| vcpm_fixed_option.VcpmFixedRatePricingOption
|
|
173
|
+
| vcpm_auction_option.VcpmAuctionPricingOption
|
|
174
|
+
| cpc_option.CpcPricingOption
|
|
175
|
+
| cpcv_option.CpcvPricingOption
|
|
176
|
+
| cpv_option.CpvPricingOption
|
|
177
|
+
| cpp_option.CppPricingOption
|
|
178
|
+
| flat_rate_option.FlatRatePricingOption
|
|
179
|
+
],
|
|
180
|
+
Field(description="Available pricing models for this product", min_length=1),
|
|
181
|
+
]
|
|
182
|
+
product_card: Annotated[
|
|
183
|
+
ProductCard | None,
|
|
184
|
+
Field(
|
|
185
|
+
description="Optional standard visual card (300x400px) for displaying this product in user interfaces. Can be rendered via preview_creative or pre-generated."
|
|
186
|
+
),
|
|
187
|
+
] = None
|
|
188
|
+
product_card_detailed: Annotated[
|
|
189
|
+
ProductCardDetailed | None,
|
|
190
|
+
Field(
|
|
191
|
+
description="Optional detailed card with carousel and full specifications. Provides rich product presentation similar to media kit pages."
|
|
192
|
+
),
|
|
193
|
+
] = None
|
|
194
|
+
product_id: Annotated[str, Field(description="Unique identifier for the product")]
|
|
195
|
+
publisher_properties: Annotated[
|
|
196
|
+
list[PublisherProperties | PublisherProperties3],
|
|
197
|
+
Field(
|
|
198
|
+
description="Publisher properties covered by this product. Buyers fetch actual property definitions from each publisher's adagents.json and validate agent authorization.",
|
|
199
|
+
min_length=1,
|
|
200
|
+
),
|
|
201
|
+
]
|
|
202
|
+
reporting_capabilities: reporting_capabilities_1.ReportingCapabilities | None = None
|
|
203
|
+
|
|
204
|
+
@model_validator(mode="after")
|
|
205
|
+
def validate_publisher_properties_items(self) -> "Product":
|
|
206
|
+
"""Validate all publisher_properties items."""
|
|
207
|
+
from adcp.validation import validate_product
|
|
208
|
+
|
|
209
|
+
data = self.model_dump()
|
|
210
|
+
validate_product(data)
|
|
211
|
+
return self
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# generated by datamodel-codegen:
|
|
2
|
+
# filename: promoted-offerings.json
|
|
3
|
+
# timestamp: 2025-11-15T22:03:55+00:00
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
from enum import Enum
|
|
8
|
+
from typing import Annotated, Any
|
|
9
|
+
|
|
10
|
+
from adcp.types.base import AdCPBaseModel
|
|
11
|
+
from pydantic import AnyUrl, ConfigDict, Field
|
|
12
|
+
|
|
13
|
+
from . import brand_manifest_ref as brand_manifest_1
|
|
14
|
+
from . import promoted_products
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class AssetType(Enum):
|
|
18
|
+
image = "image"
|
|
19
|
+
video = "video"
|
|
20
|
+
audio = "audio"
|
|
21
|
+
vast = "vast"
|
|
22
|
+
daast = "daast"
|
|
23
|
+
text = "text"
|
|
24
|
+
url = "url"
|
|
25
|
+
html = "html"
|
|
26
|
+
css = "css"
|
|
27
|
+
javascript = "javascript"
|
|
28
|
+
webhook = "webhook"
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class AssetSelectors(AdCPBaseModel):
|
|
32
|
+
model_config = ConfigDict(
|
|
33
|
+
extra="forbid",
|
|
34
|
+
)
|
|
35
|
+
asset_types: Annotated[
|
|
36
|
+
list[AssetType] | None, Field(description="Filter by asset type (e.g., ['image', 'video'])")
|
|
37
|
+
] = None
|
|
38
|
+
exclude_tags: Annotated[
|
|
39
|
+
list[str] | None, Field(description="Exclude assets with these tags")
|
|
40
|
+
] = None
|
|
41
|
+
tags: Annotated[
|
|
42
|
+
list[str] | None,
|
|
43
|
+
Field(description="Select assets with specific tags (e.g., ['holiday', 'premium'])"),
|
|
44
|
+
] = None
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class Offering(AdCPBaseModel):
|
|
48
|
+
model_config = ConfigDict(
|
|
49
|
+
extra="forbid",
|
|
50
|
+
)
|
|
51
|
+
assets: Annotated[
|
|
52
|
+
list[dict[str, Any]] | None, Field(description="Assets specific to this offering")
|
|
53
|
+
] = None
|
|
54
|
+
description: Annotated[str | None, Field(description="Description of what's being offered")] = (
|
|
55
|
+
None
|
|
56
|
+
)
|
|
57
|
+
name: Annotated[
|
|
58
|
+
str, Field(description="Offering name (e.g., 'Winter Sale', 'New Product Launch')")
|
|
59
|
+
]
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class PromotedOfferings(AdCPBaseModel):
|
|
63
|
+
model_config = ConfigDict(
|
|
64
|
+
extra="forbid",
|
|
65
|
+
)
|
|
66
|
+
asset_selectors: Annotated[
|
|
67
|
+
AssetSelectors | None,
|
|
68
|
+
Field(description="Selectors to choose specific assets from the brand manifest"),
|
|
69
|
+
] = None
|
|
70
|
+
brand_manifest: Annotated[
|
|
71
|
+
brand_manifest_1.BrandManifest | AnyUrl,
|
|
72
|
+
Field(
|
|
73
|
+
description="Brand information manifest containing assets, themes, and guidelines. Can be provided inline or as a URL reference to a hosted manifest.",
|
|
74
|
+
examples=[
|
|
75
|
+
{
|
|
76
|
+
"data": {
|
|
77
|
+
"colors": {"primary": "#FF6B35"},
|
|
78
|
+
"name": "ACME Corporation",
|
|
79
|
+
"url": "https://acmecorp.com",
|
|
80
|
+
},
|
|
81
|
+
"description": "Inline brand manifest",
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
"data": "https://cdn.acmecorp.com/brand-manifest.json",
|
|
85
|
+
"description": "URL string reference to hosted manifest",
|
|
86
|
+
},
|
|
87
|
+
],
|
|
88
|
+
title="Brand Manifest Reference",
|
|
89
|
+
),
|
|
90
|
+
]
|
|
91
|
+
offerings: Annotated[
|
|
92
|
+
list[Offering] | None,
|
|
93
|
+
Field(
|
|
94
|
+
description="Inline offerings for campaigns without a product catalog. Each offering has a name, description, and associated assets."
|
|
95
|
+
),
|
|
96
|
+
] = None
|
|
97
|
+
product_selectors: Annotated[
|
|
98
|
+
promoted_products.PromotedProducts | None,
|
|
99
|
+
Field(
|
|
100
|
+
description="Selectors to choose which products/offerings from the brand manifest product catalog to promote"
|
|
101
|
+
),
|
|
102
|
+
] = None
|