Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .changeset/experimental-token-spellings.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
"adcontextprotocol": minor
---

Give three experimental 3.3 values the spelling their stable or sibling counterpart already uses (adcp#8901). Each was spelled two ways for one concept, and the side that changes is experimental, added in 3.3 and only in the 3.3 betas.

- **`enums/execution-readiness-status.json` (`media_buy.execution_readiness`, #7934, beta.1 to beta.5):** `input_required` becomes `input-required`, the spelling of `enums/task-status.json`, which follows A2A's task states.
- **`enums/creative-change-kind.json` (`creative.live_updates`, #8488, beta.3 to beta.5):** `click_through` becomes `clickthrough`, the `url_type` value the change kind names in `enums/url-asset-type.json`.
- **`enums/delivery-projection-end-state.json` (`media_buy.delivery_projection`, #8043, beta.0 to beta.5):** `underdelivery` becomes `under_delivery`, the spelling of `enums/offer-reason.json`. DR-0029 is amended to the new spelling.

**This changes 3.3.0-beta.0 through beta.5; no stable release has these enums.** The values are renamed in place, with no alias: they are experimental, and the additive-minor check compares against 3.2.x, which has none of the three files. The betas are immutable, so a seller or buyer built from a beta bundle sends and accepts the new spelling: `readiness_status` and the product rollup, `creative.live_updates.in_place[].change`, `staged_update.change_kinds[]` and the `CREATIVE_LIVE_UPDATE_UNSUPPORTED` details, and `projection.projected_end_state`. The training agent classifies creative changes with `clickthrough`.

The consumed changesets for these features stay in `.changeset/pre/` as history.
4 changes: 2 additions & 2 deletions docs/creative/task-reference/sync_creatives.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -491,7 +491,7 @@ A creative is **live** when its `status` is `approved` and it has at least one a

| Kind | Changed fields |
|---|---|
| `click_through` | A `url` asset with `url_type: "clickthrough"` |
| `clickthrough` | A `url` asset with `url_type: "clickthrough"` |
| `trackers` | A `url` asset with `url_type` `tracker_pixel` or `tracker_script`, or a `pixel_tracker`, `vast_tracker`, or `daast_tracker` asset |
| `format` | `format_id`, `format_kind`, or `format_option_ref` |
| `asset_content` | Any other field of [canonical revision content](#creative-revisions), including future ones: any other asset (markup or VAST that embeds clicks or trackers included), `component_assets`, `localization`, `representation_selection`, `inputs`, `provenance`, `rights`, `industry_identifiers` |
Expand Down Expand Up @@ -527,7 +527,7 @@ Modes rank from least to most disruptive: `uninterrupted`, `staged` with `on_rej

**Staged update notifications.** A staged outcome is not a status transition, so it is not reported on `creative.status_changed`: an `approved → approved` fire would fail the closed validator of a buyer on a release that predates live updates. The seller reports it on the separate experimental `creative.staged_update_changed` event ([`creative-staged-update-changed-webhook.json`](https://adcontextprotocol.org/schemas/latest/creative/creative-staged-update-changed-webhook.json)), and only to `notification_configs[]` entries whose `event_types[]` include it. A buyer that does not register it never receives it and reads the outcome from `staged_update` on [`list_creatives`](/docs/creative/task-reference/list_creatives#staged-update-readback). See [lifecycle webhooks](/docs/creative/specification#lifecycle-webhooks).

**In every mode**, one `creative_id` is one creative. An accepted or promoted change applies to every assignment of the creative on every media buy, and the seller MUST NOT leave a prior version serving alongside the new one beyond the declared `max_propagation_seconds` (cache, SSAI, and exchange propagation). An assignment's own [`landing_page_url`](#assignment-landing-pages) or [`trackers`](#assignment-trackers) still apply on that assignment: a library `click_through` change does not reach an assignment that overrides it.
**In every mode**, one `creative_id` is one creative. An accepted or promoted change applies to every assignment of the creative on every media buy, and the seller MUST NOT leave a prior version serving alongside the new one beyond the declared `max_propagation_seconds` (cache, SSAI, and exchange propagation). An assignment's own [`landing_page_url`](#assignment-landing-pages) or [`trackers`](#assignment-trackers) still apply on that assignment: a library `clickthrough` change does not reach an assignment that overrides it.

**Refusal.** A declaring seller fails an item it does not apply in place to a live creative with [`CREATIVE_LIVE_UPDATE_UNSUPPORTED`](/docs/building/verification/compliance-catalog#error-code-creative-live-update-unsupported), and leaves the creative, its review state, and its serving unchanged. Other items in the request still process. `error.details` SHOULD conform to [`error-details/creative-live-update-unsupported.json`](https://adcontextprotocol.org/schemas/latest/error-details/creative-live-update-unsupported.json): `refused_changes` and `live_package_ids`. To make the change anyway, sync it as a new `creative_id` and swap it in with an `assignment_operations` `replace` on each live package. A seller that does not declare `creative.live_updates` is not covered by this section: the original rule applies unchanged (creatives on active, non-paused packages cannot be updated, and the refusal is [`INVALID_STATE`](/docs/building/verification/compliance-catalog#error-code-invalid-state)), so buyers handle both codes.

Expand Down
6 changes: 3 additions & 3 deletions docs/media-buy/specification.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -452,7 +452,7 @@ Statuses, per requirement and rolled up per product:
| `ready` | The account has exactly one suitable resource (for a connection, the one the seller would use is connected) | None beyond binding (below) |
| `setup_required` | The account has none, or the connection is `missing`, `pending`, `expired`, or `revoked` | Create or restore it, for example with `sync_event_sources`, `sync_catalogs`, or `connection_state.authorization_url` |
| `selection_required` | The account has several suitable resources | Choose one from `candidates[]` and bind it |
| `input_required` | The seller cannot discover a suitable resource from the account | Supply one on the request, such as an inline catalog |
| `input-required` | The seller cannot discover a suitable resource from the account | Supply one on the request, such as an inline catalog |
| `unknown` | The seller could not read the account's resources | Depends on `unknown_reason`: `permission_denied` needs a human to fix the seller's grant on the account, `platform_unavailable` is worth retrying, `not_evaluated` means refetch fewer products. Meanwhile the purchase task decides |

Rules:
Expand All @@ -464,7 +464,7 @@ Rules:
`execution_requirements` get an entry. A missing entry means not evaluated,
not ready.
- **Rollup.** A product's `readiness_status` is the first of `setup_required`,
`input_required`, `selection_required`, `unknown` that any requirement
`input-required`, `selection_required`, `unknown` that any requirement
reports, else `ready`: the most blocking state the seller could establish.
Buyers needing more MUST read `requirements[]`.
- **Could not check is not lacking.** `unknown` carries `unknown_reason`
Expand Down Expand Up @@ -494,7 +494,7 @@ Rules:
`missing`, `expired`, or `revoked` connection SHOULD include
`authorization_url` or `authorization_instructions`; `pending` MAY omit both. This
slice does not list several identities or let the buyer choose among them.
`selection_required` and `input_required` never apply to connections.
`selection_required` and `input-required` never apply to connections.
- **Account-scoped and advisory.** The map appears only when the request set
`include_execution_readiness: true` and carried an `account` the caller is
authorized for; otherwise the seller omits it (an `account` that does not
Expand Down
6 changes: 3 additions & 3 deletions docs/media-buy/task-reference/get_media_buy_delivery.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -756,15 +756,15 @@ The `by_package` array provides per-package delivery details with these key fiel
"$schema": "https://adcontextprotocol.org/schemas/latest/core/delivery-projection.json",
"projected_impressions": 1180000,
"projected_spend": 9440.00,
"projected_end_state": "underdelivery",
"projected_end_state": "under_delivery",
"basis": "trailing_daily_avg",
"as_of": "2026-10-01T00:00:00Z"
}
```

| Field | Meaning |
|---|---|
| `projected_end_state` | Required. One package-level judgment against the package's binding constraint, whichever of goal or budget it would reach first. `on_pace`: reaches it at flight end, within the seller's tolerance. `complete` (a projected early finish, unrelated to `delivery_status: completed`): reaches it before flight end, with the undelivered share of the flight below the seller's materiality threshold, so it simply finishes early. `early_exhaustion`: reaches it before flight end, with the undelivered share at or above the materiality threshold. `underdelivery`: falls short at flight end by more than tolerance. There is no over-delivery state: a package projected to exceed its constraint is projected to reach it early. |
| `projected_end_state` | Required. One package-level judgment against the package's binding constraint, whichever of goal or budget it would reach first. `on_pace`: reaches it at flight end, within the seller's tolerance. `complete` (a projected early finish, unrelated to `delivery_status: completed`): reaches it before flight end, with the undelivered share of the flight below the seller's materiality threshold, so it simply finishes early. `early_exhaustion`: reaches it before flight end, with the undelivered share at or above the materiality threshold. `under_delivery`: falls short at flight end by more than tolerance. There is no over-delivery state: a package projected to exceed its constraint is projected to reach it early. |
| `projected_impressions`, `projected_spend` | Optional supporting numbers. Projected **lifetime** totals when delivery ends, counted from the package's start rather than `reporting_period.start`, so they include delivery already reported and are not comparable to the row's period `impressions` and `spend` unless the period covers the flight to date. Spend is in the package row's `currency`. A seller omits a volume it does not project; a projection with only an end state is valid. |
| `basis` | Required. The method class: `trailing_daily_avg`, `trailing_hourly_avg`, `platform_model`, or `seller_defined`. It names the class, not the parameters. Window length, model name, and seasonality inputs belong in the projection's `ext`. `basis` is how the projection was sampled or modeled. It is not the commitment tier of [`forecast_method`](https://adcontextprotocol.org/schemas/v3/enums/forecast-method.json) (`estimate`, `modeled`, `guaranteed`), and a projection from actuals carries no delivery commitment at any `basis`. A client on an older schema version treats an unrecognized value like `seller_defined`. |
| `as_of` | Required. The latest delivery data the projection was computed from. It is independent of `reporting_period` and can precede the response time because reporting lags. |
Expand All @@ -780,7 +780,7 @@ Tolerance and materiality are the seller's own thresholds, which it SHOULD also
| `projection.projected_end_state` | Expected `pacing_risk` on the same package |
|---|---|
| `on_pace`, `complete` | Not present |
| `underdelivery`, `early_exhaustion` | Present when the seller's tolerance treats the gap as material |
| `under_delivery`, `early_exhaustion` | Present when the seller's tolerance treats the gap as material |

A seller MAY emit `projection` without advertising `pacing_risk`, and the reverse. The two share the seller's tolerance, so neither is a substitute for the other and a buyer MUST NOT infer one from the absence of the other. `pacing_risk` also covers over-delivery, which `projection` has no state for beyond early completion. Use `pacing_risk` to decide when to look, and `projection` for the number behind it.

Expand Down
2 changes: 1 addition & 1 deletion docs/media-buy/task-reference/list_products.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ With `include_execution_readiness: true` and an `account`, a seller that lists `
|-------|------|-------------|
| `version` | string | Opaque token for the account's readiness, independent of `feed_version` and `pricing_version`. Compare for equality only. |
| `evaluated_at` | string (date-time) | When the seller read the account's resources. |
| `products` | object | Readiness keyed by `product_id`, for products on the page that declare `execution_requirements`. Each value has a rollup `readiness_status` (`ready`, `setup_required`, `selection_required`, `input_required`, `unknown`) and one `requirements[]` entry per declared requirement. A missing entry means not evaluated, not ready. |
| `products` | object | Readiness keyed by `product_id`, for products on the page that declare `execution_requirements`. Each value has a rollup `readiness_status` (`ready`, `setup_required`, `selection_required`, `input-required`, `unknown`) and one `requirements[]` entry per declared requirement. A missing entry means not evaluated, not ready. |

Each `requirements[]` entry echoes the declared `requirement` and carries `readiness_status`, plus `binding_field`, `resolved` (when `ready`), `candidates[]` (when `selection_required`), `connection_state` (for `downstream_connection`), `unknown_reason` (when `unknown`), and `issues[]`. `binding_field` names the [`buy_products`](/docs/media-buy/task-reference/buy_products) path: `purchases[].optimization_goals[].event_sources[].event_source_id` for an event source and `purchases[].catalog_ids[]` for a catalog. A `candidates[].resource_id` or `resolved.resource_id` is directly usable there. `ready` does not waive binding, and `unknown` means the seller could not check, not that the account lacks the resource. See [per-account execution readiness](/docs/media-buy/specification#per-account-execution-readiness-experimental) for the full rules.

Expand Down
2 changes: 1 addition & 1 deletion docs/protocol/get_adcp_capabilities.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -1567,7 +1567,7 @@ Creative protocol capabilities. Only present if `creative` is in `supported_prot
| `supports_assignment_trackers` | boolean | Added in 3.3; defaults to `false`. When `true`, accepts assignment-scoped `trackers` in `sync_creatives` assignment requests, fires them alongside the creative's own trackers or rejects the assignment, enforces shared format tracker-slot limits where the format declares tracker slots, and returns the assignment tracker list in readback. Requires `has_creative_library: true`. When `false` or absent, buyers MUST NOT send the field and the agent MUST reject it with [`UNSUPPORTED_FEATURE`](/docs/building/verification/compliance-catalog#error-code-unsupported-feature). Independent of landing-page override support. See [assignment trackers](/docs/creative/task-reference/sync_creatives#assignment-trackers). |
| `supports_revisions` | boolean | When `true`, the library accepts buyer-authored immutable `revision_id` values and preserves them through sync echo, current readback, review attribution, and revision-homogeneous delivery rows. Requires `has_creative_library: true`. Does not imply revision history, rollback, or staged activation. |
| `supports_assignment_landing_page` | boolean | Added in 3.3; defaults to `false`. When `true`, accepts assignment-scoped `landing_page_url` in `sync_creatives` assignment requests, serves the override or rejects the assignment, and reports the effective destination in assignment readback. Requires `has_creative_library: true`. When `false` or absent, buyers MUST NOT send the field and the agent MUST reject it with [`UNSUPPORTED_FEATURE`](/docs/building/verification/compliance-catalog#error-code-unsupported-feature). See [assignment landing pages](/docs/creative/task-reference/sync_creatives#assignment-landing-pages). |
| `live_updates` | object | Experimental; added in 3.3. Which kinds of change (`click_through`, `trackers`, `asset_content`, `format`) the agent applies in place to a live creative under the same `creative_id`, and how the creative serves while each is decided: `uninterrupted`, `staged` (the prior version serves until the change is approved; `on_rejection` is `keeps_prior` or `stops`), or `paused_for_review`. A floor: listed kinds are accepted on every live creative in the listed mode or a less disruptive one. Optional `max_propagation_seconds` bounds how long a prior version may still serve after a change applies. A declaring agent refuses other changes with [`CREATIVE_LIVE_UPDATE_UNSUPPORTED`](/docs/building/verification/compliance-catalog#error-code-creative-live-update-unsupported) and answers the exact outcome of one change on a [`sync_creatives` `dry_run`](/docs/creative/task-reference/sync_creatives#live-creative-updates). Requires `has_creative_library: true`. See [Live creative updates](/docs/creative/task-reference/sync_creatives#live-creative-updates). |
| `live_updates` | object | Experimental; added in 3.3. Which kinds of change (`clickthrough`, `trackers`, `asset_content`, `format`) the agent applies in place to a live creative under the same `creative_id`, and how the creative serves while each is decided: `uninterrupted`, `staged` (the prior version serves until the change is approved; `on_rejection` is `keeps_prior` or `stops`), or `paused_for_review`. A floor: listed kinds are accepted on every live creative in the listed mode or a less disruptive one. Optional `max_propagation_seconds` bounds how long a prior version may still serve after a change applies. A declaring agent refuses other changes with [`CREATIVE_LIVE_UPDATE_UNSUPPORTED`](/docs/building/verification/compliance-catalog#error-code-creative-live-update-unsupported) and answers the exact outcome of one change on a [`sync_creatives` `dry_run`](/docs/creative/task-reference/sync_creatives#live-creative-updates). Requires `has_creative_library: true`. See [Live creative updates](/docs/creative/task-reference/sync_creatives#live-creative-updates). |
| `supports_assignment_merge` | boolean | When `true`, the agent accepts the `merge` operation in [`sync_creatives`](/docs/creative/task-reference/sync_creatives#merging-a-seller-created-copy) `assignment_operations`, which moves a seller-assigned creative's assignment on a package, with its serving object, approval, and delivery continuity, to the buyer's matching `creative_id`. Requires `has_creative_library: true` and `stable_creative_ids: true`, so the seller-created creative being merged has a stable ID. When `false` or absent, the agent rejects `merge` with `UNSUPPORTED_FEATURE` and buyers MUST NOT send it. |
| `representation_resolution` | object | Destination-sales-agent opt-in to accept a complete `creative_representation_set` on [`build_creative`](/docs/creative/task-reference/build_creative), verify its revision digest, and select one compatible `representation_id` against that seller's current product and execution contract using an advertised deterministic strategy. Standalone creative agents cannot advertise seller-bound resolution. Absence means the caller selects before sending a seller-bound manifest; the agent cannot guess. See [creative representation sets](/docs/creative/representation-sets). |
| `supported_formats` | object[] | Canonical creative operation catalog. New 3.2 producers MUST emit a stable `capability_id`, a full canonical `format` declaration, and explicit `operations` (`build`, `validate`, `preview`). Exact publisher support carries `{publisher_domain, format_option_id}` inside `format`; generic capabilities declare a satisfiable canonical parameter envelope. For 3.x compatibility, consumers accept entries without `capability_id` and interpret absent `operations` as `build`; such entries can be matched by contract but not selected through a capability-ID route. Replaces [`list_creative_formats`](/docs/creative/task-reference/list_creative_formats) in 3.2. |
Expand Down
Loading
Loading