AdCP 4.0 compatibility checks
AdCP 4.0 removes fields and tightens requirements that 3.x agents depend on today. The compliance suite checks a 3.x agent against each of these changes, so the agent learns what to fix before a 4.0 buyer stops working with it.These checks are advisory throughout 3.x. A failing check never fails a 3.x conformance run. Each one is graded inside a storyboard step that already runs, so it adds no new calls and no new ways to fail.The checks ship in compliance bundles from 3.3 onward. Released bundles never change, so an agent graded against an earlier bundle shows every check as not observable until it is graded against a bundle that carries them.
Reading the results
Each check has a stable id. The registry atuniversal/v4-compatibility.yaml in the compliance bundle names the storyboard step and validation, or the runner notice, that observes it. A report joins a run’s output against that registry and shows one of three results for each check:
In raw runner output, a check observed by a validation appears as a
validation_result whose id is the check id. Checks added only for 4.0 carry severity: "advisory". A check observed by a notice appears as a notice whose code is the check id; a notice is only evidence of a pass from a runner known to emit that code.
Checks
Products declare canonical format options
Check id:format_ids_removed_in_4_0 · Change: removal
Detects: a product returned by get_products declares format_ids without format_options.
4.0 removes the exact plural format_ids fields. format_options[] becomes the only way a product declares the creative formats it accepts, so a 4.0 buyer sees no formats on a product that carries format_ids alone.
Fix: author canonical format_options[] on every product. You can keep projecting format_ids for older 3.x buyers until 4.0. See Canonical formats migration.
The check inspects every product in the media_buy_seller brief response, which returns up to five products. It uses the all_fields_present check kind; a runner that does not implement it reports the check as not observable.
Capabilities declare release-precision versions
Check id:major_versions_removed_in_4_0 · Change: removal
Detects: get_adcp_capabilities declares adcp.major_versions without adcp.supported_versions.
4.0 removes adcp.major_versions and the request field adcp_major_version. A 4.0 buyer reads adcp.supported_versions only.
Fix: list every release you speak in adcp.supported_versions, as release-precision strings such as "3.2". Keep emitting adcp.major_versions through 3.x. See Versioning.
3.2 certification already requires supported_versions, so this check adds no new failure: it labels an existing requirement as one 4.0 depends on.
Responses echo the served release
Check id:adcp_version_echo_required_in_4_0 · Change: new requirement
Detects: the response envelope does not echo the served release in adcp_version.
The echo is SHOULD-level in 3.x. 4.0 makes it a MUST, and buyers lose the major-version fallback.
Fix: echo the release you served in adcp_version on every response envelope. 3.2 certification already requires the echo.
Capabilities do not claim the signed-requests specialism
Check id:signed_requests_specialism_deprecated · Change: removal
Detects: get_adcp_capabilities lists signed-requests in specialisms.
4.0 removes the signed-requests specialism enum value. Request signing is a capability, not a specialism.
Fix: drop signed-requests from specialisms and advertise request_signing.supported: true. See Signed requests.
Sellers verify signed requests
Check id:request_signing_required_in_4_0 · Change: new requirement
Detects: get_adcp_capabilities does not advertise request_signing.supported: true.
Request signing is optional in 3.x. 4.0 requires it on spend-committing operations.
Fix: verify RFC 9421 request signatures, advertise request_signing.supported: true, and register the compliance runner’s test key before the 4.0 cut. See Signed requests.
Webhooks do not fall back to HMAC
Check id:legacy_hmac_fallback_removed_in_4_0 · Change: removal
Detects: get_adcp_capabilities advertises webhook_signing.legacy_hmac_fallback: true.
4.0 removes the HMAC-SHA256 webhook fallback.
Fix: sign webhooks with RFC 9421 only and stop advertising legacy_hmac_fallback. See Webhooks.
Changes not checked yet
A check is added once its 4.0 change is decided. These changes are still proposals or under working group review, so the suite does not grade them yet:channelsrequired on every product (#7869)duration_msrequired on hosted video assets (#5668)- the
account_idfromsync_accountsas the only account reference after provisioning (#7850) - nested
statusrenamed tomedia_buy_status(#4905)
x-removed-in: "4.0.0". The registry lists each one, either under the check that covers it or in schema_removals_not_checked with the reason no check covers it yet. Most uncovered fields are sent by buyers, so a seller run can’t observe them. A few are seller-emitted and checkable but not graded yet: flat valid_actions, response-wide delivery currency and aggregated_totals, inline_creative_management, and the format-level build and pricing surface that list_transformers replaces.
The full list of planned 4.0 work is the 4.0 milestone.
Adding a check
Every 4.0 issue that removes or tightens something an agent relies on declares a stable check id and a one-line detection rule. When the change is accepted, the same PR:- Adds the observation. Prefer an advisory validation on a step that already makes the needed call, with
idset to the check id,severity: advisory, andpermanent_advisory. Don’t useexpires_after_version, which promotes the check on runner version rather than on the spec version the agent is graded against. A check the runner already reports as a canonical notice witheffective_version: "4.0"uses the notice code as its id. - Adds the entry to
universal/v4-compatibility.yaml, with the removed schema nodes inschema_sites. - Adds a section here with an
<a id>anchor that matches the check id.
"deprecated": true and "x-removed-in": "4.0.0", and the registry lists it once: in a check’s schema_sites, or in schema_removals_not_checked with its 4.0 tracking issue and a reason. Marking a node therefore forces the decision of whether a 3.x agent can be checked for it, and gives every removal a tracking issue.
scripts/lint-v4-compatibility-registry.cjs fails the compliance build when the registry, the storyboards, the notice codes, the schema markers, and this page disagree.