@adcp/client 4.21.0 → 4.22.0
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.
- package/AGENTS.md +278 -0
- package/README.md +96 -61
- package/bin/adcp.js +342 -4
- package/dist/lib/agents/index.generated.d.ts +9 -1
- package/dist/lib/agents/index.generated.d.ts.map +1 -1
- package/dist/lib/agents/index.generated.js +12 -0
- package/dist/lib/agents/index.generated.js.map +1 -1
- package/dist/lib/core/AgentClient.d.ts.map +1 -1
- package/dist/lib/core/SingleAgentClient.d.ts +2 -1
- package/dist/lib/core/SingleAgentClient.d.ts.map +1 -1
- package/dist/lib/core/SingleAgentClient.js +10 -1
- package/dist/lib/core/SingleAgentClient.js.map +1 -1
- package/dist/lib/discovery/property-crawler.d.ts +4 -0
- package/dist/lib/discovery/property-crawler.d.ts.map +1 -1
- package/dist/lib/discovery/property-crawler.js +10 -2
- package/dist/lib/discovery/property-crawler.js.map +1 -1
- package/dist/lib/index.d.ts +4 -4
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/index.js +6 -4
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/protocols/index.d.ts.map +1 -1
- package/dist/lib/protocols/index.js +8 -6
- package/dist/lib/protocols/index.js.map +1 -1
- package/dist/lib/protocols/mcp.d.ts.map +1 -1
- package/dist/lib/protocols/mcp.js +24 -11
- package/dist/lib/protocols/mcp.js.map +1 -1
- package/dist/lib/server/index.d.ts +2 -0
- package/dist/lib/server/index.d.ts.map +1 -1
- package/dist/lib/server/index.js +3 -1
- package/dist/lib/server/index.js.map +1 -1
- package/dist/lib/server/serve.d.ts +45 -0
- package/dist/lib/server/serve.d.ts.map +1 -0
- package/dist/lib/server/serve.js +86 -0
- package/dist/lib/server/serve.js.map +1 -0
- package/dist/lib/testing/client.d.ts.map +1 -1
- package/dist/lib/testing/client.js +1 -0
- package/dist/lib/testing/client.js.map +1 -1
- package/dist/lib/testing/compliance/comply.d.ts.map +1 -1
- package/dist/lib/testing/compliance/comply.js +48 -63
- package/dist/lib/testing/compliance/comply.js.map +1 -1
- package/dist/lib/testing/compliance/storyboard-tracks.d.ts +24 -0
- package/dist/lib/testing/compliance/storyboard-tracks.d.ts.map +1 -0
- package/dist/lib/testing/compliance/storyboard-tracks.js +157 -0
- package/dist/lib/testing/compliance/storyboard-tracks.js.map +1 -0
- package/dist/lib/testing/compliance/types.d.ts +1 -1
- package/dist/lib/testing/compliance/types.d.ts.map +1 -1
- package/dist/lib/testing/index.d.ts +1 -0
- package/dist/lib/testing/index.d.ts.map +1 -1
- package/dist/lib/testing/index.js +23 -1
- package/dist/lib/testing/index.js.map +1 -1
- package/dist/lib/testing/orchestrator.d.ts +8 -0
- package/dist/lib/testing/orchestrator.d.ts.map +1 -1
- package/dist/lib/testing/orchestrator.js +8 -0
- package/dist/lib/testing/orchestrator.js.map +1 -1
- package/dist/lib/testing/storyboard/context.d.ts +34 -0
- package/dist/lib/testing/storyboard/context.d.ts.map +1 -0
- package/dist/lib/testing/storyboard/context.js +257 -0
- package/dist/lib/testing/storyboard/context.js.map +1 -0
- package/dist/lib/testing/storyboard/index.d.ts +15 -0
- package/dist/lib/testing/storyboard/index.d.ts.map +1 -0
- package/dist/lib/testing/storyboard/index.js +48 -0
- package/dist/lib/testing/storyboard/index.js.map +1 -0
- package/dist/lib/testing/storyboard/loader.d.ts +53 -0
- package/dist/lib/testing/storyboard/loader.d.ts.map +1 -0
- package/dist/lib/testing/storyboard/loader.js +114 -0
- package/dist/lib/testing/storyboard/loader.js.map +1 -0
- package/dist/lib/testing/storyboard/path.d.ts +29 -0
- package/dist/lib/testing/storyboard/path.d.ts.map +1 -0
- package/dist/lib/testing/storyboard/path.js +121 -0
- package/dist/lib/testing/storyboard/path.js.map +1 -0
- package/dist/lib/testing/storyboard/request-builder.d.ts +28 -0
- package/dist/lib/testing/storyboard/request-builder.d.ts.map +1 -0
- package/dist/lib/testing/storyboard/request-builder.js +410 -0
- package/dist/lib/testing/storyboard/request-builder.js.map +1 -0
- package/dist/lib/testing/storyboard/runner.d.ts +24 -0
- package/dist/lib/testing/storyboard/runner.d.ts.map +1 -0
- package/dist/lib/testing/storyboard/runner.js +280 -0
- package/dist/lib/testing/storyboard/runner.js.map +1 -0
- package/dist/lib/testing/storyboard/task-map.d.ts +21 -0
- package/dist/lib/testing/storyboard/task-map.d.ts.map +1 -0
- package/dist/lib/testing/storyboard/task-map.js +84 -0
- package/dist/lib/testing/storyboard/task-map.js.map +1 -0
- package/dist/lib/testing/storyboard/types.d.ts +156 -0
- package/dist/lib/testing/storyboard/types.d.ts.map +1 -0
- package/dist/lib/testing/storyboard/types.js +10 -0
- package/dist/lib/testing/storyboard/types.js.map +1 -0
- package/dist/lib/testing/storyboard/validations.d.ts +17 -0
- package/dist/lib/testing/storyboard/validations.d.ts.map +1 -0
- package/dist/lib/testing/storyboard/validations.js +166 -0
- package/dist/lib/testing/storyboard/validations.js.map +1 -0
- package/dist/lib/testing/types.d.ts +2 -0
- package/dist/lib/testing/types.d.ts.map +1 -1
- package/dist/lib/types/core.generated.d.ts +2 -2
- package/dist/lib/types/core.generated.d.ts.map +1 -1
- package/dist/lib/types/core.generated.js +1 -1
- package/dist/lib/types/schemas.generated.d.ts +193 -34
- package/dist/lib/types/schemas.generated.d.ts.map +1 -1
- package/dist/lib/types/schemas.generated.js +87 -5
- package/dist/lib/types/schemas.generated.js.map +1 -1
- package/dist/lib/types/tools.generated.d.ts +280 -3
- package/dist/lib/types/tools.generated.d.ts.map +1 -1
- package/dist/lib/utils/response-schemas.d.ts.map +1 -1
- package/dist/lib/utils/response-schemas.js +34 -3
- package/dist/lib/utils/response-schemas.js.map +1 -1
- package/dist/lib/utils/validate-user-agent.d.ts +8 -0
- package/dist/lib/utils/validate-user-agent.d.ts.map +1 -0
- package/dist/lib/utils/validate-user-agent.js +15 -0
- package/dist/lib/utils/validate-user-agent.js.map +1 -0
- package/dist/lib/version.d.ts +6 -0
- package/dist/lib/version.d.ts.map +1 -1
- package/dist/lib/version.js +7 -1
- package/dist/lib/version.js.map +1 -1
- package/docs/README.md +42 -0
- package/docs/guides/BUILD-AN-AGENT.md +292 -0
- package/docs/llms.txt +634 -0
- package/examples/README.md +106 -0
- package/examples/adcp.config.json +30 -0
- package/examples/basic-a2a.ts +76 -0
- package/examples/basic-mcp.ts +50 -0
- package/examples/batch-preview-test.ts +266 -0
- package/examples/conversation-client.ts +291 -0
- package/examples/debug-preview-response.ts +73 -0
- package/examples/debug-preview-with-logging.ts +50 -0
- package/examples/easy-config-demo.ts +242 -0
- package/examples/env-config.ts +51 -0
- package/examples/error-compliant-server.ts +237 -0
- package/examples/generative-creative-demo.ts +205 -0
- package/examples/inspect-card-formats.ts +161 -0
- package/examples/logger-usage.ts +165 -0
- package/examples/oauth-cli-example.ts +154 -0
- package/examples/pr78-async-patterns-demo.ts +247 -0
- package/examples/signals-agent.ts +162 -0
- package/examples/simple-getting-started.ts +225 -0
- package/examples/simple-protocol-demo.ts +75 -0
- package/examples/test-helpers-demo.ts +239 -0
- package/examples/zod-validation-example.ts +126 -0
- package/package.json +12 -2
- package/skills/adcp/SKILL.md +13 -2
- package/storyboards/audience_sync.yaml +199 -0
- package/storyboards/behavioral_analysis.yaml +244 -0
- package/storyboards/brand_rights.yaml +131 -0
- package/storyboards/creative_ad_server.yaml +171 -0
- package/storyboards/creative_sales_agent.yaml +169 -0
- package/storyboards/creative_template.yaml +306 -0
- package/storyboards/deterministic_testing.yaml +925 -0
- package/storyboards/error_compliance.yaml +231 -0
- package/storyboards/governance_content_standards.yaml +213 -0
- package/storyboards/governance_property_lists.yaml +372 -0
- package/storyboards/media_buy_catalog_creative.yaml +457 -0
- package/storyboards/media_buy_governance_escalation.yaml +467 -0
- package/storyboards/media_buy_guaranteed_approval.yaml +396 -0
- package/storyboards/media_buy_non_guaranteed.yaml +288 -0
- package/storyboards/media_buy_proposal_mode.yaml +369 -0
- package/storyboards/media_buy_seller.yaml +560 -0
- package/storyboards/media_buy_state_machine.yaml +254 -0
- package/storyboards/schema.yaml +65 -0
- package/storyboards/schema_validation.yaml +166 -0
- package/storyboards/si_session.yaml +384 -0
- package/storyboards/signal_marketplace.yaml +283 -0
- package/storyboards/signal_owned.yaml +211 -0
|
@@ -0,0 +1,560 @@
|
|
|
1
|
+
id: media_buy_seller
|
|
2
|
+
version: '1.0.0'
|
|
3
|
+
title: 'Media buy seller agent'
|
|
4
|
+
category: media_buy_seller
|
|
5
|
+
summary: 'Seller agent that receives briefs, returns products, accepts media buys, and reports delivery.'
|
|
6
|
+
platform_types:
|
|
7
|
+
- display_ad_server
|
|
8
|
+
- video_ad_server
|
|
9
|
+
- social_platform
|
|
10
|
+
- retail_media
|
|
11
|
+
- search_platform
|
|
12
|
+
- audio_platform
|
|
13
|
+
- linear_tv_platform
|
|
14
|
+
- dsp
|
|
15
|
+
- pmax_platform
|
|
16
|
+
- ai_ad_network
|
|
17
|
+
- ai_platform
|
|
18
|
+
- generative_dsp
|
|
19
|
+
|
|
20
|
+
track: reporting
|
|
21
|
+
required_tools:
|
|
22
|
+
- get_media_buy_delivery
|
|
23
|
+
narrative: |
|
|
24
|
+
You run a sell-side platform — a publisher, SSP, retail media network, or any system that
|
|
25
|
+
sells advertising inventory. A buyer agent connects to discover your products, negotiate
|
|
26
|
+
proposals, create media buys, and monitor delivery. Your agent handles the full lifecycle
|
|
27
|
+
from brief to reporting.
|
|
28
|
+
|
|
29
|
+
The buyer starts by setting up an account and optionally registering governance agents.
|
|
30
|
+
Then they send a natural-language brief, refine the resulting products, create a media buy,
|
|
31
|
+
sync creatives, and monitor delivery — all through AdCP tasks.
|
|
32
|
+
|
|
33
|
+
This storyboard walks through the complete media buy flow from the buyer's perspective,
|
|
34
|
+
including async operations and human-in-the-loop approval gates.
|
|
35
|
+
|
|
36
|
+
agent:
|
|
37
|
+
interaction_model: media_buy_seller
|
|
38
|
+
capabilities:
|
|
39
|
+
- sells_media
|
|
40
|
+
- accepts_briefs
|
|
41
|
+
- supports_guaranteed
|
|
42
|
+
- supports_non_guaranteed
|
|
43
|
+
examples:
|
|
44
|
+
- 'Yahoo'
|
|
45
|
+
- 'Retail media networks'
|
|
46
|
+
- 'Publisher platforms'
|
|
47
|
+
- 'SSPs'
|
|
48
|
+
|
|
49
|
+
caller:
|
|
50
|
+
role: buyer_agent
|
|
51
|
+
example: 'Scope3 (DSP)'
|
|
52
|
+
|
|
53
|
+
prerequisites:
|
|
54
|
+
description: |
|
|
55
|
+
The caller needs a brand identity and operator credentials for account setup.
|
|
56
|
+
The test kit provides a sample brand (Acme Outdoor) with campaign parameters
|
|
57
|
+
suitable for testing the full media buy flow.
|
|
58
|
+
test_kit: 'test-kits/acme-outdoor.yaml'
|
|
59
|
+
|
|
60
|
+
phases:
|
|
61
|
+
- id: account_setup
|
|
62
|
+
title: 'Account setup'
|
|
63
|
+
narrative: |
|
|
64
|
+
Before buying anything, the buyer establishes an account relationship with
|
|
65
|
+
your platform. This is the handshake: the buyer tells you which brand and
|
|
66
|
+
agency (operator) they represent, and you return an account ID, status, and
|
|
67
|
+
any setup requirements.
|
|
68
|
+
|
|
69
|
+
Some platforms approve accounts instantly. Others require human review — the
|
|
70
|
+
buyer gets back a pending_approval status and a URL to complete setup. The
|
|
71
|
+
buyer polls or waits for a webhook until the account is active.
|
|
72
|
+
|
|
73
|
+
steps:
|
|
74
|
+
- id: sync_accounts
|
|
75
|
+
title: 'Establish account relationship'
|
|
76
|
+
narrative: |
|
|
77
|
+
The buyer registers their brand and operator with your platform. This is
|
|
78
|
+
the first call in any new relationship. Your platform validates the request,
|
|
79
|
+
provisions the account, and returns its status.
|
|
80
|
+
|
|
81
|
+
If your platform requires manual approval (credit checks, sales team review),
|
|
82
|
+
return pending_approval with a setup URL. The buyer will complete setup there
|
|
83
|
+
and poll list_accounts until the status changes to active.
|
|
84
|
+
task: sync_accounts
|
|
85
|
+
schema_ref: 'account/sync-accounts-request.json'
|
|
86
|
+
response_schema_ref: 'account/sync-accounts-response.json'
|
|
87
|
+
doc_ref: '/accounts/tasks/sync_accounts'
|
|
88
|
+
comply_scenario: account_setup
|
|
89
|
+
stateful: true
|
|
90
|
+
expected: |
|
|
91
|
+
Return the account with:
|
|
92
|
+
- account_id: your platform's identifier for this relationship
|
|
93
|
+
- action: created or updated
|
|
94
|
+
- status: active (instant approval) or pending_approval (requires human review)
|
|
95
|
+
- account_scope: operator, brand, operator_brand, or agent
|
|
96
|
+
- setup: URL and message if pending_approval (where the human completes onboarding)
|
|
97
|
+
- rate_card: pricing tiers if applicable
|
|
98
|
+
- payment_terms: net_30, prepay, etc.
|
|
99
|
+
|
|
100
|
+
sample_request:
|
|
101
|
+
accounts:
|
|
102
|
+
- brand:
|
|
103
|
+
domain: 'acmeoutdoor.com'
|
|
104
|
+
operator: 'pinnacle-agency.com'
|
|
105
|
+
billing: 'operator'
|
|
106
|
+
payment_terms: 'net_30'
|
|
107
|
+
|
|
108
|
+
validations:
|
|
109
|
+
- check: response_schema
|
|
110
|
+
description: 'Response matches sync-accounts-response.json schema'
|
|
111
|
+
- check: field_present
|
|
112
|
+
path: 'accounts[0].account_id'
|
|
113
|
+
description: 'Account has a platform-assigned ID'
|
|
114
|
+
- check: field_present
|
|
115
|
+
path: 'accounts[0].status'
|
|
116
|
+
description: 'Account has a status (active or pending_approval)'
|
|
117
|
+
|
|
118
|
+
- id: governance_setup
|
|
119
|
+
title: 'Governance agent registration'
|
|
120
|
+
narrative: |
|
|
121
|
+
The buyer registers their governance agent with your platform. This tells your
|
|
122
|
+
platform where to call check_governance before confirming media buys. The
|
|
123
|
+
governance agent validates budget authority, brand safety, and compliance
|
|
124
|
+
independently of both the buyer and seller.
|
|
125
|
+
|
|
126
|
+
This step is optional but strongly recommended. Platforms that support governance
|
|
127
|
+
will call the registered agent during create_media_buy to validate the buy before
|
|
128
|
+
confirming it.
|
|
129
|
+
|
|
130
|
+
steps:
|
|
131
|
+
- id: sync_governance
|
|
132
|
+
title: 'Register governance agents'
|
|
133
|
+
narrative: |
|
|
134
|
+
The buyer tells your platform: "Before you confirm any media buy for this
|
|
135
|
+
account, call this governance agent to validate it." Your platform stores
|
|
136
|
+
the governance agent URL and will call it during create_media_buy.
|
|
137
|
+
|
|
138
|
+
This uses replace semantics — each sync_governance call replaces any
|
|
139
|
+
previously registered agents for the account.
|
|
140
|
+
task: sync_governance
|
|
141
|
+
schema_ref: 'account/sync-governance-request.json'
|
|
142
|
+
response_schema_ref: 'account/sync-governance-response.json'
|
|
143
|
+
doc_ref: '/accounts/tasks/sync_governance'
|
|
144
|
+
comply_scenario: governance_setup
|
|
145
|
+
stateful: true
|
|
146
|
+
expected: |
|
|
147
|
+
Acknowledge the governance agents. Your platform should:
|
|
148
|
+
- Store the governance agent URLs for the specified accounts
|
|
149
|
+
- Return confirmation that agents were registered
|
|
150
|
+
- Use these agents during create_media_buy validation
|
|
151
|
+
|
|
152
|
+
sample_request:
|
|
153
|
+
accounts:
|
|
154
|
+
- account:
|
|
155
|
+
brand:
|
|
156
|
+
domain: 'acmeoutdoor.com'
|
|
157
|
+
operator: 'pinnacle-agency.com'
|
|
158
|
+
governance_agents:
|
|
159
|
+
- url: 'https://governance.pinnacle-agency.example'
|
|
160
|
+
authentication:
|
|
161
|
+
schemes: ['Bearer']
|
|
162
|
+
credentials: 'gov-token-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
|
|
163
|
+
categories: ['budget_authority', 'brand_policy']
|
|
164
|
+
|
|
165
|
+
validations:
|
|
166
|
+
- check: response_schema
|
|
167
|
+
description: 'Response matches sync-governance-response.json schema'
|
|
168
|
+
|
|
169
|
+
- id: product_discovery
|
|
170
|
+
title: 'Product discovery'
|
|
171
|
+
narrative: |
|
|
172
|
+
The buyer sends a natural-language brief describing what they want to buy.
|
|
173
|
+
Your platform interprets the brief against your inventory and returns products —
|
|
174
|
+
structured representations of what you can sell, with pricing, delivery forecasts,
|
|
175
|
+
targeting options, and creative requirements.
|
|
176
|
+
|
|
177
|
+
This is where seller differentiation happens. The same brief sent to three sellers
|
|
178
|
+
produces three different product sets. Your AI interprets "premium video on sports
|
|
179
|
+
and outdoor lifestyle" against your specific inventory, audiences, and pricing.
|
|
180
|
+
|
|
181
|
+
steps:
|
|
182
|
+
- id: get_products_brief
|
|
183
|
+
title: 'Send a brief'
|
|
184
|
+
narrative: |
|
|
185
|
+
The buyer describes what they want in natural language. Your platform returns
|
|
186
|
+
products that match the brief, including pricing options, delivery forecasts,
|
|
187
|
+
and creative format requirements.
|
|
188
|
+
|
|
189
|
+
This call may take up to 60 seconds — your platform is running AI inference
|
|
190
|
+
against your inventory catalog. If the brief is ambiguous, you can return
|
|
191
|
+
input-required to ask clarifying questions before producing results.
|
|
192
|
+
task: get_products
|
|
193
|
+
schema_ref: 'media-buy/get-products-request.json'
|
|
194
|
+
response_schema_ref: 'media-buy/get-products-response.json'
|
|
195
|
+
doc_ref: '/media-buy/task-reference/get_products'
|
|
196
|
+
comply_scenario: media_buy_flow
|
|
197
|
+
stateful: false
|
|
198
|
+
expected: |
|
|
199
|
+
Return products matching the brief. Each product should include:
|
|
200
|
+
- product_id: unique identifier
|
|
201
|
+
- name and description
|
|
202
|
+
- delivery_type: guaranteed or non_guaranteed
|
|
203
|
+
- pricing_models: available pricing options (CPM, CPC, etc.)
|
|
204
|
+
- forecast: estimated impressions, reach
|
|
205
|
+
- creative_format_ids: what creative formats this product requires
|
|
206
|
+
- targeting: what audiences or contexts this product reaches
|
|
207
|
+
|
|
208
|
+
Optionally return proposals — curated media plans that bundle products
|
|
209
|
+
with budget allocations the buyer can accept or refine.
|
|
210
|
+
|
|
211
|
+
If the brief is unclear, return input-required with clarifying questions.
|
|
212
|
+
|
|
213
|
+
sample_request:
|
|
214
|
+
buying_mode: 'brief'
|
|
215
|
+
brief: 'Premium video inventory on sports and outdoor lifestyle publishers. Q2 flight, $50K budget. Adults 25-54, US and Canada.'
|
|
216
|
+
brand:
|
|
217
|
+
domain: 'acmeoutdoor.com'
|
|
218
|
+
account:
|
|
219
|
+
brand:
|
|
220
|
+
domain: 'acmeoutdoor.com'
|
|
221
|
+
operator: 'pinnacle-agency.com'
|
|
222
|
+
|
|
223
|
+
validations:
|
|
224
|
+
- check: response_schema
|
|
225
|
+
description: 'Response matches get-products-response.json schema'
|
|
226
|
+
- check: field_present
|
|
227
|
+
path: 'products'
|
|
228
|
+
description: 'Response contains a products array'
|
|
229
|
+
- check: field_present
|
|
230
|
+
path: 'products[0].product_id'
|
|
231
|
+
description: 'Each product has a product_id'
|
|
232
|
+
- check: field_present
|
|
233
|
+
path: 'products[0].delivery_type'
|
|
234
|
+
description: 'Each product declares guaranteed or non_guaranteed delivery'
|
|
235
|
+
|
|
236
|
+
- id: proposal_refinement
|
|
237
|
+
title: 'Proposal refinement'
|
|
238
|
+
narrative: |
|
|
239
|
+
The buyer reviews the products from the brief and wants to narrow down. They
|
|
240
|
+
switch to refine mode, layering constraints without starting over. Each refinement
|
|
241
|
+
narrows the previous result set.
|
|
242
|
+
|
|
243
|
+
This is iterative negotiation. The buyer might say "only guaranteed packages" or
|
|
244
|
+
"increase the CTV allocation to 60%" or "drop the audio product and redistribute
|
|
245
|
+
that budget." Your platform adjusts the products and proposals accordingly.
|
|
246
|
+
|
|
247
|
+
steps:
|
|
248
|
+
- id: get_products_refine
|
|
249
|
+
title: 'Refine the proposal'
|
|
250
|
+
narrative: |
|
|
251
|
+
The buyer has reviewed the initial products and wants adjustments. They call
|
|
252
|
+
get_products with buying_mode: refine and a refine array describing what to
|
|
253
|
+
change. Your platform applies the refinements and returns updated products.
|
|
254
|
+
task: get_products
|
|
255
|
+
schema_ref: 'media-buy/get-products-request.json'
|
|
256
|
+
response_schema_ref: 'media-buy/get-products-response.json'
|
|
257
|
+
doc_ref: '/media-buy/task-reference/get_products'
|
|
258
|
+
comply_scenario: media_buy_flow
|
|
259
|
+
stateful: true
|
|
260
|
+
expected: |
|
|
261
|
+
Return updated products reflecting the refinements. The response should:
|
|
262
|
+
- Apply each refinement to the relevant scope (request, product, or proposal)
|
|
263
|
+
- Include refinement_applied showing how each request was handled
|
|
264
|
+
- Preserve products that weren't targeted by refinements
|
|
265
|
+
- Update pricing and forecasts to reflect the changes
|
|
266
|
+
|
|
267
|
+
sample_request:
|
|
268
|
+
buying_mode: 'refine'
|
|
269
|
+
refine:
|
|
270
|
+
- scope: 'request'
|
|
271
|
+
ask: 'Only guaranteed packages. Must include completion rate SLA above 80%.'
|
|
272
|
+
- scope: 'product'
|
|
273
|
+
product_id: 'sports_preroll_q2'
|
|
274
|
+
ask: 'Increase budget allocation to $30K'
|
|
275
|
+
brand:
|
|
276
|
+
domain: 'acmeoutdoor.com'
|
|
277
|
+
account:
|
|
278
|
+
brand:
|
|
279
|
+
domain: 'acmeoutdoor.com'
|
|
280
|
+
operator: 'pinnacle-agency.com'
|
|
281
|
+
|
|
282
|
+
validations:
|
|
283
|
+
- check: response_schema
|
|
284
|
+
description: 'Response matches get-products-response.json schema'
|
|
285
|
+
- check: field_present
|
|
286
|
+
path: 'products'
|
|
287
|
+
description: 'Response contains updated products'
|
|
288
|
+
|
|
289
|
+
- id: create_buy
|
|
290
|
+
title: 'Create the media buy'
|
|
291
|
+
narrative: |
|
|
292
|
+
The buyer is satisfied with the products and creates a media buy. This is the
|
|
293
|
+
equivalent of signing an IO — the buyer commits to specific products, budgets,
|
|
294
|
+
and flight dates.
|
|
295
|
+
|
|
296
|
+
This operation may be synchronous (completed immediately), asynchronous (working
|
|
297
|
+
or submitted while your platform processes), or require human approval
|
|
298
|
+
(pending_approval with a URL for the human to sign off).
|
|
299
|
+
|
|
300
|
+
If the buyer registered governance agents in Phase 2, your platform calls
|
|
301
|
+
check_governance before confirming the buy. The governance agent validates budget
|
|
302
|
+
authority, brand safety, and compliance. If governance denies the buy, return the
|
|
303
|
+
denial — don't override it.
|
|
304
|
+
|
|
305
|
+
steps:
|
|
306
|
+
- id: create_media_buy
|
|
307
|
+
title: 'Create a media buy'
|
|
308
|
+
narrative: |
|
|
309
|
+
The buyer commits to specific products with budgets and flight dates. Your
|
|
310
|
+
platform validates the request, optionally calls governance, and either confirms
|
|
311
|
+
the buy or sends it through an approval workflow.
|
|
312
|
+
|
|
313
|
+
Two creation modes:
|
|
314
|
+
- Manual: buyer specifies packages array with explicit product selections
|
|
315
|
+
- Proposal: buyer passes a proposal_id from get_products to execute a proposal
|
|
316
|
+
|
|
317
|
+
The response status tells the buyer what happens next:
|
|
318
|
+
- completed: buy is confirmed and live
|
|
319
|
+
- working: your platform is processing (poll or wait for webhook)
|
|
320
|
+
- submitted: long-running async — approval workflow, IO signing, etc.
|
|
321
|
+
- input-required: need more information (budget clarification, approval)
|
|
322
|
+
task: create_media_buy
|
|
323
|
+
schema_ref: 'media-buy/create-media-buy-request.json'
|
|
324
|
+
response_schema_ref: 'media-buy/create-media-buy-response.json'
|
|
325
|
+
doc_ref: '/media-buy/task-reference/create_media_buy'
|
|
326
|
+
comply_scenario: media_buy_flow
|
|
327
|
+
stateful: true
|
|
328
|
+
expected: |
|
|
329
|
+
Process the media buy request and return one of:
|
|
330
|
+
|
|
331
|
+
Synchronous (completed):
|
|
332
|
+
- media_buy_id: your platform's identifier
|
|
333
|
+
- status: confirmed or pending_creatives
|
|
334
|
+
- packages: confirmed line items with pricing
|
|
335
|
+
- confirmed_at: timestamp
|
|
336
|
+
- valid_actions: what the buyer can do next
|
|
337
|
+
|
|
338
|
+
Asynchronous (working):
|
|
339
|
+
- percentage: 0-100 completion
|
|
340
|
+
- current_step: what's happening ("Validating inventory", "Checking governance")
|
|
341
|
+
|
|
342
|
+
Async with human approval (submitted):
|
|
343
|
+
- estimated_completion: when the buyer should expect a result
|
|
344
|
+
- The buyer configures push_notification_config to receive a webhook when done
|
|
345
|
+
|
|
346
|
+
Needs input (input-required):
|
|
347
|
+
- reason: APPROVAL_REQUIRED, BUDGET_EXCEEDS_LIMIT, CLARIFICATION_NEEDED
|
|
348
|
+
- errors: what needs to be resolved
|
|
349
|
+
- setup URL for human to complete approval (IO signing, budget authorization)
|
|
350
|
+
|
|
351
|
+
sample_request:
|
|
352
|
+
account:
|
|
353
|
+
brand:
|
|
354
|
+
domain: 'acmeoutdoor.com'
|
|
355
|
+
operator: 'pinnacle-agency.com'
|
|
356
|
+
brand:
|
|
357
|
+
domain: 'acmeoutdoor.com'
|
|
358
|
+
start_time: '2026-04-01T00:00:00Z'
|
|
359
|
+
end_time: '2026-06-30T23:59:59Z'
|
|
360
|
+
packages:
|
|
361
|
+
- product_id: 'sports_preroll_q2'
|
|
362
|
+
budget: 25000
|
|
363
|
+
pricing_option_id: 'cpm_guaranteed'
|
|
364
|
+
creative_assignments:
|
|
365
|
+
- creative_id: 'video_30s_trail_pro'
|
|
366
|
+
- product_id: 'lifestyle_display_q2'
|
|
367
|
+
budget: 15000
|
|
368
|
+
pricing_option_id: 'cpm_standard'
|
|
369
|
+
push_notification_config:
|
|
370
|
+
url: 'https://buyer.example/webhooks/adcp'
|
|
371
|
+
authentication:
|
|
372
|
+
scheme: 'HMAC-SHA256'
|
|
373
|
+
|
|
374
|
+
validations:
|
|
375
|
+
- check: response_schema
|
|
376
|
+
description: 'Response matches create-media-buy-response.json schema'
|
|
377
|
+
|
|
378
|
+
- id: check_buy_status
|
|
379
|
+
title: 'Check media buy status'
|
|
380
|
+
narrative: |
|
|
381
|
+
If create_media_buy returned working or submitted, the buyer polls for status
|
|
382
|
+
updates. Your platform returns the current state of the media buy — whether
|
|
383
|
+
it's still processing, awaiting approval, or confirmed.
|
|
384
|
+
|
|
385
|
+
This is also how the buyer checks for pending_approval status. If your platform
|
|
386
|
+
requires IO signing or human authorization, the buy sits at pending_approval
|
|
387
|
+
until the human completes the action. Your platform sends back a URL where the
|
|
388
|
+
human goes to approve.
|
|
389
|
+
task: get_media_buys
|
|
390
|
+
schema_ref: 'media-buy/get-media-buys-request.json'
|
|
391
|
+
response_schema_ref: 'media-buy/get-media-buys-response.json'
|
|
392
|
+
doc_ref: '/media-buy/task-reference/get_media_buys'
|
|
393
|
+
comply_scenario: media_buy_flow
|
|
394
|
+
stateful: true
|
|
395
|
+
expected: |
|
|
396
|
+
Return the current state of the media buy:
|
|
397
|
+
- media_buy_id: matches what was returned from create_media_buy
|
|
398
|
+
- status: draft, pending_approval, confirmed, active, paused, completed, canceled
|
|
399
|
+
- packages: line items with current delivery status
|
|
400
|
+
- valid_actions: what operations are available in this state
|
|
401
|
+
|
|
402
|
+
If pending_approval:
|
|
403
|
+
- Include setup URL where the human completes approval
|
|
404
|
+
- Include message explaining what's needed
|
|
405
|
+
|
|
406
|
+
sample_request:
|
|
407
|
+
account:
|
|
408
|
+
brand:
|
|
409
|
+
domain: 'acmeoutdoor.com'
|
|
410
|
+
operator: 'pinnacle-agency.com'
|
|
411
|
+
media_buy_ids:
|
|
412
|
+
- 'mb_acme_q2_2026'
|
|
413
|
+
|
|
414
|
+
validations:
|
|
415
|
+
- check: response_schema
|
|
416
|
+
description: 'Response matches get-media-buys-response.json schema'
|
|
417
|
+
- check: field_present
|
|
418
|
+
path: 'media_buys[0].status'
|
|
419
|
+
description: 'Each media buy has a status'
|
|
420
|
+
|
|
421
|
+
- id: creative_sync
|
|
422
|
+
title: 'Creative sync'
|
|
423
|
+
narrative: |
|
|
424
|
+
With the media buy confirmed, the buyer syncs creative assets to your platform.
|
|
425
|
+
Each package in the buy has creative format requirements — the buyer discovered
|
|
426
|
+
these during product discovery and now pushes matching assets.
|
|
427
|
+
|
|
428
|
+
Your platform validates each creative against the format specs and returns
|
|
429
|
+
per-creative status. If assets need review or transcoding, the operation may
|
|
430
|
+
go async.
|
|
431
|
+
|
|
432
|
+
steps:
|
|
433
|
+
- id: list_formats
|
|
434
|
+
title: 'Check creative format requirements'
|
|
435
|
+
narrative: |
|
|
436
|
+
The buyer confirms what creative formats the confirmed packages require.
|
|
437
|
+
Your platform returns format specs with asset requirements, dimensions,
|
|
438
|
+
and constraints.
|
|
439
|
+
task: list_creative_formats
|
|
440
|
+
schema_ref: 'creative/list-creative-formats-request.json'
|
|
441
|
+
response_schema_ref: 'creative/list-creative-formats-response.json'
|
|
442
|
+
doc_ref: '/creative/task-reference/list_creative_formats'
|
|
443
|
+
comply_scenario: creative_sync
|
|
444
|
+
stateful: false
|
|
445
|
+
expected: |
|
|
446
|
+
Return creative formats your platform accepts. Each format should define:
|
|
447
|
+
- format_id with your agent_url and unique id
|
|
448
|
+
- Asset requirements (dimensions, file sizes, mime types)
|
|
449
|
+
- Render dimensions
|
|
450
|
+
|
|
451
|
+
sample_request: {}
|
|
452
|
+
|
|
453
|
+
validations:
|
|
454
|
+
- check: response_schema
|
|
455
|
+
description: 'Response matches list-creative-formats-response.json schema'
|
|
456
|
+
- check: field_present
|
|
457
|
+
path: 'formats'
|
|
458
|
+
description: 'Response contains formats array'
|
|
459
|
+
|
|
460
|
+
- id: sync_creatives
|
|
461
|
+
title: 'Push creative assets'
|
|
462
|
+
narrative: |
|
|
463
|
+
The buyer uploads creative assets for the confirmed packages. Your platform
|
|
464
|
+
validates each creative against the format specs, transcodes if necessary,
|
|
465
|
+
and returns per-creative status.
|
|
466
|
+
task: sync_creatives
|
|
467
|
+
schema_ref: 'creative/sync-creatives-request.json'
|
|
468
|
+
response_schema_ref: 'creative/sync-creatives-response.json'
|
|
469
|
+
doc_ref: '/creative/task-reference/sync_creatives'
|
|
470
|
+
comply_scenario: creative_sync
|
|
471
|
+
stateful: true
|
|
472
|
+
expected: |
|
|
473
|
+
Accept and validate creatives:
|
|
474
|
+
- Per-creative action: created or updated
|
|
475
|
+
- Per-creative status: accepted, pending_review, or rejected
|
|
476
|
+
- Validation errors for rejected creatives
|
|
477
|
+
- Platform-assigned IDs if applicable
|
|
478
|
+
|
|
479
|
+
sample_request:
|
|
480
|
+
account:
|
|
481
|
+
brand:
|
|
482
|
+
domain: 'acmeoutdoor.com'
|
|
483
|
+
operator: 'pinnacle-agency.com'
|
|
484
|
+
creatives:
|
|
485
|
+
- creative_id: 'video_30s_trail_pro'
|
|
486
|
+
name: 'Trail Pro 3000 - 30s CTV Spot'
|
|
487
|
+
format_id:
|
|
488
|
+
agent_url: 'https://your-platform.example.com'
|
|
489
|
+
id: 'ssai_30s'
|
|
490
|
+
assets:
|
|
491
|
+
- asset_id: 'video'
|
|
492
|
+
asset_type: 'video'
|
|
493
|
+
url: 'https://cdn.pinnacle-agency.example/trail-pro-30s.mp4'
|
|
494
|
+
mime_type: 'video/mp4'
|
|
495
|
+
- creative_id: 'display_trail_pro_300x250'
|
|
496
|
+
name: 'Trail Pro 3000 - Display 300x250'
|
|
497
|
+
format_id:
|
|
498
|
+
agent_url: 'https://your-platform.example.com'
|
|
499
|
+
id: 'display_300x250'
|
|
500
|
+
assets:
|
|
501
|
+
- asset_id: 'image'
|
|
502
|
+
asset_type: 'image'
|
|
503
|
+
url: 'https://cdn.pinnacle-agency.example/trail-pro-300x250.png'
|
|
504
|
+
mime_type: 'image/png'
|
|
505
|
+
|
|
506
|
+
validations:
|
|
507
|
+
- check: response_schema
|
|
508
|
+
description: 'Response matches sync-creatives-response.json schema'
|
|
509
|
+
- check: field_present
|
|
510
|
+
path: 'creatives[0].action'
|
|
511
|
+
description: 'Each creative has an action (created/updated)'
|
|
512
|
+
|
|
513
|
+
- id: delivery_monitoring
|
|
514
|
+
title: 'Delivery and reporting'
|
|
515
|
+
narrative: |
|
|
516
|
+
The campaign is live. The buyer monitors delivery through two tasks:
|
|
517
|
+
get_media_buys for status and get_media_buy_delivery for performance metrics.
|
|
518
|
+
|
|
519
|
+
Your platform reports in a standard format — impressions, clicks, spend,
|
|
520
|
+
completion rates — so the buyer can compare delivery across multiple sellers
|
|
521
|
+
in a single view.
|
|
522
|
+
|
|
523
|
+
steps:
|
|
524
|
+
- id: get_delivery
|
|
525
|
+
title: 'Check delivery metrics'
|
|
526
|
+
narrative: |
|
|
527
|
+
The buyer requests delivery data for the active media buy. Your platform
|
|
528
|
+
returns performance metrics — impressions, clicks, spend, completion rates —
|
|
529
|
+
broken down by package and optionally by day.
|
|
530
|
+
|
|
531
|
+
This call may take up to 60 seconds as your platform aggregates reporting
|
|
532
|
+
data across delivery systems.
|
|
533
|
+
task: get_media_buy_delivery
|
|
534
|
+
schema_ref: 'media-buy/get-media-buy-delivery-request.json'
|
|
535
|
+
response_schema_ref: 'media-buy/get-media-buy-delivery-response.json'
|
|
536
|
+
doc_ref: '/media-buy/task-reference/get_media_buy_delivery'
|
|
537
|
+
comply_scenario: media_buy_flow
|
|
538
|
+
stateful: true
|
|
539
|
+
expected: |
|
|
540
|
+
Return delivery metrics for the media buy:
|
|
541
|
+
- Per-package delivery: impressions, clicks, spend, completion rates
|
|
542
|
+
- Daily breakdown if requested (include_package_daily_breakdown)
|
|
543
|
+
- Pacing information: on track, ahead, behind
|
|
544
|
+
- Budget utilization: spent vs. committed
|
|
545
|
+
|
|
546
|
+
sample_request:
|
|
547
|
+
account:
|
|
548
|
+
brand:
|
|
549
|
+
domain: 'acmeoutdoor.com'
|
|
550
|
+
operator: 'pinnacle-agency.com'
|
|
551
|
+
media_buy_ids:
|
|
552
|
+
- 'mb_acme_q2_2026'
|
|
553
|
+
include_package_daily_breakdown: true
|
|
554
|
+
|
|
555
|
+
validations:
|
|
556
|
+
- check: response_schema
|
|
557
|
+
description: 'Response matches get-media-buy-delivery-response.json schema'
|
|
558
|
+
- check: field_present
|
|
559
|
+
path: 'media_buy_deliveries'
|
|
560
|
+
description: 'Response contains media buy delivery data'
|