diff --git a/.changeset/refresh-3-3-release-docs-beta3.md b/.changeset/refresh-3-3-release-docs-beta3.md
new file mode 100644
index 00000000000..e1e6a988f51
--- /dev/null
+++ b/.changeset/refresh-3-3-release-docs-beta3.md
@@ -0,0 +1,5 @@
+---
+"adcontextprotocol": patch
+---
+
+Docs: refresh the 3.3 release notes, What's new, the 3.2 to 3.3 migration guide, and the 3.3 beta program page through `3.3.0-beta.3`. Covers the beta.1 to beta.3 checkpoints, the account identity model and `request_account`, the protocol envelope on every task response, DR-0034 and DR-0036, structural capability bounds, undisclosed rosters, live creative updates, reporting subscriptions, the commercial experiments, SDK guidance, and the refreshed in-review table.
diff --git a/docs/reference/3-3-beta.mdx b/docs/reference/3-3-beta.mdx
index 8680d9affa0..1de153d00c8 100644
--- a/docs/reference/3-3-beta.mdx
+++ b/docs/reference/3-3-beta.mdx
@@ -1,7 +1,7 @@
---
title: AdCP 3.3 beta program
sidebarTitle: 3.3 beta program
-description: "How to test AdCP 3.3 beta.0 before SDK support, prepare SDKs from the signed protocol bundle, complete beta.1 protocol and SDK convergence, and see which proposals are still in review for 3.3."
+description: "Where the AdCP 3.3 beta stands at beta.3, how to test a beta before SDK support, which SDK versions bundle which beta, and which proposals are still in review for 3.3."
"og:title": "AdCP — 3.3 beta program"
---
@@ -13,39 +13,44 @@ description: "How to test AdCP 3.3 beta.0 before SDK support, prepare SDKs from
3.3 is a minor release with a deliberately short cycle. Its beta follows the same order as 3.2: the protocol first, then the SDKs.
-| Checkpoint | Purpose | Who should test |
-|---|---|---|
-| `3.3.0-beta.0` | Canonical schemas, compliance assets, skills, and protocol manifest for SDK implementation | SDK maintainers, code-generator maintainers, raw-wire implementers, and agent teams that can validate without generated 3.3 SDK types |
-| SDK wave | SDKs ingest the signed beta.0 tarball and publish exact support statements | TypeScript, Python, and Go maintainers and early adopters |
-| `3.3.0-beta.1` | Pull integration corrections into the protocol; a second SDK refresh then establishes exact beta.1 support | Buyer and seller teams running end-to-end integrations, followed by SDK maintainers |
+## Beta status
+
+The latest checkpoint is **`3.3.0-beta.3`, published 2026-10-31**. Each beta is an immutable, signed checkpoint, and later betas may change 3.3 surfaces before GA. GA follows the first beta that meets every one of the proposed GA criteria in [#8600](https://github.com/adcontextprotocol/adcp/issues/8600): SDK support for the latest beta, green storyboards, the closed-schema triage ([#8501](https://github.com/adcontextprotocol/adcp/issues/8501)), no open objections on consent items and decision records, and current release docs. Objections are due by 2026-11-06, or at the 2026-11-09 working-group session.
+
+| Checkpoint | Published | Purpose | Who should test |
+|---|---|---|---|
+| `3.3.0-beta.0` | 2026-10-22 | Canonical schemas, compliance assets, skills, and protocol manifest for SDK implementation | SDK maintainers, code-generator maintainers, raw-wire implementers, and agent teams that can validate without generated 3.3 SDK types |
+| `3.3.0-beta.1` | 2026-10-29 | Beta.0 integration corrections, the account identity model, `request_account`, principal-level reporting subscriptions, undisclosed rosters, and the first commercial experiments | Buyer and seller teams running end-to-end integrations, and SDK maintainers ingesting the bundle |
+| `3.3.0-beta.2` | 2026-10-30 | Account change outcomes, seller offers, measurement provenance, structural capability bounds, the principal clarification, reporting-subscription convergence, and the withdrawal of definition pins, purchase rights, and installment selection | The same teams, against the withdrawn surfaces removed |
+| `3.3.0-beta.3` | 2026-10-31 | Live creative updates, the protocol envelope on every task response, money terms on resolved account requests, revocation as no access, and reporting-subscription coverage computable from the wire | The same teams; this is the checkpoint the docs describe |
-Beta.0 is not waiting for the SDKs. Beta.1 is a two-stage convergence point: publish the corrected protocol checkpoint, then have SDKs ingest that exact bundle. Call beta.1 SDK-backed only after the matching SDK versions and integration evidence are published.
+Beta.0 did not wait for the SDKs. A checkpoint is SDK-backed only after the matching SDK versions and integration evidence are published, and no published SDK bundles beta.3 yet ([SDK guidance](#sdk-guidance)). Three features that shipped in the betas are [withdrawn after beta.1](#withdrawn-after-beta-1).
## Know which version string to use
The artifact version, wire pin, and documentation selector are related but not interchangeable:
-| Surface | beta.0 | beta.1 |
-|---|---|---|
-| Protocol artifact | `3.3.0-beta.0` | `3.3.0-beta.1` |
-| Git tag | `v3.3.0-beta.0` | `v3.3.0-beta.1` |
-| `adcp_version` wire pin | `"3.3-beta.0"` | `"3.3-beta.1"` |
-| Documentation selector | `3.3-beta` | `3.3-beta` |
+| Surface | beta.0 | beta.1 | beta.2 | beta.3 |
+|---|---|---|---|---|
+| Protocol artifact | `3.3.0-beta.0` | `3.3.0-beta.1` | `3.3.0-beta.2` | `3.3.0-beta.3` |
+| Git tag | `v3.3.0-beta.0` | `v3.3.0-beta.1` | `v3.3.0-beta.2` | `v3.3.0-beta.3` |
+| `adcp_version` wire pin | `"3.3-beta.0"` | `"3.3-beta.1"` | `"3.3-beta.2"` | `"3.3-beta.3"` |
+| Documentation selector | `3.3-beta` | `3.3-beta` | `3.3-beta` | `3.3-beta` |
-Only send a prerelease wire pin to a peer that advertises that exact value in `get_adcp_capabilities.adcp.supported_versions`. Prerelease pins are exact: a buyer pinned to `"3.3-beta.0"` must not silently negotiate to beta.1, and a stable `"3.2"` pin must not silently negotiate to a beta.
+Only send a prerelease wire pin to a peer that advertises that exact value in `get_adcp_capabilities.adcp.supported_versions`. Prerelease pins are exact: a buyer pinned to `"3.3-beta.2"` must not silently negotiate to beta.3, and a stable `"3.2"` pin must not silently negotiate to a beta.
-## Test beta.0 without an SDK
+## Test a beta without an SDK
-Once `v3.3.0-beta.0` is published, download the signed protocol bundle rather than copying schemas from `main` or from the moving `/schemas/latest/` path:
+Download the signed protocol bundle of the beta you test (the commands use the latest, `3.3.0-beta.3`; substitute another published checkpoint) rather than copying schemas from `main` or from the moving `/schemas/latest/` path:
```bash
-curl -fLO https://adcontextprotocol.org/protocol/3.3.0-beta.0.tgz
-curl -fLO https://adcontextprotocol.org/protocol/3.3.0-beta.0.tgz.sha256
-shasum -a 256 -c 3.3.0-beta.0.tgz.sha256
-tar -xzf 3.3.0-beta.0.tgz
+curl -fLO https://adcontextprotocol.org/protocol/3.3.0-beta.3.tgz
+curl -fLO https://adcontextprotocol.org/protocol/3.3.0-beta.3.tgz.sha256
+shasum -a 256 -c 3.3.0-beta.3.tgz.sha256
+tar -xzf 3.3.0-beta.3.tgz
```
-The extracted `adcp-3.3.0-beta.0/` directory contains:
+The extracted `adcp-3.3.0-beta.3/` directory contains:
- `manifest.json`: release version, bundle contents, skills, and file count;
- `schemas/`: source-shaped and bundled request/response schemas, including `schemas/manifest.json` for the task and capability inventory;
@@ -55,16 +60,16 @@ The extracted `adcp-3.3.0-beta.0/` directory contains:
Verify the Sigstore signature before using the bundle as a build input. See [Verifying protocol tarballs](/docs/reference/verifying-protocol-tarballs) for the certificate-identity and issuer checks.
-At beta.0, useful tests are:
+Useful tests are:
1. Generate or refresh types from the pinned bundled schemas.
-2. Validate representative requests and responses for the roles you implement, including the new 3.3 surfaces you plan to adopt: `expected_confirmation_at`, vendor-metric `outcome_target` goals, `reporting_webhook.operation_id`, `media_buy.features.catalog_ingestion`, the DOOH `location` and `dooh_inventory_summary` fields, `sync_audiences` audience sizes, and the experimental spot, print, daypart, loudness, and governance `budget.periods[]` fields.
+2. Validate representative requests and responses for the roles you implement, including the new 3.3 surfaces you plan to adopt: the `account_id` identity model and, if you support it, `request_account`; `status` on every response through the protocol envelope; `expected_confirmation_at`, vendor-metric `outcome_target` goals, `reporting_webhook.operation_id`, `media_buy.features.catalog_ingestion`, the DOOH `location` and `dooh_inventory_summary` fields, `sync_audiences` audience sizes, and the experimental spot, print, daypart, loudness, reporting-subscription, live-creative-update, and governance `budget.periods[]` fields.
3. Compare your advertised tools with `schemas/manifest.json`.
-4. Exercise raw MCP or A2A calls with `adcp_version: "3.3-beta.0"` against a staging peer that advertises the same pin.
+4. Exercise raw MCP or A2A calls with `adcp_version: "3.3-beta.3"` against a staging peer that advertises the same pin.
5. Run the compliance assets with a source-compatible runner if you maintain one. Do not weaken production authentication to accommodate a beta runner.
-**No 3.3 verification badge is issued from beta.0.** The protocol-first cut is an implementation input, not a certification target.
+**No 3.3 verification badge is issued from a beta.** A beta bundle is an implementation input, not a certification target, and prerelease grading runs are diagnostic, as they were for 3.2.
## SDK support contract
@@ -77,21 +82,31 @@ An SDK support claim must name all of the following:
- known unsupported or raw-only surfaces;
- install command and one tested validation command.
-The SDK compatibility matrix lives in [Choose your SDK](/docs/building/by-layer/L4/choose-your-sdk). Until a row names beta.0 support, treat that SDK's generated 3.3 types and validators as unavailable. Raw JSON calls may still be possible, but they are not equivalent to SDK support.
+The SDK compatibility matrix lives in [Choose your SDK](/docs/building/by-layer/L4/choose-your-sdk). Until a row names support for a beta, treat that SDK's generated 3.3 types and validators for it as unavailable. Raw JSON calls may still be possible, but they are not equivalent to SDK support.
+
+SDK maintainers should report protocol ambiguities against the [AdCP repository](https://github.com/adcontextprotocol/adcp/issues). Report SDK implementation bugs in the SDK's own repository. Accepted protocol fixes receive a changeset and ship in the next beta; a published beta is never rebuilt in place.
+
+## SDK guidance
+
+**TypeScript.** Use `@adcp/sdk` **17.0.0-beta.6 or later** (npm `beta` dist-tag) to test 3.3. The published prereleases bundle a signed AdCP release: 17.0.0-beta.6 bundles `3.3.0-beta.1`, and 17.0.0-beta.10 bundles `3.3.0-beta.2`. No published `@adcp/sdk` bundles `3.3.0-beta.3` yet, so the beta.3 surfaces (live creative updates, the envelope on every response, money terms on resolved account requests, and the reporting-subscription coverage rules) are raw-wire only until an SDK ingests that bundle. Pin the exact SDK version, and send a prerelease `adcp_version` only to a peer that advertises that exact pin. `@adcp/sdk` 17 is a major release; read its [16 to 17 migration guide](https://github.com/adcontextprotocol/adcp-client/blob/main/docs/migration-16-to-17.md) first.
+
+**Python.** There is no Python SDK release that bundles a 3.3 beta. Support is pending [adcp-client-python#1560](https://github.com/adcontextprotocol/adcp-client-python/issues/1560), which is open. Until it lands, use the `adcp` 3.2 release for production-line work and validate 3.3 behavior over the raw wire against the signed bundle.
+
+**Go.** Check the [adcp-go releases](https://github.com/adcontextprotocol/adcp-go/releases) for a published 3.3 support statement; this page names none.
-SDK maintainers should report protocol ambiguities against the [AdCP repository](https://github.com/adcontextprotocol/adcp/issues). Report SDK implementation bugs in the SDK's own repository. Accepted protocol fixes receive a changeset and ship in beta.1; beta.0 is never rebuilt in place.
+Do not combine an SDK that bundles an earlier beta with a later wire pin unless that SDK explicitly documents forward compatibility. GA needs SDK support for the latest beta, so these versions will move; [Choose your SDK](/docs/building/by-layer/L4/choose-your-sdk) is the SDK matrix, and it can lag the npm dist-tag.
-## beta.1 convergence
+## SDK convergence
-The beta.1 protocol checkpoint is ready to cut when:
+A beta is the SDK-backed ecosystem checkpoint only when:
-- every first-party SDK's beta.0 support is marked supported, partial, or unavailable with an exact package version;
-- accepted beta.0 protocol feedback is merged;
-- the integration scenarios below have run against beta.0 and identify any correction included in the beta.1 candidate;
+- every first-party SDK's support for it is marked supported, partial, or unavailable with an exact package version;
+- accepted protocol feedback from the previous beta is merged;
+- the integration scenarios below have run against the previous beta and identify any correction in the candidate;
- copy/paste installation and validation commands have been executed as published;
-- the cumulative migration guide and release notes describe any beta.0-to-beta.1 correction that requires adopter action.
+- the cumulative migration guide and release notes describe any correction that requires adopter action.
-After `3.3.0-beta.1` is published, SDK maintainers ingest that signed bundle and publish an exact beta.1 support statement or an explicit unsupported/partial result. Only after the matching buyer/seller scenarios pass is beta.1 the SDK-backed ecosystem checkpoint. Do not combine an SDK generated from beta.0 with a beta.1 wire pin unless that SDK explicitly documents forward compatibility.
+After a beta is published, SDK maintainers ingest that signed bundle and publish an exact support statement or an explicit unsupported or partial result. Only after the matching buyer and seller scenarios pass is that beta the SDK-backed checkpoint.
## Withdrawn after beta.1
@@ -123,15 +138,15 @@ The [3.3.0 milestone](https://github.com/adcontextprotocol/adcp/milestone/10) is
- [Open 3.3 pull requests](https://github.com/adcontextprotocol/adcp/pulls?q=is%3Aopen+milestone%3A3.3.0)
- [Closed 3.3 milestone work](https://github.com/adcontextprotocol/adcp/milestone/10?closed=1)
-Milestone assignment means **candidate for the 3.3 line**, not a commitment to beta.1 or GA. A change is included in a beta only when it is merged before that beta's tag. Items may be deferred, split, or moved to a later release as working groups resolve scope and interoperability risk.
+Milestone assignment means **candidate for the 3.3 line**, not a commitment to any particular beta or GA. A change is included in a beta only when it is merged before that beta's tag. Items may be deferred, split, or moved to a later release as working groups resolve scope and interoperability risk.
### In review for 3.3
-**These are proposals, not features.** Each row is an issue that was open in the 3.3.0 milestone on 2026-10-22 (58 issues), with its open pull request where one exists. None is part of a beta unless it merges before that beta's tag. "Merged so far" names the slice that already shipped on `main`; the rest of the issue is still in review. The live lists are the [open 3.3 issues](https://github.com/adcontextprotocol/adcp/issues?q=is%3Aopen+is%3Aissue+milestone%3A3.3.0) and [open pull requests](https://github.com/adcontextprotocol/adcp/pulls?q=is%3Aopen+is%3Apr+draft%3Afalse) and [drafts](https://github.com/adcontextprotocol/adcp/pulls?q=is%3Aopen+is%3Apr+draft%3Atrue).
+**These are proposals, not features.** Each row is an issue that was open in the 3.3.0 milestone on 2026-10-31 (28 issues, not counting the [GA tracking issue](https://github.com/adcontextprotocol/adcp/issues/8600)), with its open pull request where one exists. An issue stays open while part of it is still in review, so a row can list merged work. Issues whose work has fully merged have been closed and are not listed; see [What's new](/docs/reference/whats-new-in-3-3) and the [release notes](/docs/reference/release-notes#version-3-3-0) for what they shipped. None is part of a beta unless it merges before that beta's tag. "Merged so far" names the slice that already shipped on `main`; the rest of the issue is still in review. The live lists are the [open 3.3 issues](https://github.com/adcontextprotocol/adcp/issues?q=is%3Aopen+is%3Aissue+milestone%3A3.3.0) and [open pull requests](https://github.com/adcontextprotocol/adcp/pulls?q=is%3Aopen+is%3Apr+draft%3Afalse) and [drafts](https://github.com/adcontextprotocol/adcp/pulls?q=is%3Aopen+is%3Apr+draft%3Atrue).
-#### Ratified decisions
+#### Decisions
| Decision | What it changes | Status |
|---|---|---|
@@ -140,8 +155,10 @@ Milestone assignment means **candidate for the 3.3 line**, not a commitment to b
| Demand-side grants ([DR-0025](https://github.com/adcontextprotocol/adcp/blob/main/governance/decisions/DR-0025-demand-side-grants-in-trust-json.md)) | An operator declares in trust.json which agents may act for it, and sellers report `grant_absent`. | Merged: [#8157](https://github.com/adcontextprotocol/adcp/pull/8157), [#8169](https://github.com/adcontextprotocol/adcp/pull/8169). |
| JWS artifacts use the Web Bot Auth key directory ([DR-0026](https://github.com/adcontextprotocol/adcp/blob/main/governance/decisions/DR-0026-jws-artifacts-use-the-wba-key-directory.md)) | Governance contexts, designated-task response signatures, and rights attestations from an origin its trust record lists verify against that origin's Web Bot Auth key directory in 3.3; amends DR-0023. | Merged: [#8299](https://github.com/adcontextprotocol/adcp/pull/8299). |
| Seller revisions advance on every committed change ([DR-0031](https://github.com/adcontextprotocol/adcp/blob/main/governance/decisions/DR-0031-seller-revision-any-origin.md)) | A seller-maintained revision (media-buy and account `revision`, creative `seller_revision`) advances on every committed change, whatever its origin; the `sync_creatives` assignment carve-out is removed. Other resource families are deferred to 3.4. | Merged: [#8159](https://github.com/adcontextprotocol/adcp/pull/8159); recorded in [#8389](https://github.com/adcontextprotocol/adcp/pull/8389). |
+| A major-only request is served the oldest supported release ([DR-0034](https://github.com/adcontextprotocol/adcp/blob/main/governance/decisions/DR-0034-major-only-requests-are-served-the-oldest-release.md)) | A request that carries `adcp_major_version` and no `adcp_version` is served the oldest release the seller supports in that major, 3.0 where supported, and the response echoes it. `adcp_major_version` is removed in 4.0 ([DR-0035](https://github.com/adcontextprotocol/adcp/blob/main/governance/decisions/DR-0035-adcp-major-version-removed-in-4-0.md)). | Accepted 2026-10-26; ratified in [#8410](https://github.com/adcontextprotocol/adcp/pull/8410). |
+| Closed schemas stay closed within a major ([DR-0036](https://github.com/adcontextprotocol/adcp/blob/main/governance/decisions/DR-0036-closed-schemas-stay-closed-within-a-major.md)) | A minor adds only to open schemas, and four recorded corrections are the only exceptions. This is why definition pins, purchase rights, and installment selection are [withdrawn](#withdrawn-after-beta-1). | Proposed, awaiting ratification. The corrections merged in [#8531](https://github.com/adcontextprotocol/adcp/pull/8531) and [#8547](https://github.com/adcontextprotocol/adcp/pull/8547), and the CI guard in [#8502](https://github.com/adcontextprotocol/adcp/pull/8502). |
-Four proposed records document surfaces merged for beta.0 and await working-group ratification: [DR-0027](https://github.com/adcontextprotocol/adcp/blob/main/governance/decisions/DR-0027-mutation-outcome-on-error.md) (`error.mutation_outcome`), [DR-0028](https://github.com/adcontextprotocol/adcp/blob/main/governance/decisions/DR-0028-sales-fixed-rate-specialism.md) (`sales-fixed-rate`), [DR-0029](https://github.com/adcontextprotocol/adcp/blob/main/governance/decisions/DR-0029-delivery-projection-advisory.md) (delivery projection), and [DR-0030](https://github.com/adcontextprotocol/adcp/blob/main/governance/decisions/DR-0030-media-buy-lineage-forward-only.md) (media-buy lineage).
+Four records document surfaces merged for beta.0 and are accepted (decided 2026-10-30): [DR-0027](https://github.com/adcontextprotocol/adcp/blob/main/governance/decisions/DR-0027-mutation-outcome-on-error.md) (`error.mutation_outcome`), [DR-0028](https://github.com/adcontextprotocol/adcp/blob/main/governance/decisions/DR-0028-sales-fixed-rate-specialism.md) (`sales-fixed-rate`), [DR-0029](https://github.com/adcontextprotocol/adcp/blob/main/governance/decisions/DR-0029-delivery-projection-advisory.md) (delivery projection), and [DR-0030](https://github.com/adcontextprotocol/adcp/blob/main/governance/decisions/DR-0030-media-buy-lineage-forward-only.md) (media-buy lineage).
#### Open 3.3.0 milestone issues
@@ -156,66 +173,35 @@ Four proposed records document surfaces merged for beta.0 and await working-grou
| Area | Issue | Topic | Open PR | Merged so far |
|---|---|---|---|---|
| Commercial flow | [#7902](https://github.com/adcontextprotocol/adcp/issues/7902) | Core `opportunity` on `get_products` | [#8034](https://github.com/adcontextprotocol/adcp/pull/8034) (draft) | — |
-| Commercial flow | [#7107](https://github.com/adcontextprotocol/adcp/issues/7107) | Delegated proposal composition | — | `product_ids_exclusive` and `terms_only` finalize (#7954) |
-| Commercial flow | [#7659](https://github.com/adcontextprotocol/adcp/issues/7659) | Price adjustments for buyer-selectable dimensions | [#7955](https://github.com/adcontextprotocol/adcp/pull/7955) (draft) | — |
-| Commercial flow | [#7763](https://github.com/adcontextprotocol/adcp/issues/7763) | Per-account execution readiness | [#7934](https://github.com/adcontextprotocol/adcp/pull/7934) | — |
| Commercial flow | [#8010](https://github.com/adcontextprotocol/adcp/issues/8010) | Booking rounds for scheduled media | [#8022](https://github.com/adcontextprotocol/adcp/pull/8022) (draft) | `expected_confirmation_at` (#8016) |
| Commercial flow | [#5673](https://github.com/adcontextprotocol/adcp/issues/5673) | Best-first ordering of products and proposals | [#8037](https://github.com/adcontextprotocol/adcp/pull/8037) (draft) | — |
-| Commercial flow | [#6303](https://github.com/adcontextprotocol/adcp/issues/6303) | Fixed-price, non-guaranteed specialism | — | `sales-fixed-rate` specialism and `expected_confirmation_at` on `get_media_buys` (#7963) |
| Commercial flow | [#7852](https://github.com/adcontextprotocol/adcp/issues/7852) | Delivery-mode-aware media-buy baseline | [#7973](https://github.com/adcontextprotocol/adcp/pull/7973) (draft) | — |
-| Commercial flow | [#8096](https://github.com/adcontextprotocol/adcp/issues/8096) | Open opportunities: later proposals and `list_proposals` | — | Experimental open opportunities and `list_proposals` (#8103), seller-offer origin and `media_buy_ids` filter (#8223) |
-| Commercial flow | [#8086](https://github.com/adcontextprotocol/adcp/issues/8086) | Hold extension, ranking, and installment holds | — | `expected_confirmation_at` on `refine_proposals` (#8104, #8203), `hold_policy` (#8140), `extend_hold` (#8097), hold ranking (#8255), and installment holds (#8257) |
-| Commercial flow | [#8087](https://github.com/adcontextprotocol/adcp/issues/8087) | Seller-proposed changes to a signed media buy | [#8102](https://github.com/adcontextprotocol/adcp/pull/8102) (draft) | — |
-| Commercial flow | [#8090](https://github.com/adcontextprotocol/adcp/issues/8090) | Usage and amplification rights in the purchase | [#8101](https://github.com/adcontextprotocol/adcp/pull/8101) (merged, shipped in beta.1, then withdrawn) | Withdrawn from 3.3 and planned for 4.0; see [Withdrawn after beta.1](#withdrawn-after-beta-1) |
-| Commercial flow | [#8158](https://github.com/adcontextprotocol/adcp/issues/8158) | Signal for buys accepted under a compromised key, and bulk resolution | — | — |
-| Commercial flow | [#8184](https://github.com/adcontextprotocol/adcp/issues/8184) | Invoice lines on `get_account_financials` tied to billed reporting | [#8207](https://github.com/adcontextprotocol/adcp/pull/8207) (draft) | — |
-| Commercial flow | [#8142](https://github.com/adcontextprotocol/adcp/issues/8142) | Seller revision that advances on every committed change | — | Media-buy, account, and creative seller revisions from any origin (#8159, DR-0031 recorded in #8389); other resource families deferred to 3.4 |
| Commercial flow | [#6810](https://github.com/adcontextprotocol/adcp/issues/6810) | Complete account change visibility across seller-managed state | — | `idempotency_key` echo and required `changed_paths` on change records (#8160) |
-| Commercial flow | [#8280](https://github.com/adcontextprotocol/adcp/issues/8280) | `request_account` and one pending-action shape (agent identity P10) | — | `request_account` and the pending action (#8293); `request_account` as the single account write and `list_accounts` request reads (#8551); change outcomes and the separate-account opt-in (#8580, #8582); money terms on resolved requests and consistent timezone changes (#8620) |
-| Commercial flow | [#8230](https://github.com/adcontextprotocol/adcp/issues/8230) | Installments on the canonical Product in the proposal lifecycle | [#8246](https://github.com/adcontextprotocol/adcp/pull/8246) | — |
-| Delivery and measurement | [#8543](https://github.com/adcontextprotocol/adcp/issues/8543) | Reporting subscriptions on the principal | — | Experimental `reporting_subscriptions` on `sync_principal` and exceptions-only `subscription_coverage` (#8552); beta.2 and beta.3 convergence (#8585, #8588, #8593, #8596, #8607, #8613, #8616, #8617, #8618, #8619, #8621, #8622) |
-| Delivery and measurement | [#5683](https://github.com/adcontextprotocol/adcp/issues/5683) | Linear TV preemption notice and replacement offer | [#8102](https://github.com/adcontextprotocol/adcp/pull/8102) (draft) | Report-time spot lifecycle (#8017); contract-time half planned for 3.4 |
+| Delivery and measurement | [#8543](https://github.com/adcontextprotocol/adcp/issues/8543) | Reporting subscriptions on the principal | — | `request_account` as the single account write (#8551); experimental `reporting_subscriptions` on `sync_principal` and exceptions-only `subscription_coverage` (#8552); beta.2 and beta.3 convergence (#8585, #8588, #8593, #8596, #8607, #8613, #8616, #8617, #8618, #8619, #8621, #8622) |
+| Delivery and measurement | [#5683](https://github.com/adcontextprotocol/adcp/issues/5683) | Linear TV preemption notice and replacement offer | — | Report-time spot lifecycle (#8017); the offer-and-accept loop as experimental seller offers (#8102); contract-time preemption criteria planned for 3.4 |
| Delivery and measurement | [#8009](https://github.com/adcontextprotocol/adcp/issues/8009) | Book and report position in break | — | Reporting half (#8017) |
| Delivery and measurement | [#7777](https://github.com/adcontextprotocol/adcp/issues/7777) | Delivery evidence gaps for scheduled and offline channels | — | `change_cutoff` (#8054) |
-| Delivery and measurement | [#6878](https://github.com/adcontextprotocol/adcp/issues/6878) | Seller-initiated trackers and measurement sources | [#7940](https://github.com/adcontextprotocol/adcp/pull/7940) | — |
+| Delivery and measurement | [#6878](https://github.com/adcontextprotocol/adcp/issues/6878) | Seller-initiated trackers and measurement sources | — | Experimental `collection-mechanism` vocabulary, `counting_mechanisms[]`, and `vendor_metric_provenance[]` (#7940); seller-initiated trackers and `impression_id` joinability remain open |
| Delivery and measurement | [#6628](https://github.com/adcontextprotocol/adcp/issues/6628) | Reporting metric coherence findings | — | Flat totals omitted for multi-qualifier metrics (#8055) |
-| Delivery and measurement | [#7718](https://github.com/adcontextprotocol/adcp/issues/7718) | Responses conform to the served release (DR-0024) | [#8156](https://github.com/adcontextprotocol/adcp/pull/8156) | Normative rule and record (#8117) |
-| Delivery and measurement | [#8088](https://github.com/adcontextprotocol/adcp/issues/8088) | Installment publication record (proof of post) | — | Installment lifecycle and proof of publication on `by_installment[]` (#8116); publish notification deferred to 3.4 |
-| Security and signing | [#7066](https://github.com/adcontextprotocol/adcp/issues/7066) | Production security profile | — | Experimental `adcp-prod-security-3.3` profile (#8155) |
-| Security and signing | [#7878](https://github.com/adcontextprotocol/adcp/issues/7878) | Web Bot Auth profile for request signing | — | Profile (#7894), Web Bot Auth identities and RFC 9421 deprecation (#8162) |
-| Security and signing | [#7809](https://github.com/adcontextprotocol/adcp/issues/7809) | Split identity and trust out of brand.json (`trust.json`) | — | Experimental `trust.json` v1 schemas, origin identity (#8067, #8121) |
+| Delivery and measurement | [#7253](https://github.com/adcontextprotocol/adcp/issues/7253) | DOOH impression basis: typed tier, effective multiplier, and derivation link | — | — |
| Security and signing | [#7812](https://github.com/adcontextprotocol/adcp/issues/7812) | `error.mutation_outcome` on failed mutations | — | `mutation_outcome` on `core/error.json` (#7935) |
-| Security and signing | [#7565](https://github.com/adcontextprotocol/adcp/issues/7565) | JSON-RPC batches in signed bodies | [#8064](https://github.com/adcontextprotocol/adcp/pull/8064) | — |
-| Security and signing | [#7563](https://github.com/adcontextprotocol/adcp/issues/7563) | Signature requirement triggered by a nested payload field | [#8064](https://github.com/adcontextprotocol/adcp/pull/8064) | — |
-| Security and signing | [#7905](https://github.com/adcontextprotocol/adcp/issues/7905) | Step-1 header rules in the signing vectors | — | Vectors 029–031, guards 013–015 (#8066), and profile-3.2 mirrors (#8068), shipped in 3.2.4 |
| Security and signing | [#7577](https://github.com/adcontextprotocol/adcp/issues/7577) | Checklist step position grading | — | — |
-| Security and signing | [#8118](https://github.com/adcontextprotocol/adcp/issues/8118) | Agent identity and buyer self-onboarding (umbrella; DR-0023) | [#8293](https://github.com/adcontextprotocol/adcp/pull/8293) | #7894, #8155, #8157, #8162, #8168, #8169, #8170, #8172, #8219, #8299 |
-| Security and signing | [#6033](https://github.com/adcontextprotocol/adcp/issues/6033) | Demand-side acts-for authorization (DR-0025) | — | Grants in trust.json and `grant_absent` (#8157, #8169) |
-| Targeting and inventory | [#7921](https://github.com/adcontextprotocol/adcp/issues/7921) | Gender in demographic targeting | [#7925](https://github.com/adcontextprotocol/adcp/pull/7925) | — |
-| Targeting and inventory | [#7834](https://github.com/adcontextprotocol/adcp/issues/7834) | Combine several collection lists in a package | — | Experimental `collection_lists` and `collection_lists_exclude` (#8061) |
-| Targeting and inventory | [#6135](https://github.com/adcontextprotocol/adcp/issues/6135) | Publisher-property coverage completeness | [#7948](https://github.com/adcontextprotocol/adcp/pull/7948) (draft) | — |
-| Creative and brand | [#8011](https://github.com/adcontextprotocol/adcp/issues/8011) | Broadcast creative: clearinghouse delivery reference | — | `mxf`, broadcast codecs, and `loudness` (#8019) |
-| Creative and brand | [#5375](https://github.com/adcontextprotocol/adcp/issues/5375) | `build_creative` refinement scope | — | Compliance carries forward across refinement (#7937) |
-| Creative and brand | [#4282](https://github.com/adcontextprotocol/adcp/issues/4282) | Provenance on listed and delivered creative variants | — | Creative-level `provenance` on `list_creatives` (#8063) |
-| Creative and brand | [#8048](https://github.com/adcontextprotocol/adcp/issues/8048) | Brand-wide `prohibited_terms` in brand.json | — | `prohibited_terms` on the brand.json brand definition (#8056) |
+| Targeting and inventory | [#8375](https://github.com/adcontextprotocol/adcp/issues/8375) | Supported match keys in capabilities and `Product.identity` | [#8446](https://github.com/adcontextprotocol/adcp/pull/8446) (draft) | — |
+| Targeting and inventory | [#8450](https://github.com/adcontextprotocol/adcp/issues/8450) | `required_match_keys` filter on `get_products` for cross-publisher cap planning | — (follow-up to draft [#8446](https://github.com/adcontextprotocol/adcp/pull/8446)) | — |
+| Targeting and inventory | [#8451](https://github.com/adcontextprotocol/adcp/issues/8451) | Conformance coverage for match keys before graduating `media_buy.match_keys` | — (follow-up to draft [#8446](https://github.com/adcontextprotocol/adcp/pull/8446)) | — |
| Creative and brand | [#8107](https://github.com/adcontextprotocol/adcp/issues/8107) | `3gp`, `mpeg`, and `m4v` video containers | — | — |
| Creative and brand | [#8092](https://github.com/adcontextprotocol/adcp/issues/8092) | Creator and show cards on collections | — | Collection cards, follower counts, response collections, and `list_collections` (#8094, #8098, #8141, #8279) |
-| Creative and brand | [#6348](https://github.com/adcontextprotocol/adcp/issues/6348) | Anchored creative feedback and per-party review records | — | — |
| Signals, audiences, catalogs | [#8023](https://github.com/adcontextprotocol/adcp/issues/8023) | Audience overlap read | [#8031](https://github.com/adcontextprotocol/adcp/pull/8031) (draft) | Audience size ranges (#8024) |
| Signals, audiences, catalogs | [#6872](https://github.com/adcontextprotocol/adcp/issues/6872) | `uids[].value` shape per type | — | Wire form documented (#8059) |
-| Signals, audiences, catalogs | [#6552](https://github.com/adcontextprotocol/adcp/issues/6552) | Provider-initiated signal delivery | [#8044](https://github.com/adcontextprotocol/adcp/pull/8044) | — |
-| Signals, audiences, catalogs | [#7898](https://github.com/adcontextprotocol/adcp/issues/7898) | Signal pricing groups | [#8058](https://github.com/adcontextprotocol/adcp/pull/8058) (draft) | — |
-| Signals, audiences, catalogs | [#7807](https://github.com/adcontextprotocol/adcp/issues/7807) | Per-source archive on `sync_event_sources` | — | `archived` on `sync_event_sources` items (#8060) |
-| Signals, audiences, catalogs | [#8125](https://github.com/adcontextprotocol/adcp/issues/8125) | Buyers name target audiences in audience evidence requirements | [#8215](https://github.com/adcontextprotocol/adcp/pull/8215) (draft) | — |
-| Signals, audiences, catalogs | [#8375](https://github.com/adcontextprotocol/adcp/issues/8375) | Supported match keys in capabilities and `Product.identity` | — | — |
| Conformance and governance | [#7068](https://github.com/adcontextprotocol/adcp/issues/7068) | Machine-observed implementation matrix | [#8040](https://github.com/adcontextprotocol/adcp/pull/8040) (draft) | — |
| Conformance and governance | [#3959](https://github.com/adcontextprotocol/adcp/issues/3959) | Governance framework mapping | [#8035](https://github.com/adcontextprotocol/adcp/pull/8035) (draft) | — |
-| Conformance and governance | [#7911](https://github.com/adcontextprotocol/adcp/issues/7911) | Training agent honours `property_list` targeting | — | Training agent support (#8078) |
| Conformance and governance | [#8093](https://github.com/adcontextprotocol/adcp/issues/8093) | Creator marketplace training fixtures | — | CreatorLoop seller and proposal fixtures (#8106) |
| Conformance and governance | [#8182](https://github.com/adcontextprotocol/adcp/issues/8182) | `hold_policy` and `extend_hold` storyboards and controller scenario | — | `force_hold_unavailable` controller scenario and hold-policy vector gaps (#8214); storyboards still open |
-| Conformance and governance | [#8201](https://github.com/adcontextprotocol/adcp/issues/8201) | 3.2 compact proposal storyboards and `sales-dooh` opt into fixture resolution | [#8333](https://github.com/adcontextprotocol/adcp/pull/8333) (draft) | `olv` channel match for `outdoor_video_auction` discovery (#8211) |
+| Conformance and governance | [#8201](https://github.com/adcontextprotocol/adcp/issues/8201) | 3.2 compact proposal storyboards and `sales-dooh` opt into fixture resolution | — | `olv` channel match for `outdoor_video_auction` discovery (#8211) |
+| Conformance and governance | [#8181](https://github.com/adcontextprotocol/adcp/issues/8181) | Training agent serves the experimental 3.3 hold-policy, `extend_hold`, and response-collection surfaces | — | — |
+| Conformance and governance | [#8398](https://github.com/adcontextprotocol/adcp/issues/8398) | URL validation is over-specified: eight patterns where `^https://` is enough | — | `setup_url` pattern relaxed to `^https://` with `format: uri` (#8548) |
-Also open, without a 3.3 milestone issue: [#7958](https://github.com/adcontextprotocol/adcp/pull/7958) composable delivery breakdowns and [#7957](https://github.com/adcontextprotocol/adcp/pull/7957) metric aggregation semantics (both drafts; their issues moved to 3.4.0), [#7446](https://github.com/adcontextprotocol/adcp/pull/7446) TMP Context Match cache isolation (on the 3.3.0 milestone), and [#8346](https://github.com/adcontextprotocol/adcp/pull/8346) signed creative addons (draft; asks the working group to reconsider a 3.4 deferral).
+Also open, without a 3.3 milestone issue: [#7958](https://github.com/adcontextprotocol/adcp/pull/7958) composable delivery breakdowns and [#7957](https://github.com/adcontextprotocol/adcp/pull/7957) metric aggregation semantics (both drafts; their issues moved to 3.4.0), [#7446](https://github.com/adcontextprotocol/adcp/pull/7446) TMP Context Match cache isolation (on the 3.3.0 milestone), and [#8346](https://github.com/adcontextprotocol/adcp/pull/8346) signed creative addons (open; asks the working group to reconsider a 3.4 deferral, and WG approval is pending).
## Known beta boundaries
@@ -235,7 +221,7 @@ Include this information in a beta issue:
- schema path or JSON Pointer involved;
- expected and actual behavior;
- minimal redacted payload and validation error;
-- whether the problem blocks beta.1 interoperability.
+- whether the problem blocks interoperability on the beta you tested.
Never include credentials, signed URLs, bearer tokens, private keys, or live customer payloads.
diff --git a/docs/reference/migration/3-2-to-3-3.mdx b/docs/reference/migration/3-2-to-3-3.mdx
index ce232ebb2a9..ebd822c485b 100644
--- a/docs/reference/migration/3-2-to-3-3.mdx
+++ b/docs/reference/migration/3-2-to-3-3.mdx
@@ -1,21 +1,21 @@
---
title: Migrating from 3.2 to 3.3
sidebarTitle: 3.2 to 3.3
-description: "Role-based migration checklist for adopting the AdCP 3.3 beta while preserving 3.2 compatibility: normative narrowings, loosened guarantees, version-gated new fields, SDK-facing schema changes, experimental notices, two deprecated result fields, one deprecated usage, and the deprecated account identity-rekey machinery."
+description: "Role-based migration checklist for adopting the AdCP 3.3 beta while preserving 3.2 compatibility: normative narrowings, loosened guarantees, version-gated new fields, SDK-facing schema changes, experimental notices, deprecated result fields, one deprecated usage, and the deprecated account identity-rekey machinery."
"og:title": "AdCP — Migrating from 3.2 to 3.3"
---
# Migrating from 3.2 to 3.3
-**3.3 is in its beta cycle.** Keep production traffic pinned to `"3.2"` while validating 3.3 in staging. See the [3.3 beta program](/docs/reference/3-3-beta) for artifact and SDK timing.
+**3.3 is in its beta cycle.** This guide is current through `3.3.0-beta.3` (published 2026-10-31). Keep production traffic pinned to `"3.2"` while validating 3.3 in staging. See the [3.3 beta program](/docs/reference/3-3-beta) for artifact and SDK timing.
3.3 is a minor release over 3.2. It adds optional fields, enum values, and capability declarations. No stable field, enum value, or task is removed; the one removal is the experimental `build_creative.evaluator.evaluator_id` source form (see [below](#experimental-creative-evaluator-drops-evaluator_id)). `seller_id` on event source and audience results is deprecated in favor of the new `platform_id` field. Natural-key account references after provisioning, the account identity-rekey machinery, and condition (b) of `request_signature_required` are also deprecated (see [Deprecations](#deprecations)). A caller opts into 3.3 only after the peer advertises the exact release in `supported_versions`. Existing 3.2 integrations that need nothing else can stay pinned to `"3.2"`.
Read these first:
-- [Required to claim 3.3 behavior](#required-to-claim-3-3-behavior): rules that narrow what a conformant implementation may do, including [unsupported webhook HMAC and batch bodies](#webhook-signing-mode-and-batch-bodies), [responses that conform to the served release](#responses-conform-to-the-served-release), [refinement that carries compliance forward](#refinement-carries-compliance-forward), [bounded counterparty-asserted domain lists](#counterparty-asserted-domain-lists-are-bounded), [seller revisions that advance on every committed change](#seller-revisions-advance-on-every-committed-change), [flight start for committed buys only](#flight-start-activates-committed-buys-only), [flat totals for multi-qualifier metrics](#multi-qualifier-metrics-omit-flat-totals), [enforceable domain identifiers](#property-domain-identifiers-have-an-enforceable-format), [property list references through AdCP tasks](#property-list-references-resolve-through-adcp-tasks), and [dual emission of platform IDs](#platform-ids-are-emitted-under-both-names).
+- [Required to claim 3.3 behavior](#required-to-claim-3-3-behavior): rules that narrow what a conformant implementation may do, including [unsupported webhook HMAC and batch bodies](#webhook-signing-mode-and-batch-bodies), [responses that conform to the served release](#responses-conform-to-the-served-release), [refinement that carries compliance forward](#refinement-carries-compliance-forward), [bounded counterparty-asserted domain lists](#counterparty-asserted-domain-lists-are-bounded), [seller revisions that advance on every committed change](#seller-revisions-advance-on-every-committed-change), [flight start for committed buys only](#flight-start-activates-committed-buys-only), [flat totals for multi-qualifier metrics](#multi-qualifier-metrics-omit-flat-totals), [enforceable domain identifiers](#property-domain-identifiers-have-an-enforceable-format), [property list references through AdCP tasks](#property-list-references-resolve-through-adcp-tasks), and [dual emission of platform IDs](#platform-ids-are-emitted-under-both-names), [`request_account` as the single account write](#request_account-is-the-single-account-write-where-supported), [the protocol envelope on every task response](#every-task-response-composes-the-protocol-envelope), [major-only requests served the oldest release](#a-major-only-request-is-served-the-oldest-supported-release), [closed schemas that stay closed](#closed-schemas-stay-closed-within-a-major), and [capabilities bounded by structure](#capabilities-are-bounded-by-structure).
- [Brand JSON size cap rises to 2 MiB](#brand-json-size-cap-rises-to-2-mib), [audience match counts](#audience-match-counts-may-be-absent), and the [4 MiB response-size default](#client-response-size-default-rises-to-4-mib): three loosened guarantees, so a 3.2 peer can reject or misread what a 3.3 peer sends.
- [Recommended: bound agent response size](#recommended-bound-agent-response-size): a new SHOULD that tightens what an adopting buyer accepts.
- [Send only to 3.3 peers](#send-only-to-3-3-peers): new fields a 3.2 validator rejects.
@@ -29,7 +29,7 @@ Everything else is an optional declaration or a clarification. Agent identity (D
| Step | Who | Action |
|---|---|---|
| 1 | Everyone | Keep production on `"3.2"`; choose an exact 3.3 beta artifact for staging. |
-| 2 | SDK and codegen maintainers | Generate from the signed `3.3.0-beta.0` protocol tarball, not `main` or `/schemas/latest/`. |
+| 2 | SDK and codegen maintainers | Generate from the signed `3.3.0-beta.3` protocol tarball (the latest checkpoint), not `main` or `/schemas/latest/`. |
| 3 | SDK and codegen maintainers | Treat `daypart_targets[].start_hour` / `end_hour` as optional in generated types (#8025). |
| 4 | SDK and codegen maintainers | Resolve `#/$defs/Provenance` in bundled schemas instead of expecting inlined provenance (#7950, already in 3.2.4). |
| 5 | SDK and codegen maintainers | Expect stricter response validation of `compact-task-submitted.json` (#7946, already in 3.2.4). |
@@ -53,7 +53,7 @@ Everything else is an optional declaration or a clarification. Agent identity (D
| 23 | Sellers and buyers of event sources and audiences | Sellers emit `platform_id` and the deprecated `seller_id` with identical values; buyers prefer `platform_id`. |
| 24 | Sellers with a media-buy, account or creative revision | Advance it on every committed change from any origin, including `sync_creatives` assignments and ingested connected-platform changes; add `origin` to `history` entries; optionally return `seller_revision` on `list_creatives`. |
| 25 | Buyers that update media buys | Pass the latest `revision`, and expect `CONFLICT` after a seller or connected-platform change; re-read and retry. |
-| 26 | Compliance operators | Use beta.0 for protocol feedback; do not issue a 3.3 badge from beta.0. |
+| 26 | Compliance operators | Use each 3.3 beta bundle for protocol feedback; as for 3.2, prerelease grading runs are diagnostic, not a badge. |
| 27 | Buyers and sellers of hosted video or audio | Optionally move playback trackers from `event: custom` to the new `pixel_tracker` playback events. |
| 28 | Users of the experimental `creative.evaluator` surface | Replace `evaluator_id` with an allowlisted `agent_url` or inline `exemplars` ([details](#experimental-creative-evaluator-drops-evaluator_id)). |
| 29 | Creative agents that advertise `creative.supports_refinement` | Retain each leaf's compliance inputs for as long as the leaf, apply them to every refinement, and never treat a refined leaf as approved ([details](#refinement-carries-compliance-forward)). |
@@ -62,6 +62,16 @@ Everything else is an optional declaration or a clarification. Agent identity (D
| 32 | Buyers and in-house clients | Send `adcp_version` on every request, with the deprecated `adcp_major_version` mirror through 3.x. 4.0 removes `adcp_major_version` and `adcp.major_versions` ([details](#deprecations)). |
| 33 | Network and run-of-network sellers | Return `publisher_properties: []` or `collections: []` only to callers served 3.3 or later; apply any exclusion list you accept against your full internal roster, and reject one you cannot apply with `UNSUPPORTED_FEATURE` ([details](#product-rosters-can-be-undisclosed)). |
| 34 | Buyers and SDK maintainers | Treat an empty roster as undisclosed and opaque, never as an empty set; do not index `publisher_properties[0]` or `collections[0]` ([details](#product-rosters-can-be-undisclosed)). |
+| 35 | Sellers that open accounts | Return and accept `account_id` everywhere, accept `account_id`-keyed settings updates, and never change an `account_id` ([#8474](https://github.com/adcontextprotocol/adcp/pull/8474), [details](#account-identity-is-the-account-id)). Stop relying on `operator_identity`, `ACCOUNT_MOVED`, `ACCOUNT_IDENTITY_CONFLICT`, and `stable_account_id`; they are [deprecated](#deprecations). |
+| 36 | Sellers and buyers that support `account.requests` | Use `request_account` for every account write, `list_accounts` for request reads, and `sync_principal` for subscriptions. Return `account` with money terms on `matched` and `created` resolutions ([details](#request_account-is-the-single-account-write-where-supported)). |
+| 37 | Sellers and SDKs that build task responses | Compose `core/protocol-envelope.json` on every response, include `status`, and truncate a `message` over 2,000 characters ([details](#every-task-response-composes-the-protocol-envelope)). |
+| 38 | In-house clients that send only `adcp_major_version` | Expect the oldest supported release in that major, 3.0 where supported (DR-0034); send `adcp_version` for newer behavior ([details](#a-major-only-request-is-served-the-oldest-supported-release)). |
+| 39 | Sellers and buyers that register webhooks | Select the signing mode in the registration: `signing_profile` or the deprecated `authentication` block. A seller with `legacy_hmac_fallback: false` rejects the block with `UNSUPPORTED_FEATURE` ([details](#webhook-signing-mode-and-batch-bodies)). |
+| 40 | Agents that publish `get_adcp_capabilities` | Stay within the structural bounds; do not design to a byte figure ([details](#capabilities-are-bounded-by-structure)). |
+| 41 | Sellers of creatives that are serving | Optionally declare `creative.live_updates` (experimental) and refuse undeclared changes with `CREATIVE_LIVE_UPDATE_UNSUPPORTED` ([details](#live-creative-updates-experimental)). |
+| 42 | Buyers and sellers of reporting | Adopt principal-level reporting subscriptions (experimental) and compute coverage from the wire ([details](#reporting-subscriptions-experimental)). |
+| 43 | Sellers that adopt the commercial experiments | Gate [seller offers, price adjustments, execution readiness, gender targeting, signal pricing groups, provider-initiated delivery, and measurement provenance](#commercial-and-targeting-experiments) on the negotiated version and the feature id. |
+| 44 | Sellers that keep package records | Retain packages on canceled and completed buys, and start approved creatives by default when others are pending review ([details](#canceled-and-completed-buys-keep-their-packages)). |
## Withdrawn from 3.3, planned for 4.0
@@ -168,7 +178,7 @@ See [Rows without impressions](/docs/media-buy/media-buys/optimization-reporting
### Product rosters can be undisclosed
-A product's `publisher_properties` and `collections` no longer require at least one entry. A non-empty list is the complete roster, as before. An empty list (`[]`) now means the seller does not disclose the roster: it is not an empty set and it bounds nothing. There is no new field and no partial state. An absent `collections` still makes no collection declaration, and `publisher_properties` stays required on a `Product`.
+A product's `publisher_properties` and `collections` no longer require at least one entry ([#7948](https://github.com/adcontextprotocol/adcp/pull/7948), refs [#6135](https://github.com/adcontextprotocol/adcp/issues/6135)). A non-empty list is the complete roster, as before. An empty list (`[]`) now means the seller does not disclose the roster: it is not an empty set and it bounds nothing. There is no new field and no partial state. An absent `collections` still makes no collection declaration, and `publisher_properties` stays required on a `Product`.
- **Emission gate.** A seller serving a release below 3.3 MUST NOT return a product with an empty roster; the 3.2 schema requires one entry, so it omits the product and returns the others ([Serving an older pin](/docs/reference/versioning#serving-an-older-pin)). Wholesale feeds and webhooks are not defined by this release.
- **Allow lists** (`property_list`, `collection_list`, `collection_lists`) MAY be accepted against an undisclosed roster. The package runs only on the items the seller matches, with no promise to cover every listed item.
@@ -329,7 +339,7 @@ A seller reporting an event source or audience platform ID in a 3.3 or later 3.x
### Account identity is the account ID
-An account's identity is the seller-assigned `account_id`. A brand is its domain, plus `brand_id` where its `brand.json` lists several brands. `brand.countries`, `currency`, `timezone`, `sandbox`, and `operator_unit` are account attributes, not identity.
+An account's identity is the seller-assigned `account_id` ([#8474](https://github.com/adcontextprotocol/adcp/pull/8474), from [#8280](https://github.com/adcontextprotocol/adcp/issues/8280) and [#8442](https://github.com/adcontextprotocol/adcp/issues/8442)). A brand is its domain, plus `brand_id` where its `brand.json` lists several brands. `brand.countries`, `currency`, `timezone`, `sandbox`, and `operator_unit` are account attributes, not identity.
- **Sellers** MUST return `account_id` on every non-failed `sync_accounts` provisioning result once the account is resolved, never issue one that might later change, accept `{ "account_id": "..." }` wherever an `AccountRef` is accepted, and never change it. If you open buyer-declared accounts through `sync_accounts`, accept settings-update entries keyed by `account_id`. Such an entry updates attributes, `brand.countries` and `billing` included, on the same account. Validate a changed attribute as you do when the account opens, and reject a change you do not support with `UNSUPPORTED_FEATURE`. `currency`, `timezone`, and `sandbox` are set at opening: you MAY refuse a `currency` or `timezone` change, and `sandbox` never changes. You can review a `countries` change first: report `pending_approval` on the entry's result row, and keep the current countries until you approve. A natural-key reference resolves only when exactly one of the caller's accounts matches; otherwise return `ACCOUNT_AMBIGUOUS`, and MAY list the candidates in `details.candidates`.
- **What narrows for sellers.** In 3.2, returning `account_id` was a SHOULD and accepting it was optional. Both are MUST, so a seller that met only the 3.2 wording does not conform. In 3.2, a buyer-declared seller could reject settings-update entries; in 3.3 it accepts them. A provisioning entry never changes an existing account. When it matches exactly one account in your account scope, on `brand` and `operator` with its attributes as filters as the [`request_account` deduplication guidance](/docs/accounts/tasks/request_account#deduplication) describes, you SHOULD return that `account_id` instead of opening another. The exact-or-reject rules for `billing` and `payment_terms` still apply.
@@ -339,6 +349,66 @@ An account's identity is the seller-assigned `account_id`. A brand is its domain
See [Account identity](/docs/accounts/overview#account-identity) and [Updating account attributes](/docs/accounts/tasks/sync_accounts#updating-account-attributes).
+### `request_account` is the single account write where supported
+
+Applies to sellers that declare the experimental `account.requests` capability ([#8293](https://github.com/adcontextprotocol/adcp/pull/8293), [#8551](https://github.com/adcontextprotocol/adcp/pull/8551), [#8543](https://github.com/adcontextprotocol/adcp/issues/8543) Part A). A seller that does not declare it keeps the 3.2 `sync_accounts` behavior, and `sync_accounts` stays stable and available everywhere in 3.3. Its formal deprecation follows `account.requests` leaving experimental status.
+
+- **One write.** `request_account` opens an account (`brand` and `operator`) and changes one. With an `account_id` and other fields, each field is a requested change: the brand's `countries` (with a matching `domain` and `brand_id`), `operator_unit`, `billing`, `billing_entity`, and `payment_terms`. A `revision` guards the change, and it is required when the change touches `billing`, `billing_entity`, or `payment_terms` (a stale one returns `CONFLICT`). `sandbox` never changes. `currency` and `timezone` change only on a seller that lists them in `account.requests.changeable_attributes`, and a seller that changes timezone MUST list it; otherwise the change is refused with `UNSUPPORTED_FEATURE`.
+- **Outcomes.** A request is `in_review` with a single `pending_action` saying whose turn it is, `resolved`, `ambiguous`, or `rejected`. A change resolves as `updated` on the named account, `matched` to an account the caller already holds, or `created` as a separate account carrying the change, and in the last two cases the named account is untouched and the seller MUST NOT move media buys, creatives, or reporting between the accounts. A `created` resolution happens only when the request set `allow_separate_account: true` (default `false`). A seller that would take the change only on a separate account otherwise refuses with the correctable `ACCOUNT_CHANGE_REQUIRES_NEW_ACCOUNT` ([#8580](https://github.com/adcontextprotocol/adcp/pull/8580), [#8582](https://github.com/adcontextprotocol/adcp/pull/8582)).
+- **Money terms (beta.3).** A request that resolves `matched` or `created` MUST carry `account`, with its `billing`, `billing_entity` (without write-only fields), and `payment_terms`, because they can differ from the terms requested. An `updated` request that changed `billing`, `billing_entity`, or `payment_terms` carries `effective_at`, when the new terms take effect. A `created` separate account carries `not_carried_over`, the account-level configurations it doesn't have ([#8620](https://github.com/adcontextprotocol/adcp/pull/8620)). A seller that returned these resolutions without `account` fails validation.
+- **Reads.** `list_accounts` takes `include_requests` and `request_ids` and returns `account_requests[]` beside `accounts[]`. Requests page through `requests_pagination` and `account_requests_pagination`; the top-level `pagination` pages accounts only. The unreleased `get_account_requests` task is gone, and `account.requests.read_task` is `list_accounts`.
+- **Authorization.** The seller resolves `account_id` against the caller's access before any other check, so an unreachable account answers like an unknown one. A change needs `request_account` in the grant's `allowed_tasks` with `read_only: false`, and every changed field in the grant's `field_scopes` when it lists them (`SCOPE_INSUFFICIENT`, `READ_ONLY_SCOPE`, `FIELD_NOT_PERMITTED`). A newer change request from the same caller supersedes the open one, which is rejected with `CONFLICT` and `details.superseded_by`.
+- **`sync_accounts` where `account.requests` is supported.** Buyers SHOULD use `request_account`, `list_accounts`, and `sync_principal` instead. A `sync_accounts` entry that carries only `notification_configs` or `reporting_delivery_configs` is a subscription write: it MUST name an account the caller already holds (otherwise `ACCOUNT_NOT_FOUND`), and the seller MUST NOT provision, review, or change account attributes for it. A settings update under review carries its `request_id`.
+
+**Buyers.** Send `request_account` to the seller that declares it, read `resolution` (`updated`, `matched`, or `created`; for the last two the resolved `account_id` differs from `requested.account_id`), and read `account` for the terms that apply. Keep using `sync_accounts` against sellers that don't declare the capability. See [`request_account`](/docs/accounts/tasks/request_account).
+
+### Every task response composes the protocol envelope
+
+([#8547](https://github.com/adcontextprotocol/adcp/pull/8547), correction (b) in [DR-0036](https://github.com/adcontextprotocol/adcp/blob/main/governance/decisions/DR-0036-closed-schemas-stay-closed-within-a-major.md).) Every task response schema and async status payload composes `core/protocol-envelope.json` through its root `allOf`, as the envelope's own notes already required. Envelope fields (`status`, `task_id`, `context_id`, `context`, `message`, `timestamp`, `replayed`, `adcp_error`, `push_notification_config`, `governance_context`) are siblings of the body fields at the response root on MCP and REST. Before, 47 of the 124 response and status schemas did not compose it, and 18 closed roots and branches rejected envelope fields, so generated types could not represent a conforming response.
+
+- **`status` is required.** The envelope required it already, and the schemas now enforce it on every response served at 3.3, including the async status payloads and governance responses that omitted it. A webhook `result` example carries the task's `status`.
+- **Version fields.** `core/protocol-envelope.json` composes `core/version-envelope.json`, so `adcp_version` and `adcp_major_version` are envelope fields on every response, stamped by the server framework rather than carried as task data. The `adcp_version` echo validates on the `control_media_buy`, `decline_proposals`, `buy_products`, and `accept_proposal` responses.
+- **Open roots.** Every response root and status branch is open. The 18 closed ones are reopened: the 3.2 proposal-flow roots and branches, the new 3.3 `list_collections`, `list_proposals`, `get_media_buy_issue`, and `report_media_buy_issue` responses, and the experimental `get_reporting_status` failure branches. Closed value objects and rows inside a body stay closed.
+- **`message`.** A task-level `message` is at most 2,000 characters, defined once in `core/task-message.json` and treated as untrusted input by the receiver. A seller whose text is longer MUST truncate it rather than fail the task.
+- **`task_id`.** One definition, `core/task-id.json` (`type: string`, `minLength: 1`), serves every declaration. An empty `task_id` is rejected. A submitted response requires `task_id`, a working body requires `status: working`, and an input-required body requires `status: input-required`, each through a shared schema.
+- **`replayed`.** An absent value means `false`, and a response may carry `replayed: false`; `replayed: true` appears only on a replay.
+
+No body field is added, renamed, or removed. **Sellers and SDKs** include `status` on every response and truncate `message`. **Buyers and SDK maintainers** regenerate types, since envelope fields now appear on every response type, and `status` enums on the `decline_proposals`, `request_proposals`, and `refine_proposals` roots are replaced by their branch constants.
+
+### A major-only request is served the oldest supported release
+
+A request that carries `adcp_major_version` and no `adcp_version` is served the **oldest** release the seller supports in that major, and the response echoes it ([DR-0034](https://github.com/adcontextprotocol/adcp/blob/main/governance/decisions/DR-0034-major-only-requests-are-served-the-oldest-release.md), accepted 2026-10-26). For a major-only `adcp_major_version: 3` request to a seller that supports 3.0, that is 3.0. Before, the rule was the newest. Every 3.1 and later SDK sends `adcp_version`, so in practice a major-only request comes from a 3.0 buyer whose payload is 3.0-shaped; answering with the newest release would return a shape its validator rejects. A request that carries neither field is still served the seller's default release. The rule is 3.x only and ends when 4.0 removes `adcp_major_version` ([DR-0035](https://github.com/adcontextprotocol/adcp/blob/main/governance/decisions/DR-0035-adcp-major-version-removed-in-4-0.md)).
+
+**Sellers.** Resolve a major-only request to the oldest supported release in that major, and serve and echo it ([Serving an older pin](/docs/reference/versioning#serving-an-older-pin)). **In-house clients** that send only the integer lose newer fields; send `adcp_version`.
+
+### Closed schemas stay closed within a major
+
+A schema that any stable release of a major published closed (`additionalProperties: false` or `unevaluatedProperties: false`) stays as that release published it until the next major. A minor adds nothing to it, even to peers that negotiated the newer minor, and even for an experimental field ([DR-0036](https://github.com/adcontextprotocol/adcp/blob/main/governance/decisions/DR-0036-closed-schemas-stay-closed-within-a-major.md), status: proposed, awaiting working-group ratification). Four recorded corrections are the only exceptions, each bringing a schema back to text the spec already required: (a) the 3.2 proposal flow is reopened, (b) the envelope is composed on every response with `status` required, (c) `task_id` identifies a task, and (d) `message` is bounded. Each ships in 3.3 and in a 3.2.x patch.
+
+What this means for 3.3 adopters:
+
+- **Features that needed to add terms to `commercial_terms` are withdrawn** ([above](#withdrawn-from-3-3-planned-for-4-0)), and seller-held change terms are planned for 4.0 instead of shipping as `commercial_terms.change_terms[]`.
+- **New 3.3 additions sit on open schemas or in sibling fields.** `target_audiences[]` is a sibling of the closed `audience_evidence_requirements`, `vendor_metric_provenance[]` is a sibling of the closed `vendor_metric_values[]` row, and `counting_mechanisms` reaches the closed canonical measurement terms in 4.0.
+- **Send a 3.3 field on a reopened schema only to a 3.3 peer.** A strict validator on an earlier 3.2 patch still rejects it ([Send only to 3.3 peers](#send-only-to-3-3-peers)).
+
+### Capabilities are bounded by structure
+
+([#8505](https://github.com/adcontextprotocol/adcp/pull/8505), restated in [#8526](https://github.com/adcontextprotocol/adcp/pull/8526), [#8198](https://github.com/adcontextprotocol/adcp/issues/8198).) The `maxItems`, `maxLength`, and `maxProperties` limits in the `get_adcp_capabilities` schema, and the `x-max-items-4.0`, `x-max-length-4.0`, and `x-max-properties-4.0` annotations on fields that were stable before 3.3, are the protocol's limit on the document. Agents MUST NOT design to a byte figure.
+
+- **New and experimental fields enforce the limit with the keywords.** Fields stable before 3.3 carry it as the 4.0 annotations, a SHOULD through 3.x that 4.0 turns into the keyword. No schema-valid 3.2 document becomes invalid.
+- **`MAX_CAPABILITIES_BYTES` (64 KiB) keeps its name and value** as a receiver backstop and deployment guidance: receivers commonly bound response size at the HTTP or gateway layer, and a limit near 64 KiB is a reasonable guard against runaway or hostile documents. It is not a design target and not a rule on senders. It stays the fetch budget of step 1 in the deprecated RFC 9421 key-discovery chain through 3.x.
+- **Counterparty-asserted lists are unchanged.** The 8,192-byte budget per field and 16,384 bytes together stand, as in [above](#counterparty-asserted-domain-lists-are-bounded).
+
+**Agents** keep their capabilities well inside the structural bounds, and an agent with a large creative catalog adopts the Web Bot Auth profile or keeps its document under the receiver backstop. **Receivers** apply the backstop at the transport layer, not as a protocol rule.
+
+### Canceled and completed buys keep their packages
+
+([#8467](https://github.com/adcontextprotocol/adcp/pull/8467).) From 3.3 a seller retains packages on canceled and completed media buys. It preserves records it held at adoption and packages it later creates or observes, including stable identities, correlation data, platform mappings, and the latest recorded committed configuration whatever its origin. Irrecoverable earlier or never-observed external history is disclosed through nonfatal errors, not by silently returning an incomplete list. Prior terminal package outcomes and the original cancellation metadata are preserved, released creative assignments stay released, and missing statistics are never reported as zero delivery. Responses served as 3.2 permit empty terminal package lists and carry no retention guarantee. A 3.3 stateful conformance scenario checks complete package readback after individual and whole-buy cancellation.
+
+### Mixed creative approval states at startup
+
+([#8485](https://github.com/adcontextprotocol/adcp/pull/8485).) A seller keeps valid pending-review and rejected assignments and starts the eligible approved assignments by default. An optional package `start_requires_all_creatives_approved` gate, declared through `media_buy.features.creative_start_policy`, holds the start until every assignment is approved, and a structured-only `update_creative_start_policy` action sets it independently of assignment changes. The gate is consumed at first enablement for serving. A seller distinguishes its own review (`pending_start`) from buyer-actionable missing coverage or a blocking rejection (`pending_creatives`). The new pre-activation `pending_start` to `pending_creatives` transition needs corresponding SDK transition-validator support before you adopt it. Buyers assign the complete launch set atomically or keep delivery paused during staged supply.
+
### Receivers ignore `aggregated_totals` in delivery webhooks
Senders still MUST NOT put `aggregated_totals` in a delivery webhook result. Receivers now MUST ignore it if present, MUST NOT treat it as authoritative, and MUST NOT reject the payload for carrying it. Reconcile totals from `get_media_buy_delivery` or from the per-delivery rows. See [webhooks](/docs/building/by-layer/L3/webhooks).
@@ -383,13 +453,13 @@ The recommended client safety limit on a whole MCP message or A2A call rises fro
### Webhook signing mode and batch bodies
-The buyer's webhook registration selects the signing mode, as in 3.2. An `authentication` block asks for the legacy scheme, and without one the seller signs under the registration's `signing_profile`.
+The buyer's webhook registration selects the signing mode, as in 3.2 ([#8475](https://github.com/adcontextprotocol/adcp/pull/8475)). An `authentication` block asks for the legacy scheme, and without one the seller signs under the registration's `signing_profile` (`adcp/webhook-signing/v1` when it is omitted). `legacy_hmac_fallback` is a discovery flag that a buyer checks before asking for legacy signing; it does not select the mode.
- **Sellers with `legacy_hmac_fallback: false`.** Reject a registration carrying an `authentication` block with `UNSUPPORTED_FEATURE`, not `request_signature_required`. Point `error.field` at the block.
- **Sellers with `legacy_hmac_fallback: true`.** 3.2 behavior stays valid through 3.x, including the signature requirement on a registration that carries `authentication` (condition (b)). Condition (b) is deprecated and removed in 4.0 with the block.
- **`reporting_webhook` and `artifact_webhook`.** Their `authentication` is optional from 3.3 and still required on a request served below 3.3. These rules apply to them only on a request served at 3.3 or later; below 3.3 nothing changes. An absent block signs under the registration's `signing_profile` (`adcp/webhook-signing/v1` by default).
- **Buyers.** Send `authentication` only to a seller whose `legacy_hmac_fallback` is `true`. Compare a received webhook's signing mode with the mode you registered.
-- **Batch bodies.** A JSON array body, signed or unsigned, is rejected with `request_body_malformed` (SHOULD in 3.2.x, MUST from 3.3). A client that batches JSON-RPC messages, which older MCP protocol versions allowed, sends one message per request.
+- **Batch bodies.** A JSON array body, signed or unsigned, is rejected with `request_body_malformed` (SHOULD in 3.2.x, MUST from 3.3, [#8064](https://github.com/adcontextprotocol/adcp/pull/8064)); this replaces the 3.2 interim rule that let a verifier resolve every element of a batch. A client that batches JSON-RPC messages, which older MCP protocol versions allowed, sends one message per request.
## Recommended: bound inbound push and webhook bodies
@@ -416,6 +486,12 @@ Many 3.3 additions sit inside objects that 3.2 closes, so a strict 3.2 validator
| Seller | `hold_policy` on products and proposals, `committed` proposals under `terms_only` finalize | The fields are not in 3.2, and a 3.2 buyer reads `committed` as an inventory hold. |
| Seller | `dooh_inventory_summary` on canonical products (`list_products`, `request_proposals`, `refine_proposals`) | 3.2 `canonical-product.json` is closed. |
| Buyer | `brand`, `operator_unit`, `currency`, `timezone`, or `billing` on a `sync_accounts` settings-update entry | 3.2 `SettingsUpdateMode` forbids them. |
+| Seller | `proposal_initiator`, `offer_reason`, seller offers, and `proposal.offered` notifications | `proposal_initiator` is a 3.3 field on a schema reopened in 3.3. A caller with no declared pin is treated as below 3.3. |
+| Seller | A `price_adjustments` table on a fixed-price pricing option | The table is a 3.3 field, never returned to a caller below 3.3. |
+| Seller | `credit_note` records on `get_account_financials` invoices | A pre-3.3 buyer summing `invoices[].amount` would count a credit as a charge. |
+| Buyer | Core `demographics.gender` targeting | 3.2 core targeting is age-only. |
+| Seller | `counting_mechanisms[]` on `measurement_terms` and `vendor_metric_provenance[]` on delivery metrics | Strict older validators reject the new fields. |
+| Buyer | `reporting_subscriptions` on `sync_principal` | A seller that lists only `sync_principal` in `reporting_delivery.configuration_tasks[]` serves reporting registration to 3.3 callers only. |
| Buyer | `pixel_tracker` `event` values `start`, `first_quartile`, `midpoint`, `third_quartile`, `complete` | 3.2 closes the `event` enum; send them as `event: custom` until the seller negotiates 3.3 ([below](#hosted-video-and-audio-playback-trackers)). |
New enum values (`nmo`, `videoamp`, `mxf`, `mpeg2`, `avc_intra`, `xavc`, `print_metrics` in `available-metric`, `operator_fee` in `adjustment-kind`) fall under the 3.x rule that clients tolerate unknown values, but a strict 3.2 validator still rejects them; send them only to 3.3 peers too.
@@ -446,7 +522,8 @@ These change generated types or bundle shape without changing what a conformant
- **Envelope composition (#7946, 3.2.4).** Nine compact and experimental request schemas and `core/compact-task-submitted.json` now compose `core/version-envelope.json` through root `allOf`, so generated types share envelope ancestry. Request validation is unchanged; `compact-task-submitted.json` response validation is tightened as listed above.
- **`media_buy.features` is no longer boolean-only (#7927).** `catalog_ingestion` is an object, so generators that emit a map of booleans for `media_buy.features` break.
- **Daypart requirements (#8025).** `required_overlay_support.daypart_targets.timezone_modes` is no longer required; a requirement carries `timezone_modes`, `time_granularity`, or both.
-- **Product rosters (#6135).** `publisher_properties` and `collections` lose `minItems: 1` on `product.json` and `canonical-product.json`. Generated types change for every product (a TypeScript non-empty tuple becomes `T[]`; a Pydantic `min_length` is dropped). Do not index `[0]` without a guard, and treat `[]` as undisclosed, not empty.
+- **Product rosters (#7948, refs #6135).** `publisher_properties` and `collections` lose `minItems: 1` on `product.json` and `canonical-product.json`. Generated types change for every product (a TypeScript non-empty tuple becomes `T[]`; a Pydantic `min_length` is dropped). Do not index `[0]` without a guard, and treat `[]` as undisclosed, not empty.
+- **Envelope on every response (#8547).** Response types compose `core/protocol-envelope.json`: `status` is required on every task response and async status payload, `message` is bounded at 2,000 characters through `core/task-message.json`, `task_id` is `core/task-id.json` (`minLength: 1`), and `replayed` accepts `false`. Response roots and status branches are open, and 66 local copies of envelope fields are removed so the envelope's declarations govern. Regenerate types; a hand-written response model that omitted `status` must add it.
- **Delivery rows (#8108).** `impressions` is optional on `daily_breakdown` and dimensional breakdown rows; `aggregated_totals` still requires it.
- **Reporting issue codes (#8099, 3.2.4).** The closed reporting status issue-code enum gains `REVISION_UNREADABLE`, with a `reporting_revision_id` field. Strict readers must accept it.
- **Spot rows (#8017).** `by_spot[].aired_at` is required only on `aired` and `makegood` rows and on rows without `spot_status`.
@@ -482,7 +559,7 @@ Optional, two pieces with different stability.
A migration note: a legacy installment that carries only the deprecated `collection_id` cannot be represented on the canonical surface. Add `collection_ref` before declaring 3.3 — a seller that drops such installments from its canonical projection is asserting run-of-collection for a product that actually sells named slots.
-**Not in 3.3.** Naming the exact installments a purchase buys, and dropping or swapping one through `refine_proposals`, was merged for 3.3 and is [withdrawn to 4.0](#installment-selection-merged-after-beta-0-removed-before-beta-1). A purchase buys the product as offered.
+**Not in 3.3.** Naming the exact installments a purchase buys, and dropping or swapping one through `refine_proposals`, was merged for 3.3 and is [withdrawn to 4.0](#installment-selection-published-in-beta-1-removed-after-beta-1). A purchase buys the product as offered.
### Creative `seller_revision`
@@ -590,6 +667,46 @@ The field is stable in 3.3, not experimental. It completes the basis vocabulary
- **`trust.json` (experimental).** `trust/v1/trust.json` and `trust/v1/trust-acknowledgements.json` are published under `identity.trust_json` (#8067). An agent is identified by the canonical origin of its URL, one agent per origin, and the record carries no keys (#8121). In 3.3 its reader is the experimental Web Bot Auth profile, which derives the record from the agent's origin, and grants are read at `sync_accounts`. Publishers declare nothing. See [trust.json](/docs/reference/trust-json) and the [agent identity migration guide](/docs/reference/migration/agent-identity-3-3).
- **`ext.adcp.opportunity`.** Cooperating `get_products` integrations can carry an opportunity binding under `ext.adcp.opportunity`, declared by listing `adcp` in `extensions_supported`. Durable association needs an authorized account scope, and a mismatched ID on refine is rejected with `INVALID_REQUEST`. The core `opportunity` field is still in review. See [AdCP opportunity extension](/docs/building/by-layer/L2/context-sessions#adcp-opportunity-extension).
+### Live creative updates (experimental)
+
+Optional (`creative.live_updates`, [#8488](https://github.com/adcontextprotocol/adcp/pull/8488), folding in staged activation from [#6780](https://github.com/adcontextprotocol/adcp/issues/6780)). A buyer changes a creative that is serving by syncing it again under the same `creative_id`. A seller that lists the feature id declares in `creative.live_updates` which kinds of change (`click_through`, `trackers`, `asset_content`, `format`) it applies in place and how the creative serves meanwhile: `uninterrupted` (decided inside the sync call), `staged` (the approved prior version keeps serving until the change is approved, then is promoted atomically; `on_rejection` is `keeps_prior` or `stops`), or `paused_for_review` (the existing lifecycle). Name and tag changes are always accepted.
+
+- `list_creatives` and the `sync_creatives` item return `staged_update` while a change awaits promotion; `dry_run` returns the exact outcome of one change. There is no per-creative policy readback: the declaration is the general floor and `dry_run` answers for one change.
+- The new notification type `creative.staged_update_changed` reports a staged update's outcome (`promoted` or `rejected`) only to subscribers that register it. `creative.status_changed` is unchanged, so a buyer on an earlier release never receives an `approved` to `approved` event that its closed validator would reject.
+- A seller that declares the capability refuses an undeclared change with `CREATIVE_LIVE_UPDATE_UNSUPPORTED` (with `error-details/creative-live-update-unsupported.json`) in place of `INVALID_STATE`. A seller that doesn't declare it keeps the original rule: creatives on active, non-paused packages cannot be updated, and the refusal is `INVALID_STATE`.
+- `comply_test_controller` `force_creative_status` forces a staged update's review outcome. The storyboards are `media_buy_seller/creative_live_updates` and `media_buy_seller/creative_live_update_refusal`.
+
+See [Live creative updates](/docs/creative/task-reference/sync_creatives#live-creative-updates).
+
+### Reporting subscriptions (experimental)
+
+Optional (`media_buy.reporting_subscriptions`, [#8543](https://github.com/adcontextprotocol/adcp/issues/8543) Part B, [#8552](https://github.com/adcontextprotocol/adcp/pull/8552), settled through beta.3). Reliable Reporting was configured one account at a time through `sync_accounts` `reporting_delivery_configs`, so a new account reported nothing until someone configured it. `sync_principal` now takes `reporting_subscriptions`: one registration per feed purpose, scoped to `all_authorized_accounts: true` (an explicit acknowledgment) or named `account_ids`, with a cross-seller `selector` (`feed_purpose`, `period_duration`, `required_finality`, optional `alignment` and `dimensions[]`, and `match`). Sellers list accepted registration tasks in `reporting_delivery.configuration_tasks[]`; `configuration_task` stays `"sync_accounts"` for callers pinned below 3.3 and is deprecated. A caller's own active `sync_accounts` entry for an account and feed purpose still wins over its subscriptions.
+
+**What the buyer can compute from the wire.** `get_reporting_status` reports only exceptions under `subscription_coverage`, and an exception removes periods from what is owed and never adds any, so a missing report is still an owed period.
+
+- **Which periods are owed.** A buy is owed every period that ends after its `confirmed_at` and overlaps its flight, starting at the first boundary at or after the later of the subscription version's `accepted_at` and the account's `authorization.authorized_at`, so the period in which a buy is confirmed is owed in full ([#8593](https://github.com/adcontextprotocol/adcp/pull/8593)). The flight stops at the earliest of `end_time`, `cancellation_effective_at` (the delivery stop, later than `canceled_at` when the seller delivers through a notice period), and `completed_at`. A flight that stops at or before its `start_time` owes nothing.
+- **Cutovers and billing stubs.** A change takes effect as a cutover at instant T. When a billing feed's incoming schedule has no boundary at the handoff, the stretch to its first boundary is owed as one stub obligation (`stub: true`); pacing and analytics feeds leave it unowed. This covers account timezone changes and account-level `sync_accounts` billing configurations ([#8617](https://github.com/adcontextprotocol/adcp/pull/8617)).
+- **Wire inputs.** `authorization.regranted_at`, `flight_history` on media buys and `get_media_buys`, `packages[].reporting_delivery_offering_ids` fixed at confirmation, `available_from` and `withdrawn_at` on offerings, and per-version `configuration` in `prior_versions` ([#8618](https://github.com/adcontextprotocol/adcp/pull/8618), [#8588](https://github.com/adcontextprotocol/adcp/pull/8588)). Offerings publish `standard_dimensions` so the buyer resolves `match` exactly as the seller does, and sellers MUST publish it on every offering ([#8585](https://github.com/adcontextprotocol/adcp/pull/8585)).
+- **Determinism and scale.** Resolution is per package and fixed per buy and version until the resolved offering is withdrawn. `max_accounts` admission is sticky, ordered by `authorization.authorized_at` then `account_id` in byte order. Billing subscriptions MUST use `match: exact` with `dimensions`. `destination_overrides[]` route accounts to other destinations, membership edits apply in place as `excluded_by_buyer` intervals without a new `subscription_version`, and the readback lists 16 prior versions and 1,000 accounts inline, with `get_principal` paging the rest through `reporting_subscription_page` ([#8619](https://github.com/adcontextprotocol/adcp/pull/8619)).
+- **Deactivation and revocation.** A deactivated subscription reads `inactive` with a required `deactivated_at`, and periods that started before deactivation stay owed ([#8613](https://github.com/adcontextprotocol/adcp/pull/8613)). After the caller loses authority for an account, `sync_reporting_receipts` and `sync_reporting_status` treat every reference to it like an unknown identifier ([#8607](https://github.com/adcontextprotocol/adcp/pull/8607)). A seller that wants a buyer to finish reconciling keeps a reduced grant that lists only the reconciliation tasks, and a grant that lists `get_reporting_status` but not the receipt or status tasks keeps the account covered and refuses the missing tasks with `SCOPE_INSUFFICIENT`.
+- **Period arithmetic.** Years, months, and days are civil time; hours, minutes, and seconds are elapsed time. Under a local alignment each local date's first instant is a boundary, so `PT24H` equals `P1D`, and a sub-daily duration MUST divide 24 hours. `billing_cycle` needs a date component, weeks (`P7D`) under `utc`, `account_timezone`, and `source_timezone` start on Thursday, and `status_retention_days` counts exact 24-hour days ([#8588](https://github.com/adcontextprotocol/adcp/pull/8588), [#8622](https://github.com/adcontextprotocol/adcp/pull/8622)).
+- **Delivery stays inside the flight.** A seller that lists the feature id MUST NOT deliver on a buy outside its flight; to deliver later, including a make-good with remedy `additional_delivery`, it first extends `end_time`.
+
+Test assets: canonical coverage vectors with an independent reference model under `static/compliance/source/test-vectors/reporting-subscriptions/` ([#8616](https://github.com/adcontextprotocol/adcp/pull/8616)), and the `comply_test_controller` `reporting_subscription_probe` scenario for grants, account timezones, and the virtual clock ([#8621](https://github.com/adcontextprotocol/adcp/pull/8621)). See [Reporting subscriptions](/docs/protocol/sync_principal#reporting-subscriptions) and [Subscription coverage](/docs/media-buy/task-reference/get_reporting_status#subscription-coverage).
+
+### Commercial and targeting experiments
+
+Each is optional and experimental: a seller that emits it lists the feature id in `experimental_features`, and a seller that declares nothing keeps 3.2 behavior.
+
+- **Seller offers (`media_buy.seller_offers`, [#8102](https://github.com/adcontextprotocol/adcp/pull/8102)).** A seller proposes a change to an accepted buy as a `committed` canonical proposal with `proposal_initiator: "seller"` and an `offer_reason` (`installment_postponed`, `installment_cancelled`, `preemption`, `under_delivery`, `seller_request`), a `media_buy_update` or `media_buy_cancellation` that carries `parent_proposal_id`, `media_buy_id`, and `base_media_buy_revision`. Buyers read offers through `list_proposals`, announced by the identifiers-only `proposal.offered` notification, and accept with `accept_proposal`, decline with `decline_proposals`, or revise with `refine_proposals`. `expires_at` is the response deadline; at it the signed terms stand and `accept_proposal` returns `PROPOSAL_EXPIRED`, so silence is never acceptance. A seller that lists the feature id MUST also list `media_buy.open_opportunities` and advertise `list_proposals`. Sellers MUST NOT send offers to callers served below 3.3. Pre-agreed seller changes inside `commercial_terms` are not part of 3.3. See [Seller offers](/docs/media-buy/product-discovery/proposal-negotiation#seller-offers).
+- **Price adjustments (`media_buy.price_adjustments`, [#7955](https://github.com/adcontextprotocol/adcp/pull/7955), [#7659](https://github.com/adcontextprotocol/adcp/issues/7659)).** A binding fixed-price pricing option (`cpm`, `vcpm`, `cpc`, `cpcv`, `cpv`, `cpp`, `flat_rate`) can carry an ordered table of `fee` and `discount` rows, each with a `rate` or a fixed `amount`, keyed by `format_option`, `placement_selection` (needs `overlay_support.placement_selection`), or `always`, and optionally a `valid_from` and `valid_until` window evaluated at the purchase `start_time`; a flight that crosses a window boundary is rejected. Selection rows fire at most once per dimension, then each firing row applies to one running total in declared order, rounding half away from zero at every step. A table is optional: without one, the price applies only to what was quoted. A seller never returns a table to a caller below 3.3. See [Selection-dependent price adjustments](/docs/media-buy/advanced-topics/pricing-models#selection-dependent-price-adjustments).
+- **Execution readiness (`media_buy.execution_readiness`, [#7934](https://github.com/adcontextprotocol/adcp/pull/7934)).** For products that declare `execution_requirements`, a `get_products` request with `account` can set `include_execution_readiness: true`. The response carries an `execution_readiness` map keyed by `product_id`, versioned independently of `wholesale_feed_version` so public wholesale catalogs keep `cache_scope: "public"`. Each product and requirement reports `ready`, `setup_required`, `selection_required`, `input_required`, or `unknown` (the seller could not check, which is not the same as the account lacking the resource), with candidates whose `resource_id` is directly usable in the existing binding field. See [Per-account execution readiness](/docs/media-buy/specification#per-account-execution-readiness-experimental).
+- **Gender targeting (`media_buy.gender_targeting`, [#7925](https://github.com/adcontextprotocol/adcp/pull/7925)).** Core `demographics.gender` predicates with `female`, `male`, and `non_binary` value sets and an independent unknown group, whose `include_unknown` covers both unavailable gender and an explicit choice not to state it. Product-scoped capabilities, exact gender-only and mixed age and gender readback, and `sex_gender` governance classification come with it. Demographic delivery reporting stays age-only in 3.3, so a gender-targeted package has no gendered delivery readback. Buyers MUST NOT send core gender fields on a 3.2 contract. See [Core gender targeting](/docs/media-buy/advanced-topics/targeting#core-gender-targeting-3-3).
+- **Signal pricing groups (`signals.pricing_groups`, [#8058](https://github.com/adcontextprotocol/adcp/pull/8058), [#7898](https://github.com/adcontextprotocol/adcp/issues/7898)).** An optional `pricing_group` on `get_signals` results and on `Product.signal_targeting_options[]`, with `signal_pricing_group_rules[]` (`{pricing_group, pricing_combination: highest | each}`) on the response and on `signal_targeting_rules`, lets a seller price signals such as alternative age bands as one audience. A group with no rule and every ungrouped signal is charged `each`, and `flat_fee`, `per_unit`, `custom`, and `percent_of_media` options are always charged `each`. See [Signal pricing groups](/docs/media-buy/advanced-topics/targeting#signal-pricing-groups).
+- **Provider-initiated signal delivery (`signals.delivery_methods`, [#8044](https://github.com/adcontextprotocol/adcp/pull/8044), [#6552](https://github.com/adcontextprotocol/adcp/issues/6552)).** A signal agent declares `signals.delivery_methods[]` on `get_adcp_capabilities`, with the same pattern vocabulary as audience activation methods read from the send side. An `activate_signal` agent destination may pin a `delivery_method`; with no pattern and vendor intersection the destination fails with `UNSUPPORTED_FEATURE`, and a pin sent to an agent that doesn't list it is rejected the same way. Agent deployments gain `delivery_status` (`awaiting_read`, `delivered`, `failed`), a `delivery` descriptor, `delivery_error`, and an optional match outcome. A receiver field not yet established fails the destination with `ACCOUNT_SETUP_REQUIRED`. See [Declaring delivery methods](/docs/signals/tasks/activate_signal#declaring-delivery-methods).
+- **Measurement provenance (`media_buy.measurement_provenance`, [#7940](https://github.com/adcontextprotocol/adcp/pull/7940)).** A shared `enums/collection-mechanism.json` vocabulary (`set_top_box`, `acr`, `panel`, `server_logs`, `client_tracker`, `sdk`) has two uses, both on open schemas: `measurement_terms.billing_measurement.counting_mechanisms[]` declares what the billing count is counted from (a seller whose own system is the named vendor SHOULD declare it; absence means undeclared), and `vendor_metric_provenance[]` on delivery metrics carries `mechanisms[]` and an optional `deduplicated` for a `vendor_metric_values[]` row, joined on `(vendor, metric_id, qualifier)`. A collection mechanism is not `measurement_source`, which stays the provider slug, and broadcast as-run logs stay airing evidence in `by_spot[]`. Sellers serving an older pin omit both fields.
+- **Audience evidence targets and invoice lines.** `target_audiences[]` (`media_buy.audience_evidence_targets`, [#8215](https://github.com/adcontextprotocol/adcp/pull/8215)) names the audience a buyer wants evidence for beside `audience_evidence_requirements`, satisfied only by an admissible evidence item for exactly that audience; it is never a targeting predicate. `lines[]`, `invoice_kind`, and `adjusts_invoice_id` on `get_account_financials` invoices (`account.invoice_lines`, [#8207](https://github.com/adcontextprotocol/adcp/pull/8207)) tie an amount to the buys, packages, and reporting revisions it bills, and never settle an invoice.
+
## Experimental surface notices
### Experimental creative evaluator drops `evaluator_id`
@@ -645,12 +762,12 @@ Adopters of these patches have already seen these; their changesets reappear in
3.3 deprecates two result fields, the principal kind field and assertion, the RFC 9421 signing profiles, one usage, and the account identity-rekey machinery; all remain functional throughout 3.x:
- **`seller_id` on `sync_event_sources` and `sync_audiences` results.** Use the new optional `platform_id` for the object's ID in the seller's ad platform, matching `sync_creatives` and `sync_catalogs`. **Sellers** reporting a platform identifier in 3.3 and later 3.x responses MUST emit both fields with identical values, including discovery responses and seller-managed event sources. **Buyers** MUST prefer `platform_id` and fall back to `seller_id` only when `platform_id` is absent. Either field may be absent in legacy responses, and both may be absent when no platform identifier is available. Continue using `event_source_id` and `audience_id` in AdCP requests. The aliases keep their object-ID semantics; they are never seller identity. `adagents.json` `contact.seller_id` and publisher identifiers of type `seller_id` are unchanged. Removal is no earlier than 4.0 and subject to the [six-month notice policy](/docs/reference/versioning#deprecation-policy). See [event source migration](/docs/media-buy/task-reference/sync_event_sources#platform-identifier-migration-adcp-3-3) and [audience migration](/docs/media-buy/task-reference/sync_audiences#platform-identifier-migration-adcp-3-3) ([#8290](https://github.com/adcontextprotocol/adcp/issues/8290)).
-- **`principal_kind` and `expected_principal_kind` on `sync_principal` and `get_principal`**, and the `enums/principal-kind.json` enum. A principal is the buyer agent as the seller has bound it, so the kind is always `buyer_agent` and carries no information. Sellers keep returning `principal_kind` and honoring `expected_principal_kind` throughout 3.x; buyers stop reading and sending them, and don't branch on `principal_kind`. Removal is no earlier than 4.0 and subject to the [six-month notice policy](/docs/reference/versioning#deprecation-policy). The task names are unchanged ([#8280](https://github.com/adcontextprotocol/adcp/issues/8280)).
+- **`principal_kind` and `expected_principal_kind` on `sync_principal` and `get_principal`**, and the `enums/principal-kind.json` enum. A principal is the buyer agent as the seller has bound it, so the kind is always `buyer_agent` and carries no information. Sellers keep returning `principal_kind` and honoring `expected_principal_kind` throughout 3.x; buyers stop reading and sending them, and don't branch on `principal_kind`. Removal is no earlier than 4.0 and subject to the [six-month notice policy](/docs/reference/versioning#deprecation-policy). The task names are unchanged ([#8443](https://github.com/adcontextprotocol/adcp/pull/8443), [#8280](https://github.com/adcontextprotocol/adcp/issues/8280)).
- **The AdCP RFC 9421 signing profiles**, for requests (`adcp/request-signing/v1`) and webhooks (`adcp/webhook-signing/v1`), with keys found through brand.json and `identity.brand_json_url`. They keep working throughout 3.x and are removed in AdCP 4.0, together with the brand.json trust fields ([DR-0023](https://github.com/adcontextprotocol/adcp/blob/main/governance/decisions/DR-0023-agent-identity-is-an-origin.md)). Their replacement is the experimental Web Bot Auth profile ([Web Bot Auth identities](/docs/building/by-layer/L1/security#web-bot-auth-identities); role-by-role steps in the [agent identity migration guide](/docs/reference/migration/agent-identity-3-3)): identity is the signer's origin, keys come from that origin's key directory, and no capabilities call is needed. **Signers** that serve no capabilities endpoint can move now. **Verifiers** keep accepting RFC 9421 signatures through 3.x, under the no-downgrade rule once an origin is bound.
- **The natural key as the account reference after provisioning.** Sending the natural-key `AccountRef` on account-scoped tasks once the account exists is deprecated and planned for removal in AdCP 4.0 ([#7850](https://github.com/adcontextprotocol/adcp/issues/7850)). It keeps working throughout 3.x. The natural key itself stays: buyers use it to open accounts with `sync_accounts` and as a `list_accounts` filter to look up an account's ID. **Buyers** store the returned ID and send it. See [Account identity](/docs/accounts/overview#account-identity).
-- **The account identity-rekey machinery.** The `account.identity_updates` capability is deprecated and planned for removal in AdCP 4.0, with everything it gates. That covers `operator_identity` and `destination_billing_entity` on `sync_accounts`, the `identity_change` and `identity_change_preview` fields, and the `ACCOUNT_MOVED` and `ACCOUNT_IDENTITY_CONFLICT` error codes. `account.stable_account_id` is deprecated with it. An account's identity never changes, so no rekey or former key exists. **Sellers** that implement `operator_identity` keep it working through 3.x and SHOULD declare `stable_account_id: true` while the field exists. **Buyers** change `operator_unit` as an attribute and send `account_id` without checking `stable_account_id`.
+- **The account identity-rekey machinery** ([#8474](https://github.com/adcontextprotocol/adcp/pull/8474)). The `account.identity_updates` capability is deprecated and planned for removal in AdCP 4.0, with everything it gates. That covers `operator_identity` and `destination_billing_entity` on `sync_accounts`, the `identity_change` and `identity_change_preview` fields, and the `ACCOUNT_MOVED` and `ACCOUNT_IDENTITY_CONFLICT` error codes. `account.stable_account_id` is deprecated with it. An account's identity never changes, so no rekey or former key exists. **Sellers** that implement `operator_identity` keep it working through 3.x and SHOULD declare `stable_account_id: true` while the field exists. **Buyers** change `operator_unit` as an attribute and send `account_id` without checking `stable_account_id`.
-3.3 also deprecates condition (b) of `request_signature_required`, which exists only for the already-deprecated webhook `authentication` block. It is part of the `authentication` block's existing deprecation and is removed in 4.0 with the block. A deprecation window does not reset when a deprecated feature is modified. Other existing 3.2 deprecations keep their published removal windows.
+3.3 also deprecates condition (b) of `request_signature_required` ([#8064](https://github.com/adcontextprotocol/adcp/pull/8064)), which exists only for the already-deprecated webhook `authentication` block. It is part of the `authentication` block's existing deprecation and is removed in 4.0 with the block. The experimental `configuration_task` field of `media_buy.reporting_delivery` is deprecated in favor of `configuration_tasks[]` and stays `"sync_accounts"` for clients pinned below 3.3 ([#8552](https://github.com/adcontextprotocol/adcp/pull/8552)). A deprecation window does not reset when a deprecated feature is modified. Other existing 3.2 deprecations keep their published removal windows.
One earlier deprecation is worth restating before 4.0. The integer request field `adcp_major_version` and the `adcp.major_versions` capability field, deprecated in 3.1 in favor of `adcp_version` and `adcp.supported_versions`, keep working through 3.x and are **removed in 4.0** ([DR-0035](https://github.com/adcontextprotocol/adcp/blob/main/governance/decisions/DR-0035-adcp-major-version-removed-in-4-0.md)). Buyers send `adcp_version` on every request and keep the integer mirror until then. Sellers keep emitting `adcp.major_versions` alongside `adcp.supported_versions` through 3.x. In-house clients that send only the integer should move to `adcp_version` now. The [v4 compatibility checks](/docs/reference/migration/v4-compatibility#major_versions_removed_in_4_0) flag sellers that still rely on the integer list.
@@ -662,6 +779,8 @@ One earlier deprecation is worth restating before 4.0. The integer request field
- `media_buy_seller/unprovisioned_account_reference` is new and advisory until runner capability `14.1.0`.
- `media_buy_seller/stable_account_id` is new and runs only for buyer-declared sellers that declare `account.stable_account_id: true`. That flag is deprecated in 3.3, so the gate is temporary. It addresses the account by `account_id` on `get_media_buys` and requires `@adcp/sdk` 15.8.0 or later, whose storyboard runner sends an authored `account_id` as written.
- New capability-gated scenarios: `governance/budget_periods`, `media_buy_seller/property_delivery_reporting`, `media_buy_seller/installment_property_delivery_reporting`, `media_buy_seller/outcome_target_vendor_metric`, and `media_buy_seller/outcome_target_event_cost`. Sellers that do not declare the capability skip them.
+- New experimental scenarios: `media_buy_seller/creative_live_updates` and `media_buy_seller/creative_live_update_refusal`, the `media_buy.execution_readiness` scenario, a gender-targeting conformance storyboard, and a stateful package-retention scenario for canceled and completed buys. The `definition_pin_drift` storyboard, the `definition_pin_probe` controller scenario, and the `definition-pins` vectors are removed with definition pins.
+- New controller scenario and vectors: `reporting_subscription_probe` on `comply_test_controller` (`revoke_grant`, `regrant`, `reduce_grant`, `set_account_timezone`, `advance_time`), and the canonical reporting-subscription coverage vectors with a reference model. Cross-SDK vectors for undisclosed rosters live under `static/test-vectors/product/`.
- Hosted service: grading of governance-aware sellers is covered in [AAO Verified](/docs/building/verification/aao-verified).
These change grading results, not the wire.
diff --git a/docs/reference/release-notes.mdx b/docs/reference/release-notes.mdx
index 1e9d58df51b..d40b838a689 100644
--- a/docs/reference/release-notes.mdx
+++ b/docs/reference/release-notes.mdx
@@ -11,7 +11,7 @@ Authoritative version-by-version release record for AdCP, with cumulative change
## Version 3.3.0
-**Status:** Beta cycle. 3.3 is a minor release targeting the 3.3.0 milestone. Beta.0 is the protocol-first cut used as the canonical input for SDK work; beta.1 incorporates integration feedback and becomes SDK-backed only after SDKs ingest the exact beta.1 bundle. No stable field, enum value, or task is removed. The `seller_id` result fields on event sources and audiences are deprecated in favor of additive `platform_id` fields, natural-key account references after provisioning are deprecated, and the RFC 9421 signing profiles are deprecated in favor of the experimental Web Bot Auth profile; all remain functional throughout 3.x. Normative changes that narrow conformant behavior, and the guarantees that loosen, are described under [Behavior changes to review](#behavior-changes-to-review). This section is the cumulative 3.3 narrative and is refreshed at each beta cut; `CHANGELOG.md` records what each individual cut consumed.
+**Status:** Beta cycle. The latest checkpoint is `3.3.0-beta.3`, published 2026-10-31. 3.3 is a minor release targeting the 3.3.0 milestone. Beta.0 is the protocol-first cut used as the canonical input for SDK work; beta.1 through beta.3 incorporate integration feedback, and a checkpoint counts as SDK-backed only after SDK support for the exact bundle and integration evidence are published ([3.3 beta program](/docs/reference/3-3-beta#sdk-guidance)). No stable field, enum value, or task is removed. Three beta features, definition pins, purchase rights, and installment selection, are withdrawn after beta.1 and planned for 4.0 ([below](#withdrawn-from-3-3-planned-for-4-0)). The `seller_id` result fields on event sources and audiences, `principal_kind`, the natural-key account reference after provisioning, the account identity-rekey machinery, and condition (b) of `request_signature_required` are deprecated, and the RFC 9421 signing profiles are deprecated in favor of the experimental Web Bot Auth profile; all remain functional throughout 3.x. Normative changes that narrow conformant behavior, and the guarantees that loosen, are described under [Behavior changes to review](#behavior-changes-to-review). This section is the cumulative 3.3 narrative and is refreshed at each beta cut; `CHANGELOG.md` records what each individual cut consumed.
**Where to start:** [What's new in AdCP 3.3](/docs/reference/whats-new-in-3-3) is the adopter overview. [Migrating from 3.2 to 3.3](/docs/reference/migration/3-2-to-3-3) has the role-based checklist. The [3.3 beta program](/docs/reference/3-3-beta) covers artifacts, SDK timing, and the proposals still in review.
@@ -19,10 +19,12 @@ AdCP 3.3 lets scheduled, human-gated, and offline media run through the same buy
### Beta checkpoints
-| Release | Purpose | SDK posture |
-|---|---|---|
-| `3.3.0-beta.0` | Publish signed schemas, compliance assets, skills, and manifest for implementation feedback | SDK support follows this cut; beta.0 is not an SDK-backed certification target |
-| `3.3.0-beta.1` | Incorporate beta.0 integration corrections, then trigger an exact beta.1 SDK refresh | SDK-informed at protocol publication; SDK-backed after matching SDK support and integration evidence publish |
+| Release | Published | Purpose | SDK posture |
+|---|---|---|---|
+| `3.3.0-beta.0` | 2026-10-22 | Publish signed schemas, compliance assets, skills, and manifest for implementation feedback | SDK support follows this cut; beta.0 is not an SDK-backed certification target |
+| `3.3.0-beta.1` | 2026-10-29 | Incorporate beta.0 integration corrections, and add the account identity model, `request_account`, principal-level reporting subscriptions, undisclosed rosters, and the first commercial experiments (price adjustments, gender targeting, execution readiness, signal pricing groups and provider-initiated delivery) | `@adcp/sdk` 17.0.0-beta.6 bundles this release; Python support is pending |
+| `3.3.0-beta.2` | 2026-10-30 | Account change outcomes and the separate-account opt-in, seller offers, measurement provenance, structural bounds as the capabilities limit, the principal clarification, reporting-subscription convergence, and the withdrawal of definition pins, purchase rights, and installment selection | `@adcp/sdk` 17.0.0-beta.10 bundles this release; Python support is pending |
+| `3.3.0-beta.3` | 2026-10-31 | Live creative updates, the protocol envelope composed on every task response, money terms on resolved account requests, revocation as no access, and reporting-subscription coverage computable from the wire | No published SDK bundles this release yet |
Each beta is immutable. The `3.3-beta` documentation selector advances to the latest beta, while pinned protocol, schema, compliance, and documentation artifacts remain available. See the [3.3 beta program](/docs/reference/3-3-beta).
@@ -32,9 +34,18 @@ Each beta is immutable. The `3.3-beta` documentation selector advances to the la
- **Proposals and media buys:** experimental open opportunities with later proposals, `proposal.created`, and `list_proposals`, which also reads seller offers and filters by `media_buy_ids` (#8103, #8223); seller revisions advance on every committed change from any origin, with `history[].origin` and the creative `seller_revision` (#8159, DR-0031); the `sales-fixed-rate` specialism for fixed-price, non-guaranteed sellers, with `expected_confirmation_at` on `get_media_buys` (#7963); experimental forward-only lineage with `predecessor_media_buy_id` and `lineage_reason` (#8038); `error.mutation_outcome` on failed mutations (#7935); the `operator_fee` price adjustment kind (#8356).
- **Delivery reporting:** `impressions` optional on delivery rows, version-gated (#8108); experimental spot lifecycle, makegood linkage, and break position (#8017); experimental print proof of insertion and circulation (#7936); experimental delivery `projection` on `by_package[]` rows (#8043); experimental installment lifecycle and proof of publication on `by_installment[]` rows (#8116); flat totals omitted for multi-qualifier metrics (#8055); property-grain rollup capabilities (#7982); `reporting_webhook.operation_id` (#7895); `reporting_webhook.authentication` and `artifact_webhook.authentication` optional on 3.3 requests (#8177); receivers ignore `aggregated_totals` in delivery webhooks (#8053); `custody` on Reliable Reporting report definition sources (#8213).
- **Channels:** structured DOOH `location` and `dooh_inventory_summary.venue_counts[]` (#7416); experimental minute-level dayparts (#8025); `nmo` and `videoamp` demographic systems, `mxf` and broadcast mezzanine codecs, and experimental `loudness` (#8019); the expanded broadcast TV guide (#8006).
-- **Accounts and audiences:** discovery and negotiation tasks never provision an account (#7848); the `account.stable_account_id` capability and the deprecation of natural-key account references after provisioning (#8123, #8124); audience sizes as ranges and `match_rate_basis` (#8024); the `uids[].value` wire form per type (#8059); `invoice` records on the experimental account change feed (#8095); the change feed's `idempotency_key` echo and required `changed_paths` (#8160).
+- **Accounts and audiences:** discovery and negotiation tasks never provision an account (#7848); the deprecation of natural-key account references after provisioning (#8123) and the `account.stable_account_id` capability (#8123, #8124), which the account identity model below deprecates; audience sizes as ranges and `match_rate_basis` (#8024); the `uids[].value` wire form per type (#8059); `invoice` records on the experimental account change feed (#8095); the change feed's `idempotency_key` echo and required `changed_paths` (#8160).
+- **Account identity and requests (beta.1 to beta.3):** a brand is its domain, plus `brand_id` where its `brand.json` lists several; an account is the seller's `account_id`, and `countries`, `currency`, `timezone`, `sandbox`, and `operator_unit` are attributes (#8474, #8280, #8442). Sellers MUST return and accept `account_id`; `sync_accounts` settings updates change attributes in place. The identity-rekey machinery is deprecated: `account.identity_updates`, `operator_identity`, `ACCOUNT_MOVED`, `ACCOUNT_IDENTITY_CONFLICT`, and `account.stable_account_id`. Experimental `account.requests`: `request_account` and its pending action (#8293), the single account write where supported, with `list_accounts` request reads (#8551), change outcomes `updated`, `matched`, and `created` (#8580), the opt-in `allow_separate_account` and `ACCOUNT_CHANGE_REQUIRES_NEW_ACCOUNT` (#8582), and money terms on resolved requests (#8620).
+- **Reporting subscriptions (experimental, beta.1 to beta.3):** `reporting_subscriptions` on `sync_principal` and exceptions-only `subscription_coverage` on `get_reporting_status`, under `media_buy.reporting_subscriptions` ([#8543](https://github.com/adcontextprotocol/adcp/issues/8543) Part B, #8552). Beta.2 and beta.3 settle the SDK findings and make coverage computable from the wire: #8585, #8588, #8593, #8596, #8607 (revocation means no access), #8613, #8616 (canonical vectors), #8617, #8618, #8619, #8621 (`reporting_subscription_probe`), and #8622.
+- **Commercial experiments (beta.1 and beta.2):** seller offers against an accepted buy, `media_buy.seller_offers` (#8102); selection-dependent `price_adjustments` on fixed-price pricing options, `media_buy.price_adjustments` (#7955); per-account execution readiness on `get_products`, `media_buy.execution_readiness` (#7934); `target_audiences[]` beside audience evidence requirements, `media_buy.audience_evidence_targets` (#8215); invoice lines on `get_account_financials`, `account.invoice_lines` (#8207); `media_buy.measurement_provenance`, a `collection-mechanism` vocabulary on `counting_mechanisms[]` and `vendor_metric_provenance[]` (#7940).
+- **Targeting and rosters:** experimental core gender targeting, `media_buy.gender_targeting` (#7925); an empty `publisher_properties` or `collections` list means the seller does not disclose the roster, with exclusions as the buyer's choice (#7948); optional structured package inputs for exact `get_products` availability checks (#8468).
+- **Creative:** experimental live creative updates, `creative.live_updates`, with staged activation and `CREATIVE_LIVE_UPDATE_UNSUPPORTED` (#8488); media-buy startup with mixed creative approval states and the optional `start_requires_all_creatives_approved` gate (#8485).
+- **Envelope and negotiation:** `core/protocol-envelope.json` composed on every task response, with `status` required and one definition each for `message` and `task_id` (#8547); a request carrying only `adcp_major_version` is served the oldest supported release in that major, 3.0 where supported (DR-0034); the 3.2 proposal-flow schemas reopened as a recorded correction (#8531, DR-0036); the buyer's registration selects the webhook-signing mode (#8475); condition (b) of `request_signature_required` deprecated and JSON-RPC batch bodies rejected (#8064).
+- **Capabilities:** every array, string, and keyed map in the `get_adcp_capabilities` response is bounded by structure, and the 64 KiB byte cap is a receiver backstop, not a design target (#8505, #8526).
+- **Principals:** a principal is the buyer agent as the seller has bound it, so `principal_kind` and `expected_principal_kind` are deprecated (#8443); one delegation-chain rule for demand-side grants (#8473).
+- **Service commitments and records:** product creative-review timing, business-clock SLA windows, and the `report_media_buy_issue` and `get_media_buy_issue` contracts (#8417); package retention on canceled and completed buys (#8467); an optional display `name` on measurement catalog metrics (#8437); an optional `metric_id` on performance standards (#8436); `setup_url` accepts query strings and percent-encoding (#8548).
- **Platform identifiers:** `platform_id` on `sync_event_sources` and `sync_audiences` results, with deprecated `seller_id` aliases retained throughout 3.x. Sellers reporting an ID send both with identical values; buyers prefer `platform_id` and fall back to `seller_id` when absent (#8290).
-- **Signals:** optional `age_determination_bases` on signal listings, definitions, and enrichment, so a signal can say whether its members' ages are `verified`, `declared`, or `inferred` (#8145). Stable in 3.3; 3.2 integrations carry it as `ext.adcp.age_determination_bases`. Experimental `signal_status` and `source_audience_id` on `get_signals` results (#8036).
+- **Signals:** optional `age_determination_bases` on signal listings, definitions, and enrichment, so a signal can say whether its members' ages are `verified`, `declared`, or `inferred` (#8145). Stable in 3.3; 3.2 integrations carry it as `ext.adcp.age_determination_bases`. Experimental `signal_status` and `source_audience_id` on `get_signals` results (#8036). Experimental signal pricing groups, `signals.pricing_groups` (#8058), and provider-initiated delivery to agent destinations, `signals.delivery_methods` (#8044).
- **Property lists:** enforceable `domain` / `subdomain` identifier formats, `get_property_list` reference resolution with list-scoped bearer credentials, and a registry sandbox (#8281, #8282).
- **Trust and signing:** one agent-resolution algorithm for every signing surface (#7882); A2A operation-resolution hardening becomes MUST (#7945) and the `request_signing.operation_sources` capability (#7979); invocation messages with more than one DataPart are rejected (#8050); the brand.json cap rises to 2 MiB (#8057).
- **Media buy:** optional `media_buy.features.catalog_ingestion` declarations (#7927); advertise only the `measurement_terms` you accept (#8062); `unsupported-targeting-dimension` details for `UNSUPPORTED_FEATURE` (#8052); seller-level `vendor_metric_optimization.supported_metrics` rollup (#8070); `flight_extension_opportunity` and `scale_budget_opportunity` indicator types (#8033); experimental `collection_lists` and `collection_lists_exclude` targeting (#8061); per-source archive on `sync_event_sources` (#8060).
@@ -70,20 +81,36 @@ Each beta is immutable. The `3.3-beta` documentation selector advances to the la
- **Flight start activates committed buys only (#7963).** The MUST to move a buy from `pending_start` to `active` when the flight date arrives now applies only to committed buys (`confirmed_at` non-null). A provisional buy stays `pending_start` until the seller confirms or rejects it.
- **Flat totals omitted for multi-qualifier metrics (#8055).** When a buy's packages report a `metric_id` under more than one qualifier set, sellers MUST omit that metric's flat carrier from per-buy and window `totals` (per-buy only in delivery webhooks). Buyers read the package rows.
- **Refinement carries compliance forward (#7937).** A `build_creative` refinement keeps the parent leaf's `required_disclosures` and `prohibited_claims`, fails with `COMPLIANCE_UNSATISFIED` when an instruction drops one, and never inherits the parent's approval.
+- **Account identity is the `account_id` (#8474).** A brand is its domain, plus `brand_id` where its `brand.json` lists several. Sellers MUST return `account_id` once an account resolves, accept it wherever an `AccountRef` is accepted, never change it, and, where they open buyer-declared accounts through `sync_accounts`, accept settings-update entries keyed by it. A seller that met only the 3.2 wording (return it as a SHOULD, accepting it optional) does not conform. A natural-key reference resolves only when exactly one of the caller's accounts matches; otherwise the seller returns `ACCOUNT_AMBIGUOUS`.
+- **`request_account` is the single account write where supported (#8551, #8620).** A seller that supports the experimental `account.requests` takes account changes through `request_account`, reads them through `list_accounts`, and never provisions or reviews an account from a `sync_accounts` entry that carries only subscription fields. A request that resolves `matched` or `created` MUST carry `account` with its money terms, and `effective_at` and `not_carried_over` apply as described in the [migration guide](/docs/reference/migration/3-2-to-3-3#request_account-is-the-single-account-write-where-supported).
+- **Every task response composes the protocol envelope, and `status` is required (#8547).** Every task response and async status schema composes `core/protocol-envelope.json`, so envelope fields are siblings of the body fields and `status` is required, including on async status payloads and governance responses that omitted it. A task-level `message` is at most 2,000 characters; a seller whose text is longer MUST truncate it rather than fail the task.
+- **A major-only request is served the oldest supported release (DR-0034).** A request that carries `adcp_major_version` and no `adcp_version` is served the oldest release the seller supports in that major, 3.0 where it is supported. It is no longer served the newest. Send `adcp_version`.
+- **The buyer's registration chooses the webhook-signing mode (#8475).** A seller with `legacy_hmac_fallback: false` rejects a registration that carries `authentication` with `UNSUPPORTED_FEATURE`, not `request_signature_required`. `legacy_hmac_fallback` is discovery, not selection. A JSON-RPC batch body is rejected with `request_body_malformed` (#8064).
+- **Capabilities are bounded by structure (#8505, #8526).** The `maxItems`, `maxLength`, and `maxProperties` limits, and the `x-max-*-4.0` annotations on fields that were stable before 3.3, are the limit on `get_adcp_capabilities`. Agents MUST NOT design to a byte figure. The 64 KiB `MAX_CAPABILITIES_BYTES` is a receiver backstop that keeps its name and value.
+- **Undisclosed rosters (#7948).** A product's `publisher_properties` or `collections` may be `[]`, meaning the seller does not disclose the roster. A seller serving a release below 3.3 MUST NOT return such a product. A seller that accepts an exclusion list against an undisclosed roster MUST apply it against its full internal roster, and rejects one it cannot apply with `UNSUPPORTED_FEATURE`. Buyers treat `[]` as opaque, never as an empty set.
+- **Canceled and completed buys keep their packages (#8467).** A seller serving 3.3 retains packages, with stable identities, platform mappings, and the latest committed configuration, and discloses irrecoverable history through nonfatal errors instead of returning an incomplete list. Missing statistics are never reported as zero.
+- **Mixed creative approval states at startup (#8485).** A seller keeps pending-review and rejected assignments and starts the approved ones by default, unless the package sets `start_requires_all_creatives_approved`. The new pre-activation `pending_start` to `pending_creatives` transition needs SDK transition-validator support.
+- **Revocation means no access (#8607, experimental).** After a caller loses authority for an account, `sync_reporting_receipts` and `sync_reporting_status` treat every reference to it, receipts included, as an unknown identifier.
- **Loosened: brand.json cap 2 MiB (#8057).** A verifier still enforcing 256 KiB rejects a brand.json a 3.3 verifier accepts.
- **Loosened: audience match counts (#8024).** A `ready` audience no longer promises `matched_count` and `effective_match_rate`.
- **Loosened: client response-size default 4 MiB (#8200).** A client still on 1 MiB rejects a response a 3.3 client accepts. The new SHOULD to bound responses (#8192) tightens what an adopting buyer accepts.
- **Loosened: webhook `authentication` optional (#8177).** `reporting_webhook.authentication` and `create_media_buy.artifact_webhook.authentication` are no longer required on a request served at 3.3 or later; the seller signs deliveries under the registration's signing profile. A request served below 3.3 still requires the block.
+- **Loosened: `setup_url` pattern (#8548).** `core/agent-reporting-destination-state.json` accepts any `https` URI, including a query string and percent-encoding. A 3.2 sender's value still validates. The rule that the URL carries no credential, userinfo, or signed component remains normative for receivers.
+- **Loosened: product rosters (#7948).** `publisher_properties` and `collections` lose `minItems: 1`, so generated types change for every product (a TypeScript non-empty tuple becomes `T[]`).
- **Deprecated: RFC 9421 signing profiles (#8162).** `adcp/request-signing/v1` and `adcp/webhook-signing/v1` keep working through 3.x and are removed in 4.0. The replacement is the experimental Web Bot Auth profile; see the [agent identity migration guide](/docs/reference/migration/agent-identity-3-3).
- **Deprecated: `seller_id` on event source and audience results (#8290).** Use `platform_id`; the alias keeps working through 3.x, removal no earlier than 4.0.
- **Deprecated: natural-key account references after provisioning (#8123).** They keep working through 3.x and are planned for removal in 4.0; sellers SHOULD declare `account.stable_account_id`. See [Deprecations](/docs/reference/migration/3-2-to-3-3#deprecations).
+- **Deprecated: the account identity-rekey machinery (#8474).** `account.identity_updates`, `operator_identity` and `destination_billing_entity` on `sync_accounts`, `identity_change` and `identity_change_preview`, `ACCOUNT_MOVED`, `ACCOUNT_IDENTITY_CONFLICT`, and `account.stable_account_id` keep working through 3.x and are planned for removal in 4.0. An account's identity never changes, so there is nothing to rekey.
+- **Deprecated: `principal_kind` and `expected_principal_kind` (#8443).** A principal is the buyer agent as the seller has bound it, so the kind is always `buyer_agent`. Sellers keep returning and honoring them through 3.x, and `enums/principal-kind.json` is deprecated with them.
+- **Deprecated: condition (b) of `request_signature_required` (#8064).** It exists only for the deprecated webhook `authentication` block and is removed in 4.0 with it.
+- **Deprecated: `configuration_task` in `media_buy.reporting_delivery` (experimental, #8552).** Sellers list accepted registration tasks in `configuration_tasks[]`; `configuration_task` stays `"sync_accounts"` for callers pinned below 3.3.
- **Reminder, not new in 3.3: `adcp_major_version` is removed in 4.0 ([DR-0035](https://github.com/adcontextprotocol/adcp/blob/main/governance/decisions/DR-0035-adcp-major-version-removed-in-4-0.md)).** The integer request field and the `adcp.major_versions` capability field have been deprecated since 3.1. They keep working through 3.x, and 4.0 removes both. Send `adcp_version` on every request, keeping the `adcp_major_version` mirror through 3.x. In-house clients that still send only the integer should switch before 4.0. The compliance grader already blocks sellers that do not echo `adcp_version` or emit `adcp.supported_versions`, and at 4.0 rejects the legacy fields.
-Each is detailed in the [migration guide](/docs/reference/migration/3-2-to-3-3#required-to-claim-3-3-behavior) and recorded in [3.3 exceptions to 3.x compatibility](/docs/reference/versioning#3-3-exceptions-to-3-x-compatibility-beta). Fields that a 3.2 validator rejects, and so are sent only on a negotiated 3.3 version, are listed in [Send only to 3.3 peers](/docs/reference/migration/3-2-to-3-3#send-only-to-3-3-peers). Schema-shape changes for SDK generators are in [SDK and code-generator maintainers](/docs/reference/migration/3-2-to-3-3#sdk-and-code-generator-maintainers). 3.3 deprecates no stable field, task, or enum value; it deprecates one usage and the RFC 9421 signing profiles, listed above. The `adcp_major_version` reminder restates an existing 3.1 deprecation.
+Each is detailed in the [migration guide](/docs/reference/migration/3-2-to-3-3#required-to-claim-3-3-behavior) and recorded in [3.3 exceptions to 3.x compatibility](/docs/reference/versioning#3-3-exceptions-to-3-x-compatibility-beta). Fields that a 3.2 validator rejects, and so are sent only on a negotiated 3.3 version, are listed in [Send only to 3.3 peers](/docs/reference/migration/3-2-to-3-3#send-only-to-3-3-peers). Schema-shape changes for SDK generators are in [SDK and code-generator maintainers](/docs/reference/migration/3-2-to-3-3#sdk-and-code-generator-maintainers). 3.3 removes no stable field, task, or enum value. It deprecates a few result fields and capabilities (`seller_id`, `principal_kind`, the identity-rekey machinery), one usage, one signing condition, and the RFC 9421 signing profiles, listed above. The `adcp_major_version` reminder restates an existing 3.1 deprecation.
### Experimental surfaces in 3.3
-Per the [experimental status contract](/docs/reference/experimental-status#graduation-cadence). No experimental surface graduates in 3.3. One experimental surface, `creative.evaluator`, loses a source form in 3.3, with the notice window waived as the table records; the other active notices are listed below.
+Per the [experimental status contract](/docs/reference/experimental-status#graduation-cadence). No experimental surface graduates in 3.3. One experimental surface, `creative.evaluator`, loses a source form in 3.3, with the notice window waived as the table records; the other active notices are listed below. Two experiments that shipped in beta.1, `media_buy.purchase_rights` and `media_buy.installment_selection`, are withdrawn after beta.1 and no longer registered ([below](#withdrawn-from-3-3-planned-for-4-0)).
| Feature id | Surface | Status | Expected next |
|---|---|---|---|
@@ -115,6 +142,18 @@ Per the [experimental status contract](/docs/reference/experimental-status#gradu
| `brand.collection_links` | `collections` on `get_brand_identity` and `publisher_domain` on brand.json collection links (#8141) | New in 3.3; experimental | Link shape, visibility, and `seller_agent_url` may change. |
| `creative.evaluator` | The `evaluator_id` source form on `build_creative.evaluator` is removed and the `list_evaluators` follow-on is withdrawn (#5241). Sources are inline `exemplars` or an allowlisted `agent_url`. | Still experimental; breaking removal | The 6-week pre-landing notice is waived: beta.0 is the notice vehicle, and GA ships no earlier than 6 weeks after the beta.0 tag ([migration](/docs/reference/migration/3-2-to-3-3#experimental-creative-evaluator-drops-evaluator_id)). A fourth source form for conversion-outcome evaluators stays open until an adopter appears. |
| `media_buy.reporting_delivery` | Reliable Reporting 1.0; `REVISION_UNREADABLE` shipped in 3.2.4 (#8099); `custody` on report definition sources (#8213) | Still experimental; two active breaking-change notices | The [consumer-status requirement](/docs/reference/migration/reliable-reporting-status-loop) has not merged; it may land no earlier than the first minor after October 24, 2026. [Superseded snapshot compaction](/docs/reference/migration/3-2-to-3-3#superseded-reporting-snapshots-may-be-compacted) (#8100) takes effect no earlier than the first minor after November 20, 2026, so not in 3.3 if 3.3 ships before then. |
+| `account.requests` | `request_account` (open or change an account), `request_id`, `include_requests`, and `account_requests[]` on `list_accounts`, the `account_request.changed` webhook, `request_id` and `resolution` on `sync_accounts` results (#8293, #8551); change outcomes, `allow_separate_account`, and `ACCOUNT_CHANGE_REQUIRES_NEW_ACCOUNT` (#8580, #8582); money terms, `effective_at`, and `not_carried_over` on resolved requests (#8620) | New in 3.3; experimental, no adopter yet | The pending-action kinds, the 30-day retention floor, the deduplication guidance, and how requests compose with agent onboarding and operator grants need working-group review. `sync_accounts` stays stable; its formal deprecation follows this surface leaving experimental status. |
+| `media_buy.reporting_subscriptions` | `reporting_subscriptions` on `sync_principal`, `subscription_coverage` on `get_reporting_status`, offering `standard_dimensions`, `configuration_tasks[]` (#8552); the beta.2 and beta.3 convergence: owed confirmation period, `inactive` coverage, billing stubs, `flight_history` and `regranted_at` on the wire, deterministic admission and resolution, revocation as no access (the PRs are in the [feature index](#3-3-feature-index)) | New in 3.3; experimental, no adopter yet | The dimension vocabulary, `exact` as the default match, backfill on re-grant, and whether billing feeds may use all-accounts scope are open. `reporting_subscription_probe` and the canonical coverage vectors let a seller test against the reference model. Builds on `media_buy.reporting_delivery`. |
+| `media_buy.seller_offers` | `proposal_initiator` on canonical proposals, `offer_reason` on `list_proposals` rows, the `proposal.offered` notification (#8102) | New in 3.3; experimental. Requires `media_buy.open_opportunities` | The `offer_reason` values and the `expired` disposition may change once sellers run real offers. Pre-agreed seller changes inside `commercial_terms` are planned for 4.0 with the other withdrawn features. Never sent to callers below 3.3. |
+| `creative.live_updates` | The `creative.live_updates` capability, `staged_update` on `list_creatives` and `sync_creatives`, `creative.staged_update_changed`, and `CREATIVE_LIVE_UPDATE_UNSUPPORTED` (#8488) | New in 3.3; experimental, one reference implementation | The change-kind taxonomy, the serving-mode ranking, and per-package review during a staged update need ad-server field evidence. |
+| `media_buy.measurement_provenance` | `enums/collection-mechanism.json`, `billing_measurement.counting_mechanisms[]` on `measurement_terms`, and `vendor_metric_provenance[]` on delivery metrics (#7940) | New in 3.3; experimental, no production adopter yet | The vocabulary stays experimental until two parties have used it. `counting_mechanisms` reaches the closed canonical terms in 4.0. Sellers omit the fields toward callers pinned below 3.3. |
+| `media_buy.audience_evidence_targets` | `target_audiences[]` beside `audience_evidence_requirements` on `get_products` filters and `create_media_buy` packages (#8215) | New in 3.3; experimental | Exact-match audience rules, AND across targets, and units of `minimum_value` may change. The closed purchase schemas gain the field in 4.0. |
+| `account.invoice_lines` | `lines[]`, `invoice_kind`, and `adjusts_invoice_id` on `get_account_financials` invoices (#8207) | New in 3.3; experimental, reference only | Credit notes as `invoice_kind: credit_note` with a non-negative `amount` may change. Credit-note records are never sent to callers pinned below 3.3. |
+| `media_buy.price_adjustments` | An ordered `price_adjustments` table of fee and discount rows on fixed-price pricing options (#7955) | New in 3.3; experimental, one pilot | Position in break, audience, activation method, and measurement vendor have no selectable anchor yet. A table is never returned to callers below 3.3. |
+| `media_buy.execution_readiness` | `include_execution_readiness` on `get_products` and the response-level `execution_readiness` map (#7934) | New in 3.3; experimental. Pairs with the existing `media_buy.execution_requirements` | Identity selection, lead-form and messaging-destination requirements, and proposal bindings are not specified yet. |
+| `media_buy.gender_targeting` | Core `demographics.gender` targeting and product gender capabilities (#7925) | New in 3.3; experimental | Canonical demographic delivery reporting stays age-only in 3.3, so a gender-targeted package has exact targeting readback and no gendered delivery readback. Buyers never send core gender fields on a 3.2 contract. |
+| `signals.pricing_groups` | `pricing_group` on signal listings and `signal_pricing_group_rules[]` (#8058) | New in 3.3; experimental | The `signal_charges[]` echo of per-signal charges is a follow-up. A group with no rule is charged `each`. |
+| `signals.delivery_methods` | `signals.delivery_methods[]` capability, the `delivery_method` pin, and `delivery_status` on agent deployments (#8044) | New in 3.3; experimental, one implementer | Rail-selection authority, the arrival-state vocabulary, and match-outcome placement need integration experience. |
| `measurement.core`, `measurement.gateway`, `trusted_match.core`, `trusted_match.verified_identity`, `sponsored_intelligence.core`, `creative.signal_fanout`, `media_buy.audience_activation`, `media_buy.execution_requirements`, `media_buy.product_identity` | Unchanged in 3.3 | Still experimental | None merged. Open proposals that touch them are in the [3.3 beta program](/docs/reference/3-3-beta#in-review-for-3-3). |
The [canonical list](/docs/reference/experimental-status#current-experimental-surfaces) is authoritative.
@@ -129,7 +168,7 @@ These merged on `main` during the 3.3 cycle and were also released on the 3.2 li
### Withdrawn from 3.3, planned for 4.0
-Three features are not part of 3.3. All three add terms to `commercial_terms`, and `commercial-terms` stays closed within 3.x: a buyer must not be bound by terms it cannot read, and `terms_digest` signs exactly those terms. Opening the object would let a 3.2 buyer accept a 3.3 term it silently ignored. 4.0 gives `commercial_terms` a declared extension point with must-understand and brings the features back ([adcp#8501](https://github.com/adcontextprotocol/adcp/issues/8501)).
+Three features are not part of 3.3. All three add terms to `commercial_terms`, and `commercial-terms` stays closed within 3.x: a buyer must not be bound by terms it cannot read, and `terms_digest` signs exactly those terms. Opening the object would let a 3.2 buyer accept a 3.3 term it silently ignored, and a minor release never changes a closed schema ([DR-0036](https://github.com/adcontextprotocol/adcp/blob/main/governance/decisions/DR-0036-closed-schemas-stay-closed-within-a-major.md)). 4.0 gives `commercial_terms` a declared extension point with must-understand and brings the features back ([adcp#8501](https://github.com/adcontextprotocol/adcp/issues/8501)). The removal merged in [#8537](https://github.com/adcontextprotocol/adcp/pull/8537) and first takes effect in `3.3.0-beta.2`.
- **Definition pins (#7960), published in `3.3.0-beta.0` and `3.3.0-beta.1`, removed after beta.1.** `commercial_terms.definition_pins[]`, the `definition_changed` refinement reason with `drifted_pins[]`, `REFERENCE_DEFINITION_CHANGED`, the `definition_pin_probe` controller scenario, the `definition_pin_drift` storyboard, and the `definition-pins` test vectors are removed. The beta rule that sellers MUST pin covered third-party definitions no longer applies. This is a beta-to-beta change, not a change to any stable release.
- **Purchase rights (#8101), published in `3.3.0-beta.1` as experimental `media_buy.purchase_rights` and removed after beta.1.** `purchases[].rights[]`, `brand/rights-scope.json` (so `brand/rights-terms.json` returns to its 3.2 form), and the `paid_amplification` and `content_reuse` values of `right-use` are removed.
diff --git a/docs/reference/whats-new-in-3-3.mdx b/docs/reference/whats-new-in-3-3.mdx
index d524c2b845f..01016400300 100644
--- a/docs/reference/whats-new-in-3-3.mdx
+++ b/docs/reference/whats-new-in-3-3.mdx
@@ -8,7 +8,7 @@ description: "Adopter overview of the AdCP 3.3 beta: scheduled, human-gated, and
# What's new in AdCP 3.3
-**3.3 is in its beta cycle.** Beta.0 publishes the protocol artifacts before SDK support. Beta.1 incorporates integration feedback, then becomes SDK-backed after a second SDK refresh against the exact beta.1 bundle. Use the beta in development and staging, and read the [3.3 beta program](/docs/reference/3-3-beta) before testing. This page lists only what has merged; it is refreshed at each beta cut.
+**3.3 is in its beta cycle.** The latest checkpoint is `3.3.0-beta.3`, published 2026-10-31. Beta.0 publishes the protocol artifacts before SDK support, and beta.1 through beta.3 incorporate integration feedback; a beta is SDK-backed only after SDK support for its exact bundle is published. Use the beta in development and staging, and read the [3.3 beta program](/docs/reference/3-3-beta) before testing. This page lists only what has merged; it is refreshed at each beta cut.
**Three features that shipped in the betas are withdrawn after beta.1: definition pins (beta.0 and beta.1), purchase rights, and installment selection (both beta.1).** All three wait for 4.0, because `commercial-terms` stays closed within 3.x ([details](#withdrawn-from-3-3-planned-for-4-0)).
@@ -17,7 +17,7 @@ AdCP 3.3 lets scheduled, human-gated, and offline media run through the same buy
Around that, 3.3 tightens the places where two conformant 3.2 implementations could still disagree: discovery never provisions an account, one agent-resolution rule covers every signing surface, `required_for` is enforced over A2A with its hardening clauses required, and `reporting_webhook.operation_id` correlation fails closed. Catalog intake becomes an optional declaration, verifiers can advertise A2A `required_for` enforcement through `request_signing.operation_sources`, and `ext.adcp` becomes a reserved namespace. New single-adopter surfaces ship as experimental, so 3.4 can reshape them without breaking stable integrations.
-No stable field, enum value, or task is removed. Two result fields, one usage, the account identity-rekey machinery, and the RFC 9421 signing profiles are deprecated, all functional throughout 3.x. They are `seller_id` on event source and audience results (use `platform_id`), and the natural key as the account reference after provisioning. They also include `account.identity_updates`, `operator_identity`, `ACCOUNT_MOVED`, `ACCOUNT_IDENTITY_CONFLICT`, and `account.stable_account_id` (use `account_id`), and the RFC 9421 profiles (use the experimental Web Bot Auth profile). 3.3 adds optional fields, enum values, and capability declarations. Schema-valid 3.2 messages stay schema-valid except for the new domain identifier format, and unless they already used a name 3.3 now defines with a different shape; the list is in the [migration guide](/docs/reference/migration/3-2-to-3-3#what-can-fail-validation). The normative narrowings are recorded in [Versioning and governance](/docs/reference/versioning#3-3-exceptions-to-3-x-compatibility-beta) and lead the [migration guide](/docs/reference/migration/3-2-to-3-3#required-to-claim-3-3-behavior).
+No stable field, enum value, or task is removed. Two result fields, one usage, the principal kind field, the account identity-rekey machinery, and the RFC 9421 signing profiles are deprecated, all functional throughout 3.x. They are `seller_id` on event source and audience results (use `platform_id`), and the natural key as the account reference after provisioning. They also include `account.identity_updates`, `operator_identity`, `ACCOUNT_MOVED`, `ACCOUNT_IDENTITY_CONFLICT`, and `account.stable_account_id` (use `account_id`), `principal_kind` and `expected_principal_kind` (a bound principal is always `buyer_agent`), and the RFC 9421 profiles (use the experimental Web Bot Auth profile). 3.3 adds optional fields, enum values, and capability declarations. Schema-valid 3.2 messages stay schema-valid except for the new domain identifier format, and unless they already used a name 3.3 now defines with a different shape; the list is in the [migration guide](/docs/reference/migration/3-2-to-3-3#what-can-fail-validation). The normative narrowings are recorded in [Versioning and governance](/docs/reference/versioning#3-3-exceptions-to-3-x-compatibility-beta) and lead the [migration guide](/docs/reference/migration/3-2-to-3-3#required-to-claim-3-3-behavior).
## New in beta.3
@@ -42,6 +42,31 @@ beta.3 finishes the reporting-subscription and account-request surfaces, both ex
**Live creative updates (experimental, `creative.live_updates`, [#8488](https://github.com/adcontextprotocol/adcp/pull/8488)).** A buyer changes a serving creative by syncing it again under the same `creative_id`. The seller declares, per kind of change, whether it applies `uninterrupted`, `staged` (the approved version keeps serving until the update is approved), or `paused_for_review`, and refuses the rest with `CREATIVE_LIVE_UPDATE_UNSUPPORTED`. `list_creatives` shows `staged_update`, and the opt-in `creative.staged_update_changed` event tracks it.
+**Every task response carries the envelope ([#8547](https://github.com/adcontextprotocol/adcp/pull/8547)).** Each task response and async status schema now composes `core/protocol-envelope.json`, so `status`, `task_id`, `context_id`, `message`, `replayed`, `adcp_error`, and the other envelope fields sit beside the body fields at the response root, and `status` is required. Before, 47 of the 124 response and status schemas did not compose it, and 18 closed roots rejected envelope fields outright, so generated SDK types could not represent a conforming response. The 18 are reopened. The async status payloads and the governance responses that omitted `status` now require it. A task-level `message` has one bound of 2,000 characters in `core/task-message.json`, and a seller whose text is longer MUST truncate it rather than fail the task. No body field is added, renamed, or removed.
+
+## New in beta.1 and beta.2
+
+These shipped before beta.3 and are summarized here with the rest. Everything marked experimental is a registered feature id; a seller that emits it lists the id in `experimental_features`.
+
+- **A principal is the bound buyer agent ([#8443](https://github.com/adcontextprotocol/adcp/pull/8443), beta.2).** A principal is the buyer agent as the seller has bound it, and nothing else. `principal_kind` on `get_principal` and `sync_principal` responses, `expected_principal_kind` on `sync_principal` requests, and `enums/principal-kind.json` are deprecated and keep working through 3.x, because a bound buyer agent is always `buyer_agent`.
+- **Webhook signing mode is the buyer's choice ([#8475](https://github.com/adcontextprotocol/adcp/pull/8475), beta.1).** The seller signs with the profile the registration's `signing_profile` names, or `adcp/webhook-signing/v1` when it is omitted. A buyer that needs legacy signing sends the deprecated `authentication` block. A seller with `legacy_hmac_fallback: false` rejects that block with `UNSUPPORTED_FEATURE`. Condition (b) of `request_signature_required` is deprecated with the block, and a JSON-RPC batch body is rejected with `request_body_malformed` ([#8064](https://github.com/adcontextprotocol/adcp/pull/8064)).
+- **Capabilities are bounded by structure ([#8505](https://github.com/adcontextprotocol/adcp/pull/8505), [#8526](https://github.com/adcontextprotocol/adcp/pull/8526)).** Every array, string, and keyed map in `get_adcp_capabilities` has a limit, enforced on new and experimental fields and annotated for 4.0 on fields that were stable before 3.3. Those bounds are the protocol's limit, and agents MUST NOT design to a byte figure. `MAX_CAPABILITIES_BYTES` (64 KiB) is a receiver backstop and deployment guidance, not a protocol rule on senders.
+- **Undisclosed rosters ([#7948](https://github.com/adcontextprotocol/adcp/pull/7948), beta.1).** A product's `publisher_properties` or `collections` can be `[]`, which means the seller does not disclose the roster. There is no new field and no partial state. Allow lists may be accepted against it and cover only what the seller matches. Exclusion lists are the buyer's choice, because the buyer sees the undisclosed roster at discovery: a seller that accepts one applies it to its full internal roster, and a seller that cannot rejects it with `UNSUPPORTED_FEATURE`. A seller serving a release below 3.3 never returns such a product. Buyers treat the roster as opaque and may refuse the product. See [Roster coverage](/docs/media-buy/product-discovery/media-products#roster-coverage).
+- **Canceled and completed buys keep their packages ([#8467](https://github.com/adcontextprotocol/adcp/pull/8467), beta.1).** From 3.3 a seller retains packages on terminal buys, with stable identities, platform mappings, and the latest committed configuration, and discloses irrecoverable history through nonfatal errors instead of returning an incomplete list.
+- **Mixed creative approval states at startup ([#8485](https://github.com/adcontextprotocol/adcp/pull/8485), beta.1).** A seller keeps pending-review and rejected assignments and starts the approved ones by default. The optional package `start_requires_all_creatives_approved` gate holds the start until every assignment is approved, and `media_buy.features.creative_start_policy` declares support.
+- **Review and escalation commitments ([#8417](https://github.com/adcontextprotocol/adcp/pull/8417), beta.1).** Products can declare creative-review timing and business-clock SLA windows with seller calendars. `report_media_buy_issue` and `get_media_buy_issue` give a human acknowledgement and resolution status for a critical report.
+- **Seller offers (experimental, `media_buy.seller_offers`, [#8102](https://github.com/adcontextprotocol/adcp/pull/8102), beta.2).** A seller can propose a change to an accepted buy: a postponed or canceled installment, a preemption, under-delivery. The offer is a `committed` canonical proposal with `proposal_initiator: "seller"` and an `offer_reason`, read through `list_proposals` and announced by the identifiers-only `proposal.offered` notification. The buyer accepts, declines, or revises it with the existing tasks. At `expires_at` the signed terms stand, and silence is never acceptance. Sellers never send offers to callers below 3.3. See [Seller offers](/docs/media-buy/product-discovery/proposal-negotiation#seller-offers).
+- **Price adjustments (experimental, `media_buy.price_adjustments`, [#7955](https://github.com/adcontextprotocol/adcp/pull/7955), beta.1).** A fixed-price pricing option can publish an ordered table of fee and discount rows keyed by format option, placement selection, or always, so a buyer computes the price of what it selects. The table is optional, and its resolution order and rounding are normative. See [Selection-dependent price adjustments](/docs/media-buy/advanced-topics/pricing-models#selection-dependent-price-adjustments).
+- **Execution readiness (experimental, `media_buy.execution_readiness`, [#7934](https://github.com/adcontextprotocol/adcp/pull/7934), beta.1).** A `get_products` request with `account` can set `include_execution_readiness: true` to learn, per product and per `execution_requirements` entry, whether the account is `ready`, `setup_required`, `selection_required`, `input_required`, or `unknown`, with candidates whose `resource_id` fits the existing binding field. See [Per-account execution readiness](/docs/media-buy/specification#per-account-execution-readiness-experimental).
+- **Signals (experimental).** Signal pricing groups (`signals.pricing_groups`, [#8058](https://github.com/adcontextprotocol/adcp/pull/8058)) let a seller price alternative age bands, for example, as one audience: `pricing_group` on a listing and `signal_pricing_group_rules[]` choose `highest` or `each`. See [Signal pricing groups](/docs/media-buy/advanced-topics/targeting#signal-pricing-groups). Provider-initiated delivery (`signals.delivery_methods`, [#8044](https://github.com/adcontextprotocol/adcp/pull/8044)) lets a signal agent declare the methods it can send over, a buyer pin one with `delivery_method`, and agent deployments report `delivery_status`. See [Declaring delivery methods](/docs/signals/tasks/activate_signal#declaring-delivery-methods).
+- **Gender targeting (experimental, `media_buy.gender_targeting`, [#7925](https://github.com/adcontextprotocol/adcp/pull/7925), beta.1).** Core `demographics.gender` targeting with female, male, and non_binary values, an independent unknown group, product-scoped capabilities, and exact readback for gender-only and mixed age and gender targeting. 3.3 reports demographic delivery by age only, so a gender-targeted package has no gendered delivery readback. Buyers never send core gender fields on a 3.2 contract. See [Core gender targeting](/docs/media-buy/advanced-topics/targeting#core-gender-targeting-3-3).
+- **Measurement provenance (experimental, `media_buy.measurement_provenance`, [#7940](https://github.com/adcontextprotocol/adcp/pull/7940), beta.2).** A shared `collection-mechanism` vocabulary (`set_top_box`, `acr`, `panel`, `server_logs`, `client_tracker`, `sdk`) says what a count is built from: `billing_measurement.counting_mechanisms[]` on `measurement_terms`, and `vendor_metric_provenance[]` on delivery metrics. Sellers serving an older pin omit both.
+- **Audience evidence targets (experimental, `media_buy.audience_evidence_targets`, [#8215](https://github.com/adcontextprotocol/adcp/pull/8215), beta.1).** `target_audiences[]` names the audience a buyer wants evidence for, beside `audience_evidence_requirements`. A product satisfies a target only through an admissible evidence item for exactly that audience. A target never targets delivery. See [Target audiences](/docs/media-buy/task-reference/get_products#target-audiences-experimental).
+- **Invoice lines (experimental, `account.invoice_lines`, [#8207](https://github.com/adcontextprotocol/adcp/pull/8207), beta.1).** `get_account_financials` invoices can carry `lines[]` that tie an amount to media buys, packages, and reporting revisions, plus `invoice_kind` (`credit_note` carries a non-negative `amount`) and `adjusts_invoice_id`. Lines are reference only and never settle an invoice. See [Invoice lines](/docs/accounts/tasks/get_account_financials#invoice-lines-experimental).
+- **Smaller additions.** Exact pre-booking availability checks through structured package inputs on product-scoped `get_products` refinement ([#8468](https://github.com/adcontextprotocol/adcp/pull/8468)); an optional display `name` on measurement catalog metrics ([#8437](https://github.com/adcontextprotocol/adcp/pull/8437)); an optional `metric_id` on performance standards ([#8436](https://github.com/adcontextprotocol/adcp/pull/8436)); one delegation-chain rule for demand-side grants ([#8473](https://github.com/adcontextprotocol/adcp/pull/8473)).
+
+**Version negotiation and closed schemas.** A request that carries only `adcp_major_version` is served the oldest release the seller supports in that major, 3.0 where it is supported ([DR-0034](https://github.com/adcontextprotocol/adcp/blob/main/governance/decisions/DR-0034-major-only-requests-are-served-the-oldest-release.md), accepted 2026-10-26). In practice that caller is a 3.0 buyer, so it is no longer answered in a shape its validator rejects. A buyer that wants newer behavior sends `adcp_version`. A schema that a stable release published closed stays closed until the next major: a minor adds only to open schemas, and the 3.2 proposal-flow schemas that were closed against DR-0019 are reopened as a recorded correction ([#8531](https://github.com/adcontextprotocol/adcp/pull/8531), [DR-0036](https://github.com/adcontextprotocol/adcp/blob/main/governance/decisions/DR-0036-closed-schemas-stay-closed-within-a-major.md), proposed and awaiting ratification).
+
## Scheduled and human-gated buying
- **An account is its account ID.** Sellers MUST return `account_id` from `sync_accounts` once the account is resolved, accept it on every account-scoped task, and never change it. A brand is its domain, plus `brand_id` where its `brand.json` lists several brands. Countries, currency, timezone, sandbox, and `operator_unit` are account attributes that a settings update changes without changing the account. Currency, timezone, and sandbox are set at opening, and a seller can review a countries change before applying it. A seller SHOULD return the existing account when a provisioning entry matches exactly one. Natural keys keep working throughout 3.x, but using them as the reference after provisioning is deprecated and planned for removal in 4.0. They remain the way to open an account and to look up its ID. `account.identity_updates`, `ACCOUNT_MOVED`, `ACCOUNT_IDENTITY_CONFLICT`, and `account.stable_account_id` are deprecated. See [Account identity](/docs/accounts/overview#account-identity).
@@ -185,7 +210,7 @@ Reliable Reporting was configured one account at a time, so a new account report
## Experimental in 3.3
-New feature ids are `media_buy.spot_lifecycle`, `media_buy.daypart_granularity`, `creative.broadcast_loudness`, `media_buy.hold_policy`, `media_buy.hold_ranking`, `media_buy.installment_holds`, `media_buy.hold_extension`, `media_buy.delegated_composition`, `media_buy.collection_cards`, `media_buy.collection_catalog`, `brand.collection_links`, `media_buy.open_opportunities`, `media_buy.lineage`, `media_buy.delivery_projection`, `media_buy.installment_lifecycle`, `media_buy.collection_lists`, `media_buy.offline_delivery_metrics`, `signals.signal_lifecycle`, `signing.web_bot_auth`, `account.agent_onboarding`, `account.requests`, `media_buy.reporting_subscriptions`, `security.profiles`, and `identity.trust_json`. `media_buy.offline_delivery_metrics` registers the new `print_metrics` block together with the 3.2 `ooh_metrics` block. `identity.trust_json` publishes the `trust.json` v1 schemas, identifying agents by origin with no keys in the record; the Web Bot Auth profile reads it, and publishers declare nothing ([trust.json](/docs/reference/trust-json)). Governance budget periods extend the existing `governance.campaign` cluster, `get_principal` relationship status extends `protocol.principal`, and rights channel restrictions extend `brand.rights_lifecycle`. The `creative.evaluator` surface on `build_creative` drops its account-arranged `evaluator_id` source form and withdraws the `list_evaluators` follow-on: sources are now inline `exemplars` or an allowlisted `agent_url`, and a seller's house evaluator is an agent it lists in `creative_policy.accepted_verifiers[]` ([migration](/docs/reference/migration/3-2-to-3-3#experimental-creative-evaluator-drops-evaluator_id)). Reliable Reporting carries a new breaking-change notice: older superseded snapshots [may be compacted](/docs/reference/migration/3-2-to-3-3#superseded-reporting-snapshots-may-be-compacted) no earlier than the first minor after November 20, 2026. The per-surface status table is in the [release notes](/docs/reference/release-notes#experimental-surfaces-in-3-3).
+New feature ids are `media_buy.spot_lifecycle`, `media_buy.daypart_granularity`, `creative.broadcast_loudness`, `media_buy.hold_policy`, `media_buy.hold_ranking`, `media_buy.installment_holds`, `media_buy.hold_extension`, `media_buy.delegated_composition`, `media_buy.collection_cards`, `media_buy.collection_catalog`, `brand.collection_links`, `media_buy.open_opportunities`, `media_buy.lineage`, `media_buy.delivery_projection`, `media_buy.installment_lifecycle`, `media_buy.collection_lists`, `media_buy.offline_delivery_metrics`, `signals.signal_lifecycle`, `signing.web_bot_auth`, `account.agent_onboarding`, `account.requests`, `media_buy.reporting_subscriptions`, `creative.live_updates`, `media_buy.seller_offers`, `media_buy.price_adjustments`, `media_buy.execution_readiness`, `media_buy.gender_targeting`, `media_buy.measurement_provenance`, `media_buy.audience_evidence_targets`, `account.invoice_lines`, `signals.pricing_groups`, `signals.delivery_methods`, `security.profiles`, and `identity.trust_json`. `media_buy.purchase_rights` and `media_buy.installment_selection` shipped in beta.1 and are withdrawn, so they are not registered. `media_buy.offline_delivery_metrics` registers the new `print_metrics` block together with the 3.2 `ooh_metrics` block. `identity.trust_json` publishes the `trust.json` v1 schemas, identifying agents by origin with no keys in the record; the Web Bot Auth profile reads it, and publishers declare nothing ([trust.json](/docs/reference/trust-json)). Governance budget periods extend the existing `governance.campaign` cluster, `get_principal` relationship status extends `protocol.principal`, and rights channel restrictions extend `brand.rights_lifecycle`. The `creative.evaluator` surface on `build_creative` drops its account-arranged `evaluator_id` source form and withdraws the `list_evaluators` follow-on: sources are now inline `exemplars` or an allowlisted `agent_url`, and a seller's house evaluator is an agent it lists in `creative_policy.accepted_verifiers[]` ([migration](/docs/reference/migration/3-2-to-3-3#experimental-creative-evaluator-drops-evaluator_id)). Reliable Reporting carries a new breaking-change notice: older superseded snapshots [may be compacted](/docs/reference/migration/3-2-to-3-3#superseded-reporting-snapshots-may-be-compacted) no earlier than the first minor after November 20, 2026. The per-surface status table is in the [release notes](/docs/reference/release-notes#experimental-surfaces-in-3-3).
## Clarifications and conformance
@@ -219,7 +244,7 @@ These merged on `main` during the 3.3 cycle and were also released on the 3.2 li
| A fixed-price, non-guaranteed seller | Claim `sales-fixed-rate`; keep a held buy in `pending_start` until you confirm or reject it. |
| A seller that wants to send proposals after the first response | Opt in to `media_buy.open_opportunities`: advertise `list_proposals` first, then `later_proposals` with a `max_open_duration`, and honor buyer consent and limits. |
| A linear TV, print, or DOOH seller | Adopt the delivery fields you can populate; gate 3.3-only rows and fields on the negotiated version. |
-| An SDK maintainer | Generate from the signed beta.0 tarball and check the [SDK-facing changes](/docs/reference/migration/3-2-to-3-3#sdk-and-code-generator-maintainers). |
+| An SDK maintainer | Generate from the signed `3.3.0-beta.3` tarball, not `main`, and check the [SDK-facing changes](/docs/reference/migration/3-2-to-3-3#sdk-and-code-generator-maintainers). |
| A seller that opens buyer-declared accounts | Return `account_id` from `sync_accounts`, accept it on every account-scoped task, and never change it; update countries and other attributes in place. |
| A seller supporting `account.requests` | Return `account`, with its money terms, on every request that resolves `matched` or `created`; send `effective_at` on money changes and `not_carried_over` on a separate account; refuse `currency` or `timezone` changes you don't list in `changeable_attributes`. |
| A seller advertising `media_buy.reporting_subscriptions` | Publish `cancellation_effective_at`, `flight_history`, per-package `reporting_delivery_offering_ids`, `authorization.regranted_at`, and offering `available_from` / `withdrawn_at`; owe billing stubs at cutovers; deliver only inside a buy's flight; key managed-delivery rows on `account_id`. |
@@ -231,7 +256,17 @@ These merged on `main` during the 3.3 cycle and were also released on the 3.2 li
| A buyer or SDK maintainer | Adopt the 4 MiB response-size default; size your aggregate budget, not just the per-call one, if you fan out across agents. |
| Any agent operator | Measure `tools/list`, `get_adcp_capabilities`, and your agent card. Oversized discovery makes you unreachable, and oversized capabilities also breaks signing-key discovery. |
| A buyer operating a webhook or push-notification receiver | Bound the request body (4 MiB default) before signature verification, and answer an over-limit request with 413. |
-| A compliance operator | Treat beta.0 as an implementation input. Do not issue a 3.3 badge from beta.0. |
+| A seller listing a principal on `get_principal` or `sync_principal` | Keep returning `principal_kind` and honoring `expected_principal_kind` through 3.x; buyers stop reading and sending them. |
+| A seller that registers webhooks | Sign with the profile `signing_profile` names, default `adcp/webhook-signing/v1`; with `legacy_hmac_fallback: false`, reject an `authentication` block with `UNSUPPORTED_FEATURE`. |
+| A seller that returns product rosters | Return `publisher_properties: []` or `collections: []` only to callers served 3.3 or later; apply any exclusion list you accept against your full internal roster. |
+| A seller with canceled or completed buys | Keep the packages, with stable identities and the latest committed configuration, and disclose irrecoverable history through nonfatal errors. |
+| A seller or SDK that builds task responses | Compose the protocol envelope on every response, include `status`, and truncate (MUST, not fail) a `message` over 2,000 characters. Regenerate types from the beta.3 schemas. |
+| An in-house client that sends only `adcp_major_version` | You are served the oldest supported release in that major (3.0 where supported). Send `adcp_version` to get newer behavior. |
+| A seller that advertises `get_adcp_capabilities` fields | Stay within the structural bounds; do not design to a byte figure. |
+| A seller that wants to offer a change to a signed buy | Opt in to `media_buy.seller_offers` after `media_buy.open_opportunities`; send offers only to callers served 3.3. |
+| A seller of signals | Declare `signals.delivery_methods` before accepting a `delivery_method` pin; publish `signal_pricing_group_rules[]` if listings share a `pricing_group`. |
+| A seller with live creatives | Declare `creative.live_updates` per change kind, and refuse the rest with `CREATIVE_LIVE_UPDATE_UNSUPPORTED`. |
+| A compliance operator | Treat each 3.3 beta bundle as an implementation input. As for 3.2, prerelease grading runs are diagnostic, not a badge. |
## Withdrawn from 3.3, planned for 4.0
@@ -247,7 +282,7 @@ The designs are kept for 4.0: see [Planned for 4.0](/docs/reference/migration/v4
## In review for 3.3
-Open 3.3 proposals are not part of any beta until they merge. Five working-group decisions are ratified, and their normative text has merged:
+Open 3.3 proposals are not part of any beta until they merge. Five working-group decisions are ratified or accepted, and their normative text has merged:
- **Agent identity is an origin ([DR-0023](https://github.com/adcontextprotocol/adcp/blob/main/governance/decisions/DR-0023-agent-identity-is-an-origin.md)).** Merged: the [Web Bot Auth profile](/docs/building/by-layer/L1/wba-profile) [#7894](https://github.com/adcontextprotocol/adcp/pull/7894), Web Bot Auth identities and the deprecation of the RFC 9421 brand.json profile [#8162](https://github.com/adcontextprotocol/adcp/pull/8162), first-contact binding [#8168](https://github.com/adcontextprotocol/adcp/pull/8168), the buyer walkthrough and migration guide [#8172](https://github.com/adcontextprotocol/adcp/pull/8172), the experimental production security profile [#8155](https://github.com/adcontextprotocol/adcp/pull/8155), seller onboarding posture [#8170](https://github.com/adcontextprotocol/adcp/pull/8170), and the R7/R8 erratum [#8219](https://github.com/adcontextprotocol/adcp/pull/8219). `request_account` [#8293](https://github.com/adcontextprotocol/adcp/pull/8293), then the single account write and reporting subscriptions ([#8543](https://github.com/adcontextprotocol/adcp/issues/8543): [#8551](https://github.com/adcontextprotocol/adcp/pull/8551), [#8552](https://github.com/adcontextprotocol/adcp/pull/8552)).
- **Responses conform to the served release ([DR-0024](https://github.com/adcontextprotocol/adcp/blob/main/governance/decisions/DR-0024-responses-conform-to-served-release.md), [#8117](https://github.com/adcontextprotocol/adcp/pull/8117)).** Merged. The rule is in [Serving an older pin](/docs/reference/versioning#serving-an-older-pin); grading is open in [#8156](https://github.com/adcontextprotocol/adcp/pull/8156).
@@ -255,7 +290,7 @@ Open 3.3 proposals are not part of any beta until they merge. Five working-group
- **JWS artifacts use the Web Bot Auth key directory ([DR-0026](https://github.com/adcontextprotocol/adcp/blob/main/governance/decisions/DR-0026-jws-artifacts-use-the-wba-key-directory.md), [#8299](https://github.com/adcontextprotocol/adcp/pull/8299)).** Merged. It amends DR-0023: governance contexts, designated-task response signatures, and rights attestations from a listed origin verify against its key directory in 3.3.
- **Seller revisions advance on every committed change ([DR-0031](https://github.com/adcontextprotocol/adcp/blob/main/governance/decisions/DR-0031-seller-revision-any-origin.md), [#8159](https://github.com/adcontextprotocol/adcp/pull/8159)).** Merged; recorded in [#8389](https://github.com/adcontextprotocol/adcp/pull/8389). See [Tightened rules](#tightened-rules).
-Proposed records DR-0027 to DR-0030 (mutation outcome, `sales-fixed-rate`, delivery projection, and lineage) describe surfaces merged for beta.0 and await ratification. The open proposals are listed in the [3.3 beta program](/docs/reference/3-3-beta#in-review-for-3-3).
+Records DR-0027 to DR-0030 (mutation outcome, `sales-fixed-rate`, delivery projection, and lineage) describe surfaces merged for beta.0 and are accepted. DR-0034 (major-only requests) is accepted, and DR-0036 (closed schemas stay closed) is proposed and awaiting ratification. The open proposals are listed in the [3.3 beta program](/docs/reference/3-3-beta#in-review-for-3-3).
## Start here