Optionalformat_option_id?: stringStable identifier for this format declaration within its namespace. REQUIRED when the parent product's format_options contains multiple declarations sharing the same format_kind (so buyers can disambiguate which option a manifest targets via manifest.format_option_ref). SHOULD be set on EVERY format_options[] entry — not just when structurally required to break a format_kind collision — so V2-mental-model buyers can use the V2 authoring path (PackageRequest.format_option_refs[], creative-manifest.format_option_ref) against the product. Publisher-catalog-backed options pair this with publisher_domain; product-local options omit publisher_domain and are selected by format_option_id within the target product. A product that ships without selectable format_option_id values on its format_options[] entries is structurally 3.1-conformant but is not V2-authorable: buyers fall back to v1 format_ids[] and lose the stable naming the V2 path was designed to provide. Sellers MUST reject V2 authoring against such products with UNSUPPORTED_FEATURE and error.details.reason set to format_option_refs_not_published per package-request.json. Format-internal (not a URI). Examples: 'display_image_300x250', 'responsive_search', 'daily_pulse_homepage_image'.
Optionalpublisher_domain?: stringNamespace for format_option_id when this declaration references or narrows a publisher-declared format option from that publisher's adagents.json top-level formats[]. Product-local options omit this field and are selected by format_option_id within the target product.
Optionaldisplay_name?: stringOptional seller-controlled human-readable label for this format declaration. Used by buyer dashboards, catalog UIs, and reporting surfaces to show a seller's own naming ('Homepage Takeover', 'Branded Canvas', 'Reels Premium Video') rather than the raw format_kind or format_option_id. Has no machine semantics — buyer agents route on format_kind and format_option_id; display_name is purely for human presentation. Freeform; no enumeration. Sellers SHOULD keep it stable once published to avoid dashboard churn.
Optionalapplies_to_channels?: MediaChannel[]Optional subset of the parent product's channels to which this declaration applies. When omitted, the declaration applies to ALL channels declared on the product. Lets a multi-channel product (e.g., channels: ['display', 'video']) carry distinct format_options per channel — format_options: [{format_kind: 'image', applies_to_channels: ['display']}, {format_kind: 'video_hosted', applies_to_channels: ['video']}]. Buyers ship channel-appropriate manifests per applies_to_channels.
Optionalseller_preference?: "preferred" | "accepted" | "discouraged"Optional soft routing hint within a product's accepted set of formats — NOT an enforcement axis. preferred — seller actively recommends this format (often because of measurement, viewability, or render-quality differences); accepted — supported on equal footing with other format_options (default when omitted); discouraged — supported but suboptimal (e.g., legacy 3p-tag where the seller would prefer html5 for OM-SDK coverage). Buyer agents picking between format_options SHOULD respect seller preferences when their own constraints don't override.
Not an enforcement axis (normative). seller_preference does NOT carry the meaning of 'this format won't work / required-only'. That case is structural: format_options[] IS the closed set of accepted formats; anything outside the list is rejected at create_media_buy regardless of preference. A seller that accepts only one format lists exactly that one entry — the structural fact does the enforcement work, no enum value needed. There is intentionally no required value; preference is bounded to ranking within the already-accepted set, not gating into it.
Optionalcanonical_formats_only?: booleanWhen true, this format declaration has no clean v1 projection and SDKs MUST NOT synthesize a v1 format_id for it. Buyers reading the product on the v1 wire path see this declaration absent from format_ids; only v2-aware buyers (reading format_options) discover it. Set explicitly for format_kind: "custom" declarations (no canonical exists in v1 to project onto) and for declarations whose canonical/parameter shape cannot round-trip through a v1 named format without semantic loss. The protocol does NOT mint synthetic v1 format_ids for unmappable declarations — the alternative (an aao-synth/* namespace populated automatically) was considered and rejected because adopters would index on synthetic IDs that have no stable identity. Producers SHOULD set canonical_formats_only: true rather than omit the declaration from format_options — explicit v2-only is more useful than silent absence.
Optionalexperimental?: booleanWhen true, THIS seller's specific product declaration may not work as declared — even if the underlying canonical is stable. Use for beta runtime paths, forward-looking catalog entries the runtime doesn't yet honor, or experimental products where the seller wants buyer-side caution. Buyers reading experimental: true on a product declaration SHOULD prefer the legacy named-format path when a fallback exists for the same product (via format_ids on the parent product or via this declaration's v1_format_ref) and SHOULD validate via validate_input or a sandbox before routing production budget.
Independent of the canonical's own experimental flag — a stable canonical (e.g., image, video_hosted) can carry an experimental product declaration when the seller is shipping a new runtime path that isn't fully wired yet. Conversely, an experimental canonical (sponsored_placement, responsive_creative, agent_placement) MAY carry non-experimental product declarations where the seller's adopter contract is well-tested. Buyer SDKs SHOULD filter products with experimental: true from default views and offer an opt-in flag to surface them.
Replaces the earlier runtime_status enum (stable | preview | declared_only) — same semantic ('use with caution') without the cognitive overhead of two stability axes.
Optionalformat_shape?: stringREQUIRED when format_kind: "custom"; otherwise MUST be absent. Recognized global pattern this custom shape is an instance of, drawn from the format-shape vocabulary registry (multi_placement_takeover, roadblock, branded_content, cross_screen_sponsorship, sponsorship_lockup, newsletter_sponsorship, ar_lens, playable, live_event_sponsorship, …). Non-canonical values valid (validators MAY soft-warn) — adopters CAN ship a shape that isn't yet in the registry. Adding entries is a vocabulary PR. Once a format_shape entry sees 2+ adopters with substantively similar format_schema content for 90+ days, the working group promotes it to a first-class canonical.
Optionalv1_format_ref?: FormatReferenceStructuredObject[]Authoritative v2 → v1 link, expressed as an array of one or more v1 format_id ({agent_url, id}) values. Each entry asserts that this canonical-formats declaration IS the same underlying format as the referenced v1 named format. Always an array (single-ref is [{...}]) so the multi-size case below has a clean wire shape — adopters surveyed in the SDK implementor review pushed for this over the lossy single-ref form.
The v2 declaration's params MUST narrow (be compatible with) each referenced v1 format's requirements — see the 'Narrows — formal definition' section in canonical-formats.mdx. SDKs comparing dual-emitted shapes (Product.format_ids[] ⊇ entries from v1_format_ref AND Product.format_options[] carrying this declaration) treat the link as the authoritative pairing and run the narrowing check between this declaration and EACH referenced v1 format file's requirements.
Multi-size fan-out (normative). When the declaration carries params.sizes: [{w,h}, ...] (multi-size flexible slot), sellers SHOULD carry one v1_format_ref[] entry per size, each pointing at the per-size v1 named format in the AAO catalog. Example: a multi-size image declaration with sizes: [300x250, 728x90, 970x250] SHOULD carry v1_format_ref: [{aao, display_300x250_image}, {aao, display_728x90_image}, {aao, display_970x250_image}]. v1-only buyers then see the product on all three sizes via the format_ids[] dual-emission. When v1_format_ref[] count < sizes[] count, SDKs MUST emit FORMAT_DECLARATION_V1_LOSSY_MULTI_SIZE on the response errors[] (advisory, alongside the partial-coverage v1 emit — NOT in place of it). SDKs MAY (non-normative) fan out automatically by catalog lookup when v1_format_ref[] has length 1 and sizes[] has length N — opt-in, requires catalog access; sellers asserting refs is the source of truth.
Mutually exclusive with canonical_formats_only: true — a declaration can EITHER assert no v1 projection (canonical_formats_only: true) OR link to v1 named formats (v1_format_ref[]), never both. When neither is present, SDKs fall back to the resolution order in v1-canonical-mapping.json (seller's explicit canonical field on the v1 file → registry glob → structural match → fail-closed).
This is the v2-side authoritative replacement for the v1-side canonical_parameters field on format.json (which is deprecated for 3.1, removed at 4.0). Sellers SHOULD prefer authoring v2 declarations with v1_format_ref[] over mirroring the v2 shape onto v1 files via canonical_parameters; the directional link (v2 declaration → v1 identifiers) is the same fact without the parallel-shape drift surface.
AAO-hosted convention (normative). For IAB-standard formats (image dimensions, VAST/DAAST tags, standard third-party tags, HTML5 banner bundles), sellers SHOULD point each v1_format_ref[].agent_url at the AAO-hosted canonical agent URL https://creative.adcontextprotocol.org and use the registry-published id (e.g., display_300x250_image, video_vast_30s, audio_standard_30s, display_300x250_html, display_js). This converges the v1-wire namespace: every seller's IAB MREC points at the same {agent_url, id} pair, so v1-only buyers' allowlists work uniformly. Without this convention, every publisher's 300x250 ships with a different v1_format_ref (theirs vs nytimes.example vs cnn.example vs …) and the v1 wire fragments into per-publisher namespaces — exactly what canonical-formats was designed to eliminate.
For platform-specific formats (Meta Reels, TikTok Spark, Snap Spotlight, etc.), each v1_format_ref[].agent_url SHOULD point at the platform's own agent_url when the platform has adopted AdCP and publishes its own adagents.json with formats[]. When the platform has NOT adopted AdCP, sellers SHOULD point at the AAO community-registry mirror — https://creative.adcontextprotocol.org/translated/<platform> + id: <platform-format-name> (e.g., https://creative.adcontextprotocol.org/translated/meta + id: meta_reels). This keeps the v1 namespace converged across all sellers selling that platform's inventory until the platform owns its own adagents.json.
Platform-adoption cutover (normative). When a platform adopts AdCP and publishes its own adagents.json, sellers MUST update v1_format_ref[].agent_url to the platform's adopted agent_url in the same minor release as the AAO mirror entry's superseded_by field goes live (see static/schemas/source/adagents.json#superseded_by). The AAO mirror entry SHOULD continue serving for ≥1 minor release after superseded_by is set, returning an advisory 'superseded' marker so v1 buyer allowlists keyed on the mirror URL get an explicit signal rather than a silent break. Identity-confusion note: the mirror URL is format-shape namespace, NOT seller identity. Inventory authorization always flows from authorized_agents[] + publisher signing keys; a buyer matching v1_format_ref[].agent_url against an allowlist is matching format-shape provenance, not seller identity.
Mirror domain migration (3.1). Earlier drafts used https://mirror.adcontextprotocol.org/translated/<platform>. As of this release, the convention is https://creative.adcontextprotocol.org/translated/<platform> — sibling content under the AAO catalog domain we already host. Adopters who hardcoded the earlier mirror URL MUST migrate to the new path; the canonical-formats.mdx migration section documents the move. No transitional redirect is currently published (the earlier subdomain was never provisioned).
For seller-bespoke formats (a publisher's acme_homepage_takeover that doesn't fit IAB conventions), each v1_format_ref[].agent_url is the seller's own agent_url and the id is seller-namespaced. These won't appear in v1-canonical-mapping.json's registry; they're seller-asserted only.
Optionalformat_schema?: PlatformExtensionReference
Inline format declaration on a product. The
format_kinddiscriminator names which canonical format the product narrows;paramscarries the canonical's parameter schema (slots, dimensions, durations, codecs, character limits, platform_extensions, etc.). Optionalformat_option_id(stable identifier for routing when a product'sformat_optionscontains multiple declarations sharing the sameformat_kind), optionalpublisher_domain(namespace for the format option when it comes from a publisher adagents.json catalog),display_name(seller-controlled human-readable label for dashboard and catalog UIs), andapplies_to_channels(subset of the product's declared channels this declaration applies to — lets a multi-channel product carry distinct format_options per channel). Discriminated-union shape generates clean tagged unions in TypeScript and Pydantic codegen. Replaces v1's named-format pattern (where products referenced a separately-defined format file via compoundformat_id). v1 named formats remain supported through the deprecation cycle; v2 product-bound declarations are opt-in.Closed-set semantics (normative).
format_options[]is the closed set of accepted formats for this product. Sellers MUST rejectcreate_media_buyrequests targeting anyformat_kind(or format option reference) not present in this list — typically withUNSUPPORTED_FEATUREor a seller-specific code; the rejection is structural, not negotiable.seller_preferencemodulates within the accepted set (a soft ranking hint between equally-acceptable options), it is NOT an enforcement axis. A product wanting to say 'this format is the only one that works' lists exactly that one entry informat_options[]; everything else falls outside the set and is rejected by the closed-set rule.Format matching vs satisfaction (normative). Legacy named formats MUST be normalized to canonical declarations before comparison; do not exact-match raw
(agent_url, id)pairs once aformat_idhas been projected throughcanonical,v1_format_ref, or the canonical mapping registry. Equivalence matching can treat a legacy fixed-size display ID andformat_kind: "image"with matchingwidth/heightas the same underlying shape. Product satisfaction is stricter and directional: when this declaration specifies fixed constraints such aswidth,height,duration_ms_exact, orduration_ms_range, a buyer request or creative manifest MUST declare and satisfy those constraints. A broad request with no dimensions or duration does not satisfy a fixed-size or fixed-duration product; a broad product MAY accept a more specific creative unless another product constraint excludes it. Duration precedence isduration_ms_exact>duration_ms_range. Range constraints use containment: a range-based request satisfies this declaration only when every value it permits falls within this declaration's accepted range; overlap alone is insufficient. An exact value satisfies a range when the exact value falls inside the accepted interval. For hosted audio/video, a null range endpoint is unbounded: [null, 60000] means up to 60s, and [15000, null] means at least 15s; [null, null] is invalid because at least one endpoint must be bounded.Custom format_kind (
format_kind: "custom"): for adopter-defined shapes that don't fit the 12 canonicals (multi-placement takeover, roadblock, branded content, cross-screen sponsorship, sponsorship lockup, newsletter sponsorship, AR lens, playable, live event sponsorship). Whenformat_kindiscustom, the declaration MUST carryformat_shape(recognized global pattern from the format-shape vocabulary registry) ANDformat_schema(URI+digest reference to a fetchable schema describing the actualparamsandslots). Buyer agents fetch the schema, validate manifests structurally, and reason about manifests without per-seller integration code. See adcp#3666 for the canonical promotion queue.