@adcp/sdk 8.1.0-beta.7 → 8.1.0-beta.8

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.
Files changed (56) hide show
  1. package/README.md +12 -0
  2. package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
  3. package/dist/lib/types/activate-signal.d.ts +647 -0
  4. package/dist/lib/types/build-creative.d.ts +2105 -0
  5. package/dist/lib/types/calibrate-content.d.ts +675 -0
  6. package/dist/lib/types/check-governance.d.ts +619 -0
  7. package/dist/lib/types/comply-test-controller.d.ts +8428 -0
  8. package/dist/lib/types/create-collection-list.d.ts +693 -0
  9. package/dist/lib/types/create-content-standards.d.ts +830 -0
  10. package/dist/lib/types/create-media-buy.d.ts +3374 -0
  11. package/dist/lib/types/create-property-list.d.ts +836 -0
  12. package/dist/lib/types/delete-collection-list.d.ts +497 -0
  13. package/dist/lib/types/delete-property-list.d.ts +497 -0
  14. package/dist/lib/types/get-account-financials.d.ts +624 -0
  15. package/dist/lib/types/get-adcp-capabilities.d.ts +2863 -0
  16. package/dist/lib/types/get-collection-list.d.ts +763 -0
  17. package/dist/lib/types/get-content-standards.d.ts +919 -0
  18. package/dist/lib/types/get-creative-delivery.d.ts +2219 -0
  19. package/dist/lib/types/get-creative-features.d.ts +1736 -0
  20. package/dist/lib/types/get-media-buy-artifacts.d.ts +864 -0
  21. package/dist/lib/types/get-media-buys.d.ts +1670 -0
  22. package/dist/lib/types/get-plan-audit-logs.d.ts +455 -0
  23. package/dist/lib/types/get-products.d.ts +4935 -0
  24. package/dist/lib/types/get-property-list.d.ts +874 -0
  25. package/dist/lib/types/get-signals.d.ts +986 -0
  26. package/dist/lib/types/list-accounts.d.ts +851 -0
  27. package/dist/lib/types/list-content-standards.d.ts +975 -0
  28. package/dist/lib/types/list-creative-formats.d.ts +3132 -0
  29. package/dist/lib/types/list-creatives.d.ts +2390 -0
  30. package/dist/lib/types/list-property-lists.d.ts +855 -0
  31. package/dist/lib/types/log-event.d.ts +373 -0
  32. package/dist/lib/types/per-tool-index.json +391 -0
  33. package/dist/lib/types/preview-creative.d.ts +1981 -0
  34. package/dist/lib/types/provide-performance-feedback.d.ts +218 -0
  35. package/dist/lib/types/report-plan-outcome.d.ts +433 -0
  36. package/dist/lib/types/report-usage.d.ts +579 -0
  37. package/dist/lib/types/si-get-offering.d.ts +259 -0
  38. package/dist/lib/types/si-initiate-session.d.ts +372 -0
  39. package/dist/lib/types/si-send-message.d.ts +300 -0
  40. package/dist/lib/types/si-terminate-session.d.ts +213 -0
  41. package/dist/lib/types/sync-accounts.d.ts +856 -0
  42. package/dist/lib/types/sync-audiences.d.ts +707 -0
  43. package/dist/lib/types/sync-catalogs.d.ts +766 -0
  44. package/dist/lib/types/sync-creatives.d.ts +2134 -0
  45. package/dist/lib/types/sync-event-sources.d.ts +665 -0
  46. package/dist/lib/types/sync-governance.d.ts +558 -0
  47. package/dist/lib/types/sync-plans.d.ts +979 -0
  48. package/dist/lib/types/update-collection-list.d.ts +697 -0
  49. package/dist/lib/types/update-content-standards.d.ts +847 -0
  50. package/dist/lib/types/update-media-buy.d.ts +3047 -0
  51. package/dist/lib/types/update-property-list.d.ts +840 -0
  52. package/dist/lib/types/validate-content-delivery.d.ts +722 -0
  53. package/dist/lib/types/validate-input.d.ts +1683 -0
  54. package/dist/lib/version.d.ts +3 -3
  55. package/dist/lib/version.js +3 -3
  56. package/package.json +9 -2
