Documentation Index
Fetch the complete documentation index at: https://docs.adcontextprotocol.org/llms.txt
Use this file to discover all available pages before exploring further.
Migration: v1 named formats → Canonical Formats
This guide walks through the shift from v1 named formats (format_id as { agent_url, id } referencing a separately-defined format file) to canonical-format product-bound declarations introduced by RFC #3305. v1 named formats remain a first-class path through 4.x; canonical formats are the new path, opt-in indefinitely.
For the architecture, read canonical-formats first. This page is just the migration mechanics.
Naming note: The v1↔v2 terminology used throughout this page describes the two format-authoring models —format_ids(legacy, v1) vsformat_options(canonical formats, v2). It does NOT refer to AdCP-the-protocol’s version (currently 3.x). The “v2” path is also called the canonical-formats path; both phrasings mean the same thing.
What stays unchanged
Most of AdCP doesn’t change. v2 builds on the existing primitives:- All asset primitive schemas (
image-asset.json,video-asset.json,audio-asset.json,vast-asset.json,daast-asset.json) — unchanged - Catalog and offering schemas — unchanged
- Manifest envelope shape (
creative-manifest.jsonkeyed byassetsmap) — unchanged - Response envelopes, error schemas, common types — unchanged
- v1 named formats (
format.jsonwith compoundformat_id) — still supported through 4.x - v1
list_creative_formatstool — deprecated but functional through 4.x; removed at 5.0 - All existing producers and consumers — continue to work without changes
Side-by-side: a v1 named format → v2 product format declaration
v1 — separate format file referenced by product
test=false
v2 — inline format declarations on the product
test=false
format_options is an array. The 90% case is one element — one canonical narrowed for the product. Multi-element arrays declare that the product accepts any of the listed format options, picked by the buyer at sync_creatives time. Common multi-element use cases: a placement that accepts EITHER a third-party-hosted creative (e.g., Flashtalking-served html5) OR an internal display_tag; a video product that accepts a hosted upload (video_hosted) OR a tag (video_vast). Each entry is a discriminated union: format_kind names the canonical format; params carries that canonical’s parameter schema. SDKs codegen clean tagged unions in TypeScript and Pydantic.
Dual emission during the migration window: Products MAY carry format_ids, format_options, or BOTH; at least one is required (the schema enforces this via an anyOf, not oneOf). The recommended seller pattern is to author once and let the SDK project to both wire shapes via the v1↔v2 canonical mapping registry, so every buyer reads what it knows. When both shapes are present on a product, the two MUST refer to the same underlying format declaration — the format_options[i] must narrow the canonical that format_ids[i] resolves to via the registry. SDKs that derive both shapes from one source guarantee this invariant; SDKs that hand-author both MUST treat divergence as a build error and refuse to emit. Buyers prefer format_options when both are present; treat format_ids as fallback for v1-only buyers. Sellers whose v1 named formats have no clean v2 projection ship format_ids only for those products until they add an explicit canonical declaration on the v1 format (see “v1 → v2 canonical mapping” below) — the SDK MUST NOT emit format_options for non-projectable formats.
For 14 fully-validated reference Product fixtures spanning all 12 canonical formats — Meta Reels (video_hosted vertical), IAB MREC (image 300×250), NYTimes HTML5 (html5), GAM 3P display tag (display_tag), Meta Carousel (image_carousel), YouTube VAST pre-roll (video_vast), podcast 30s host-read (audio_hosted), Triton DAAST audio (audio_daast), Amazon Sponsored Products (sponsored_placement), Taboola Content Recommendation (native_in_feed), Google PMax (responsive_creative), ChatGPT brand mention (agent_placement), Veo 15s generative video (video_hosted with synthesis_nondeterministic + provenance_required) — plus 1 get_products response fixture exercising bundled extensions, see static/examples/products/canonical/ and static/examples/get_products_responses/canonical/. The Veo fixture exercises synthesis_nondeterministic: true and provenance_required: true. Each fixture passes npm run test:canonical-fixtures.
v1 → v2 canonical mapping
The slot-levelasset_group_id bridge below tells SDKs which v2 canonical slot a v1 slot corresponds to. The format-level mapping — which v2 canonical format a v1 named format projects to — is solved by two complementary mechanisms:
The canonical mapping registry
/schemas/registries/v1-canonical-mapping.json is the authoritative AAO-published registry. SDKs consume it to project v1 formats to v2 canonicals during dual-emission and v1↔v2 translation. Two match modes per entry:
format_id_glob— exact / glob match against v1format_id.id. Covers IAB-conventional sizes (iab/mrec_300x250→image300×250), named platform formats, common publisher conventions.structural— match against the format’s slot shape, asset types, and version constraints. Catches custom v1 formats that are structurally a standard format under a different name (a seller’sacme_homepage_300x250is structurally an IAB MREC).
asset-group-vocabulary.json: PR with rationale + ≥1 reference adopter + AAO maintainer review; entries are additive and digest-pinned.
canonical field on v1 format declarations (custom / non-registered formats)
For custom seller formats not covered by the registry, the seller declares the mapping inline at the v1 format-declaration level:
test=false
canonical field names the v2 canonical; canonical_parameters (optional) carries a full ProductFormatDeclaration the SDK projects this v1 format into. Combined with slot-level asset_group_id declarations on each assets[] entry, the v1 format becomes fully self-describing for v1↔v2 translation. Seller does this once per custom format, not per buyer or per product.
For the format_kind: "custom" case (a custom seller format that itself doesn’t fit any v2 canonical), the canonical_parameters carries the same format_kind: "custom" + format_shape + format_schema triple as a normal v2 declaration would.
Normative SDK projection rules
Resolution order when an SDK projects a v1 format to its v2 canonical (or back):- If the v1 format declaration carries
canonical, use it (seller-declared, highest priority). Whencanonical_parametersis also present, use that as the projected ProductFormatDeclaration verbatim. - Else, look up
format_idin/schemas/registries/v1-canonical-mapping.json’sformat_id_globentries. - Else, attempt structural match against the registry’s
structuralentries. - Else, fail closed: SDK MUST NOT emit
format_optionsfor products carrying this format. Surface a validation warning suggesting the seller add an explicitcanonicalfield or file a registry entry. Buyers seeformat_idsonly for these products.
Slot name mapping (v1 → canonical)
If a v1 format slot uses an author-invented name that the canonical vocabulary covers, the format declaration carries an optionalasset_group_id field on the slot pointing at the canonical entry. Same as the existing asset_role field, but referencing the canonical vocabulary rather than free text.
test=false
aliases field captures common v1 alias names per canonical entry (e.g., landing_page_url aliases include click_url, link, final_url, link_url, click_through_url, landing_url). Six different names for the same field collapse to one canonical.
Common alias mappings (from the audit-grounded set in asset-group-vocabulary.json):
| Canonical | Common v1 aliases |
|---|---|
headlines | headline, title, tagline, headline_text |
descriptions | description, body, body_text, text, content |
images_landscape | image, hero_image, landscape_image, banner_image |
images_vertical | vertical_image, story_image, portrait_image |
images_square | square_image, feed_image |
logo | brand_logo, logo_image |
video | video_file, hero_video, video_asset, video_main |
audio | audio_file, hero_audio, audio_asset, audio_main |
landing_page_url | click_url, link, final_url, link_url, click_through_url, landing_url |
Discovery surface migration
list_creative_formats is uniformly deprecated. Replacements:
| Role | v1 path | v2 path |
|---|---|---|
| Sales agent | list_creative_formats returns the seller’s accepted formats | get_products — each product carries its format declaration inline. Optionally also creative.supported_formats on get_adcp_capabilities for a flat summary. |
| Creative agent (no inventory) | list_creative_formats overloaded as “what I can produce” | creative.supported_formats on get_adcp_capabilities. Each entry uses the same ProductFormatDeclaration shape as products’ inline format. |
list_creative_formats shape from v2 product format declarations through 4.0, so existing dashboards and tooling keep working. The wrapper iterates over get_products, reads each product’s format declaration, and emits a v1-compatible format file plus a format_ids reference.
Generative formats — *_generated_* files dissolve
The agentic-adapters audit found ~30 *_generated_* format files (e.g., meta_generated_reels, tiktok_generated_video_9x16) that mirror their non-generated counterparts but accept a creative_brief instead of an asset upload. In v2 these collapse:
- The format declaration’s
slotsarray enumerates everything the buyer ships in the manifest’sassetsmap — each entry is a canonicalasset_group_idpaired with anasset_type. Some slots are rendered verbatim (image / video / audio); some are consumed for production (text script → host-read audio; brief → synthesized image; video_brief → generated video). The seller dispatches per slot. - Whether the seller’s internal production is generative AI, host recording, transcoding, or asset rendering is invisible to the buyer
- A single canonical format (e.g.,
audio_hosted) handles both buyer-uploaded audio and agent-produced audio; the format’sasset_sourceandbuyer_asset_acceptanceparameters describe which flows are accepted
test=false
inputs map — the buyer ships the brief and voice_id as text/brief assets in the assets map under those slot names. The seller dispatches per the format’s slot declaration: brief → consume for synthesis; rendered audio is what comes out the other side.
Brand identity — slots disappear
v1 formats sometimes redeclaredbrand_logo, brand_colors, brand_voice, brand_tagline as explicit slots. v2 formats don’t. When the manifest carries a BrandRef (brand: { domain: "acme.com" }, optionally with brand_id for house-of-brands), the seller fetches brand.json for context automatically.
For the case where brand.json is missing or stale, the BrandRef itself carries an inline brand_kit_override (same inline-override pattern BrandRef already uses for industries and data_subject_contestation):
test=false
brand.json for the call carrying this BrandRef.
Tools — what’s new vs unchanged
| Tool | v1 | v2 |
|---|---|---|
get_products | Returns products with format_ids | Returns products with either format_ids (v1 path) or format (v2 inline) |
sync_creatives | Submit creative manifest | Unchanged. Sales agents accept manifests with assets keyed by slot name per the format’s slots declaration. |
preview_creative | Submit manifest, get preview | Same surface; preview shows output regardless of whether the slots ship rendered creative (image/video/audio) or production content (script/brief/video_brief). The single-render hoist in #3268 lands alongside v2. |
validate_input | (didn’t exist) | New buyer dry-run primitive. Validates a manifest against canonical formats and/or specific products without committing to a render. Cheap; predicted field carries pre-flight estimates. |
build_creative | Generative tool on creative agents | Same role; creative-agent surface only. Sales agents do not expose build_creative. Creative agents may also expose sync_creatives for ad-server use cases. |
list_creative_formats | Both sales and creative agents | Deprecated. Sales agents migrate to get_products; creative agents to creative.supported_formats. v1 tool stays functional through 4.x. |
Adopter migration paths
Sales agents (DSPs, SSPs, retail media networks, walled gardens)
- Inventory: enumerate your existing v1 named formats. Confirm each maps to one of the 12 v2 canonicals OR to a custom shape (see “Shipping a custom format” below). Composed/coordinated/sponsorship shapes (multi-placement takeover, roadblock, branded content, cross-screen sponsorship, sponsorship lockup, newsletter, AR lens, playable, live event sponsorship) ship as
format_kind: "custom"with aformat_shaperegistry classifier and aformat_schemaURI+digest reference. - Translate: for each named format, write a v2
ProductFormatDeclarationnarrowing the canonical with your platform’s parameters. For custom shapes, author a JSON Schema describing your format’sparamsandslots, host it at a stable URI on your subdomain (or via the AAO mirror for walled-garden sellers), and reference it fromformat_schema. - Be honest about runtime readiness: set
experimental: trueon each declaration whose runtime path isn’t fully wired yet. Same flag whether the concern is “spec is still settling” (canonical-level) or “my runtime is mid-migration” (declaration-level). Buyers SHOULD filterexperimental: truefrom default views; they SHOULD prefer the v1 fallback (via the declaration’sv1_format_refor the parent product’sformat_ids) until you drop the flag. Drop the flag when the runtime catches up. - Test: validate translated declarations against
/schemas/core/product.json(use thenpm run test:canonical-fixturespattern). - Publish dual: keep your v1 named formats and
list_creative_formatsworking through 4.x. Add the v2format_optionsfield on products that have it. - Flatten wrapper: implement a server-side wrapper that derives the v1
list_creative_formatsshape from v2 product declarations. Lets v1-era dashboards and tooling keep working. - Deprecate timing: at 5.0, remove v1
format_idsreferences on your products. Until then, both paths coexist.
Server-side implementation considerations
Three concrete hooks v2 introduces that existing seller implementations don’t have today:sync_creativesprovenance verification whenprovenance_required: true. When a v2 product’s format declaration carriesprovenance_required: true(and the buyer’s manifest contains synthesized assets — typically video/image from generative platforms),sync_creativesMUST verify a C2PA-compatible provenance manifest is attached and reject unsigned synthesized assets. This is a natural extension of existing AI-provenance tracking on Creative (EU AI Act Article 50 work) — the new piece is a validation hook that gates submission. Sellers without existing provenance plumbing only need this once they ship a v2 product with the flag set; until then it’s no-op.get_productsresponse gathers extension definitions. When products carry v2format.params.platform_extensionsreferences, the response SHOULD include the referenced extension definitions in theextensionsmap keyed by<uri>@sha256:<digest>. Implementations gather extensions referenced by any product in the response, dedupe by digest, and emit. Buyers cache by URI@digest; subsequent responses MAY omit definitions the buyer already has cached. Trivial when no products use v2 declarations; only kicks in when tenants opt in.production_window_business_dayson host-read / agent-produced products. Today most server implementations don’t model production turnaround on Products — the field is a v2 addition. Only matters once a tenant ships a v2 host-read or generative-video product (audio_hosted withasset_source: 'publisher_host_recorded', or any product withsynthesis_nondeterministic: true). Today many of these flows route through hand-trafficked sponsorships and don’t surface turnaround over the protocol; v2 makes it declarable.
Shipping a custom format
Sellers with creative structures 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) ship viaformat_kind: "custom". Three pieces:
- Pick a
format_shapefrom the vocabulary registry. If your shape isn’t there, file a vocabulary PR — adding entries is governance-light, doesn’t require a major version bump, and helps the working group track adoption velocity per shape. - Author a JSON Schema describing your format’s
paramsandslots. The schema’s job is to give buyer agents enough structure to validate manifests and reason about what assets you accept, how you track, what the impression contract is. Treat it like authoring a v1 named format file — same level of rigor, just hosted at your URI rather than under AdCP’s roof. Industry-shared schemas (e.g., a sharedmulti_placement_takeover_v1schema several publishers converge on) are encouraged and accelerate canonical promotion. - Host the schema at a stable URI with
Cache-Control: public, max-age=31536000, immutableand a digest. Open-ecosystem publishers host on their own subdomain (https://yourpub.example/schemas/formats/your_shape_v1); walled-garden sellers route through the AAO mirror athttps://creative.adcontextprotocol.org/translated/<vendor>/<shape>(AAO accepts translation submissions; same hosting / immutability contract). Reference the schema fromformat_schema: { uri, digest }on yourProductFormatDeclaration.
uri@digest, cache it (immutable), and validate manifests structurally. No human-in-the-loop is required for buyer agents to interpret your format — that’s the load-bearing claim and the reason custom + format_schema isn’t ext. Ext remains for genuinely experimental shapes that don’t even fit a format_shape entry yet, but that’s the rare case.
When 2+ adopters ship the same format_shape with substantively similar format_schema content for 90+ days, the working group promotes the shape to a first-class canonical (creates /schemas/formats/canonical/<name>.json, adds the value to canonical-format-kind.json, retires the registry entry). Adopters migrate from format_kind: "custom" to format_kind: "<canonical>" at that point. The promotion queue is tracked at adcp#3666.
Creative agents (Flashtalking, AudioStack, generative platforms, AI rendering services)
The spec has historically read sales-agent-first. v2 reshapes the creative-agent path enough to warrant its own walkthrough — both for ad-server-shaped creative agents (Flashtalking, Innovid, Sizmek-class) and transformation-shaped creative agents (AudioStack, Pencil, AdCreative.ai-class).What changes for a creative agent in v2
| Concern | v1 | v2 |
|---|---|---|
| Format catalog publishing | list_creative_formats returned your producible catalog; sales agents could reference it via creative_agents[] recursive-discovery hint on their own list_creative_formats | creative.supported_formats on get_adcp_capabilities (each entry is a ProductFormatDeclaration — same shape as a sales agent’s product format_options[i]). v1 list_creative_formats stays functional through 4.x. |
| Format authoring | You authored named formats keyed under your-domain.example and published them | You declare which AdCP-defined canonical formats you can produce (format_kind discriminator) with your platform-specific narrowing (params). No more publishing free-text named formats. |
| Discovery | Sales agents pointed buyers at you via creative_agents[] (recursive query); buyers fetched your list_creative_formats to learn what you produce | Buyers reach you directly — through brand-side relationships, AAO registry, direct knowledge. Sales agents in v2 do NOT carry a list of “approved creative agents.” Each side is independent. |
build_creative contract | Buyer shipped a manifest with format_id + assets + inputs (separate “production inputs” map) | Buyer ships the same envelope, but inputs is collapsed into assets — everything goes through one assets map keyed by canonical asset_group_id. The format’s slots declaration tells you which assets to expect, each typed by asset_type. The seller (you) dispatches per slot — render verbatim for image / video / audio slots; consume for production for text / brief / object slots (e.g., script text → host-recorded audio; creative_brief brief → generated image). |
| Production-source declaration | Implicit (the named format’s name implied the model — *_generated_* for AI-produced) | Explicit per-canonical: asset_source / asset_source / asset_source enums declare who renders and when (buyer_uploaded / publisher_host_recorded / seller_pre_rendered_from_brief / seller_human_designed / agent_synthesized). Plus synthesis_nondeterministic: true for Veo/Sora-class flows that need post-synthesis QA-loop semantics. |
| Tracking integration | Your platform’s pixel IDs, viewability vendors, OM-SDK partners lived in your named format’s tracking_events field — sellers and buyers parsed your free-text declarations | Declare via platform_extensions: [{uri, digest}] on each supported_formats[].format. Each extension is a URI you host (or the AAO mirror translates) describing the schema for your platform’s tracking surface (pixel IDs, conversion event taxonomies). The extension’s extends: "tracking" metadata lets buyers filter tracking-related entries without a separate tracking_extensions array. Sellers and buyers cache by uri@digest; SDK codegen produces typed extension handlers. |
| Hosting of produced bytes | Your CDN, your call | Your CDN, your call. v2 disaggregation is conceptual (the spec separates production from serving from tracking) — operationally, produced asset URLs in the manifest you return from build_creative continue to point at your CDN, your tracking JS continues to instrument, your platform extensions document the integration. |
Concrete example: Flashtalking-shaped creative agent
A creative agent that produces image / VAST / html5 creatives across multiple sizes and surfaces. Pre-v2, it published 30+ named formats (one per size × surface combination). v2 collapses to a smallersupported_formats set:
test=false
tracking_events array, each with its own slot vocabulary. What replaces them: 3 canonical declarations narrowed by params + platform_extensions for Flashtalking-specific tracking. SDK codegen on the buyer side produces a typed handler per format_kind rather than a typed handler per Flashtalking-named-format — a 10× reduction in surface area for buyers integrating Flashtalking.
The buyer flow is unchanged from a Flashtalking perspective: build_creative still receives a brief / assets / brand reference; you produce a manifest with rendered asset URLs on Flashtalking’s CDN; the buyer submits that manifest to whatever sales agent they’re shipping to. The sales agent validates against canonical image / video_vast / html5 — NOT against your Flashtalking narrowing. Your platform_extensions remain attached to the manifest so the sales agent honors Flashtalking pixel IDs and viewability vendors at serve time.
Concrete example: AudioStack-shaped transformation agent
A transformation agent that takes a buyer’s brief or script and produces a rendered audio file. Pre-v2, AudioStack publishedaudiostack_audio_30s_generated and similar. v2 collapses to a per-canonical declaration with explicit production-source semantics:
test=false
supported_formats entries sharing format_kind: audio_hosted but with different asset_source values. capability_id disambiguates which capability the buyer is invoking when they call build_creative.
Server-side hooks for creative agents
Three implementation considerations specific to creative agents in v2:creative.supported_formatsis your public contract. Buyers and sales agents read it to know what you produce. Keepcapability_idvalues stable across releases — buyers reference them in theirbuild_creativecalls.synthesis_nondeterministic: trueimplies a QA-loop obligation. When you declare it, you commit to: validating each synthesis attempt against the format’s parameter constraints; reseeding up to N times to produce in-spec output; returningtask_failedwithsynthesis_failedreason if the loop exhausts. There is no protocol state for orphaned out-of-spec artifacts — the buyer never sees a partial result.provenance_required: truerequires C2PA attestation. When a sales agent’s product carriesprovenance_required: trueand the buyer is shipping your produced asset, the manifest you return MUST include a C2PA-compatible provenance manifest attributing synthesis to your agent (not the buyer, not the seller). EU AI Act Article 50 alignment.
Migration timing for creative agents
| Item | Timing |
|---|---|
Continue to expose list_creative_formats (v1) | Through 4.x. Sales agents and buyers may still call it. |
Add creative.supported_formats to get_adcp_capabilities | Anytime in 3.1+. Additive — doesn’t break v1 callers. |
| Stop publishing new v1 named formats | When 80% of your buyers are reading supported_formats (track via your own analytics — buyers calling get_adcp_capabilities vs list_creative_formats). |
Drop list_creative_formats | Coordinated with the v1 deprecation calendar (2027-Q4 floor / 2029-Q1 ceiling) — same window as sales agents dropping format_ids. |
Buyers / DSPs
- Update your client to read either
format_ids(v1) orformat(v2 inline) on products. - Use
validate_inputfor cheap dry-run validation before committing to renders. - Use the canonical
asset_group_idvocabulary when constructing manifests; the registry’saliasesfield maps v1-era slot names to canonical equivalents. - Submit creative via
sync_creativesas before. For products whose slots accept production content (host-read podcasts ship ascripttext asset; generative video ships acreative_briefandvideo_brief), either pre-produce via a creative agent’sbuild_creativeto get back a manifest with rendered assets OR submit the production-content assets directly and let the seller produce internally — both flows are valid.
Publisher direct (GAM/prebid path)
- The
zipasset type (Phase 1) handles HTML5 banner bundles cleanly. URL-delivered HTML/JS routes throughurl-asset.jsonwith appropriateurl_type. - Tag-based delivery (VAST, third-party display tags) maps to the
display_tag,video_vast, andaudio_daastcanonical formats. - Native canonical format is deferred to 3.2 after the TemplateCreative + OpenRTB Native 1.2 audit; until then, native formats stay on the v1 path.
Realistic timeline by adopter type
| Adopter | Cost | Realistic timeline |
|---|---|---|
| DSP buyer agents (TTD-shaped) | Low | 3.1-3.2 |
| SSP/sales agents (Magnite, PubMatic, retail media) | Medium-high | 3.3-4.0 |
| Walled gardens (Meta, Google, Amazon, TikTok, Snap, Pinterest) | High, low motivation | 4.0-5.0 if at all (gated on AAO providing a translator from existing format docs) |
| Creative agents (AudioStack-shaped) | Low, high motivation | 3.1-3.2 |
| Publisher direct (GAM/prebid path) | Medium | Blocked on native canonical pre-audit |
When does v1 format_ids get removed?
The oneOf(format_ids, format_options) shape on Product persists through 4.x — every validator, codegen, and adopter has to handle both shapes. The 5.0 cut is adoption-driven, with calendar floor and ceiling:
- Floor (minimum end-of-life): v1
format_idsis supported through at least 2027-Q4 regardless of adoption signal. Adopters whose org reality (legacy ad-server integrations, walled-garden translation gaps, slow procurement cycles) prevents immediate migration get an unconditional 18-month runway from 3.1 GA. - Ceiling (maximum end-of-life): v1
format_idsis removed no later than 2029-Q1 regardless of adoption signal. Caps the long-tail liability for SDK authors and validator maintainers; matches the v2-sunset-policy pattern from 3.0. - Adoption trigger (within the floor / ceiling window): AAO computes the ratio of registered sales agents declaring
format_options(vsformat_ids) from cachedget_productscapabilities responses. The trigger is denominator = sales agents declaringcreativeinsupported_protocols; numerator = those whose latestget_productsresponse carriesformat_optionson every product. When the ratio crosses 80% and stays there for 30 consecutive days within the floor/ceiling window, the 5.0 cut sequence opens (deprecation warnings escalate; the next major dropsformat_ids). Until that signal trips, both shapes remain valid.
https://adcontextprotocol.org/registry/format-options-adoption.json (concrete shape and refresh cadence to be committed in a follow-up issue before 3.1 GA). Adopters who want to influence the timing should migrate early and watch the public ratio. Walled gardens that don’t migrate are absorbed by the ceiling.
creative_id stability across v1 ↔ v2
A creative registered against v1 format_id retains the same creative_id when later viewed via the v2 flatten path. sync_creatives request and response shapes are unchanged; the manifest envelope is unchanged. Migration is read-side: existing creatives keep working and resolve identically through both paths. SDK authors building flatten wrappers MUST honor this invariant.
product_card and product_card_detailed are typed inline
The product_card and product_card_detailed fields on the Product object are typed inline structures in v2 — no format_id indirection, no manifest. They describe the UI rendering of the product itself (what catalog browsers, dashboards, and admin interfaces display so humans and agents can see what a product is). Distinct from format (which describes the ad creative the product accepts).
test=false
product_card was { format_id, manifest } referencing a product_card_standard format file): drop the format reference; populate the typed fields directly. The image, title, and description flatten out of what was previously a manifest. v2-only adopters who don’t render product cards can ignore both fields entirely.
What v2 gives you that OpenRTB doesn’t
Adopters with existing OpenRTB Native / Display / Audio pipelines reasonably ask “why migrate to v2 when I already have a working creative-spec model?” The differential value:- Buyer validates against the canonical, not the seller’s narrowing. OpenRTB has no canonical layer. Each SSP authors its own native asset spec (Native 1.2 left placement-specific assets to “see the impl”); each video player authors its own VAST extensions; each retail-media network publishes its own catalog field shape. Buyers must discover and validate against per-seller specs at runtime. v2’s canonical-as-contract decouples buyer validation from per-seller schema discovery — the buyer ships a manifest that satisfies canonical
imageand knows it’s structurally valid against any seller speaking that canonical, BEFORE knowing which seller wins the auction. - Discovery is operational, not implicit. OpenRTB Display 1.x and Native 1.2 expect adopters to read the spec, write per-version handlers, and pre-bake support for what each seller might require. v2 carries the format declaration inline on the product (
format_options[i]onget_products) and on the creative agent (creative.supported_formatsonget_adcp_capabilities). Buyers fetch what’s accepted at runtime; SDK codegen produces typed handlers for the canonicals; new sellers don’t require buyer-side code changes. - Production source is first-class. OpenRTB has no notion of “buyer ships a brief; seller renders.” The closest expression is OpenRTB Native’s
nobid_reasonafter submission. v2 makes production source a declared parameter (*_sourceenums), so generative DSPs and host-read products are visible at discovery time, not only after rejection. - Tracking model is canonical-defined. OpenRTB tracking (impression NURL, click NURL, third-party trackers) is consistent for VAST but fragmented for native and display. v2 bakes the tracking model into each canonical (impression pixel for image, MRAID + OM-SDK for html5, VAST events for video_vast, per-card pixels for image_carousel) — buyers know what tracking shape applies from the canonical alone.
Validating your migration
Run the fixture validation against your translated products:test=false
static/examples/products/canonical/ are validated against /schemas/core/product.json. Adopters can drop their own translated products into a sibling directory and reuse the same validator pattern.
Related
- Canonical Formats overview
- RFC #3305 — architectural decisions and rationale
- Asset group vocabulary
- BrandRef schema
- Universal macros — substitution patterns referenced from canonical tracking