VERSION_UNSUPPORTED error or an unexpectedly empty catalog.
What gets negotiated
AdCP negotiates at release precision —MAJOR.MINOR, e.g. 3.0 or 3.1. Patches (the third semver segment) are not negotiated: a patch by definition introduces no contract change, so a source’s exact build is surfaced separately as build_version for operational triage only, never for negotiation.
Pre-release tags (e.g.
3.1-rc, 3.1-beta) hang off a release and match exactly only — they are never a downshift target for a GA pin.
The negotiation rule
This is the single load-bearing rule:A source must downshift a buyer’s pin to the highest supported release at or below the pin, within the same major version, and serve the request.
VERSION_UNSUPPORTED is reserved only for a cross-major mismatch — where the buyer pins a major the source does not implement at all.3.1 and a source supports only 3.0, that is a same-major gap: the source must downshift to 3.0 and serve, not return an error. A source that supports major 3 returning VERSION_UNSUPPORTED for a 3.1 request is non-conformant.
The major-vs-minor line is the whole rule:
When a source downshifts, the response’s
adcp_version is set to the release it actually served. Clients should validate the response against that release’s schema, not against their original pin — which is what makes a downshift safe rather than silently lossy.
Which releases a storefront advertises
An Apostra storefront lists3.0, 3.1 and 3.2 in supported_versions. A storefront
backed by a sales adapter lists 3.1 and 3.2, because it cannot truthfully project the
3.0 signal listings. A request that pins one of these releases is served at that release
and the response says so in adcp_version. A request that pins a later 3.x release is
downshifted to 3.2. A request that pins no release is served at 3.1. A request that
sends only the legacy
adcp_major_version is served at 3.0, the oldest release the storefront lists, because
an AdCP 3.0 buyer has no other way to say which release it speaks.
A response has the shape of the release it was served at. Fields that a later release
added are left out, not sent alongside, so a buyer served at 3.1 receives a valid 3.1
response. Pin adcp_version: "3.2" to receive 3.2 fields.
A newer request shape cannot be silently downshifted
Release negotiation and request-shape validation are separate. A3.2 client cannot
send account identity fields introduced in 3.2 to a storefront that has not enabled
them and expect the storefront to discard them. Dropping operator_unit, currency,
timezone, or brand.countries could merge two distinct advertiser accounts.
A storefront that has not enabled the 3.2 complete-key accounts serves a 3.2
sync_accounts or list_accounts call exactly as it serves a 3.1 call, as long as the
request carries only the fields 3.1 has. For sync_accounts, a request that also carries
a 3.2-only identity field is rejected with VERSION_UNSUPPORTED before anything is
written. The error identifies the first unsupported field and includes:
brand.countries is different on a storefront that has enabled the 3.2 complete-key
accounts. It is part of the AdCP 3.2 account key, so that storefront accepts it, and two
keys that differ only by brand.countries are two separate seller accounts. Send the codes
as ISO 3166-1 alpha-2 values; Apostra stores them sorted and uppercase, so the order and
case you send do not matter, and an unassigned code returns INVALID_REQUEST. Omit the
field for a global identity: a confirmed identity without a country qualifier covers all
countries. Existing identities with an explicit country list retain that scope, while a
legacy identity with unknown country scope remains incomplete. Changing the country scope of
an existing seller account is a different key, so it creates a new account rather than
editing the old one, and historical buys keep their original identity.
What Apostra does
Apostra pins AdCP3.1 on requests to your sources (and emits the legacy major 3 alongside it for older sources).
When a source lists only an older release in supported_versions, Apostra speaks that
release to it and converts each request to its shape. A read loses only what the older
release cannot express. A change that would lose part of what it asks for, such as a spend
cap, a targeting exclusion or any field of a buy update, is refused before anything reaches
the source, rather than sent without it.
The component catalog requires AdCP 3.1 or newer, so Apostra does not retry a catalog warm from its current 3.1 pin at 3.0 and never interprets a 3.0 response as a component catalog. A 3.0-only source may still serve compatible live buyer requests through the pass-through path, but its components remain absent until the source supports 3.1.
The catalog warmer contains a one-shot compatibility hook for a future pin above 3.1. It can retry only the highest advertised same-major GA release that is at least 3.1 and no newer than the pin. At the current 3.1 pin there is no lower eligible release, so the hook does not fire. If no eligible release exists, Apostra records VERSION_UNSUPPORTED and the source’s products stay absent from the catalog until the source is corrected.
When you see VERSION_UNSUPPORTED
At protocol-negotiation time, aVERSION_UNSUPPORTED error has two causes, and they
have different fixes:
- Genuine cross-major incompatibility — the pinned major is one the source does not implement at all (e.g. a source that only speaks major
2). This is a spec-correct refusal; the fix is to align on a shared major version. - A non-conformant or stale source build — the source rejects a same-major minor it should have downshifted (e.g. it supports
3.0but rejects a3.1request). This is a source-side bug: the source must upgrade its AdCP server to a build that performs same-major downshift. For the component catalog it must also support at least3.1; Apostra does not mask a3.1→3.0gap with a retry.
VERSION_UNSUPPORTED, cause (2) is the usual culprit — see Source diagnostics. This is a source-side server issue, not a problem with your account or your buy.
The sync_accounts request-shape gate described above is the separate third case: its
details.reason is adcp_3_2_account_identity_not_supported, and its recovery is to
stop sending the named 3.2 fields, brand.countries among them, rather than debug
source negotiation.
Related
Connect your sales agent
How a source advertises its versions and capabilities
Source diagnostics
Trace why a source’s catalog is empty or a call failed
Errors
The shared error contract, including
VERSION_UNSUPPORTEDHow Apostra uses AdCP
The buy-side conformance picture