@@ -0,0 +1,1670 @@
1
+ // AUTO-GENERATED — DO NOT EDIT.
2
+ // Per-tool .d.ts slice for `get_media_buys`. Built from the published
3
+ // `tools.generated.d.ts` + `core.generated.d.ts` + `enums.generated.d.ts`
4
+ // by `scripts/generate-per-tool-types.ts`.
5
+ //
6
+ // Self-contained: imports nothing from the broader SDK. Adopters who
7
+ // import only this slice pay a fraction of the tsc cost of pulling in
8
+ // `@adcp/sdk` root — useful when strict + skipLibCheck:false adopters
9
+ // hit memory pressure on the full surface.
10
+
11
+ /**
12
+ * Request parameters for retrieving media buy status, creative approval state, and optional delivery snapshots
13
+ */
14
+ export interface GetMediaBuysRequest {
15
+ /**
16
+ * Release-precision AdCP version (VERSION.RELEASE, e.g. "3.0", "3.1", "3.1-beta"). On a request: the buyer's release pin — the seller validates against its supported_versions and returns VERSION_UNSUPPORTED on cross-major mismatch, or downshifts to the highest supported release within the same major. On a response: the release the seller actually served — clients SHOULD validate the response against that release's schema, not against their pin. Patches are not negotiated; surface them as build_version on capabilities for operational visibility. When omitted, falls back to adcp_major_version (deprecated) or server default. Buyers SHOULD emit both adcp_version and adcp_major_version through 3.x to remain compatible with sellers that only read the legacy field. NORMALIZATION: SDKs that read full-semver values from bundle metadata (e.g. ComplianceIndex.published_version = "3.1.0-beta.1") MUST normalize to release-precision ("3.1-beta.1") before emitting on the wire — meta-field values are NOT valid wire values.
17
+ */
18
+ adcp_version?: string;
19
+ /**
20
+ * DEPRECATED in favor of adcp_version (release-precision string). Servers MUST continue to honor this field through 3.x. Removed in 4.0. Original semantics: the AdCP major version the buyer's payloads conform to. Sellers validate against their supported major_versions and return VERSION_UNSUPPORTED if unsupported. When omitted, the seller assumes its highest supported version.
21
+ */
22
+ adcp_major_version?: number;
23
+ account?: AccountReference;
24
+ /**
25
+ * Array of media buy IDs to retrieve. When omitted, returns a paginated set of accessible media buys matching status_filter.
26
+ */
27
+ media_buy_ids?: string[];
28
+ /**
29
+ * Filter by status. Can be a single status or array of statuses. Defaults to ["active"] when media_buy_ids is omitted. When media_buy_ids is provided, no implicit status filter is applied.
30
+ */
31
+ status_filter?: MediaBuyStatus | MediaBuyStatus[];
32
+ /**
33
+ * When true, include a near-real-time delivery snapshot for each package. Snapshots reflect the latest available entity-level stats from the platform (e.g., updated every ~15 minutes on GAM, ~1 hour on batch-only platforms). The staleness_seconds field on each snapshot indicates data freshness. If a snapshot cannot be returned, package.snapshot_unavailable_reason explains why. Defaults to false.
34
+ */
35
+ include_snapshot?: boolean;
36
+ /**
37
+ * When present, include the last N revision history entries for each media buy (returns min(N, available entries)). Each entry contains revision number, timestamp, actor, and a summary of what changed. Omit or set to 0 to exclude history (default). Recommended: 5-10 for monitoring, 50+ for audit.
38
+ * @minimum 0
39
+ * @maximum 1000
40
+ */
41
+ include_history?: number;
42
+ /**
43
+ * When true, each returned media buy includes a `webhook_activity` array describing recent delivery-report webhook fires for the calling principal. Used by buyer agents to verify whether a publisher actually fired against the buyer's registered endpoint and what the endpoint returned — closes the operator-ticket loop for webhook debugging. Scoped to the calling principal: a buyer sees only fires targeting its own endpoint, even when multiple principals share visibility into the same media buy. Defaults to false. See `webhook_activity_limit` for the per-buy cap.
44
+ */
45
+ include_webhook_activity?: boolean;
46
+ /**
47
+ * Maximum number of webhook delivery records to return per media buy, ordered most-recent first. Ignored when `include_webhook_activity` is false. Sellers that surface webhook activity MUST retain records for at least 30 days from each record's `completed_at` (see `webhook_activity` description in the response schema for the `pending`-status carve-out); sellers unable to honor that floor MUST omit the field entirely rather than truncate. When a buy has more historical fires than the limit, only the most recent are returned — there is no cursor for older fires; this surface is a debug aid, not a full audit log.
48
+ * @minimum 1
49
+ * @maximum 200
50
+ */
51
+ webhook_activity_limit?: number;
52
+ pagination?: PaginationRequest;
53
+ context?: ContextObject;
54
+ ext?: ExtensionObject;
55
+ }
56
+
57
+ /**
58
+ * Response payload for get_media_buys task. Returns media buy configuration, creative approval state, and optional delivery snapshots.
59
+ */
60
+ export interface GetMediaBuysResponse {
61
+ /**
62
+ * Session/conversation identifier for tracking related operations across multiple task invocations. Managed by the protocol layer to maintain conversational context. Distinct from `context` (per-request opaque echo, see below).
63
+ */
64
+ context_id?: string;
65
+ context?: ContextObject;
66
+ /**
67
+ * Unique identifier for tracking asynchronous operations. Present when a task requires extended processing time. Used to query task status and retrieve results when complete.
68
+ */
69
+ task_id?: string;
70
+ status: TaskStatus;
71
+ /**
72
+ * 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.
73
+ */
74
+ message?: string;
75
+ /**
76
+ * ISO 8601 timestamp when the response was generated. Useful for debugging, logging, cache validation, and tracking async operation progress.
77
+ */
78
+ timestamp?: string;
79
+ /**
80
+ * Set to true when this response was returned from the idempotency cache rather than from a fresh execution. Set to false (or omitted) when the request was executed fresh. Buyers use this to distinguish cached replays from new executions — matters for billing reconciliation, audit logs, state-machine routing (cached state-tracking fields are historical snapshots, not current state — re-read via the resource's read endpoint), and any downstream system that assumes exactly-once event semantics. From 3.1 onward, `replayed` MAY appear on responses to any request that resolved via the idempotency cache, including read tools — universal `idempotency_key` (see security.mdx §Idempotency) means the cache holds read responses too.
81
+ */
82
+ replayed?: boolean;
83
+ adcp_error?: Error;
84
+ push_notification_config?: PushNotificationConfig;
85
+ /**
86
+ * Governance context token issued by the account's governance agent during check_governance. Buyers attach it to governed purchase requests (media buys, rights acquisitions, signal activations, creative services); sellers persist it and include it on all subsequent governance calls for that action's lifecycle. An account binds to one governance agent (see sync_governance); governance is phased across `purchase` / `modification` / `delivery`, not partitioned across specialist agents, so the envelope carries a single token for the full lifecycle.
87
+ *
88
+ * Value format: governance agents MUST emit a compact JWS per the AdCP JWS profile (see Security — Signed Governance Context). Sellers MAY verify; sellers that do not verify MUST persist and forward the token unchanged. In 3.1 all sellers MUST verify. Non-JWS values from pre-3.0 governance agents are deprecated.
89
+ *
90
+ * This is the primary correlation key for audit and reporting across the governance lifecycle.
91
+ */
92
+ governance_context?: string;
93
+ /**
94
+ * Conceptual grouping for the task-specific response data defined by individual task response schemas (e.g., get-products-response.json, create-media-buy-response.json). `payload` is a documentary construct — it is NOT a required wire field, and its on-the-wire shape depends on transport (see Transport serialization below). Task response schemas declare body fields without wrapping them in a `payload` object; the wire representation places those body fields per transport convention. On MCP the body fields appear as siblings of envelope fields at the root of the tool response; on A2A they appear inside `task.artifacts[0].parts[].DataPart`; on REST they appear at the root of the JSON body.
95
+ */
96
+ payload?: {};
97
+ /**
98
+ * Release-precision AdCP version (VERSION.RELEASE, e.g. "3.0", "3.1", "3.1-beta"). On a request: the buyer's release pin — the seller validates against its supported_versions and returns VERSION_UNSUPPORTED on cross-major mismatch, or downshifts to the highest supported release within the same major. On a response: the release the seller actually served — clients SHOULD validate the response against that release's schema, not against their pin. Patches are not negotiated; surface them as build_version on capabilities for operational visibility. When omitted, falls back to adcp_major_version (deprecated) or server default. Buyers SHOULD emit both adcp_version and adcp_major_version through 3.x to remain compatible with sellers that only read the legacy field. NORMALIZATION: SDKs that read full-semver values from bundle metadata (e.g. ComplianceIndex.published_version = "3.1.0-beta.1") MUST normalize to release-precision ("3.1-beta.1") before emitting on the wire — meta-field values are NOT valid wire values.
99
+ */
100
+ adcp_version?: string;
101
+ /**
102
+ * DEPRECATED in favor of adcp_version (release-precision string). Servers MUST continue to honor this field through 3.x. Removed in 4.0. Original semantics: the AdCP major version the buyer's payloads conform to. Sellers validate against their supported major_versions and return VERSION_UNSUPPORTED if unsupported. When omitted, the seller assumes its highest supported version.
103
+ */
104
+ adcp_major_version?: number;
105
+ /**
106
+ * Array of media buys with status, creative approval state, and optional delivery snapshots
107
+ */
108
+ media_buys: {
109
+ /**
110
+ * Seller's unique identifier for the media buy
111
+ */
112
+ media_buy_id: string;
113
+ account?: Account;
114
+ invoice_recipient?: BusinessEntity;
115
+ status: MediaBuyStatus;
116
+ /**
117
+ * Dependency health of the media buy, orthogonal to `status`. `ok` (default) when no upstream resource that this buy depends on is in an offline state. `impaired` when at least one such resource (audience, creative, catalog_item, event_source, property) is offline and affects delivery for one or more packages — `impairments[]` MUST be non-empty in that case. On terminal-status buys, the seller MAY leave this field in whatever state held at the terminal transition. See lifecycle.mdx § Compliance and the impairment.coherence assertion.
118
+ */
119
+ health?: MediaBuyHealth & string;
120
+ /**
121
+ * Open impairments — upstream dependency state changes that affect delivery for at least one package on this buy. Empty when `health` is `ok`; non-empty iff `health` is `impaired` (health-iff rule on non-terminal buys). Sellers MUST add an entry on the next read after a referenced resource transitions to an offline state, and MUST remove the entry when the resource returns to a serviceable state or stops being a dependency (e.g., via assignment swap via update_media_buy). Staleness budget: the snapshot MUST reflect the impairment within 5 minutes of `impairment.observed_at` regardless of buyer poll cadence — sellers cannot rely on rare buyer polls to defer write propagation. See impairment.coherence assertion for the cross-resource invariant.
122
+ */
123
+ impairments?: Impairment[];
124
+ /**
125
+ * Reason provided by the seller when status is 'rejected'. Present only when status is 'rejected'.
126
+ */
127
+ rejection_reason?: string;
128
+ /**
129
+ * ISO 4217 currency code (e.g., USD, EUR, GBP) for monetary values at this media buy level. total_budget is always denominated in this currency. Package-level fields may override with package.currency.
130
+ * @pattern ^[A-Z]{3}$
131
+ */
132
+ currency: string;
133
+ /**
134
+ * Total budget amount across all packages, denominated in media_buy.currency
135
+ * @minimum 0
136
+ */
137
+ total_budget?: number;
138
+ /**
139
+ * ISO 8601 flight start time for this media buy (earliest package start_time). Avoids requiring buyers to compute min(packages[].start_time).
140
+ * @format date-time
141
+ */
142
+ start_time?: string;
143
+ /**
144
+ * ISO 8601 flight end time for this media buy (latest package end_time). Avoids requiring buyers to compute max(packages[].end_time).
145
+ * @format date-time
146
+ */
147
+ end_time?: string;
148
+ /**
149
+ * ISO 8601 timestamp for creative upload deadline
150
+ * @format date-time
151
+ */
152
+ creative_deadline?: string;
153
+ /**
154
+ * ISO 8601 timestamp when the seller confirmed this media buy. A successful create_media_buy response constitutes order confirmation.
155
+ * @format date-time
156
+ */
157
+ confirmed_at?: string;
158
+ /**
159
+ * Cancellation metadata. Present only when status is 'canceled'.
160
+ */
161
+ cancellation?: {
162
+ /**
163
+ * ISO 8601 timestamp when this media buy was canceled.
164
+ * @format date-time
165
+ */
166
+ canceled_at: string;
167
+ canceled_by: CanceledBy;
168
+ /**
169
+ * Reason the media buy was canceled.
170
+ * @maxLength 500
171
+ */
172
+ reason?: string;
173
+ };
174
+ /**
175
+ * Current revision number. Pass this in update_media_buy for optimistic concurrency.
176
+ * @minimum 1
177
+ */
178
+ revision?: number;
179
+ /**
180
+ * Creation timestamp
181
+ * @format date-time
182
+ */
183
+ created_at?: string;
184
+ /**
185
+ * Last update timestamp
186
+ * @format date-time
187
+ */
188
+ updated_at?: string;
189
+ /**
190
+ * Flat-vocabulary actions the buyer can perform on this media buy in its current state. Eliminates the need for agents to internalize the state machine — the seller declares what is permitted right now. Deprecated in favor of `available_actions[]`, which carries `mode` (self_serve / conditional_self_serve / requires_proposal / requires_approval), optional SLA, and optional `terms_ref`. Sellers SHOULD populate both during the 3.x deprecation window; consumers MUST prefer `available_actions[]` when both are present. Removed in 4.0.
191
+ */
192
+ valid_actions?: MediaBuyValidAction[];
193
+ /**
194
+ * Structured per-buy resolution of the actions buyer can perform right now. Authoritative — divergence from product `allowed_actions[]` is expected (negotiated terms, account tier, buy-level overrides live on the deal, not the product). Each entry carries the resolved `mode` (singular, since the buy has a concrete state), optional `sla` commitment, and optional `terms_ref`. Predicate queries via #4425's `requires` grammar address fields by dotted path, e.g. `available_actions.extend_flight.sla.response_max`. Absent SLA means no commitment, not zero commitment — callers composing duration predicates MUST also compose with `present: true` to avoid silently matching sellers who never declared one.
195
+ */
196
+ available_actions?: MediaBuyAvailableAction[];
197
+ /**
198
+ * Recent reporting and health webhook fires for the calling principal, most-recent first. Present only when `include_webhook_activity` was true in the request AND the seller surfaces this debug capability for this buy. Three-state semantics: (a) field omitted — seller does not surface webhook activity (either does not persist fire history, or `capabilities.media_buy.propagation_surfaces` excludes webhook surfaces, or the buy has no registered `push_notification_config` for this principal); (b) empty array `[]` — seller persists fire history but has fired nothing recent for this principal; (c) non-empty array — actual fire records. Sellers whose declared `propagation_surfaces` does not include `webhook` MUST omit the field. **Retention (normative):** sellers that surface this field MUST retain records for at least 30 days from each record's `completed_at` (for records still in `pending` status the clock runs from `fired_at` until the attempt terminates, then resets to 30 days from `completed_at` — so retry trails do not age out mid-flight). Sellers that cannot honor the 30-day floor MUST omit the field entirely rather than return a shorter window. Sellers MAY return fewer than `webhook_activity_limit` records when fewer fire records exist within the retention window. Sellers MUST emit one record per attempt — single-attempt successes appear as a single record with `attempt: 1`. Record shape is canonical across resources: see [`/schemas/core/webhook-activity-record.json`](/schemas/v3/core/webhook-activity-record.json) and snapshot-and-log.mdx § Webhook activity log pattern.
199
+ */
200
+ webhook_activity?: WebhookActivityRecord[];
201
+ /**
202
+ * Revision history entries, most recent first. Only present when include_history > 0 in the request. Each entry represents a state change or update to the media buy. Entries are append-only: sellers MUST NOT modify or delete previously emitted history entries. Callers MAY cache entries by revision number. Returns min(N, available entries) when include_history exceeds the total.
203
+ */
204
+ history?: {
205
+ /**
206
+ * Revision number after this change was applied.
207
+ * @minimum 1
208
+ */
209
+ revision: number;
210
+ /**
211
+ * When this change occurred.
212
+ * @format date-time
213
+ */
214
+ timestamp: string;
215
+ /**
216
+ * Identity of who made the change — derived from authentication context, not caller-provided. Format is seller-defined (e.g., agent URL, user email, API key label).
217
+ */
218
+ actor?: string;
219
+ /**
220
+ * What happened. Standard actions: created, activated, paused, resumed, canceled, rejected, completed, updated_budget, updated_dates, updated_packages, package_canceled, package_paused, package_resumed. Sellers MAY use additional platform-specific actions (e.g., creative_approved, targeting_updated) — use ext on the history entry for structured metadata about custom actions.
221
+ */
222
+ action: string;
223
+ /**
224
+ * Human-readable summary of the change (e.g., 'Budget increased from $5,000 to $7,500 on pkg_abc').
225
+ * @maxLength 500
226
+ */
227
+ summary?: string;
228
+ /**
229
+ * Package affected, when the change targeted a specific package.
230
+ */
231
+ package_id?: string;
232
+ ext?: ExtensionObject;
233
+ }[];
234
+ /**
235
+ * Packages within this media buy, augmented with creative approval status and optional delivery snapshots
236
+ */
237
+ packages: PackageStatus[];
238
+ ext?: ExtensionObject;
239
+ }[];
240
+ /**
241
+ * Task-specific errors (e.g., media buy not found)
242
+ */
243
+ errors?: Error[];
244
+ pagination?: PaginationResponse;
245
+ /**
246
+ * When true, this response contains simulated data from sandbox mode.
247
+ */
248
+ sandbox?: boolean;
249
+ ext?: ExtensionObject;
250
+ }
251
+
252
+ /**
253
+ * Account billed for this media buy. Includes advertiser, billing proxy (if any), and rate card applied.
254
+ */
255
+ export interface Account {
256
+ /**
257
+ * Unique identifier for this account
258
+ */
259
+ account_id: string;
260
+ /**
261
+ * Human-readable account name (e.g., 'Acme', 'Acme c/o Pinnacle')
262
+ */
263
+ name: string;
264
+ /**
265
+ * The advertiser whose rates apply to this account
266
+ */
267
+ advertiser?: string;
268
+ /**
269
+ * Optional intermediary who receives invoices on behalf of the advertiser (e.g., agency)
270
+ */
271
+ billing_proxy?: string;
272
+ status: AccountStatus;
273
+ brand?: BrandReference;
274
+ /**
275
+ * Domain of the entity operating this account. When the brand operates directly, this is the brand's domain.
276
+ * @pattern ^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$
277
+ */
278
+ operator?: string;
279
+ billing?: BillingParty;
280
+ billing_entity?: BusinessEntity;
281
+ /**
282
+ * Identifier for the rate card applied to this account
283
+ */
284
+ rate_card?: string;
285
+ payment_terms?: PaymentTerms;
286
+ /**
287
+ * Maximum outstanding balance allowed
288
+ */
289
+ credit_limit?: {
290
+ /**
291
+ * @minimum 0
292
+ */
293
+ amount: number;
294
+ /**
295
+ * @pattern ^[A-Z]{3}$
296
+ */
297
+ currency: string;
298
+ };
299
+ /**
300
+ * Present when status is 'pending_approval'. Contains next steps for completing account activation.
301
+ */
302
+ setup?: {
303
+ /**
304
+ * URL where the human can complete the required action (credit application, legal agreement, add funds).
305
+ */
306
+ url?: string;
307
+ /**
308
+ * Human-readable description of what's needed.
309
+ */
310
+ message: string;
311
+ /**
312
+ * When this setup link expires.
313
+ * @format date-time
314
+ */
315
+ expires_at?: string;
316
+ };
317
+ account_scope?: AccountScope;
318
+ /**
319
+ * Governance agent endpoint registered on this account. Exactly one entry per sync_governance's one-agent-per-account invariant. The array shape is preserved for wire compatibility with 3.0; `maxItems: 1` is load-bearing and mirrors the singular `governance_context` on the protocol envelope. Authentication credentials are write-only and not included in responses — use sync_governance to set or update credentials.
320
+ */
321
+ governance_agents?: {
322
+ /**
323
+ * Governance agent endpoint URL. Must use HTTPS.
324
+ * @pattern ^https:\/\/
325
+ */
326
+ url: string;
327
+ }[];
328
+ /**
329
+ * Cloud storage bucket where the seller delivers offline reporting files for this account. Seller provisions a dedicated bucket or a per-account prefix within a shared bucket, and grants the buyer read access out-of-band. Access MUST be scoped at the IAM layer so each account can only read its own prefix — bucket-wide grants are non-compliant even with per-account prefixes. Seller MUST revoke access when the account's status transitions to inactive, suspended, or closed. See security considerations for offline delivery in docs/media-buy/media-buys/optimization-reporting. Only present when the seller supports offline delivery (reporting_delivery_methods includes 'offline' in capabilities).
330
+ */
331
+ reporting_bucket?: {
332
+ protocol: CloudStorageProtocol;
333
+ /**
334
+ * Bucket or container name
335
+ * @minLength 3
336
+ * @maxLength 63
337
+ * @pattern ^[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]$
338
+ */
339
+ bucket: string;
340
+ /**
341
+ * Path prefix within the bucket. Seller appends date-based partitioning beneath this prefix.
342
+ * @maxLength 512
343
+ * @pattern ^[a-zA-Z0-9\/_.-]+$
344
+ */
345
+ prefix?: string;
346
+ /**
347
+ * Cloud region for the bucket
348
+ * @maxLength 64
349
+ * @pattern ^[a-z0-9-]+$
350
+ */
351
+ region?: string;
352
+ /**
353
+ * File format for delivered files. Parquet, Avro, and ORC use internal compression (the top-level compression field is ignored for these formats).
354
+ */
355
+ format?: 'jsonl' | 'csv' | 'parquet' | 'avro' | 'orc';
356
+ /**
357
+ * Compression applied to delivered files
358
+ */
359
+ compression?: 'gzip' | 'none';
360
+ /**
361
+ * How long reporting files are retained in the bucket before deletion. Buyers must read files within this window. Minimum recommended: 14 days.
362
+ * @minimum 1
363
+ */
364
+ file_retention_days: number;
365
+ /**
366
+ * URL to documentation for configuring buyer read access to this bucket (IAM role, service account, etc.). Operator-facing documentation — buyer agents MUST NOT auto-fetch this URL; surface it to a human operator. If an implementation fetches it (for preview), apply webhook URL SSRF validation and do not pass the fetched content into an LLM context without indirect-prompt-injection guarding. See docs/media-buy/media-buys/optimization-reporting#security-considerations-for-offline-delivery.
367
+ * @pattern ^https:\/\/
368
+ */
369
+ setup_instructions?: string;
370
+ };
371
+ /**
372
+ * When true, this is a sandbox account — no real platform calls, no real spend. For explicit accounts (require_operator_auth: true), sandbox accounts are pre-existing test accounts on the platform discovered via list_accounts. For implicit accounts, sandbox is part of the natural key: the same brand/operator pair can have both a production and sandbox account.
373
+ */
374
+ sandbox?: boolean;
375
+ /**
376
+ * Account-level webhook subscriptions for notifications whose lifecycle outlives any single media buy (e.g., `creative.status_changed`, `creative.purged`, wholesale feed change payloads). Distinct from `push_notification_config` on individual operations, which anchors at a per-resource scope. Buyers register and update entries via `sync_accounts`; sellers echo the applied state here on `list_accounts` reads so buyers can verify what's active. `authentication.credentials` is write-only — sellers MUST NOT echo legacy auth credentials in this response. When two or more entries register the same `event_types`, each receives an independent fire — see #3009 multi-subscriber composition.
377
+ */
378
+ notification_configs?: NotificationConfig[];
379
+ ext?: ExtensionObject;
380
+ }
381
+
382
+ /**
383
+ * Account for product lookup. Returns products with pricing specific to this account's rate card.
384
+ */
385
+ export type AccountReference = {
386
+ /**
387
+ * Seller-assigned account identifier (from sync_accounts or list_accounts)
388
+ */
389
+ account_id: string;
390
+ } | {
391
+ brand: BrandReference;
392
+ /**
393
+ * Domain of the entity operating on the brand's behalf. When the brand operates directly, this is the brand's domain.
394
+ * @pattern ^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$
395
+ */
396
+ operator: string;
397
+ /**
398
+ * When true, references the sandbox account for this brand/operator pair. Defaults to false (production account).
399
+ */
400
+ sandbox?: boolean;
401
+ };
402
+
403
+ /**
404
+ * How the seller scoped a billing account relative to the operator and brand dimensions.
405
+ */
406
+ export type AccountScope = 'operator' | 'brand' | 'operator_brand' | 'agent';
407
+
408
+ /**
409
+ * Account lifecycle status. See the Accounts Protocol overview for the operations matrix showing which tasks are permitted in each state.
410
+ */
411
+ export type AccountStatus = 'active' | 'pending_approval' | 'rejected' | 'payment_required' | 'suspended' | 'closed';
412
+
413
+ /**
414
+ * Methods for verifying user age for compliance. Does not include 'inferred' as it is not accepted for regulatory compliance.
415
+ */
416
+ export type AgeVerificationMethod = 'facial_age_estimation' | 'id_document' | 'digital_id' | 'credit_card' | 'world_id';
417
+
418
+ /**
419
+ * Legacy authentication schemes for the webhook auth block. Bearer: token sent in Authorization header. HMAC-SHA256: legacy shared-secret signing. Both are deprecated; new integrations SHOULD omit the authentication block and use the RFC 9421 webhook signing profile (applicable on schemas where authentication is optional). Removed in AdCP 4.0.
420
+ */
421
+ export type AuthenticationScheme = 'Bearer' | 'HMAC-SHA256';
422
+
423
+ /**
424
+ * Who is invoiced on this account. See billing_entity for the invoiced party's business details.
425
+ */
426
+ export type BillingParty = 'operator' | 'agent' | 'advertiser';
427
+
428
+ /**
429
+ * Brand identifier within the house portfolio. Optional for single-brand domains.
430
+ */
431
+ export type BrandID = string;
432
+
433
+ /**
434
+ * Brand reference for product discovery context. Resolved to full brand identity at execution time.
435
+ */
436
+ export interface BrandReference {
437
+ /**
438
+ * Domain where /.well-known/brand.json is hosted, or the brand's operating domain
439
+ * @pattern ^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$
440
+ */
441
+ domain: string;
442
+ brand_id?: BrandID;
443
+ /**
444
+ * Inline override for the brand's industries. Useful when the caller cannot modify the brand's canonical brand.json but needs to declare industries for governance (e.g., Annex III vertical detection). brand.json remains the canonical source; when omitted here, governance agents SHOULD resolve from brand.json.
445
+ */
446
+ industries?: string[];
447
+ /**
448
+ * Inline override for the brand's contestation contact point. Useful when the operator does not control brand.json but needs to discharge Art 22(3) for this plan. brand.json is canonical; when omitted, governance agents resolve brand → house → missing.
449
+ */
450
+ data_subject_contestation?: {
451
+ [k: string]: unknown | undefined;
452
+ };
453
+ /**
454
+ * Inline override for brand-kit fields normally resolved from `/.well-known/brand.json` on `domain` (logo, colors, voice, tagline). Use when brand.json is missing, stale, or inappropriate for this specific call — e.g., a campaign-scoped tagline, a co-branded creative, a freshly-rebranded color palette the brand.json hasn't shipped yet. Same inline-override pattern as `industries` and `data_subject_contestation` above: brand.json is canonical, the override is per-call. Adopters needing to override fields outside this subset (`voice_attributes`, `prohibited_terms`, etc.) MUST publish a different brand.json and reference it via a different `domain` — the inline override is intentionally narrow to a small high-traffic subset.
455
+ *
456
+ * **Merge semantics (normative).** The merge is **field-level**, not whole-object replacement. Each field within `brand_kit_override` (`logo`, `colors`, `voice`, `tagline`) is evaluated independently — when a field is present on the override the override value applies; when a field is absent the brand.json value applies (or is absent if brand.json doesn't carry one either). For composite fields (`colors.primary`, `colors.secondary`, `colors.accent`), the merge is one level deeper: each color slot is evaluated independently — a producer can override `colors.primary` while still inheriting `colors.secondary` from brand.json. SDKs MUST NOT treat a present `brand_kit_override.colors` as wiping the brand.json `colors` block entirely; only the per-slot fields present in the override take precedence. Without this rule, a partial-override semantics would diverge across SDKs and produce inconsistent rendering for the same payload.
457
+ */
458
+ brand_kit_override?: {
459
+ logo?: ImageAsset;
460
+ /**
461
+ * Override brand colors (hex strings).
462
+ */
463
+ colors?: {
464
+ /**
465
+ * @pattern ^#[0-9a-fA-F]{6}$
466
+ */
467
+ primary?: string;
468
+ /**
469
+ * @pattern ^#[0-9a-fA-F]{6}$
470
+ */
471
+ secondary?: string;
472
+ /**
473
+ * @pattern ^#[0-9a-fA-F]{6}$
474
+ */
475
+ accent?: string;
476
+ };
477
+ /**
478
+ * Override brand-voice description for surface-composed text/audio output.
479
+ */
480
+ voice?: string;
481
+ /**
482
+ * Override tagline.
483
+ */
484
+ tagline?: string;
485
+ };
486
+ }
487
+
488
+ /**
489
+ * Override the account's default billing entity for this specific buy. When provided, the seller invoices this entity instead. The seller MUST validate the invoice recipient is authorized for this account. When governance_agents are configured, the seller MUST include invoice_recipient in the check_governance request.
490
+ */
491
+ export interface BusinessEntity {
492
+ /**
493
+ * Registered legal name of the business entity
494
+ * @maxLength 200
495
+ */
496
+ legal_name: string;
497
+ /**
498
+ * VAT identification number (e.g., DE123456789 for Germany, FR12345678901 for France). Required for B2B invoicing in the EU. Must be normalized: no spaces, dots, or dashes.
499
+ * @pattern ^[A-Z]{2}[A-Z0-9]{2,13}$
500
+ */
501
+ vat_id?: string;
502
+ /**
503
+ * Tax identification number for jurisdictions that do not use VAT (e.g., US EIN)
504
+ * @maxLength 30
505
+ */
506
+ tax_id?: string;
507
+ /**
508
+ * Company registration number (e.g., HRB 12345 for German Handelsregister)
509
+ * @maxLength 50
510
+ */
511
+ registration_number?: string;
512
+ /**
513
+ * Postal address for invoicing and legal correspondence
514
+ */
515
+ address?: {
516
+ /**
517
+ * Street address including building number
518
+ * @maxLength 200
519
+ */
520
+ street: string;
521
+ /**
522
+ * @maxLength 100
523
+ */
524
+ city: string;
525
+ /**
526
+ * @maxLength 20
527
+ */
528
+ postal_code: string;
529
+ /**
530
+ * State, province, or region
531
+ * @maxLength 100
532
+ */
533
+ region?: string;
534
+ /**
535
+ * ISO 3166-1 alpha-2 country code
536
+ * @pattern ^[A-Z]{2}$
537
+ */
538
+ country: string;
539
+ };
540
+ /**
541
+ * Contacts for billing, legal, and operational matters. Contains personal data subject to GDPR and equivalent regulations. Implementations MUST use this data only for invoicing and account management.
542
+ */
543
+ contacts?: {
544
+ /**
545
+ * Contact's functional role in the business relationship
546
+ */
547
+ role: 'billing' | 'legal' | 'creative' | 'general';
548
+ /**
549
+ * Full name of the contact
550
+ * @maxLength 200
551
+ */
552
+ name?: string;
553
+ /**
554
+ * @maxLength 254
555
+ * @format email
556
+ */
557
+ email?: string;
558
+ /**
559
+ * @maxLength 30
560
+ */
561
+ phone?: string;
562
+ }[];
563
+ /**
564
+ * Bank account details for payment processing. Write-only: included in requests to provide payment coordinates, but MUST NOT be echoed in responses. Sellers store these details and confirm receipt without returning them.
565
+ */
566
+ bank?: {
567
+ /**
568
+ * Name on the bank account
569
+ * @maxLength 200
570
+ */
571
+ account_holder: string;
572
+ /**
573
+ * International Bank Account Number (SEPA markets)
574
+ * @pattern ^[A-Z]{2}[0-9]{2}[A-Z0-9]{4,30}$
575
+ */
576
+ iban?: string;
577
+ /**
578
+ * Bank Identifier Code / SWIFT code (SEPA markets)
579
+ * @pattern ^[A-Z]{4}[A-Z]{2}[A-Z0-9]{2}([A-Z0-9]{3})?$
580
+ */
581
+ bic?: string;
582
+ /**
583
+ * Bank routing number for non-SEPA markets (e.g., US ABA routing number, Canadian transit/institution number)
584
+ * @maxLength 30
585
+ */
586
+ routing_number?: string;
587
+ /**
588
+ * Bank account number for non-SEPA markets
589
+ * @maxLength 30
590
+ */
591
+ account_number?: string;
592
+ };
593
+ ext?: ExtensionObject;
594
+ }
595
+
596
+ /**
597
+ * C2PA action classification for this watermark
598
+ */
599
+ export type C2PAWatermarkAction = 'c2pa.watermarked.bound' | 'c2pa.watermarked.unbound';
600
+
601
+ /**
602
+ * Which party initiated the package cancellation.
603
+ */
604
+ export type CanceledBy = 'buyer' | 'seller';
605
+
606
+ /**
607
+ * Cloud storage protocol
608
+ */
609
+ export type CloudStorageProtocol = 's3' | 'gcs' | 'azure_blob';
610
+
611
+ /**
612
+ * Reference to a collection list for including specific collections (programs, shows) within this product. The package runs on the intersection of matched collections and this list. Use for inclusion-based collection targeting. Seller must declare support in get_adcp_capabilities.
613
+ */
614
+ export interface CollectionListReference {
615
+ /**
616
+ * URL of the agent managing the collection list
617
+ */
618
+ agent_url: string;
619
+ /**
620
+ * Identifier for the collection list within the agent
621
+ * @minLength 1
622
+ */
623
+ list_id: string;
624
+ /**
625
+ * JWT or other authorization token for accessing the list. Optional if the list is public or caller has implicit access.
626
+ */
627
+ auth_token?: string;
628
+ }
629
+
630
+ /**
631
+ * Opaque correlation data that is echoed unchanged in responses. Used for internal tracking, UI session IDs, trace IDs, and other caller-specific identifiers that don't affect protocol behavior. Context data is never parsed by AdCP agents - it's simply preserved and returned.
632
+ */
633
+ export interface ContextObject {
634
+ }
635
+
636
+ /**
637
+ * Approval state of a creative on a specific package
638
+ */
639
+ export type CreativeApprovalStatus = 'pending_review' | 'approved' | 'rejected';
640
+
641
+ /**
642
+ * Days of the week for daypart targeting
643
+ */
644
+ export type DayOfWeek = 'monday' | 'tuesday' | 'wednesday' | 'thursday' | 'friday' | 'saturday' | 'sunday';
645
+
646
+ /**
647
+ * A time window for daypart targeting. Specifies days of week and an hour range. start_hour is inclusive, end_hour is exclusive (e.g., 6-10 = 6:00am to 10:00am). Follows the Google Ads AdScheduleInfo / DV360 DayPartTargeting pattern.
648
+ */
649
+ export interface DaypartTarget {
650
+ /**
651
+ * Days of week this window applies to. Use multiple days for compact targeting (e.g., monday-friday in one object).
652
+ */
653
+ days: DayOfWeek[];
654
+ /**
655
+ * Start hour (inclusive), 0-23 in 24-hour format. 0 = midnight, 6 = 6:00am, 18 = 6:00pm.
656
+ * @minimum 0
657
+ * @maximum 23
658
+ */
659
+ start_hour: number;
660
+ /**
661
+ * End hour (exclusive), 1-24 in 24-hour format. 10 = 10:00am, 24 = midnight. Must be greater than start_hour.
662
+ * @minimum 1
663
+ * @maximum 24
664
+ */
665
+ end_hour: number;
666
+ /**
667
+ * Optional human-readable name for this time window (e.g., 'Morning Drive', 'Prime Time')
668
+ */
669
+ label?: string;
670
+ }
671
+
672
+ /**
673
+ * Operating system platforms for device targeting. Browser values from Sec-CH-UA-Platform standard, extended for CTV.
674
+ */
675
+ export type DevicePlatform = 'ios' | 'android' | 'windows' | 'macos' | 'linux' | 'chromeos' | 'tvos' | 'tizen' | 'webos' | 'fire_os' | 'roku_os' | 'unknown';
676
+
677
+ /**
678
+ * Device form factor categories for targeting and reporting. Complements device-platform (operating system) with hardware classification. OpenRTB mapping: 1 (Mobile/Tablet General) → mobile, 2 (PC) → desktop, 4 (Phone) → mobile, 5 (Tablet) → tablet, 6 (Connected Device) → ctv, 7 (Set Top Box) → ctv. DOOH inventory uses dooh.
679
+ */
680
+ export type DeviceType = 'desktop' | 'mobile' | 'tablet' | 'ctv' | 'dooh' | 'unknown';
681
+
682
+ /**
683
+ * IPTC-aligned classification of AI involvement in producing this content
684
+ */
685
+ export type DigitalSourceType = 'digital_capture' | 'digital_creation' | 'trained_algorithmic_media' | 'composite_with_trained_algorithmic_media' | 'algorithmic_media' | 'composite_capture' | 'composite_synthetic' | 'human_edits' | 'data_driven_media';
686
+
687
+ /**
688
+ * How long the disclosure must persist during content playback or display
689
+ */
690
+ export type DisclosurePersistence = 'continuous' | 'initial' | 'flexible';
691
+
692
+ /**
693
+ * Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.
694
+ */
695
+ export type DisclosurePosition = 'prominent' | 'footer' | 'audio' | 'subtitle' | 'overlay' | 'end_card' | 'pre_roll' | 'companion';
696
+
697
+ /**
698
+ * A time duration expressed as an interval and unit. Used for frequency cap windows, attribution windows, reach optimization windows, time budgets, and other time-based settings. When unit is 'campaign', interval must be 1 — the window spans the full campaign flight.
699
+ */
700
+ export interface Duration {
701
+ /**
702
+ * Number of time units. Must be 1 when unit is 'campaign'.
703
+ * @minimum 1
704
+ */
705
+ interval: number;
706
+ /**
707
+ * Time unit. 'seconds' for sub-minute precision. 'campaign' spans the full campaign flight.
708
+ */
709
+ unit: 'seconds' | 'minutes' | 'hours' | 'days' | 'campaign';
710
+ }
711
+
712
+ /**
713
+ * How provenance data is carried within the content
714
+ */
715
+ export type EmbeddedProvenanceMethod = 'manifest_wrapper' | 'provenance_markers';
716
+
717
+ /**
718
+ * Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.
719
+ */
720
+ export interface ExtensionObject {
721
+ }
722
+
723
+ /**
724
+ * A JSON object — never a plain string — that identifies a creative format by its declaring agent and local slug. Required properties: agent_url (URI of the agent that owns the format) and id (slug matching [a-zA-Z0-9_-]+). Example: {"agent_url": "https://creative.adcontextprotocol.org", "id": "display_300x250"}. Can reference: (1) a concrete format with fixed dimensions (id only), (2) a template format without parameters (id only), or (3) a template format with parameters (id + dimensions/duration). Template formats accept parameters in format_id while concrete formats have fixed dimensions in their definition. Parameterized format IDs create unique, specific format variants. Using a plain string here is a schema violation.
725
+ */
726
+ export interface FormatReferenceStructuredObject {
727
+ /**
728
+ * URL of the agent that defines this format (e.g., 'https://creative.adcontextprotocol.org' for standard formats, or 'https://publisher.com/.well-known/adcp/sales' for custom formats). Callers comparing two `format-id` values MUST canonicalize `agent_url` per the AdCP URL canonicalization rules before treating two formats as the same. See docs/reference/url-canonicalization.
729
+ */
730
+ agent_url: string;
731
+ /**
732
+ * Format identifier within the agent's namespace (e.g., 'display_static', 'video_hosted', 'audio_standard'). When used alone, references a template format. When combined with dimension/duration fields, creates a parameterized format ID for a specific variant.
733
+ * @pattern ^[a-zA-Z0-9_-]+$
734
+ */
735
+ id: string;
736
+ /**
737
+ * Width in pixels for visual formats. When specified, height must also be specified. Both fields together create a parameterized format ID for dimension-specific variants.
738
+ * @minimum 1
739
+ */
740
+ width?: number;
741
+ /**
742
+ * Height in pixels for visual formats. When specified, width must also be specified. Both fields together create a parameterized format ID for dimension-specific variants.
743
+ * @minimum 1
744
+ */
745
+ height?: number;
746
+ /**
747
+ * Duration in milliseconds for time-based formats (video, audio). When specified, creates a parameterized format ID. Omit to reference a template format without parameters.
748
+ * @minimum 1
749
+ */
750
+ duration_ms?: number;
751
+ }
752
+
753
+ /**
754
+ * Frequency capping settings for package-level application. Two types of frequency control can be used independently or together: suppress enforces a cooldown between consecutive exposures; max_impressions + per + window caps total exposures per entity in a time window. When both suppress and max_impressions are set, an impression is delivered only if both constraints permit it (AND semantics). At least one of suppress, suppress_minutes, or max_impressions must be set.
755
+ */
756
+ export type FrequencyCap = {
757
+ [k: string]: unknown | undefined;
758
+ } & {
759
+ /**
760
+ * Cooldown period between consecutive exposures to the same entity. Prevents back-to-back ad delivery (e.g. {"interval": 60, "unit": "minutes"} for a 1-hour cooldown). Preferred over suppress_minutes.
761
+ */
762
+ suppress?: Duration;
763
+ /**
764
+ * Deprecated — use suppress instead. Cooldown period in minutes between consecutive exposures to the same entity (e.g. 60 for a 1-hour cooldown).
765
+ * @minimum 0
766
+ */
767
+ suppress_minutes?: number;
768
+ /**
769
+ * Maximum number of impressions per entity per window. For duration windows, implementations typically use a rolling window; 'campaign' applies a fixed cap across the full flight.
770
+ * @minimum 1
771
+ */
772
+ max_impressions?: number;
773
+ /**
774
+ * Entity granularity for impression counting. Required when max_impressions is set.
775
+ */
776
+ per?: ReachUnit;
777
+ /**
778
+ * Time window for the max_impressions cap (e.g. {"interval": 7, "unit": "days"} or {"interval": 1, "unit": "campaign"} for the full flight). Required when max_impressions is set.
779
+ */
780
+ window?: Duration;
781
+ };
782
+
783
+ /**
784
+ * Override logo asset.
785
+ */
786
+ export interface ImageAsset {
787
+ /**
788
+ * Discriminator identifying this as an image asset. See /schemas/creative/asset-types for the registry.
789
+ */
790
+ asset_type: 'image';
791
+ /**
792
+ * URL to the image asset
793
+ */
794
+ url: string;
795
+ /**
796
+ * Width in pixels
797
+ * @minimum 1
798
+ */
799
+ width: number;
800
+ /**
801
+ * Height in pixels
802
+ * @minimum 1
803
+ */
804
+ height: number;
805
+ /**
806
+ * Image file format (jpg, png, gif, webp, etc.)
807
+ */
808
+ format?: string;
809
+ /**
810
+ * Alternative text for accessibility
811
+ */
812
+ alt_text?: string;
813
+ provenance?: Provenance;
814
+ }
815
+
816
+ /**
817
+ * A single upstream dependency state change that affects delivery for one or more packages within a media buy. An impairment is open until the underlying resource returns to a serviceable state. Materiality: an impairment MUST list at least one package whose ability to serve is degraded; cosmetic-only effects (e.g., one rejected creative when peers remain serviceable in the same package) MUST NOT be reported as impairments. Sellers MAY report conservatively when uncertain (list a package when the materiality join is expensive to compute); sellers MUST NOT report when serving is provably unaffected. Materiality is required (MUST) for resource types where the resource→buy join is cheap and 1:N — audience, event_source, property; SHOULD-strength for creative and catalog_item, where the resource is shared across a larger pool and the join cost is higher.
818
+ */
819
+ export interface Impairment {
820
+ /**
821
+ * Stable identifier for this impairment, used as the notification_id when the impairment fires via webhook. Stable across re-emissions of the same open impairment (e.g., the seller re-fires after the buyer's receiver was down) and across the closing fire that signals resolution. A new impairment for the same resource_id after closure receives a new impairment_id. Distinct from the per-fire idempotency_key issued at the webhook transport layer — see snapshot-and-log Rule 1. Receivers correlate webhook fires to current impairments[] state by impairment_id; receivers suppress duplicate transport-layer retries by idempotency_key. Seeing the same impairment_id with different idempotency_keys is a re-emission signal, not a retry — the buyer should treat it as a notice that something may have been missed.
822
+ */
823
+ impairment_id: string;
824
+ /**
825
+ * The kind of upstream dependency that transitioned to an offline state. Values are drawn from the x-entity vocabulary (see core/x-entity-types.json) and identify a buyer-referenced object with its own lifecycle that the seller can take offline. This is the subset of x-entity types for which a media buy's serving depends on the resource — not a new typology, just the impairment-relevant slice.
826
+ */
827
+ resource_type: 'audience' | 'creative' | 'catalog_item' | 'event_source' | 'property';
828
+ /**
829
+ * Seller's identifier for the specific resource that transitioned. References the same id space as the corresponding sync_/list_ task responses (e.g., audience_id, creative_id).
830
+ */
831
+ resource_id: string;
832
+ /**
833
+ * Packages within this media buy whose delivery is degraded by the impairment. MUST list at least one package — cosmetic effects that do not degrade any package's ability to serve MUST NOT be reported as impairments.
834
+ */
835
+ package_ids: string[];
836
+ /**
837
+ * The resource-level status transition that triggered this impairment.
838
+ */
839
+ transition: {
840
+ /**
841
+ * Prior status of the resource (e.g., 'ready', 'approved', 'good'). Optional — sellers SHOULD include when known, MAY omit when the resource was discovered already in an offline state (e.g., a property depublished via brand.json crawl with no prior snapshot). Open string at the schema layer because each resource_type has its own serviceable-state vocabulary; the pattern constraint blocks free-form garbage, and the impairment.coherence assertion validates that 'from' is a known serviceable value for the resource_type.
842
+ * @pattern ^[a-z][a-z0-9_]*$
843
+ */
844
+ from?: string;
845
+ to: ImpairmentOfflineState;
846
+ };
847
+ reason_code: ImpairmentReasonCode;
848
+ /**
849
+ * Human-readable explanation. Supplements reason_code with seller-specific detail.
850
+ * @maxLength 500
851
+ */
852
+ reason?: string;
853
+ /**
854
+ * ISO 8601 timestamp when the seller observed the resource transition to its offline state.
855
+ * @format date-time
856
+ */
857
+ observed_at: string;
858
+ /**
859
+ * Action the buyer can take to clear the impairment, if any. Free text. Absent when no buyer-side remediation is possible (e.g., seller-initiated withdrawal pending re-publication).
860
+ * @maxLength 500
861
+ */
862
+ remediation?: string;
863
+ }
864
+
865
+ /**
866
+ * Current (offline) status of the resource. Drawn from the resource_type's canonical lifecycle enum; see impairment-offline-state for per-value resource_type pairing. The pairing is validated by impairment.coherence.
867
+ */
868
+ export type ImpairmentOfflineState = 'suspended' | 'rejected' | 'withdrawn' | 'insufficient' | 'depublished';
869
+
870
+ /**
871
+ * Categorical reason for the offline transition. Drives buyer-side remediation logic.
872
+ */
873
+ export type ImpairmentReasonCode = 'policy_violation' | 'consent_expired' | 'ttl_expired' | 'pii_audit_failed' | 'seller_removed' | 'content_rejected' | 'source_offline' | 'property_depublished';
874
+
875
+ /**
876
+ * Keyword targeting match type. broad: ads may serve on queries semantically related to the keyword. phrase: ads serve when the query contains the keyword phrase. exact: ads serve only when the query matches the keyword exactly.
877
+ */
878
+ export type MatchType = 'broad' | 'phrase' | 'exact';
879
+
880
+ /**
881
+ * How a seller honors a given action on a media buy. Buyers branch on this to decide whether to expect a synchronous response, an automatic-with-fallback flow, a proposal lifecycle round-trip, or an asynchronous human approval. The mode is declared on each entry of `allowed_actions[]` (product, as `modes[]` array) or `available_actions[]` (buy, as singular `mode`).
882
+ */
883
+ export type MediaBuyActionMode = 'self_serve' | 'conditional_self_serve' | 'requires_proposal' | 'requires_approval';
884
+
885
+ /**
886
+ * An action currently available on a media buy, resolved against the buy's current status, negotiated terms, account tier, and any buy-level overrides. Authoritative per-buy capability — buyer SDKs MUST read this rather than re-deriving from the product's `allowed_actions[]`, because divergence from the product template is expected (negotiated terms and IO addenda live on the deal, not the product SKU). The containing `available_actions[]` array is uniquely keyed by `action`; sellers MUST NOT emit two entries with the same `action` value (this is a contract-level invariant — JSON Schema `uniqueItems` only catches structurally identical objects, so validators MUST enforce action-uniqueness separately). Predicate evaluators consuming dotted paths like `available_actions.extend_flight.sla.response_max` MUST index by `action` rather than by array position. The `mode` and `sla` values are advisory at the moment of emission; sellers MAY resolve to a different mode by the time the mutation arrives (state can change), in which case the request is rejected with `ACTION_NOT_ALLOWED` (`reason: mode_mismatch`).
887
+ */
888
+ export interface MediaBuyAvailableAction {
889
+ action: MediaBuyValidAction;
890
+ mode: MediaBuyActionMode;
891
+ sla?: SLAWindow;
892
+ /**
893
+ * Optional pointer into buy-terms negotiation (forward-references the buy-terms namespace landing via separate RFC). Schema accepts any string for now and will tighten to a structured reference when the buy-terms RFC ships.
894
+ */
895
+ terms_ref?: string;
896
+ }
897
+
898
+ /**
899
+ * Aggregate health of a media buy based on upstream dependency state. Orthogonal to media-buy-status — a buy can be paused-and-impaired, pending-and-impaired, or active-and-impaired. Always set; defaults to 'ok' when no open impairments exist.
900
+ */
901
+ export type MediaBuyHealth = 'ok' | 'impaired';
902
+
903
+ /**
904
+ * Status of a media buy.
905
+ */
906
+ export type MediaBuyStatus = 'pending_creatives' | 'pending_start' | 'active' | 'paused' | 'completed' | 'rejected' | 'canceled';
907
+
908
+ /**
909
+ * The action identifier.
910
+ */
911
+ export type MediaBuyValidAction = 'pause' | 'resume' | 'cancel' | 'extend_flight' | 'shorten_flight' | 'update_flight_dates' | 'increase_budget' | 'decrease_budget' | 'reallocate_budget' | 'update_targeting' | 'update_pacing' | 'update_frequency_caps' | 'replace_creative' | 'update_creative_assignments' | 'remove_creative' | 'add_packages' | 'remove_packages' | 'update_budget' | 'update_dates' | 'update_packages' | 'sync_creatives';
912
+
913
+ /**
914
+ * Metro classification system
915
+ */
916
+ export type MetroAreaSystem = 'nielsen_dma' | 'uk_itl1' | 'uk_itl2' | 'eurostat_nuts2' | 'custom';
917
+
918
+ /**
919
+ * Account-level webhook subscription for notifications whose lifecycle outlives any single media buy — creative state changes, library purges, wholesale feed change webhooks, and future account-scoped events. Distinct from `push-notification-config.json`, which anchors at a per-resource operation (a single task or media buy). An account MAY register multiple notification configs to fan a single seller's events out to multiple buyer-side endpoints; each entry filters by `event_types`. As with push-notification-config, the default signing scheme is the AdCP RFC 9421 webhook profile against the seller's brand.json `agents[]` JWKS; the optional `authentication` block opts into the deprecated Bearer / HMAC-SHA256 fallback for compatibility. Credentials and shared secrets in `authentication.credentials` are write-only — sellers MUST NOT echo them back in `list_accounts` responses. Sellers MUST verify endpoint control before activating account-level notification configs for high-volume event families such as wholesale feed changes; delivery-time SSRF validation still applies to every fire.
920
+ */
921
+ export interface NotificationConfig {
922
+ /**
923
+ * Buyer-supplied identifier for this subscription endpoint. Echoed on every webhook payload and on every `webhook_activity[]` record fired against this config so the buyer can attribute fires across multiple endpoints. MUST be unique within the account's `notification_configs[]` — uniqueness is enforced by the seller at registration time; duplicates are rejected with `errors[]`. Always required (even with a single subscriber) so the SDK contract is uniform — no conditional required-when-multiple rules to trip up implementations. Format is opaque — recommended values are short kebab-case slugs (`buyer-primary`, `audit-bus`, `dx-team`).
924
+ * @minLength 1
925
+ * @maxLength 64
926
+ * @pattern ^[A-Za-z0-9_.:-]{1,64}$
927
+ */
928
+ subscriber_id: string;
929
+ /**
930
+ * Webhook endpoint URL. Same wire contract as `push-notification-config.url` — `format: "uri"`, no destination-port allowlist enforced by the protocol, SSRF protection via the IP-range check defined in docs/building/by-layer/L1/security.mdx#webhook-url-validation-ssrf. For wholesale feed subscribers, sellers MUST complete an activation challenge or equivalent proof-of-control before treating the subscriber as active.
931
+ */
932
+ url: string;
933
+ /**
934
+ * Notification types this subscriber wishes to receive on the registered `url`. The seller MUST NOT fire other types against this endpoint, and MUST NOT silently widen the filter when new types are added to `notification-type.json`. When omitted, the seller MUST default to a no-fire policy and surface an `errors[]` entry on `sync_accounts` so the buyer notices the missing filter. Values are drawn from `notification-type.json`, but only types whose contract anchors at the account scope are valid here — creative lifecycle events and wholesale feed change payloads are valid; media-buy-anchored types (`scheduled`, `final`, `delayed`, `adjusted`, `impairment`) belong on a media buy's `push_notification_config`, not on this surface; sellers MUST reject those entries as per-account validation failures with `INVALID_REQUEST` or `VALIDATION_ERROR` and `error.field` pointing at the invalid `event_types` entry rather than silently dropping them.
935
+ */
936
+ event_types: NotificationType[];
937
+ /**
938
+ * Legacy authentication selector. Same precedence and semantics as `push-notification-config.authentication` — presence opts the seller into Bearer or HMAC-SHA256 signing; absence selects the default RFC 9421 webhook profile keyed off the seller's brand.json `agents[]` JWKS. The same signed-registration downgrade-resistance rules apply to accounts[].notification_configs[].authentication. Deprecated; removed in AdCP 4.0. Credentials are write-only and MUST NOT be echoed on `list_accounts` reads.
939
+ */
940
+ authentication?: {
941
+ schemes: AuthenticationScheme[];
942
+ /**
943
+ * Credentials for the legacy scheme. Bearer: token. HMAC-SHA256: shared secret. Minimum 32 characters. Exchanged out-of-band during onboarding. Write-only.
944
+ * @minLength 32
945
+ */
946
+ credentials: string;
947
+ };
948
+ /**
949
+ * When false, the seller persists the configuration but suppresses fires. Use to pause a noisy subscriber without losing the registration. Sellers MUST NOT skip persisting the entry when `active: false` — the buyer's next `sync_accounts` MUST observe the same array, otherwise the buyer cannot distinguish pause from drop.
950
+ */
951
+ active?: boolean;
952
+ ext?: ExtensionObject;
953
+ }
954
+
955
+ /**
956
+ * Type of push notification fired by a seller agent. Media-buy-anchored notifications (`scheduled`, `final`, `delayed`, `adjusted`, `impairment`) fire against a media buy's `push_notification_config`. Account-anchored notifications (`creative.status_changed`, `creative.purged`, `product.*`, `signal.*`, `wholesale_feed.bulk_change`) fire against an account's `notification_configs[]` entries whose `event_types` include the value — these outlive any single media buy and anchor at the account. Wholesale feed notifications carry the actual change payload in `/schemas/core/wholesale-feed-webhook.json`; receivers use `get_products` / `get_signals` with `if_wholesale_feed_version` to repair or reconcile. New notification types added to this enum MUST declare their anchor (media-buy or account) and per-type `notification_id` semantics in the enumDescription. Sellers MUST reject `notification_configs[]` entries whose `event_types` include any media-buy-anchored type, and MUST reject `push_notification_config` registrations for account-anchored types.
957
+ */
958
+ export type NotificationType = 'scheduled' | 'final' | 'delayed' | 'adjusted' | 'impairment' | 'creative.status_changed' | 'creative.purged' | 'product.created' | 'product.updated' | 'product.priced' | 'product.removed' | 'signal.created' | 'signal.updated' | 'signal.priced' | 'signal.removed' | 'wholesale_feed.bulk_change';
959
+
960
+ /**
961
+ * Current status of a package within a media buy — includes creative approval state and optional delivery snapshot. For the creation input shape, see PackageRequest. For the creation output shape, see Package.
962
+ */
963
+ export interface PackageStatus {
964
+ /**
965
+ * Seller's package identifier
966
+ */
967
+ package_id: string;
968
+ /**
969
+ * Product identifier this package is purchased from
970
+ */
971
+ product_id?: string;
972
+ /**
973
+ * Package budget amount, denominated in package.currency when present, otherwise media_buy.currency
974
+ * @minimum 0
975
+ */
976
+ budget?: number;
977
+ /**
978
+ * ISO 4217 currency code for monetary values at this package level (budget, bid_price, snapshot.spend). When absent, inherit media_buy.currency.
979
+ * @pattern ^[A-Z]{3}$
980
+ */
981
+ currency?: string;
982
+ /**
983
+ * Current bid price for auction-based packages. Denominated in package.currency when present, otherwise media_buy.currency. Relevant for automated price optimization loops.
984
+ * @minimum 0
985
+ */
986
+ bid_price?: number;
987
+ /**
988
+ * Goal impression count for impression-based packages
989
+ * @minimum 0
990
+ */
991
+ impressions?: number;
992
+ targeting_overlay?: TargetingOverlay;
993
+ /**
994
+ * ISO 8601 flight start time for this package. Use to determine whether the package is within its scheduled flight before interpreting delivery status.
995
+ * @format date-time
996
+ */
997
+ start_time?: string;
998
+ /**
999
+ * ISO 8601 flight end time for this package
1000
+ * @format date-time
1001
+ */
1002
+ end_time?: string;
1003
+ /**
1004
+ * Whether this package is currently paused by the buyer
1005
+ */
1006
+ paused?: boolean;
1007
+ /**
1008
+ * Whether this package has been canceled. Canceled packages stop delivery and cannot be reactivated.
1009
+ */
1010
+ canceled?: boolean;
1011
+ /**
1012
+ * Cancellation metadata. Present only when canceled is true.
1013
+ */
1014
+ cancellation?: {
1015
+ /**
1016
+ * ISO 8601 timestamp when this package was canceled.
1017
+ * @format date-time
1018
+ */
1019
+ canceled_at: string;
1020
+ canceled_by: CanceledBy;
1021
+ /**
1022
+ * Reason the package was canceled.
1023
+ * @maxLength 500
1024
+ */
1025
+ reason?: string;
1026
+ };
1027
+ /**
1028
+ * ISO 8601 timestamp for creative upload or change deadline for this package. After this deadline, creative changes are rejected. When absent, the media buy's creative_deadline applies.
1029
+ * @format date-time
1030
+ */
1031
+ creative_deadline?: string;
1032
+ /**
1033
+ * Approval status for each creative assigned to this package. Absent when no creatives have been assigned.
1034
+ */
1035
+ creative_approvals?: {
1036
+ /**
1037
+ * Creative identifier
1038
+ */
1039
+ creative_id: string;
1040
+ approval_status?: CreativeApprovalStatus;
1041
+ /**
1042
+ * Human-readable explanation of why the creative was rejected. Present only when approval_status is 'rejected'.
1043
+ */
1044
+ rejection_reason?: string;
1045
+ }[];
1046
+ /**
1047
+ * Format IDs from the original create_media_buy format_ids_to_provide that have not yet been uploaded via sync_creatives. When empty or absent, all required formats have been provided.
1048
+ */
1049
+ format_ids_pending?: FormatReferenceStructuredObject[];
1050
+ snapshot_unavailable_reason?: SnapshotUnavailableReason;
1051
+ /**
1052
+ * Near-real-time delivery snapshot for this package. Only present when include_snapshot was true in the request. Represents the latest available entity-level stats from the platform — not billing-grade data.
1053
+ */
1054
+ snapshot?: {
1055
+ /**
1056
+ * ISO 8601 timestamp when this snapshot was captured by the platform
1057
+ * @format date-time
1058
+ */
1059
+ as_of: string;
1060
+ /**
1061
+ * Maximum age of this data in seconds. For example, 900 means the data may be up to 15 minutes old. Use this to interpret zero delivery: a value of 900 means zero impressions is likely real; a value of 14400 means reporting may still be catching up.
1062
+ * @minimum 0
1063
+ */
1064
+ staleness_seconds: number;
1065
+ /**
1066
+ * Total impressions delivered since package start
1067
+ * @minimum 0
1068
+ */
1069
+ impressions: number;
1070
+ /**
1071
+ * Total spend since package start, denominated in snapshot.currency when present, otherwise package.currency or media_buy.currency
1072
+ * @minimum 0
1073
+ */
1074
+ spend: number;
1075
+ /**
1076
+ * ISO 4217 currency code for spend in this snapshot. Optional when unchanged from package.currency or media_buy.currency.
1077
+ * @pattern ^[A-Z]{3}$
1078
+ */
1079
+ currency?: string;
1080
+ /**
1081
+ * Total clicks since package start (when available)
1082
+ * @minimum 0
1083
+ */
1084
+ clicks?: number;
1085
+ /**
1086
+ * Current delivery pace relative to expected (1.0 = on track, <1.0 = behind, >1.0 = ahead). Absent when pacing cannot be determined.
1087
+ * @minimum 0
1088
+ */
1089
+ pacing_index?: number;
1090
+ /**
1091
+ * Operational delivery state of this package. 'not_delivering' means the package is within its scheduled flight but has delivered zero impressions for at least one full staleness cycle — the signal for automated price adjustments or buyer alerts. Implementers must not return 'not_delivering' until at least staleness_seconds have elapsed since package activation.
1092
+ */
1093
+ delivery_status?: 'delivering' | 'not_delivering' | 'completed' | 'budget_exhausted' | 'flight_ended' | 'goal_met';
1094
+ ext?: ExtensionObject;
1095
+ };
1096
+ ext?: ExtensionObject;
1097
+ }
1098
+
1099
+ /**
1100
+ * Standard cursor-based pagination parameters for list operations
1101
+ */
1102
+ export interface PaginationRequest {
1103
+ /**
1104
+ * Maximum number of items to return per page
1105
+ * @minimum 1
1106
+ * @maximum 100
1107
+ */
1108
+ max_results?: number;
1109
+ /**
1110
+ * Opaque cursor from a previous response to fetch the next page
1111
+ */
1112
+ cursor?: string;
1113
+ }
1114
+
1115
+ /**
1116
+ * Standard cursor-based pagination metadata for list responses
1117
+ */
1118
+ export interface PaginationResponse {
1119
+ /**
1120
+ * Whether more results are available beyond this page
1121
+ */
1122
+ has_more: boolean;
1123
+ /**
1124
+ * Opaque cursor to pass in the next request to fetch the next page. Only present when has_more is true.
1125
+ */
1126
+ cursor?: string;
1127
+ /**
1128
+ * Total number of items matching the query across all pages. Optional because not all backends can efficiently compute this.
1129
+ * @minimum 0
1130
+ */
1131
+ total_count?: number;
1132
+ }
1133
+
1134
+ /**
1135
+ * Payment terms agreed for this account. Binding for all invoices when the account is active.
1136
+ */
1137
+ export type PaymentTerms = 'net_15' | 'net_30' | 'net_45' | 'net_60' | 'net_90' | 'prepay';
1138
+
1139
+ /**
1140
+ * Postal code system (e.g., 'us_zip', 'gb_outward')
1141
+ */
1142
+ export type PostalCodeSystem = 'us_zip' | 'us_zip_plus_four' | 'gb_outward' | 'gb_full' | 'ca_fsa' | 'ca_full' | 'de_plz' | 'fr_code_postal' | 'au_postcode' | 'ch_plz' | 'at_plz';
1143
+
1144
+ /**
1145
+ * [AdCP 3.0] Reference to an externally managed property list. When provided, the sales agent should filter products to only those available on properties in the list.
1146
+ */
1147
+ export interface PropertyListReference {
1148
+ /**
1149
+ * URL of the agent managing the property list
1150
+ */
1151
+ agent_url: string;
1152
+ /**
1153
+ * Identifier for the property list within the agent
1154
+ * @minLength 1
1155
+ */
1156
+ list_id: string;
1157
+ /**
1158
+ * JWT or other authorization token for accessing the list. Optional if the list is public or caller has implicit access.
1159
+ */
1160
+ auth_token?: string;
1161
+ }
1162
+
1163
+ /**
1164
+ * Provenance metadata for this asset, overrides manifest-level provenance
1165
+ */
1166
+ export interface Provenance {
1167
+ digital_source_type?: DigitalSourceType;
1168
+ /**
1169
+ * AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.
1170
+ */
1171
+ ai_tool?: {
1172
+ /**
1173
+ * Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')
1174
+ */
1175
+ name: string;
1176
+ /**
1177
+ * Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version.
1178
+ */
1179
+ version?: string;
1180
+ /**
1181
+ * Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')
1182
+ */
1183
+ provider?: string;
1184
+ };
1185
+ /**
1186
+ * Level of human involvement in the AI-assisted creation process. Independent of `disclosure.required` — the protocol does not derive disclosure obligations from oversight level. Some regulations include carve-outs for human-edited or human-directed AI output, but those carve-outs have factual prerequisites the schema cannot evaluate. Asserting `edited` or `directed` does not by itself justify `disclosure.required: false`.
1187
+ */
1188
+ human_oversight?: 'none' | 'prompt_only' | 'selected' | 'edited' | 'directed';
1189
+ /**
1190
+ * Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.
1191
+ */
1192
+ declared_by?: {
1193
+ /**
1194
+ * URL of the agent or service that declared this provenance
1195
+ */
1196
+ agent_url?: string;
1197
+ /**
1198
+ * Role of the declaring party in the supply chain
1199
+ */
1200
+ role: 'creator' | 'advertiser' | 'agency' | 'platform' | 'tool';
1201
+ };
1202
+ /**
1203
+ * When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance.
1204
+ * @format date-time
1205
+ */
1206
+ declared_at?: string;
1207
+ /**
1208
+ * When this content was created or generated (ISO 8601)
1209
+ * @format date-time
1210
+ */
1211
+ created_time?: string;
1212
+ /**
1213
+ * C2PA sidecar manifest reference. Links to a detached cryptographic provenance manifest for this content. Note: file-level C2PA bindings break when ad servers transcode, resize, or re-encode assets. For pipelines with intermediaries, consider embedded_provenance as the primary provenance mechanism.
1214
+ */
1215
+ c2pa?: {
1216
+ /**
1217
+ * URL to the C2PA manifest store for this content
1218
+ */
1219
+ manifest_url: string;
1220
+ };
1221
+ /**
1222
+ * Provenance metadata embedded within the content stream. Each entry declares one embedding layer: structured provenance data carried inside the content itself, as distinct from sidecar references (c2pa.manifest_url). Embedded provenance survives operations that break sidecar and file-level bindings: ad-server transcoding, CMS ingestion, copy-paste, reformatting, and CDN re-encoding. For ad-tech pipelines where content passes through multiple intermediaries, embedded provenance is the reliable path for provenance that persists from declaration through delivery. This is a declaration by the embedding party. The receiving party (the seller) is the verifier-of-record: it confirms the claim by calling a governance agent it trusts (typically one published in `creative_policy.accepted_verifiers`).
1223
+ */
1224
+ embedded_provenance?: {
1225
+ method: EmbeddedProvenanceMethod;
1226
+ /**
1227
+ * Standard the embedding conforms to, if any (e.g., 'c2pa' for C2PA Section A.7 text manifest embedding)
1228
+ */
1229
+ standard?: string;
1230
+ /**
1231
+ * Organization that performed the embedding (e.g., 'Encypher', 'Digimarc'). Display label and audit context — not a wire identifier.
1232
+ */
1233
+ provider: string;
1234
+ /**
1235
+ * Buyer's representation that this embedding can be verified by a governance agent on the seller's `creative_policy.accepted_verifiers` list. The `agent_url` MUST match (canonicalized) one of the seller's published `accepted_verifiers[].agent_url` entries; sellers reject `sync_creatives` submissions whose `verify_agent.agent_url` is off-list with `PROVENANCE_VERIFIER_NOT_ACCEPTED`. This is buyer-supplied evidence, not buyer-driven routing — the seller is the verifier-of-record and the seller controls which agent it actually calls (the seller MAY use a different on-list agent if it determines this is more appropriate; the seller does not call buyer-asserted endpoints outside its allowlist). MAY be omitted for self-verifiable embeddings (e.g., a C2PA text manifest with a public key the seller already trusts).
1236
+ */
1237
+ verify_agent?: {
1238
+ /**
1239
+ * URL of the governance agent the buyer represents was used to embed/verify this layer. MUST use the `https://` scheme and MUST appear in the seller's `creative_policy.accepted_verifiers[].agent_url` list (canonicalized per /docs/reference/url-canonicalization: lowercase scheme and host, strip default port, normalize path dot-segments). Sellers MUST NOT call this URL until the canonicalized match is confirmed.
1240
+ * @pattern ^https:\/\/
1241
+ */
1242
+ agent_url: string;
1243
+ /**
1244
+ * Optional `feature_id` the buyer represents the seller should request via `get_creative_features` (e.g., `encypher.markers_present_v2`). SHOULD match the `feature_id` declared on the matching `accepted_verifiers[]` entry, or be omitted to defer the selector to the seller. When the seller's entry pins a `feature_id`, that value wins; when neither side pins, the seller selects from the agent's `governance.creative_features` catalog.
1245
+ */
1246
+ feature_id?: string;
1247
+ };
1248
+ /**
1249
+ * When the provenance data was embedded (ISO 8601)
1250
+ * @format date-time
1251
+ */
1252
+ embedded_at?: string;
1253
+ }[];
1254
+ /**
1255
+ * Content watermarks applied to this asset. Each entry declares one watermarking layer: a content modification that encodes an identifier or fingerprint within the asset. Watermarks differ from embedded provenance: a watermark encodes an identifier (who generated it, who owns it), while embedded provenance carries or references a structured provenance record (the full chain of custody). A single asset may carry both. Aligns with C2PA action taxonomy: c2pa.watermarked.bound (watermark linked to a C2PA manifest) and c2pa.watermarked.unbound (watermark independent of any manifest). This is a declaration by the watermarking party. The receiving party (the seller) is the verifier-of-record: it confirms the claim by calling a governance agent it trusts (typically one published in `creative_policy.accepted_verifiers`).
1256
+ */
1257
+ watermarks?: {
1258
+ media_type: WatermarkMediaType;
1259
+ /**
1260
+ * Organization that applied the watermark (e.g., 'Imatag', 'Steg.AI', 'Encypher'). Display label and audit context — not a wire identifier.
1261
+ */
1262
+ provider: string;
1263
+ /**
1264
+ * Buyer's representation that this watermark can be detected by a governance agent on the seller's `creative_policy.accepted_verifiers` list. The `agent_url` MUST match (canonicalized) one of the seller's published `accepted_verifiers[].agent_url` entries; sellers reject `sync_creatives` submissions whose `verify_agent.agent_url` is off-list with `PROVENANCE_VERIFIER_NOT_ACCEPTED`. This is buyer-supplied evidence, not buyer-driven routing — the seller is the verifier-of-record and the seller controls which agent it actually calls (the seller MAY use a different on-list agent if it determines this is more appropriate; the seller does not call buyer-asserted endpoints outside its allowlist).
1265
+ */
1266
+ verify_agent?: {
1267
+ /**
1268
+ * URL of the governance agent the buyer represents was used to apply/detect this watermark. MUST use the `https://` scheme and MUST appear in the seller's `creative_policy.accepted_verifiers[].agent_url` list (canonicalized per /docs/reference/url-canonicalization: lowercase scheme and host, strip default port, normalize path dot-segments). Sellers MUST NOT call this URL until the canonicalized match is confirmed.
1269
+ * @pattern ^https:\/\/
1270
+ */
1271
+ agent_url: string;
1272
+ /**
1273
+ * Optional `feature_id` the buyer represents the seller should request via `get_creative_features` (e.g., `imatag.watermark_detected`). SHOULD match the `feature_id` declared on the matching `accepted_verifiers[]` entry, or be omitted to defer the selector to the seller. When the seller's entry pins a `feature_id`, that value wins; when neither side pins, the seller selects from the agent's `governance.creative_features` catalog.
1274
+ */
1275
+ feature_id?: string;
1276
+ };
1277
+ c2pa_action?: C2PAWatermarkAction;
1278
+ /**
1279
+ * When the watermark was applied (ISO 8601)
1280
+ * @format date-time
1281
+ */
1282
+ embedded_at?: string;
1283
+ }[];
1284
+ /**
1285
+ * Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.
1286
+ */
1287
+ disclosure?: {
1288
+ /**
1289
+ * The declaring party's claim that AI disclosure is required for this content under applicable regulations. This is a declared signal carried through the supply chain — useful as a routing and audit input — not a regulatory determination made by the protocol. Receiving parties remain responsible for their own jurisdictional analysis and should not treat `required: false` as compliance cover.
1290
+ */
1291
+ required: boolean;
1292
+ /**
1293
+ * Jurisdictions where disclosure obligations apply
1294
+ */
1295
+ jurisdictions?: {
1296
+ /**
1297
+ * ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')
1298
+ */
1299
+ country: string;
1300
+ /**
1301
+ * Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)
1302
+ */
1303
+ region?: string;
1304
+ /**
1305
+ * Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')
1306
+ */
1307
+ regulation: string;
1308
+ /**
1309
+ * Required disclosure label text for this jurisdiction, in the local language
1310
+ */
1311
+ label_text?: string;
1312
+ /**
1313
+ * How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.
1314
+ */
1315
+ render_guidance?: {
1316
+ persistence?: DisclosurePersistence;
1317
+ /**
1318
+ * Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial — without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available.
1319
+ * @minimum 1
1320
+ */
1321
+ min_duration_ms?: number;
1322
+ /**
1323
+ * Preferred disclosure positions in priority order. The first position a format supports should be used.
1324
+ */
1325
+ positions?: DisclosurePosition[];
1326
+ ext?: ExtensionObject;
1327
+ };
1328
+ }[];
1329
+ };
1330
+ /**
1331
+ * Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim — verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.
1332
+ */
1333
+ verification?: {
1334
+ /**
1335
+ * Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')
1336
+ */
1337
+ verified_by: string;
1338
+ /**
1339
+ * When the verification was performed (ISO 8601)
1340
+ * @format date-time
1341
+ */
1342
+ verified_time?: string;
1343
+ /**
1344
+ * Verification outcome
1345
+ */
1346
+ result: 'authentic' | 'ai_generated' | 'ai_modified' | 'inconclusive';
1347
+ /**
1348
+ * Confidence score of the verification result (0.0 to 1.0)
1349
+ * @minimum 0
1350
+ * @maximum 1
1351
+ */
1352
+ confidence?: number;
1353
+ /**
1354
+ * URL to the full verification report
1355
+ */
1356
+ details_url?: string;
1357
+ }[];
1358
+ ext?: ExtensionObject;
1359
+ }
1360
+
1361
+ /**
1362
+ * 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.
1363
+ */
1364
+ export interface PushNotificationConfig {
1365
+ /**
1366
+ * Webhook endpoint URL for task status notifications. The wire contract is unconstrained beyond `format: "uri"` — in particular, publishers SHOULD NOT enforce a destination-port allowlist by default, since buyers legitimately host receivers on non-standard TLS ports (`:9443`, `:4443`, path-routed multi-tenant gateways). The SSRF guard the protocol relies on is the IP-range check + DNS-rebinding-resistant connect pin defined in [Webhook URL validation (SSRF)](/docs/building/by-layer/L1/security#webhook-url-validation-ssrf), not port filtering. Operators who want a hardened destination-port allowlist as defense-in-depth (e.g., locked-down enterprise egress) opt in explicitly — see [Destination port: permissive by default](/docs/building/by-layer/L1/security#destination-port-permissive-by-default).
1367
+ */
1368
+ url: string;
1369
+ /**
1370
+ * Buyer-supplied correlation identifier for the operation that will produce webhooks against this registration. The seller MUST echo this value verbatim into every webhook payload's `operation_id` field (see [`mcp-webhook-payload.json`](/schemas/core/mcp-webhook-payload.json) and [Webhooks — Operation IDs](/docs/building/by-layer/L3/webhooks#operation-ids-and-url-templates)). Buyers SHOULD generate a unique value per task invocation (UUID recommended). This field is the canonical registration channel for `operation_id`; buyers MAY additionally embed the same value in the URL path or query as a routing aid for their own HTTP server, but the URL is opaque to the seller and the wire-level source of truth is this field. Sellers MUST NOT parse the URL to recover `operation_id`. Sellers that receive a webhook registration without `operation_id` MAY reject the task with `INVALID_REQUEST`.
1371
+ * @minLength 1
1372
+ * @maxLength 255
1373
+ * @pattern ^[A-Za-z0-9_.:-]{1,255}$
1374
+ */
1375
+ operation_id?: string;
1376
+ /**
1377
+ * Optional client-provided token for webhook validation. The seller MUST echo this value verbatim in every webhook payload's `token` field (see [`mcp-webhook-payload.json`](/schemas/core/mcp-webhook-payload.json) for the receiver-side validation obligation). Length bounds give receivers a defensive range check on the echoed value; senders SHOULD generate tokens with at least 128 bits of entropy (≥22 base64url characters). This is a complementary authenticity mechanism that can layer on top of the RFC 9421 webhook signature — unlike the `authentication` block below, it is not on the 4.0 removal track. Receivers that registered both a signing key (RFC 9421) and a `token` MUST NOT treat a valid token echo as authorization to skip signature verification; both checks remain independent obligations.
1378
+ * @minLength 16
1379
+ * @maxLength 4096
1380
+ */
1381
+ token?: string;
1382
+ /**
1383
+ * Legacy authentication configuration (A2A-compatible). Opts the seller into Bearer or HMAC-SHA256 signing instead of the default RFC 9421 webhook profile. Deprecated; removed in AdCP 4.0. **Precedence is a switch, not a fallback:** presence of this block selects the legacy scheme; absence selects 9421. A seller MUST NOT sign the same webhook both ways, and a buyer MUST NOT attempt 'try 9421 first, fall back to HMAC' verification — signature mode is determined solely by whether this block was present at registration time. The seller's baseline 9421 webhook-signing key published at its brand.json `agents[]` `jwks_uri` does not override this selector; it is always discoverable but only used when `authentication` is omitted. See docs/building/implementation/security.mdx#webhook-callbacks for the full precedence and downgrade-resistance rules (including the `webhook_mode_mismatch` rejection a buyer MUST apply when a received webhook's signing mode does not match the registered mode).
1384
+ */
1385
+ authentication?: {
1386
+ /**
1387
+ * Array of authentication schemes. Supported: ['Bearer'] for simple token auth, ['HMAC-SHA256'] for legacy shared-secret signing. Both are deprecated; new integrations SHOULD omit `authentication` and use the RFC 9421 webhook profile.
1388
+ */
1389
+ schemes: AuthenticationScheme[];
1390
+ /**
1391
+ * Credentials for the legacy scheme. For Bearer: token sent in Authorization header. For HMAC-SHA256: shared secret used to generate signature. Minimum 32 characters. Exchanged out-of-band during onboarding.
1392
+ * @minLength 32
1393
+ */
1394
+ credentials: string;
1395
+ };
1396
+ }
1397
+
1398
+ /**
1399
+ * Unit of measurement for reach and audience_size metrics in this forecast. Required for cross-channel forecast comparison.
1400
+ */
1401
+ export type ReachUnit = 'individuals' | 'households' | 'devices' | 'accounts' | 'cookies' | 'custom';
1402
+
1403
+ /**
1404
+ * Optional SLA commitment for this action on this product. Absence means no commitment.
1405
+ */
1406
+ export interface SLAWindow {
1407
+ /**
1408
+ * Maximum time from when the buyer issues the action to when the seller acknowledges receipt (mode-appropriate: synchronous response for self_serve, queue ack for requires_approval, proposal task creation for requires_proposal). ISO 8601 duration.
1409
+ * @pattern ^P(?!$)(\d+Y)?(\d+M)?(\d+D)?(T(\d+H)?(\d+M)?(\d+S)?)?$
1410
+ */
1411
+ response_max?: string;
1412
+ /**
1413
+ * Maximum time from buyer issuing the action to the seller completing it (mutation applied, proposal finalized, approval resolved). ISO 8601 duration.
1414
+ * @pattern ^P(?!$)(\d+Y)?(\d+M)?(\d+D)?(T(\d+H)?(\d+M)?(\d+S)?)?$
1415
+ */
1416
+ completion_max?: string;
1417
+ }
1418
+
1419
+ /**
1420
+ * Machine-readable reason the snapshot is omitted. Present only when include_snapshot was true and snapshot is unavailable for this package.
1421
+ */
1422
+ export type SnapshotUnavailableReason = 'SNAPSHOT_UNSUPPORTED' | 'SNAPSHOT_TEMPORARILY_UNAVAILABLE' | 'SNAPSHOT_PERMISSION_DENIED';
1423
+
1424
+ /**
1425
+ * Optional restriction overlays for media buys. Most targeting should be expressed in the brief and handled by the publisher. These fields are for functional restrictions: geographic (RCT testing, regulatory compliance, proximity targeting), age verification (alcohol, gambling), device platform (app compatibility), language (localization), and keyword targeting (search/retail media).
1426
+ */
1427
+ export interface TargetingOverlay {
1428
+ /**
1429
+ * Restrict delivery to specific countries. ISO 3166-1 alpha-2 codes (e.g., 'US', 'GB', 'DE').
1430
+ */
1431
+ geo_countries?: string[];
1432
+ /**
1433
+ * Exclude specific countries from delivery. ISO 3166-1 alpha-2 codes (e.g., 'US', 'GB', 'DE').
1434
+ */
1435
+ geo_countries_exclude?: string[];
1436
+ /**
1437
+ * Restrict delivery to specific regions/states. ISO 3166-2 subdivision codes (e.g., 'US-CA', 'GB-SCT').
1438
+ */
1439
+ geo_regions?: string[];
1440
+ /**
1441
+ * Exclude specific regions/states from delivery. ISO 3166-2 subdivision codes (e.g., 'US-CA', 'GB-SCT').
1442
+ */
1443
+ geo_regions_exclude?: string[];
1444
+ /**
1445
+ * Restrict delivery to specific metro areas. Each entry specifies the classification system and target values. Seller must declare supported systems in get_adcp_capabilities.
1446
+ */
1447
+ geo_metros?: {
1448
+ system: MetroAreaSystem;
1449
+ /**
1450
+ * Metro codes within the system (e.g., ['501', '602'] for Nielsen DMAs)
1451
+ */
1452
+ values: string[];
1453
+ }[];
1454
+ /**
1455
+ * Exclude specific metro areas from delivery. Each entry specifies the classification system and excluded values. Seller must declare supported systems in get_adcp_capabilities.
1456
+ */
1457
+ geo_metros_exclude?: {
1458
+ system: MetroAreaSystem;
1459
+ /**
1460
+ * Metro codes to exclude within the system (e.g., ['501', '602'] for Nielsen DMAs)
1461
+ */
1462
+ values: string[];
1463
+ }[];
1464
+ /**
1465
+ * Restrict delivery to specific postal areas. Each entry specifies the postal system and target values. Seller must declare supported systems in get_adcp_capabilities.
1466
+ */
1467
+ geo_postal_areas?: {
1468
+ system: PostalCodeSystem;
1469
+ /**
1470
+ * Postal codes within the system (e.g., ['10001', '10002'] for us_zip)
1471
+ */
1472
+ values: string[];
1473
+ }[];
1474
+ /**
1475
+ * Exclude specific postal areas from delivery. Each entry specifies the postal system and excluded values. Seller must declare supported systems in get_adcp_capabilities.
1476
+ */
1477
+ geo_postal_areas_exclude?: {
1478
+ system: PostalCodeSystem;
1479
+ /**
1480
+ * Postal codes to exclude within the system (e.g., ['10001', '10002'] for us_zip)
1481
+ */
1482
+ values: string[];
1483
+ }[];
1484
+ /**
1485
+ * Restrict delivery to specific time windows. Each entry specifies days of week and an hour range.
1486
+ */
1487
+ daypart_targets?: DaypartTarget[];
1488
+ /**
1489
+ * @deprecated
1490
+ * Deprecated: Use TMP provider fields instead. AXE segment ID to include for targeting.
1491
+ */
1492
+ axe_include_segment?: string;
1493
+ /**
1494
+ * @deprecated
1495
+ * Deprecated: Use TMP provider fields instead. AXE segment ID to exclude from targeting.
1496
+ */
1497
+ axe_exclude_segment?: string;
1498
+ /**
1499
+ * Restrict delivery to members of these first-party CRM audiences. Only users present in the uploaded lists are eligible. References audience_id values from sync_audiences on the same seller account — audience IDs are not portable across sellers. Not for lookalike expansion — express that intent in the campaign brief. Seller must declare support in get_adcp_capabilities.
1500
+ */
1501
+ audience_include?: string[];
1502
+ /**
1503
+ * Suppress delivery to members of these first-party CRM audiences. Matched users are excluded regardless of other targeting. References audience_id values from sync_audiences on the same seller account — audience IDs are not portable across sellers. Seller must declare support in get_adcp_capabilities.
1504
+ */
1505
+ audience_exclude?: string[];
1506
+ frequency_cap?: FrequencyCap;
1507
+ property_list?: PropertyListReference;
1508
+ collection_list?: CollectionListReference;
1509
+ collection_list_exclude?: CollectionListReference;
1510
+ /**
1511
+ * Age restriction for compliance. Use for legal requirements (alcohol, gambling), not audience targeting.
1512
+ */
1513
+ age_restriction?: {
1514
+ /**
1515
+ * Minimum age required
1516
+ * @minimum 13
1517
+ * @maximum 99
1518
+ */
1519
+ min: number;
1520
+ /**
1521
+ * Whether verified age (not inferred) is required for compliance
1522
+ */
1523
+ verification_required?: boolean;
1524
+ /**
1525
+ * Accepted verification methods. If omitted, any method the platform supports is acceptable.
1526
+ */
1527
+ accepted_methods?: AgeVerificationMethod[];
1528
+ };
1529
+ /**
1530
+ * Restrict to specific platforms. Use for technical compatibility (app only works on iOS). Values from Sec-CH-UA-Platform standard, extended for CTV.
1531
+ */
1532
+ device_platform?: DevicePlatform[];
1533
+ /**
1534
+ * Restrict to specific device form factors. Use for campaigns targeting hardware categories rather than operating systems (e.g., mobile-only promotions, CTV campaigns).
1535
+ */
1536
+ device_type?: DeviceType[];
1537
+ /**
1538
+ * Exclude specific device form factors from delivery (e.g., exclude CTV for app-install campaigns).
1539
+ */
1540
+ device_type_exclude?: DeviceType[];
1541
+ /**
1542
+ * Target users within store catchment areas from a synced store catalog. Each entry references a store-type catalog and optionally narrows to specific stores or catchment zones.
1543
+ */
1544
+ store_catchments?: {
1545
+ /**
1546
+ * Synced store-type catalog ID from sync_catalogs.
1547
+ */
1548
+ catalog_id: string;
1549
+ /**
1550
+ * Filter to specific stores within the catalog. Omit to target all stores.
1551
+ */
1552
+ store_ids?: string[];
1553
+ /**
1554
+ * Catchment zone IDs to target (e.g., 'walk', 'drive'). Omit to target all catchment zones.
1555
+ */
1556
+ catchment_ids?: string[];
1557
+ }[];
1558
+ /**
1559
+ * Target users within travel time, distance, or a custom boundary around arbitrary geographic points. Multiple entries use OR semantics — a user within range of any listed point is eligible. For campaigns targeting 10+ locations, consider using store_catchments with a location catalog instead. Seller must declare support in get_adcp_capabilities.
1560
+ */
1561
+ geo_proximity?: {
1562
+ [k: string]: unknown | undefined;
1563
+ }[];
1564
+ /**
1565
+ * Restrict to users with specific language preferences. ISO 639-1 codes (e.g., 'en', 'es', 'fr').
1566
+ */
1567
+ language?: string[];
1568
+ /**
1569
+ * Keyword targeting for search and retail media platforms. Restricts delivery to queries matching the specified keywords. Each keyword is identified by the tuple (keyword, match_type) — the same keyword string with different match types are distinct targets. Sellers SHOULD reject duplicate (keyword, match_type) pairs within a single request. Seller must declare support in get_adcp_capabilities.
1570
+ */
1571
+ keyword_targets?: {
1572
+ /**
1573
+ * The keyword to target
1574
+ * @minLength 1
1575
+ */
1576
+ keyword: string;
1577
+ match_type: MatchType;
1578
+ /**
1579
+ * Per-keyword bid price, denominated in the same currency as the package's pricing option. Overrides the package-level bid_price for this keyword. Inherits the max_bid interpretation from the pricing option: when max_bid is true, this is the keyword's bid ceiling; when false, this is the exact bid. If omitted, the package bid_price applies.
1580
+ * @minimum 0
1581
+ */
1582
+ bid_price?: number;
1583
+ }[];
1584
+ /**
1585
+ * Keywords to exclude from delivery. Queries matching these keywords will not trigger the ad. Each negative keyword is identified by the tuple (keyword, match_type). Seller must declare support in get_adcp_capabilities.
1586
+ */
1587
+ negative_keywords?: {
1588
+ /**
1589
+ * The keyword to exclude
1590
+ * @minLength 1
1591
+ */
1592
+ keyword: string;
1593
+ match_type: MatchType;
1594
+ }[];
1595
+ }
1596
+
1597
+ /**
1598
+ * Current task execution state. Indicates whether the task is completed, in progress (working), submitted for async processing, failed, or requires user input. REQUIRED on every task response envelope. Synchronous tasks (including read-only metadata calls like `get_adcp_capabilities`) MUST emit `status: "completed"`; async tasks emit `submitted`, `working`, `input-required`, etc. per their lifecycle. Agents MUST NOT emit the legacy task_status or response_status fields alongside this field — the status field is the single authoritative task state.
1599
+ */
1600
+ export type TaskStatus = 'submitted' | 'working' | 'input-required' | 'completed' | 'canceled' | 'failed' | 'rejected' | 'auth-required' | 'unknown';
1601
+
1602
+ /**
1603
+ * Media category of the watermarked content
1604
+ */
1605
+ export type WatermarkMediaType = 'audio' | 'image' | 'video' | 'text';
1606
+
1607
+ /**
1608
+ * Single webhook delivery attempt surfaced to a calling principal as a buyer-side debug aid. Represents one HTTP attempt of a logical webhook fire from the seller to the buyer's registered endpoint — retries of the same logical fire share `idempotency_key` and differ by `attempt`. This is the canonical record shape for any AdCP resource that exposes a `webhook_activity[]` log on its read API; see snapshot-and-log.mdx § Webhook activity log pattern for the full normative contract (scoping, retention, three-state presence, request-field conventions).
1609
+ */
1610
+ export interface WebhookActivityRecord {
1611
+ /**
1612
+ * Equals the `idempotency_key` carried in the webhook payload itself (see docs/building/by-layer/L3/webhooks.mdx § Dedup by `idempotency_key`). Stable across retry attempts of the same logical fire — retries with `attempt` > 1 reuse this key. Buyers correlate this surface with their own endpoint logs via this exact field; the spec deliberately reuses the payload key rather than minting a parallel `delivery_id` so callers do not need a join table. Format is sender-defined; callers MUST treat as opaque.
1613
+ */
1614
+ idempotency_key: string;
1615
+ /**
1616
+ * Identifies which registered webhook subscriber received this fire. **Required on records from account-anchored notification channels** (`notification_configs[]` registered via `sync_accounts`) — every subscriber has a `subscriber_id` at registration time, the seller MUST echo it on every fire and every activity record. **Optional on records from per-resource push channels** (`push_notification_config` on a media buy or task) — the calling principal is unambiguous in single-subscriber configurations and the field MAY be omitted; sellers MUST populate it once `reporting_webhook` adopts multi-subscriber (per #3009 in AdCP 4.0). Buyers MUST NOT use absence as a signal that no other subscribers exist; that information is not exposed by this surface.
1617
+ */
1618
+ subscriber_id?: string;
1619
+ /**
1620
+ * ISO 8601 timestamp when the seller initiated the HTTP request for this attempt.
1621
+ * @format date-time
1622
+ */
1623
+ fired_at: string;
1624
+ /**
1625
+ * ISO 8601 timestamp when the seller observed the response (or terminal timeout / connection error — for `timeout` and `connection_error` outcomes, `completed_at` is set to the moment the seller declared the attempt terminal). Explicitly `null` when the attempt is still in flight or queued for retry (status `pending`); MUST be set as `null` rather than omitted so callers can distinguish 'still in flight' from 'field missing'.
1626
+ * @format date-time
1627
+ */
1628
+ completed_at?: string | null;
1629
+ notification_type: NotificationType;
1630
+ /**
1631
+ * Sequence number from the webhook payload. Surfaced here so the buyer can spot stale-sequence drops and gaps without correlating against their own endpoint log. Absent for notification types that do not carry a sequence number.
1632
+ * @minimum 0
1633
+ */
1634
+ sequence_number?: number;
1635
+ /**
1636
+ * 1-indexed retry counter for this logical fire. Initial fire is attempt=1; retries increment. Sellers MUST emit one record per attempt, so a successful first-attempt fire appears as a single record with `attempt: 1` and a 3-attempt retry trail appears as three records sharing `idempotency_key`.
1637
+ * @minimum 1
1638
+ */
1639
+ attempt: number;
1640
+ /**
1641
+ * Outcome of this attempt. `success` — response received with 2xx (`http_status_code` populated). `failed` — response received with non-2xx (`http_status_code` populated). `timeout` — no response within the seller's configured timeout (`http_status_code` null). `connection_error` — DNS / TLS / socket failure before any HTTP response (`http_status_code` null). `pending` — attempt is in flight or queued for retry (`completed_at` null, `http_status_code` null). The `timeout` / `connection_error` split is intentional and operationally distinct: `timeout` typically signals a slow / overloaded buyer endpoint, `connection_error` typically signals it is unreachable or misconfigured.
1642
+ */
1643
+ status: 'success' | 'failed' | 'timeout' | 'connection_error' | 'pending';
1644
+ /**
1645
+ * Target URL for this fire. Query string and fragment MUST be stripped before surfacing — buyers commonly stash bearer tokens in the query string and sellers MUST NOT echo those back through this debug surface. Sellers SHOULD additionally redact path segments matching obvious secret patterns (e.g., a path segment that is high-entropy random material or matches a UUID / token format). Buyers matching this against their own configured URL should compare by origin + path; query strings will not match and that mismatch is expected.
1646
+ */
1647
+ url: string;
1648
+ /**
1649
+ * HTTP status code returned by the buyer's endpoint. Explicitly `null` when no HTTP response was received (status `timeout`, `connection_error`, or `pending`); MUST be set as `null` rather than omitted.
1650
+ * @minimum 100
1651
+ * @maximum 599
1652
+ */
1653
+ http_status_code?: number | null;
1654
+ /**
1655
+ * Wall-clock latency between request send and response receipt, in milliseconds. Explicitly `null` when the attempt did not complete (`timeout`, `connection_error`, `pending`); MUST be set as `null` rather than omitted.
1656
+ * @minimum 0
1657
+ */
1658
+ response_time_ms?: number | null;
1659
+ /**
1660
+ * Size of the request body the seller sent, in bytes. Useful for diagnosing oversized-payload rejections from the buyer's gateway.
1661
+ * @minimum 0
1662
+ */
1663
+ payload_size_bytes?: number;
1664
+ /**
1665
+ * Short human-readable server-side classification of why this attempt did not succeed (e.g., `connection refused`, `TLS handshake timeout`, `HTTP 503 Service Unavailable`). Explicitly `null` for `success` (MUST be set as `null` rather than omitted). Sellers MUST NOT include request headers, request body content, or response body content in this field — payload surfacing is reserved for a future `include_webhook_payloads` extension and is subject to stricter access controls. Sellers SHOULD also avoid including buyer-endpoint internal hostnames, stack traces, or other implementation detail leaked by the response — keep it a stable classification string.
1666
+ * @maxLength 500
1667
+ */
1668
+ error_message?: string | null;
1669
+ ext?: ExtensionObject;
1670
+ }