AdCP 3.1.13 · Negotiation layer
AdCP Media Buy
AdCP Media Buy is a schema group of the Ad Context Protocol holding 11 of the 64 operations in release 3.1.13, covering product discovery, campaign creation and updates, delivery reporting, conversion tracking, and audience and catalog sync.
The media buy group covers the buying cycle itself: get_products for discovery, create_media_buy and update_media_buy for the buy, get_media_buy_delivery for reporting, and the sync_* operations for the audiences, catalogs and conversion sources a buy refers to.
7 of the 11 write state and require idempotency_key. The other 4 are reads. adcp_version on the wire takes "3.1": the patch component of 3.1.13 identifies the bundle of schema files these tables describe and is never sent.
The order these are called in
Nothing in the registry declares a sequence. One order the schemas permit is get_products to discover inventory, then create_media_buy to commit budget to it, then sync_creatives to attach creatives, then update_media_buy for every later change, pausing included, then get_media_buy_delivery to read what ran. sync_creatives is not in this group: it lives in the creative group, and a buy with no creatives sits in pending_creatives and does not serve. The buy clears either by polling or by passing create_media_buy a push_notification_config.
The sync_* operations and log_event run alongside that sequence rather than inside it. They load the audiences, catalogs and conversion sources a buy refers to, and continue to be called long after the campaign is set up.
What the 11 media buy operations do
| Operation | Request fields | Response fields | What it does |
|---|---|---|---|
create_media_buy | 22 | 13 | create_media_buy task — create advertising campaigns in AdCP from discovered products. |
get_media_buy_delivery | 14 | 26 | get_media_buy_delivery task — retrieve impressions, spend, pacing, and dimensional breakdowns for active AdCP campaigns. |
get_media_buys | 12 | 18 | get_media_buys task — retrieve media buy status in AdCP including creative approvals, missing assets, configuration, and optional near-real-time delivery snapshots. |
get_products | 20 | 29 | get_products task — discover advertising inventory in AdCP using natural language campaign briefs or structured filters. |
list_creative_formats | 20 | 20 | Request parameters for discovering supported creative formats |
log_event | 8 | 13 | log_event task — send conversion and marketing events to AdCP sellers in batches. |
provide_performance_feedback | 12 | 13 | provide_performance_feedback task — share normalized performance scores with AdCP publishers so sellers can optimize delivery based on buyer-observed outcomes. |
sync_audiences | 8 | 13 | sync_audiences task — upload hashed first-party CRM audiences to AdCP seller accounts for retargeting, suppression, and lookalike expansion. |
sync_catalogs | 12 | 13 | sync_catalogs task — sync product feeds, store locations, and vertical catalogs (hotel, flight, vehicle, real estate) to AdCP seller accounts for catalog-driven campaigns. |
sync_event_sources | 8 | 13 | sync_event_sources task — configure website pixels, mobile SDKs, server-to-server integrations, and seller- or platform-native event sources on AdCP seller accounts for conversion tracking and attribution. |
update_media_buy | 18 | 13 | update_media_buy task — modify active AdCP campaigns with PATCH semantics. |
Response shape for writes and reads
A client generated from these schemas types cleanly on the read side. Every write returns a union that has to be discriminated in client code. 7 of the 11 responses declare no fields of their own, so their response column repeats the same 13 envelope fields.
Every operation except report_plan_outcome and check_governance returns the full envelope. 13 keys, four of which carry the protocol behaviour: task_id to follow asynchronous work, status for the lifecycle of the task itself, adcp_error for fatal failures, and payload, which core/protocol-envelope.json calls a documentary construct and states is not a required wire field. Version, context and governance keys make up the rest.
In dist/schemas/3.1.13/media-buy/create-media-buy-response.json, properties is an empty object and the shape sits in three oneOf branches named CreateMediaBuySuccess, CreateMediaBuyError and CreateMediaBuySubmitted. Every operation declaring x-mutates-state: true carries its result in a branch like that. The 4 that omit the annotation put the result at the top level, where get_products returns products and get_media_buys returns media_buys.
Those same 7 are the only operations here that require idempotency_key. The annotation is opt-in and absent on reads rather than set false, so its absence carries no guarantee: si_terminate_session and comply_test_controller mutate state without requiring idempotency_key. Whether a call requires the key is stated in its request schema, not inferred from x-mutates-state.
<code>status</code> versus <code>media_buy_status</code>
status describes the task, not the object the task acted on. A media buy's own state (pending_creatives, pending_start, active, paused, completed, rejected, canceled) moved to media_buy_status in 3.1, and the response schema states it: "the status key is reserved for the envelope TaskStatus". Polling status returns the state of the last request, not the state of the campaign.
What the documentation tree lists
Membership of this group is decided by one file, dist/schemas/3.1.13/index.json, and no page in the documentation tree lists the same 11 operations. docs/media-buy/task-reference/index.mdx lists 13 tasks under All Tasks Overview: three of them (get_adcp_capabilities, sync_creatives, list_creatives) are registered under other schema groups, and the sales-agent list_creative_formats, which the registry does file under media buy, is absent from that table.
delete_missing turns a sync into a delete
All three sync_* operations here accept delete_missing, and it defaults off. Set it and the request stops being an upsert: it becomes the complete desired state of that collection on the account named in the required account field, and anything omitted is removed. The schema states the effect: "buyer-managed catalogs on the account not included in this sync will be removed".
The schema defines no way to signal a partial payload, so a request truncated by a client-side pagination failure removes every item it omitted. sync_catalogs accepts dry_run to rehearse against; sync_audiences and sync_event_sources do not.
Asynchronous replies and callbacks
4 operations here accept push_notification_config (create_media_buy, get_products, sync_catalogs, update_media_buy), and those are the 4 here with a published async response arm, out of seven registry-wide that publish one. sync_audiences is the exception: it can answer with a SyncAudiencesSubmitted branch, so it can defer, but it carries no push config, so no callback can be requested for it.
What a version pin covers
media_buy_status arriving in 3.1 was a permitted change. AdCP numbers releases VERSION.RELEASE.PATCH, and docs/reference/versioning.mdx allows a release to change schema at the margins: flip a field between required and optional, rename one with a documented alias, tighten validation, deprecate an object when its replacement ships in the same release. The compensating guarantee is that "implementations built against 3.0 will continue to function against any 3.x release".
Negotiation runs at release precision. The spec rejects an adcp_version value carrying a patch component, so a client pins to the release, sends "3.1", and can expect field-level movement inside it.
Two different operations are called list_creative_formats
list_creative_formats is registered twice in 3.1.13, once here and once in the creative group, against request schemas that differ. The variant documented here is the media buy version; both are set out on the schema registry page.
create_media_buy
create_media_buy task — create advertising campaigns in AdCP from discovered products.
Every field and edge case for create_media_buy
create_media_buy request — 22 fields, 5 required
| Field | Type | Required | Description |
|---|---|---|---|
adcp_version | string | Release-precision AdCP version (VERSION.RELEASE, e.g. | |
adcp_major_version | integer | DEPRECATED in favor of adcp_version (release-precision string). | |
idempotency_key | string | required | Client-generated unique key for this request. |
plan_id | string | Campaign governance plan identifier. | |
account | account-ref | required | Account to bill for this media buy. |
proposal_id | string | ID of a committed proposal from get_products to execute. | |
total_budget | object | Total budget for the media buy when executing a proposal. | |
packages | package-request[] | Array of package configurations. | |
brand | brand-ref | required | Brand reference for this media buy. |
advertiser_industry | advertiser-industry | Industry classification for this specific campaign. One of: automotive, automotive.electric_vehicles, automotive.parts_accessories, automotive.luxury, beauty_cosmetics, beauty_cosmetics.skincare, beauty_cosmetics.fragrance, beauty_cosmetics.haircare, cannabis, cpg, cpg.personal_care, cpg.household, dating, education, education.higher_education, education.online_learning, education.k12, energy_utilities, energy_utilities.renewable, fashion_apparel, fashion_apparel.luxury, fashion_apparel.sportswear, finance, finance.banking. | |
invoice_recipient | business-entity | Override the account's default billing entity for this specific buy. | |
io_acceptance | object | Acceptance of an insertion order from a committed proposal. | |
po_number | string | Purchase order number for tracking | |
agency_estimate_number | string | Agency estimate or authorization number. | |
start_time | start-timing | required | Campaign start timing: 'asap' or ISO 8601 date-time |
end_time | string | required | Campaign end date/time in ISO 8601 format |
paused | boolean | Create the media buy in a paused delivery state. | |
push_notification_config | push-notification-config | Optional webhook configuration for async task status notifications. | |
reporting_webhook | reporting-webhook | Optional webhook configuration for automated reporting delivery | |
artifact_webhook | object | Optional webhook configuration for content artifact delivery. | |
context | context | Opaque correlation data that is echoed unchanged in responses. | |
ext | ext | Extension object for platform-specific, vendor-namespaced parameters. |
| Field | Type | Required | Description |
|---|---|---|---|
adcp_version | string | Release-precision AdCP version (VERSION.RELEASE, e.g. | |
adcp_major_version | integer | DEPRECATED in favor of adcp_version (release-precision string). | |
context_id | string | Session/conversation identifier for tracking related operations across multiple task invocations. | |
context | context | Per-request opaque caller-supplied correlation object echoed unchanged in the response. | |
task_id | string | Unique identifier for tracking asynchronous operations. | |
status | task-status | required | Current task execution state. One of: submitted, working, input-required, completed, canceled, failed, rejected, auth-required, unknown. |
message | string | Human-readable summary of the task result. | |
timestamp | string | ISO 8601 timestamp when the response was generated. | |
replayed | boolean | Set to true when this response was returned from the idempotency cache rather than from a fresh execution. | |
adcp_error | error | Transport-envelope error signal for fatal task failures. | |
push_notification_config | push-notification-config | Push notification configuration for async task updates (A2A and REST protocols). | |
governance_context | string | Governance context token issued by the account's governance agent during check_governance. | |
payload | object | 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). |
import { testAgent } from '@adcp/sdk/testing';
import { CreateMediaBuyResponseSchema } from '@adcp/sdk';
// Calculate dates dynamically - start tomorrow, end in 90 days
const tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 1);
tomorrow.setHours(0, 0, 0, 0);
const endDate = new Date(tomorrow);
endDate.setDate(endDate.getDate() + 90);
const result = await testAgent.createMediaBuy({
brand: {
domain: 'acmecorp.com'
},
packages: [
{
product_id: 'prod_d979b543',
pricing_option_id: 'cpm_usd_auction',
format_option_refs: [{ scope: 'product', format_option_id: 'display_300x250_image' }],
budget: 2500,
bidding: { bid_amount: 5.00 }
},
{
product_id: 'prod_e8fd6012',
pricing_option_id: 'cpm_usd_auction',
format_option_refs: [{ scope: 'product', format_option_id: 'display_300x250_html' }],
budget: 2500,
bidding: { bid_amount: 4.50 }
}
],
start_time: tomorrow.toISOString(),
end_time: endDate.toISOString()
});
if (!result.success) {
throw new Error(`Request failed: ${result.error}`);
}
// Validate response against schema
const validated = CreateMediaBuyResponseSchema.parse(result.data);
// Check for errors (discriminated union response)
if ('errors' in validated && validated.errors) {
throw new Error(`Failed to create media buy: ${JSON.stringify(validated.errors)}`);
}
if ('media_buy_id' in validated) {
console.log(`Created media buy ${validated.media_buy_id}`);
console.log(`Upload creatives by: ${validated.creative_deadline}`);
console.log(`Packages created: ${validated.packages.length}`);
} get_media_buy_delivery
get_media_buy_delivery task — retrieve impressions, spend, pacing, and dimensional breakdowns for active AdCP campaigns.
| Field | Type | Required | Description |
|---|---|---|---|
adcp_version | string | Release-precision AdCP version (VERSION.RELEASE, e.g. | |
adcp_major_version | integer | DEPRECATED in favor of adcp_version (release-precision string). | |
account | account-ref | Filter delivery data to a specific account. | |
media_buy_ids | string[] | Array of media buy IDs to get delivery data for | |
status_filter | one of several | Filter by status. | |
start_date | string | Start date for reporting period (YYYY-MM-DD). | |
end_date | string | End date for reporting period (YYYY-MM-DD). | |
include_package_daily_breakdown | boolean | When true, include daily_breakdown arrays within each package in by_package. | |
time_granularity | reporting-frequency | Per-window slice granularity for the pull, using the same vocabulary as reporting_webhook.reporting_frequency. One of: hourly, daily, monthly. | |
include_window_breakdown | boolean | When true, the response includes media_buy_deliveries[].windows[] — an array of per-window delivery slices over the date range at the requested time_granularity. | |
attribution_window | object | Attribution window to apply for conversion metrics. | |
reporting_dimensions | object | Request dimensional breakdowns in delivery reporting. | |
context | context | Opaque correlation data that is echoed unchanged in responses. | |
ext | ext | Extension object for platform-specific, vendor-namespaced parameters. |
get_media_buy_delivery response — 26 fields, 4 required
| Field | Type | Required | Description |
|---|---|---|---|
adcp_version | string | Release-precision AdCP version (VERSION.RELEASE, e.g. | |
adcp_major_version | integer | DEPRECATED in favor of adcp_version (release-precision string). | |
context_id | string | Session/conversation identifier for tracking related operations across multiple task invocations. | |
context | context | Opaque correlation data that is echoed unchanged in responses. | |
task_id | string | Unique identifier for tracking asynchronous operations. | |
status | task-status | required | Current task execution state. One of: submitted, working, input-required, completed, canceled, failed, rejected, auth-required, unknown. |
message | string | Human-readable summary of the task result. | |
timestamp | string | ISO 8601 timestamp when the response was generated. | |
replayed | boolean | Set to true when this response was returned from the idempotency cache rather than from a fresh execution. | |
adcp_error | error | Transport-envelope error signal for fatal task failures. | |
push_notification_config | push-notification-config | Push notification configuration for async task updates (A2A and REST protocols). | |
governance_context | string | Governance context token issued by the account's governance agent during check_governance. | |
payload | object | 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). | |
notification_type | string | Type of webhook notification (only present in webhook deliveries): scheduled = regular periodic update, final = campaign completed, delayed = data not yet available, adjusted = resending period with corrected data (same… One of: scheduled, final, delayed, adjusted, window_update. | |
partial_data | boolean | Indicates if any media buys in this webhook have missing/delayed data (only present in webhook deliveries) | |
unavailable_count | integer | Number of media buys with reporting_delayed or failed status (only present in webhook deliveries when partial_data is true) | |
sequence_number | integer | Sequential notification number (only present in webhook deliveries, starts at 1) | |
next_expected_at | string | ISO 8601 timestamp for next expected notification (only present in webhook deliveries when notification_type is not 'final') | |
reporting_period | object | required | Date range for the report. |
currency | string | required | ISO 4217 currency code |
attribution_window | attribution-window | Attribution methodology and lookback windows used for conversion metrics in this response. | |
aggregated_totals | object | Combined metrics across all returned media buys. | |
media_buy_deliveries | object[] | required | Array of delivery data for media buys. |
errors | error[] | Task-specific errors and warnings (e.g., missing delivery data, reporting platform issues) | |
sandbox | boolean | When true, this response contains simulated data from sandbox mode. | |
ext | ext | Extension object for platform-specific, vendor-namespaced parameters. |
{
"aggregated_totals": {
"impressions": 1000000,
"spend": 5000.00,
"media_buy_count": 3,
"metric_aggregates": [
{
"scope": "standard",
"metric_id": "viewable_rate",
"qualifier": { "viewability_standard": "mrc" },
"value": 0.7286,
"measurable_impressions": 700000,
"viewable_impressions": 510000
},
{
"scope": "standard",
"metric_id": "viewable_rate",
"qualifier": { "viewability_standard": "groupm" },
"value": 0.55,
"measurable_impressions": 180000,
"viewable_impressions": 99000
}
]
}
} get_media_buys
get_media_buys task — retrieve media buy status in AdCP including creative approvals, missing assets, configuration, and optional near-real-time delivery snapshots.
| Field | Type | Required | Description |
|---|---|---|---|
adcp_version | string | Release-precision AdCP version (VERSION.RELEASE, e.g. | |
adcp_major_version | integer | DEPRECATED in favor of adcp_version (release-precision string). | |
account | account-ref | Account to retrieve media buys for. | |
media_buy_ids | string[] | Array of media buy IDs to retrieve. | |
status_filter | one of several | Filter by status. | |
include_snapshot | boolean | When true, include a near-real-time delivery snapshot for each package. | |
include_history | integer | When present, include the last N revision history entries for each media buy (returns min(N, available entries)). | |
include_webhook_activity | boolean | When true, each returned media buy includes a `webhook_activity` array describing recent delivery-report webhook fires for the calling principal. | |
webhook_activity_limit | integer | Maximum number of webhook delivery records to return per media buy, ordered most-recent first. | |
pagination | pagination-request | Cursor-based pagination controls. | |
context | context | Opaque correlation data that is echoed unchanged in responses. | |
ext | ext | Extension object for platform-specific, vendor-namespaced parameters. |
| Field | Type | Required | Description |
|---|---|---|---|
adcp_version | string | Release-precision AdCP version (VERSION.RELEASE, e.g. | |
adcp_major_version | integer | DEPRECATED in favor of adcp_version (release-precision string). | |
context_id | string | Session/conversation identifier for tracking related operations across multiple task invocations. | |
context | context | Opaque correlation data that is echoed unchanged in responses. | |
task_id | string | Unique identifier for tracking asynchronous operations. | |
status | task-status | required | Current task execution state. One of: submitted, working, input-required, completed, canceled, failed, rejected, auth-required, unknown. |
message | string | Human-readable summary of the task result. | |
timestamp | string | ISO 8601 timestamp when the response was generated. | |
replayed | boolean | Set to true when this response was returned from the idempotency cache rather than from a fresh execution. | |
adcp_error | error | Transport-envelope error signal for fatal task failures. | |
push_notification_config | push-notification-config | Push notification configuration for async task updates (A2A and REST protocols). | |
governance_context | string | Governance context token issued by the account's governance agent during check_governance. | |
payload | object | 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). | |
media_buys | object[] | required | Array of media buys with status, creative approval state, and optional delivery snapshots |
errors | error[] | Task-specific errors (e.g., media buy not found) | |
pagination | pagination-response | Pagination metadata for the media_buys array. | |
sandbox | boolean | When true, this response contains simulated data from sandbox mode. | |
ext | ext | Extension object for platform-specific, vendor-namespaced parameters. |
import { testAgent } from '@adcp/sdk/testing';
import { GetMediaBuysResponseSchema, type WebhookActivityRecord } from '@adcp/sdk';
// The WebhookActivityRecord type is regenerated by the SDK from
// /schemas/core/webhook-activity-record.json — once the SDK rebuilds against this
// branch's schemas the import resolves. The same type appears on every AdCP resource
// that surfaces webhook_activity[], so debug helpers can be written once and reused.
function latestAttempt(trail: WebhookActivityRecord[]): WebhookActivityRecord {
return trail.reduce((a, b) => (a.attempt >= b.attempt ? a : b));
}
const result = await testAgent.getMediaBuys({
media_buy_ids: ['mb_12345'],
include_webhook_activity: true,
webhook_activity_limit: 20,
});
if (!result.success) {
throw new Error(`Request failed: ${result.error}`);
}
const validated = GetMediaBuysResponseSchema.parse(result.data);
for (const mediaBuy of validated.media_buys) {
// Three-state semantics — distinguish "seller does not surface" from "no recent fires".
if (mediaBuy.webhook_activity === undefined) {
console.log(`${mediaBuy.media_buy_id}: seller does not surface webhook activity for this buy`);
continue;
}
const fires = mediaBuy.webhook_activity;
if (fires.length === 0) {
console.log(`${mediaBuy.media_buy_id}: no recent fires for this principal`);
continue;
}
// Group attempts by idempotency_key so we can see the retry trail per logical fire.
const trails = new Map();
for (const fire of fires) {
const trail = trails.get(fire.idempotency_key) ?? [];
trail.push(fire);
trails.set(fire.idempotency_key, trail);
}
for (const [idempotencyKey, trail] of trails) {
// Pick the latest attempt by `attempt` number — robust against any iteration order.
const latest = latestAttempt(trail);
if (latest.status === 'success') continue;
const detail = latest.error_message ?? latest.http_status_code ?? '—';
console.log(
`${mediaBuy.media_buy_id} ${idempotencyKey} ` +
`(${latest.notification_type} seq=${latest.sequence_number}): ` +
`${latest.status} after ${trail.length} attempt(s) — ${detail}`
);
}
} get_products
get_products task — discover advertising inventory in AdCP using natural language campaign briefs or structured filters.
Every field and edge case for get_products
get_products request — 20 fields, 1 required
| Field | Type | Required | Description |
|---|---|---|---|
adcp_version | string | Release-precision AdCP version (VERSION.RELEASE, e.g. | |
adcp_major_version | integer | DEPRECATED in favor of adcp_version (release-precision string). | |
buying_mode | string | required | Declares buyer intent for this request. One of: brief, wholesale, refine. |
brief | string | Natural language description of campaign requirements. | |
refine | object[] | Array of change requests for iterating on products and proposals from a previous get_products response. | |
brand | brand-ref | Brand reference for product discovery context. | |
catalog | catalog | Catalog of items the buyer wants to promote. | |
account | account-ref | Account for product lookup. | |
preferred_delivery_types | delivery-type[] | Delivery types the buyer prefers, in priority order. | |
filters | product-filters | Structured filters for product discovery | |
property_list | property-list-ref | [AdCP 3.0] Reference to an externally managed property list. | |
fields | string[] | Specific product fields to include in the response. One of: product_id, name, description, publisher_properties, channels, video_placement_types, audio_distribution_types, sponsored_placement_types, social_placement_surfaces, format_ids, format_options, placements, delivery_type, exclusivity, pricing_options, forecast, outcome_measurement, delivery_measurement, reporting_capabilities, creative_policy, catalog_types, metric_optimization, conversion_tracking, data_provider_signals. | |
time_budget | object | Maximum time the buyer will commit to this request. | |
push_notification_config | push-notification-config | Optional webhook configuration for async terminal completion/failure notifications on curated discovery. | |
pagination | pagination-request | Cursor-based pagination controls for get_products. | |
if_wholesale_feed_version | string | Opaque wholesale_feed_version token returned by a prior wholesale-mode get_products response from this agent. | |
if_pricing_version | string | Opaque pricing_version token from a prior get_products response. | |
context | context | Opaque correlation data that is echoed unchanged in responses. | |
required_policies | string[] | Registry policy IDs that the buyer requires to be enforced for products in this response. | |
ext | ext | Extension object for platform-specific, vendor-namespaced parameters. |
get_products response — 29 fields, 1 required
| Field | Type | Required | Description |
|---|---|---|---|
adcp_version | string | Release-precision AdCP version (VERSION.RELEASE, e.g. | |
adcp_major_version | integer | DEPRECATED in favor of adcp_version (release-precision string). | |
context_id | string | Session/conversation identifier for tracking related operations across multiple task invocations. | |
context | context | Opaque correlation data that is echoed unchanged in responses. | |
task_id | string | Unique identifier for tracking asynchronous operations. | |
status | task-status | required | Current task execution state. One of: submitted, working, input-required, completed, canceled, failed, rejected, auth-required, unknown. |
message | string | Human-readable summary of the task result. | |
timestamp | string | ISO 8601 timestamp when the response was generated. | |
replayed | boolean | Set to true when this response was returned from the idempotency cache rather than from a fresh execution. | |
adcp_error | error | Transport-envelope error signal for fatal task failures. | |
push_notification_config | push-notification-config | Push notification configuration for async task updates (A2A and REST protocols). | |
governance_context | string | Governance context token issued by the account's governance agent during check_governance. | |
payload | object | 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). | |
products | product[] | Array of matching products | |
extensions | object | Bundled platform-extension definitions referenced by any product in `products`. | |
proposals | proposal[] | Optional array of proposed media plans with budget allocations across products. | |
errors | error[] | Task-specific errors and warnings (e.g., product filtering issues) | |
property_list_applied | boolean | [AdCP 3.0] Indicates whether property_list filtering was applied. | |
catalog_applied | boolean | Whether the seller filtered results based on the provided catalog. | |
refinement_applied | object[] | Seller's response to each change request in the refine array, matched by position. | |
incomplete | object[] | Declares what the seller could not finish within the buyer's time_budget or due to internal limits. | |
filter_diagnostics | object | Optional non-fatal diagnostic block describing how the request's `filters` narrowed the candidate set. | |
pagination | pagination-response | Cursor metadata for paginated get_products responses. | |
wholesale_feed_version | string | Opaque token representing the version of the wholesale product feed state used to compose this response. | |
pricing_version | string | Opaque token representing the version of the pricing layer, including product pricing_options and nested signal_targeting_options pricing_options. | |
cache_scope | string | Declares whether the wholesale_feed_version and pricing_version on this response describe a universal layer or an account-specific overlay. One of: public, account. | |
unchanged | boolean | Present and `true` ONLY on wholesale-mode responses when the request carried if_wholesale_feed_version (and/or if_pricing_version) matching the seller's current version for the buyer's cache_scope, in which case product… | |
sandbox | boolean | When true, this response contains simulated data from sandbox mode. | |
ext | ext | Extension object for platform-specific, vendor-namespaced parameters. |
import { testAgent } from '@adcp/sdk/testing';
import { GetProductsResponseSchema } from '@adcp/sdk';
const result = await testAgent.getProducts({
buying_mode: 'brief',
brief: 'Premium athletic footwear with innovative cushioning',
brand: {
domain: 'acmecorp.com'
}
});
if (!result.success) {
throw new Error(`Request failed: ${result.error}`);
}
// Validate response against schema
const validated = GetProductsResponseSchema.parse(result.data);
if (validated.status === 'rejected') {
console.log(`Seller declined the brief: ${validated.reason}`);
for (const suggestion of validated.suggestions ?? []) {
console.log(`- ${suggestion}`);
}
} else {
console.log(`Found ${validated.products.length} products`);
// Access validated product fields
for (const product of validated.products) {
console.log(`- ${product.name} (${product.delivery_type})`);
console.log(` Formats: ${product.format_options.map(option => option.format_kind).join(', ')}`);
}
} list_creative_formats
Request parameters for discovering supported creative formats
list_creative_formats request — 20 fields, 0 required
| Field | Type | Required | Description |
|---|---|---|---|
adcp_version | string | Release-precision AdCP version (VERSION.RELEASE, e.g. | |
adcp_major_version | integer | DEPRECATED in favor of adcp_version (release-precision string). | |
format_ids | format-id[] | Return only these specific format IDs (e.g., from get_products response) | |
asset_types | asset-content-type[] | Filter to formats that include these asset types. | |
max_width | integer | Maximum width in pixels (inclusive). | |
max_height | integer | Maximum height in pixels (inclusive). | |
min_width | integer | Minimum width in pixels (inclusive). | |
min_height | integer | Minimum height in pixels (inclusive). | |
is_responsive | boolean | Filter for responsive formats that adapt to container size. | |
name_search | string | Search for formats by name (case-insensitive partial match) | |
publisher_domain | string | Filter to formats supported by the named publisher. | |
property_id | property-id | Filter to formats supported on the named property within the publisher's catalog. | |
wcag_level | wcag-level | Filter to formats that meet at least this WCAG conformance level (A < AA < AAA) One of: A, AA, AAA. | |
disclosure_positions | disclosure-position[] | Filter to formats that support all of these disclosure positions. | |
disclosure_persistence | disclosure-persistence[] | Filter to formats where each requested persistence mode is supported by at least one position in disclosure_capabilities. | |
output_format_ids | format-id[] | Filter to formats whose output_format_ids includes any of these format IDs. | |
input_format_ids | format-id[] | Filter to formats whose input_format_ids includes any of these format IDs. | |
pagination | pagination-request | Standard cursor-based pagination parameters for list operations | |
context | context | Opaque correlation data that is echoed unchanged in responses. | |
ext | ext | Extension object for platform-specific, vendor-namespaced parameters. |
list_creative_formats response — 20 fields, 2 required
| Field | Type | Required | Description |
|---|---|---|---|
adcp_version | string | Release-precision AdCP version (VERSION.RELEASE, e.g. | |
adcp_major_version | integer | DEPRECATED in favor of adcp_version (release-precision string). | |
context_id | string | Session/conversation identifier for tracking related operations across multiple task invocations. | |
context | context | Opaque correlation data that is echoed unchanged in responses. | |
task_id | string | Unique identifier for tracking asynchronous operations. | |
status | task-status | required | Current task execution state. One of: submitted, working, input-required, completed, canceled, failed, rejected, auth-required, unknown. |
message | string | Human-readable summary of the task result. | |
timestamp | string | ISO 8601 timestamp when the response was generated. | |
replayed | boolean | Set to true when this response was returned from the idempotency cache rather than from a fresh execution. | |
adcp_error | error | Transport-envelope error signal for fatal task failures. | |
push_notification_config | push-notification-config | Push notification configuration for async task updates (A2A and REST protocols). | |
governance_context | string | Governance context token issued by the account's governance agent during check_governance. | |
payload | object | 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). | |
formats | format[] | required | Full format definitions for all formats this agent supports. |
source | string | Which tier of the resolution order produced this `formats[]` list when the request carried a `publisher_domain` filter. One of: publisher, aao_mirror, agent_derived. | |
creative_agents | object[] | Optional: Creative agents that provide additional formats. | |
errors | error[] | Task-specific errors and warnings (e.g., format availability issues) | |
pagination | pagination-response | Standard cursor-based pagination metadata for list responses | |
sandbox | boolean | When true, this response contains simulated data from sandbox mode. | |
ext | ext | Extension object for platform-specific, vendor-namespaced parameters. |
log_event
log_event task — send conversion and marketing events to AdCP sellers in batches.
| Field | Type | Required | Description |
|---|---|---|---|
adcp_version | string | Release-precision AdCP version (VERSION.RELEASE, e.g. | |
adcp_major_version | integer | DEPRECATED in favor of adcp_version (release-precision string). | |
event_source_id | string | required | Event source configured on the account via sync_event_sources |
test_event_code | string | Test event code for validation without affecting production data. | |
events | event[] | required | Events to log |
idempotency_key | string | required | Client-generated unique key for this request. |
context | context | Opaque correlation data that is echoed unchanged in responses. | |
ext | ext | Extension object for platform-specific, vendor-namespaced parameters. |
| Field | Type | Required | Description |
|---|---|---|---|
adcp_version | string | Release-precision AdCP version (VERSION.RELEASE, e.g. | |
adcp_major_version | integer | DEPRECATED in favor of adcp_version (release-precision string). | |
context_id | string | Session/conversation identifier for tracking related operations across multiple task invocations. | |
context | context | Per-request opaque caller-supplied correlation object echoed unchanged in the response. | |
task_id | string | Unique identifier for tracking asynchronous operations. | |
status | task-status | required | Current task execution state. One of: submitted, working, input-required, completed, canceled, failed, rejected, auth-required, unknown. |
message | string | Human-readable summary of the task result. | |
timestamp | string | ISO 8601 timestamp when the response was generated. | |
replayed | boolean | Set to true when this response was returned from the idempotency cache rather than from a fresh execution. | |
adcp_error | error | Transport-envelope error signal for fatal task failures. | |
push_notification_config | push-notification-config | Push notification configuration for async task updates (A2A and REST protocols). | |
governance_context | string | Governance context token issued by the account's governance agent during check_governance. | |
payload | object | 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). |
import { testAgent } from "@adcp/sdk/testing";
import { LogEventResponseSchema } from "@adcp/sdk";
const result = await testAgent.logEvent({
event_source_id: "website_pixel",
events: [
{
event_id: "evt_purchase_12345",
event_type: "purchase",
event_time: "2026-01-15T14:30:00Z",
action_source: "website",
event_source_url: "https://www.example.com/checkout/confirm",
user_match: {
click_id: "abc123def456",
click_id_type: "gclid",
},
custom_data: {
value: 149.99,
currency: "USD",
order_id: "order_98765",
num_items: 3,
},
},
],
});
if (!result.success) {
throw new Error(`Request failed: ${result.error}`);
}
// Validate response against schema
const validated = LogEventResponseSchema.parse(result.data);
// Check for operation-level errors first (discriminated union)
if ("errors" in validated && validated.errors) {
throw new Error(`Operation failed: ${JSON.stringify(validated.errors)}`);
}
if ("events_received" in validated) {
console.log(`Received: ${validated.events_received}, Processed: ${validated.events_processed}`);
if (validated.match_quality !== undefined) {
console.log(`Match quality: ${(validated.match_quality * 100).toFixed(0)}%`);
}
} provide_performance_feedback
provide_performance_feedback task — share normalized performance scores with AdCP publishers so sellers can optimize delivery based on buyer-observed outcomes.
| Field | Type | Required | Description |
|---|---|---|---|
adcp_version | string | Release-precision AdCP version (VERSION.RELEASE, e.g. | |
adcp_major_version | integer | DEPRECATED in favor of adcp_version (release-precision string). | |
media_buy_id | string | required | Seller's media buy identifier |
idempotency_key | string | required | Client-generated unique key for this request. |
measurement_period | datetime-range | required | Time period for performance measurement |
performance_index | number | required | Normalized performance score (0.0 = no value, 1.0 = expected, >1.0 = above expected) |
package_id | string | Specific package within the media buy (if feedback is package-specific) | |
creative_id | string | Specific creative asset (if feedback is creative-specific) | |
metric_type | metric-type | The business metric being measured One of: overall_performance, conversion_rate, brand_lift, click_through_rate, completion_rate, viewability, brand_safety, cost_efficiency. | |
feedback_source | feedback-source | Source of the performance data One of: buyer_attribution, third_party_measurement, platform_analytics, verification_partner. | |
context | context | Opaque correlation data that is echoed unchanged in responses. | |
ext | ext | Extension object for platform-specific, vendor-namespaced parameters. |
| Field | Type | Required | Description |
|---|---|---|---|
adcp_version | string | Release-precision AdCP version (VERSION.RELEASE, e.g. | |
adcp_major_version | integer | DEPRECATED in favor of adcp_version (release-precision string). | |
context_id | string | Session/conversation identifier for tracking related operations across multiple task invocations. | |
context | context | Per-request opaque caller-supplied correlation object echoed unchanged in the response. | |
task_id | string | Unique identifier for tracking asynchronous operations. | |
status | task-status | required | Current task execution state. One of: submitted, working, input-required, completed, canceled, failed, rejected, auth-required, unknown. |
message | string | Human-readable summary of the task result. | |
timestamp | string | ISO 8601 timestamp when the response was generated. | |
replayed | boolean | Set to true when this response was returned from the idempotency cache rather than from a fresh execution. | |
adcp_error | error | Transport-envelope error signal for fatal task failures. | |
push_notification_config | push-notification-config | Push notification configuration for async task updates (A2A and REST protocols). | |
governance_context | string | Governance context token issued by the account's governance agent during check_governance. | |
payload | object | 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). |
{
"success": "boolean",
"message": "string"
} sync_audiences
sync_audiences task — upload hashed first-party CRM audiences to AdCP seller accounts for retargeting, suppression, and lookalike expansion.
| Field | Type | Required | Description |
|---|---|---|---|
adcp_version | string | Release-precision AdCP version (VERSION.RELEASE, e.g. | |
adcp_major_version | integer | DEPRECATED in favor of adcp_version (release-precision string). | |
idempotency_key | string | required | Client-generated unique key for at-most-once execution. |
account | account-ref | required | Account to manage audiences for. |
audiences | object[] | Audiences to sync (create or update). | |
delete_missing | boolean | When true, buyer-managed audiences on the account not included in this sync will be removed. | |
context | context | Opaque correlation data that is echoed unchanged in responses. | |
ext | ext | Extension object for platform-specific, vendor-namespaced parameters. |
| Field | Type | Required | Description |
|---|---|---|---|
adcp_version | string | Release-precision AdCP version (VERSION.RELEASE, e.g. | |
adcp_major_version | integer | DEPRECATED in favor of adcp_version (release-precision string). | |
context_id | string | Session/conversation identifier for tracking related operations across multiple task invocations. | |
context | context | Per-request opaque caller-supplied correlation object echoed unchanged in the response. | |
task_id | string | Unique identifier for tracking asynchronous operations. | |
status | task-status | required | Current task execution state. One of: submitted, working, input-required, completed, canceled, failed, rejected, auth-required, unknown. |
message | string | Human-readable summary of the task result. | |
timestamp | string | ISO 8601 timestamp when the response was generated. | |
replayed | boolean | Set to true when this response was returned from the idempotency cache rather than from a fresh execution. | |
adcp_error | error | Transport-envelope error signal for fatal task failures. | |
push_notification_config | push-notification-config | Push notification configuration for async task updates (A2A and REST protocols). | |
governance_context | string | Governance context token issued by the account's governance agent during check_governance. | |
payload | object | 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). |
import { testAgent } from "@adcp/sdk/testing";
import { SyncAudiencesResponseSchema } from "@adcp/sdk";
import { createHash } from "crypto";
const hashEmail = (email) =>
createHash("sha256").update(email.toLowerCase().trim()).digest("hex");
const hashPhone = (e164Phone) =>
createHash("sha256").update(e164Phone).digest("hex");
const result = await testAgent.syncAudiences({
account: { account_id: "acct_12345" },
audiences: [
{
audience_id: "existing_customers",
name: "Existing customers",
add: [
{ external_id: "crm_1001", hashed_email: hashEmail("alice@example.com") },
{ external_id: "crm_1002", hashed_email: hashEmail("bob@example.com"), hashed_phone: hashPhone("+12065551234") },
],
},
],
});
if (!result.success) {
throw new Error(`Request failed: ${result.error}`);
}
const validated = SyncAudiencesResponseSchema.parse(result.data);
// Three-shape discriminated union: errors | submitted | audiences
if ("status" in validated && validated.status === "submitted") {
// Whole sync queued asynchronously — poll tasks/get with task_id or await webhook
console.log(`Sync queued as task ${validated.task_id}: ${validated.message ?? ""}`);
} else if ("errors" in validated && validated.errors && !("audiences" in validated)) {
throw new Error(`Operation failed: ${JSON.stringify(validated.errors)}`);
} else if ("audiences" in validated) {
for (const audience of validated.audiences) {
console.log(`${audience.audience_id}: ${audience.action} (${audience.status ?? "n/a"})`);
if (audience.status === "ready") {
console.log(` Matched ${audience.matched_count} of ${audience.uploaded_count} members (this sync)`);
}
}
} sync_catalogs
sync_catalogs task — sync product feeds, store locations, and vertical catalogs (hotel, flight, vehicle, real estate) to AdCP seller accounts for catalog-driven campaigns.
| Field | Type | Required | Description |
|---|---|---|---|
adcp_version | string | Release-precision AdCP version (VERSION.RELEASE, e.g. | |
adcp_major_version | integer | DEPRECATED in favor of adcp_version (release-precision string). | |
idempotency_key | string | required | Client-generated unique key for at-most-once execution. |
account | account-ref | required | Account that owns these catalogs. |
catalogs | catalog[] | Array of catalog feeds to sync (create or update). | |
catalog_ids | string[] | Optional filter to limit sync scope to specific catalog IDs. | |
delete_missing | boolean | When true, buyer-managed catalogs on the account not included in this sync will be removed. | |
dry_run | boolean | When true, preview changes without applying them. | |
validation_mode | validation-mode | Validation strictness. One of: strict, lenient. | |
push_notification_config | push-notification-config | Optional webhook configuration for async sync notifications. | |
context | context | Opaque correlation data that is echoed unchanged in responses. | |
ext | ext | Extension object for platform-specific, vendor-namespaced parameters. |
| Field | Type | Required | Description |
|---|---|---|---|
adcp_version | string | Release-precision AdCP version (VERSION.RELEASE, e.g. | |
adcp_major_version | integer | DEPRECATED in favor of adcp_version (release-precision string). | |
context_id | string | Session/conversation identifier for tracking related operations across multiple task invocations. | |
context | context | Per-request opaque caller-supplied correlation object echoed unchanged in the response. | |
task_id | string | Unique identifier for tracking asynchronous operations. | |
status | task-status | required | Current task execution state. One of: submitted, working, input-required, completed, canceled, failed, rejected, auth-required, unknown. |
message | string | Human-readable summary of the task result. | |
timestamp | string | ISO 8601 timestamp when the response was generated. | |
replayed | boolean | Set to true when this response was returned from the idempotency cache rather than from a fresh execution. | |
adcp_error | error | Transport-envelope error signal for fatal task failures. | |
push_notification_config | push-notification-config | Push notification configuration for async task updates (A2A and REST protocols). | |
governance_context | string | Governance context token issued by the account's governance agent during check_governance. | |
payload | object | 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). |
{
"account": { "account_id": "acct_acmecorp" },
"catalogs": [
{
"catalog_id": "product-feed",
"name": "Acme Product Catalog",
"type": "product",
"url": "https://feeds.acmecorp.com/products.xml",
"feed_format": "google_merchant_center",
"update_frequency": "daily"
}
]
} sync_event_sources
sync_event_sources task — configure website pixels, mobile SDKs, server-to-server integrations, and seller- or platform-native event sources on AdCP seller accounts for conversion tracking and attribution.
| Field | Type | Required | Description |
|---|---|---|---|
adcp_version | string | Release-precision AdCP version (VERSION.RELEASE, e.g. | |
adcp_major_version | integer | DEPRECATED in favor of adcp_version (release-precision string). | |
idempotency_key | string | required | Client-generated unique key for at-most-once execution. |
account | account-ref | required | Account to configure event sources for. |
event_sources | object[] | Event sources to sync (create or update). | |
delete_missing | boolean | When true, event sources not included in this sync will be removed | |
context | context | Opaque correlation data that is echoed unchanged in responses. | |
ext | ext | Extension object for platform-specific, vendor-namespaced parameters. |
| Field | Type | Required | Description |
|---|---|---|---|
adcp_version | string | Release-precision AdCP version (VERSION.RELEASE, e.g. | |
adcp_major_version | integer | DEPRECATED in favor of adcp_version (release-precision string). | |
context_id | string | Session/conversation identifier for tracking related operations across multiple task invocations. | |
context | context | Per-request opaque caller-supplied correlation object echoed unchanged in the response. | |
task_id | string | Unique identifier for tracking asynchronous operations. | |
status | task-status | required | Current task execution state. One of: submitted, working, input-required, completed, canceled, failed, rejected, auth-required, unknown. |
message | string | Human-readable summary of the task result. | |
timestamp | string | ISO 8601 timestamp when the response was generated. | |
replayed | boolean | Set to true when this response was returned from the idempotency cache rather than from a fresh execution. | |
adcp_error | error | Transport-envelope error signal for fatal task failures. | |
push_notification_config | push-notification-config | Push notification configuration for async task updates (A2A and REST protocols). | |
governance_context | string | Governance context token issued by the account's governance agent during check_governance. | |
payload | object | 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). |
import { testAgent } from "@adcp/sdk/testing";
import { SyncEventSourcesResponseSchema } from "@adcp/sdk";
const result = await testAgent.syncEventSources({
account: { account_id: "acct_12345" },
event_sources: [
{
event_source_id: "website_pixel",
name: "Main Website Pixel",
event_types: ["purchase", "lead", "add_to_cart"],
allowed_domains: ["www.example.com", "shop.example.com"],
},
],
});
if (!result.success) {
throw new Error(`Request failed: ${result.error}`);
}
// Validate response against schema
const validated = SyncEventSourcesResponseSchema.parse(result.data);
// Check for operation-level errors first (discriminated union)
if ("errors" in validated && validated.errors) {
throw new Error(`Operation failed: ${JSON.stringify(validated.errors)}`);
}
if ("event_sources" in validated) {
for (const source of validated.event_sources) {
console.log(`${source.event_source_id}: ${source.action}`);
if (source.setup?.snippet) {
console.log(` Install: ${source.setup.snippet_type}`);
}
}
} update_media_buy
update_media_buy task — modify active AdCP campaigns with PATCH semantics.
| Field | Type | Required | Description |
|---|---|---|---|
adcp_version | string | Release-precision AdCP version (VERSION.RELEASE, e.g. | |
adcp_major_version | integer | DEPRECATED in favor of adcp_version (release-precision string). | |
account | account-ref | required | Account that owns this media buy. |
media_buy_id | string | required | Seller's ID of the media buy to update |
revision | integer | Expected current revision for optimistic concurrency. | |
paused | boolean | Pause/resume the entire media buy (true = paused, false = active) | |
canceled | boolean | Cancel the entire media buy. | |
cancellation_reason | string | Reason for cancellation. | |
start_time | start-timing | Campaign start timing: 'asap' or ISO 8601 date-time | |
end_time | string | New end date/time in ISO 8601 format | |
packages | package-update[] | Package-specific updates for existing packages | |
invoice_recipient | business-entity | Update who receives the invoice for this buy. | |
new_packages | package-request[] | New packages to add to this media buy. | |
reporting_webhook | reporting-webhook | Optional webhook configuration for automated reporting delivery. | |
push_notification_config | push-notification-config | Optional webhook configuration for async update notifications. | |
idempotency_key | string | required | Client-generated idempotency key for safe retries. |
context | context | Opaque correlation data that is echoed unchanged in responses. | |
ext | ext | Extension object for platform-specific, vendor-namespaced parameters. |
| Field | Type | Required | Description |
|---|---|---|---|
adcp_version | string | Release-precision AdCP version (VERSION.RELEASE, e.g. | |
adcp_major_version | integer | DEPRECATED in favor of adcp_version (release-precision string). | |
context_id | string | Session/conversation identifier for tracking related operations across multiple task invocations. | |
context | context | Per-request opaque caller-supplied correlation object echoed unchanged in the response. | |
task_id | string | Unique identifier for tracking asynchronous operations. | |
status | task-status | required | Current task execution state. One of: submitted, working, input-required, completed, canceled, failed, rejected, auth-required, unknown. |
message | string | Human-readable summary of the task result. | |
timestamp | string | ISO 8601 timestamp when the response was generated. | |
replayed | boolean | Set to true when this response was returned from the idempotency cache rather than from a fresh execution. | |
adcp_error | error | Transport-envelope error signal for fatal task failures. | |
push_notification_config | push-notification-config | Push notification configuration for async task updates (A2A and REST protocols). | |
governance_context | string | Governance context token issued by the account's governance agent during check_governance. | |
payload | object | 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). |
import { testAgent } from '@adcp/sdk/testing';
import { CreateMediaBuyResponseSchema, UpdateMediaBuyResponseSchema } from '@adcp/sdk';
// First, create a media buy to update
const uniqueRef = `test_campaign_${Date.now()}`;
// Use dates in the future
const startDate = new Date();
startDate.setDate(startDate.getDate() + 7); // Start 1 week from now
const endDate = new Date();
endDate.setDate(endDate.getDate() + 37); // End 5 weeks from now
const createResult = await testAgent.createMediaBuy({
brand: { domain: 'acmecorp.com' },
packages: [{
product_id: 'prod_d979b543',
pricing_option_id: 'cpm_usd_fixed',
format_option_refs: [{ scope: 'product', format_option_id: 'display_300x250_image' }],
budget: 800,
bidding: { bid_amount: 5.00 }
}],
start_time: startDate.toISOString(),
end_time: endDate.toISOString()
});
if (!createResult.success) {
throw new Error(`Create failed: ${createResult.error}`);
}
const created = CreateMediaBuyResponseSchema.parse(createResult.data);
if ('errors' in created && created.errors) {
throw new Error(`Create failed: ${JSON.stringify(created.errors)}`);
}
console.log(`Created media buy ${created.media_buy_id}`);
// Now update it - pause the campaign
const updateResult = await testAgent.updateMediaBuy({
account: { brand: { domain: 'acmecorp.com' }, operator: 'acmecorp.com' },
media_buy_id: created.media_buy_id,
revision: created.revision,
paused: true
});
if (!updateResult.success) {
throw new Error(`Update failed: ${updateResult.error}`);
}
const updated = UpdateMediaBuyResponseSchema.parse(updateResult.data);
if ('errors' in updated && updated.errors) {
throw new Error(`Update failed: ${JSON.stringify(updated.errors)}`);
}
console.log(`Campaign ${updated.media_buy_id} paused`); Pausing and cancelling a media buy
No operation name in the registry contains "pause", "stop" or "resume". The two names carrying a destructive verb are delete_property_list and delete_collection_list, and both act on governance lists rather than on campaigns.
Pause state is carried by a field. update_media_buy takes paused: true to hold the whole buy and paused: false to release it, and each entry in packages[] carries its own paused, so one package can be held while the rest keeps serving. A buy can also start held: create_media_buy accepts paused to "create the media buy in a paused delivery state".
canceled is declared "const": true, so true is the only value the schema accepts and no un-cancel is expressible. The description reads: "Cancellation is irreversible — canceled media buys cannot be reactivated. Sellers MAY reject with NOT_CANCELLABLE if the media buy cannot be canceled in its current state." NOT_CANCELLABLE is one of 92 codes in enums/error-code.json.
A paused buy reports the state in media_buy_status, one of that field's seven values, and not in the envelope's status.
Two agents editing the same buy
update_media_buy takes a revision. It is optional, for backward compatibility, and no other field in the protocol carries a concurrency token. When it is sent, the seller must reject a stale write with CONFLICT and must make that comparison atomically with the write. The value comes from get_media_buys or from the most recent create or update response.
If revision is omitted, the seller performs the write unconditionally. Concurrent updates resolve last-write-wins, both callers receive a success response, and no field records the overwrite. Where more than one system can modify a buy — a bidder and an operator in a UI — revision is the guard the protocol defines for it.
Conversion tracking: event sources, logging and feedback
sync_event_sources registers where events come from. A source supplies one required field, its event_source_id; the action_source tag (website, app, in_store and six others) is optional, as is everything else. The response returns a seller_id for each source, the seller's own handle for it, and a setup block carrying the tag or pixel URL that activates it. log_event then posts batches of events against an event_source_id, one of only three required fields on that request and the one that determines whether anything attributes.
get_media_buy_delivery takes an attribution_window and returns conversion metrics. provide_performance_feedback runs the other way: the buyer sends a performance_index to the seller so delivery can be optimised against outcomes the seller cannot observe. The score is normalised rather than absolute: 1.0 means the campaign performed as expected, and the schema sets a floor at 0 with no upper bound. Each submission is tagged with one of eight metric_type values and one of four feedback_source values. The upstream conversion-tracking guide stops earlier: its flow diagram ends at the delivery read, and provide_performance_feedback appears nowhere in it.
The other 9 AdCP areas
- Creative — 8 operations
- Signals — 2 operations
- Protocol — 3 operations
- Accounts — 5 operations
- Brand Protocol — 6 operations
- Governance — 22 operations
- Sponsored Intelligence — 4 operations
- Trusted Match — 2 operations
- Compliance — 1 operation