The AdCP schema registry

The AdCP schema registry is the set of draft-07 JSON Schema files published per release under dist/schemas/, indexed by two files that disagree: index.json lists schemas by protocol area, manifest.json lists them by tool.

AdCP is the Ad Context Protocol, an open standard for software agents that discover inventory and buy media: a buying agent on one side of the wire, a publisher's or platform's sales agent on the other. Every message they exchange has a JSON Schema file behind it, and the release 3.1.13 tree holds 761 of them.

Schema trees

static/schemas/source/ is what the build reads. dist/schemas/<version>/ is what it writes, and dist/schemas/latest.json points at the current stable release, currently 3.1.13. That pointer carries five keys: latest, latest_stable, channel, path and index. The source tree carries a version stamp of its own, bumped only when a release is cut, so for most of a release cycle it names a version that shipped weeks earlier.

Two things exist only in the output tree: the dereferenced bundled/ copies, and manifest.json. Neither is visible when browsing the source tree on GitHub.

index.json and manifest.json

The two registry files describe the same release from different angles, and each omits operations the other carries. The operation list is the union of the two. Where both name the same tool they point at the same request and response schema, so the disagreement is entirely about what each file leaves out. Neither file references the other, and nothing in the build compares them.

AdCP 3.1.13 — what each registry file carries
Fact index.json manifest.json
Keyed by protocol area, each operation pointing at a request and a response schema tool name
creative_approval, search_brands, validate_property_delivery in no task list present
context_match, identity_match under a trusted-match key called operations, not tasks absent
list_creative_formats both variants: the media-buy request takes property_id and publisher_domain, the creative request takes account, include_pricing and type the media-buy pair only
mutating flag, specialism tags, error_code_policy no equivalent present
Async response arms, one each for submitted, working and input-required no equivalent present

Nothing at the call site declares which of the two list_creative_formats contracts applies. That comes from get_adcp_capabilities, whose supported_protocols array says whether the agent speaks media_buy or creative. Without that call there is no fallback check: both request schemas require nothing and set additionalProperties to true, so the wrong variant validates clean and the fields the receiving agent does not recognise are discarded without an error.

How a reference resolves

Every cross-file reference in a published release is an absolute, version-pinned URL path. The tree contains no relative paths. The source tree writes those same references without the version segment, so a resolver configured against GitHub source and then aimed at a release fetches paths that do not exist — every reference, not some of them. Resolving a published reference means mapping the /schemas/<version>/ prefix onto the release directory.

The same $ref in the published release and in the source tree — source
// dist/schemas/3.1.13/media-buy/get-products-request.json
{ "$ref": "/schemas/3.1.13/core/version-envelope.json" }
//   -> dist/schemas/3.1.13/core/version-envelope.json

// static/schemas/source/media-buy/get-products-request.json
{ "$ref": "/schemas/core/version-envelope.json" }
//   -> static/schemas/source/core/version-envelope.json

The shared envelopes

core/version-envelope.json declares two properties, adcp_version and adcp_major_version, is referenced by 137 files, and requests and responses compose it alike. core/protocol-envelope.json declares the rest: status, context_id, task_id, message, timestamp, payload and the async plumbing. 68 response schemas compose it and no request schema does, so a response schema inherits those fields before declaring any of its own.

Schemas with no inbound reference

Some files in the release are reachable from neither registry file nor from any $ref. Every file in error-details/ is one, and so is every file in core/async-response-refs/, which holds one copy of each async arm the manifest already names under a different path. Nothing points at either set, so nothing makes them mandatory. creative/creative-purged-webhook.json is unreferenced for a different reason: it describes a payload that arrives out of band, and a webhook body has nothing to $ref it.

Absence from index.json does not imply absence from the reference graph. formats/canonical/image.json has no entry in the index, and neither do video_hosted, html5, audio_daast or the other nine files in that directory. They are reachable two hops down: core/product-format-declaration.json refs formats/canonical/image.json, which refs formats/canonical/_base.json.

Error detail schemas

enums/error-code.json defines 92 error codes. error-details/ holds 15 schemas, one per shape those errors can take. No $ref edge joins the two files.

core/error.json is referenced by 67 schemas, more than any of the domain objects it sits alongside, and it declares details as a bare object of no particular shape, with no $ref and no discriminator. The link between a code and its detail schema lives in an enumDescriptions string, in markdown backticks. For VERSION_UNSUPPORTED: "The error details SHOULD follow error-details/version-unsupported.json". Other codes carry a pointer written the same way. A draft-07 validator applies no constraint from enumDescriptions, so the pointer has no effect on validation.

The same file carries the structured form of that pattern for a different case. Next to enumDescriptions sits an enumMetadata block whose $comment reads: "SDKs MUST consume this block instead of parsing 'Recovery: X' from enumDescriptions prose." enumMetadata carries recovery hints as structured data; the error-detail schema pointers remain in enumDescriptions prose.

Mapping a code to its detail schema is therefore a manual step. enumDescriptions names six of the fifteen outright. The other nine mappings are stated nowhere; the filename and the code name correspond by convention only. The map from code to detail schema exists in no release artefact, so a new code or a changed mapping is not detectable from a release diff.

discriminator under draft-07

42 schemas in the release use discriminator to say which branch of a oneOf applies. discriminator is an OpenAPI keyword, draft-07 does not define it, and a draft-07 validator therefore ignores it and evaluates every branch. Validation outcome is unchanged, because the nine branches under core/pricing-option.json each pin pricing_model with a const. Error output is not: an invalid pricing_model returns one failure per branch, nine in place of the single branch failure that was intended. A client that needs the intended diagnostic selects the branch on pricing_model itself and reports only that branch's errors.

Bundled schemas

docs/building/by-layer/L0/schemas.mdx directs tools that cannot resolve $ref to the bundled schemas, which have every reference inlined. That page states that all request and response task schemas are bundled. The table on the same page names eight bundled/ directories and omits brand/, collection/, account/ and governance/. The release ships those eight, so the sentence overstates the coverage.

23 of the 64 operations have no bundle: every brand-protocol operation, every collection-list operation, every account operation, the four governance plan operations, both serve-time operations and comply_test_controller. None of the 20 async response arms are bundled either. An integration built against brand rights or account financials without a $ref-resolving validator has no offline schema to load for those operations.

The 10 core objects

These are the domain nouns the operations pass around. They are not the schemas that hold the reference tree together: the most-referenced files in the release are extension, envelope and error scaffolding. media_buy_id appears in schemas across the release, while core/media-buy.json itself is referenced once, because a media buy is fetched by identifier rather than passed around.

AdCP 3.1.13 — inbound $ref count per core schema
Schema Inbound references
core/ext.json238
core/context.json177
core/version-envelope.json137
core/protocol-envelope.json68
core/error.json67
core/media-buy.json1

product

Represents available advertising inventory

product fields — 49 fields, 7 required
FieldTypeRequiredDescription
product_idstringrequiredUnique identifier for the product
namestringrequiredHuman-readable product name
descriptionstringrequiredDetailed description of the product and its inventory
publisher_propertiesany[]requiredSDK implementers MUST enforce singular-only at runtime: each entry uses the singular `publisher_domain` form; the compact `publisher_domains[]` form is rejected on products.
channelschannels[]Advertising channels this product is sold as.
format_idsformat-id[]Legacy named-format path: array of supported creative format IDs (structured format_id objects with agent_url and id).
format_optionsproduct-format-declaration[]3.1+ format-option path: one or more inline format declarations the product accepts.
placementsplacement[]Optional array of specific public placements within this product.
video_placement_typesvideo-placement-type[]Declared video placement types that may be included in this product, using IAB Tech Lab/OpenRTB 2.6 video.plcmt definitions with AdCP-native names.
audio_distribution_typesaudio-distribution-type[]Declared audio distribution types that may be included in this product, using IAB Tech Lab/OpenRTB 2.6 audio.feed definitions with AdCP-native names.
sponsored_placement_typessponsored-placement-type[]Declared sponsored-placement types that may be included in this product, distinguishing where catalog-driven retail-media placements render on the retailer surface (sponsored search, sponsored display, or sponsored nati…
social_placement_surfacessocial-placement-surface[]Declared social-placement surfaces that may be included in this product, distinguishing the in-app surface where social placements render (feed, stories, short_video, explore, or search).
delivery_typedelivery-typerequiredType of inventory delivery One of: guaranteed, non_guaranteed.
exclusivityexclusivityWhether this product offers exclusive access to its inventory. One of: none, category, exclusive.
pricing_optionspricing-option[]requiredAvailable pricing models for this product
forecastdelivery-forecastForecasted delivery metrics for this product.
outcome_measurementoutcome-measurement**Deprecated as of this minor.** Outcome capabilities (incremental sales lift, brand lift, foot traffic, etc.) are now declared via `reporting_capabilities.available_metrics` (the same path used for impressions, convers…
delivery_measurementobjectMeasurement vendors and methodology for delivery metrics.
measurement_termsmeasurement-termsSeller's default billing measurement and makegood terms.
performance_standardsperformance-standard[]Seller's default performance standards for this product: viewability, IVT, completion rate, brand safety, attention score.
cancellation_policycancellation-policyCancellation terms for this product.
allowed_actionsproduct-allowed-action[]Actions buyers may perform on buys created against this product, scoped to statuses and modes.
reporting_capabilitiesreporting-capabilitiesrequiredReporting capabilities available for a product
creative_policycreative-policyCreative requirements and restrictions for a product
is_custombooleanWhether this is a custom product
property_targeting_allowedbooleanWhether buyers can filter this product to a subset of its publisher_properties.
data_provider_signalsdata-provider-signal-selector[]Deprecated.
included_signalssignal-listing[]Non-selectable signal metadata for signals already included in, bundled with, or planned into this product.
signal_targeting_optionsproduct-signal-targeting-option[]Inline seller-offered signals that may be applied to packages for this product at create_media_buy time.
signal_targeting_rulessignal-targeting-rulesComposition rules for selecting signals on this product.
signal_targeting_allowedbooleanWhether this product has a package-level signal_targeting_groups surface.
catalog_typescatalog-type[]Catalog types this product supports for catalog-driven campaigns.
metric_optimizationobjectMetric optimization capabilities for this product.
vendor_metric_optimizationvendor-metric-optimizationVendor-attested metric optimization capabilities for this product.
max_optimization_goalsintegerMaximum number of optimization_goals this product accepts on a package.
measurement_readinessmeasurement-readinessAssessment of whether the buyer's event source setup is sufficient for this product to optimize effectively.
conversion_trackingobjectConversion event tracking for this product.
catalog_matchobjectWhen the buyer provides a catalog on get_products, indicates which catalog items are eligible for this product.
brief_relevancestringExplanation of why this product matches the brief (only included when brief is provided)
expires_atstringExpiration timestamp.
product_cardobjectOptional standard visual card for displaying this product in user interfaces (catalog browsers, dashboards, agent UIs).
product_card_detailedobjectOptional detailed card with hero + carousel + structured specifications, for rich product presentation (media-kit-style pages, full product detail views).
collectionscollection-selector[]Collections available in this product.
collection_targeting_allowedbooleanWhether buyers can target a subset of this product's collections.
installmentsinstallment[]Specific installments included in this product.
enforced_policiesstring[]Registry policy IDs the seller enforces for this product.
trusted_matchobjectTrusted Match Protocol capabilities for this product.
material_submissionobjectInstructions for submitting physical creative materials (print, static OOH, cinema).
extextExtension object for platform-specific, vendor-namespaced parameters.

media-buy

Represents a purchased advertising campaign

media-buy fields — 17 fields, 6 required
FieldTypeRequiredDescription
media_buy_idstringrequiredSeller's unique identifier for the media buy
accountaccountAccount billed for this media buy
statusmedia-buy-statusrequiredStatus of a media buy. One of: pending_creatives, pending_start, active, paused, completed, rejected, canceled.
healthobjectAggregate health based on open impairments[].
impairmentsimpairment[]Open impairments — upstream dependency state changes that affect delivery for at least one package on this buy.
rejection_reasonstringReason provided by the seller when status is 'rejected'.
confirmed_atstring | nullrequiredISO 8601 timestamp when the seller committed to this media buy.
cancellationobjectCancellation metadata.
total_budgetnumberrequiredTotal budget amount
packagespackage[]requiredArray of packages within this media buy
contextcontextOpaque media-buy-level correlation data echoed unchanged from the create_media_buy request.
invoice_recipientbusiness-entityPer-buy override for who receives the invoice.
creative_deadlinestringISO 8601 timestamp for creative upload deadline
revisionintegerrequiredMonotonically increasing optimistic concurrency token.
created_atstringCreation timestamp
updated_atstringLast update timestamp
extextExtension object for platform-specific, vendor-namespaced parameters.

package

A specific product within a media buy (line item)

package fields — 29 fields, 1 required
FieldTypeRequiredDescription
package_idstringrequiredSeller's unique identifier for the package
product_idstringID of the product this package is based on.
budgetnumberBudget allocation for this package in the currency specified by the pricing option
pacingpacingBudget pacing strategy One of: even, asap, front_loaded.
pricing_option_idstringID of the selected pricing option from the product's pricing_options array
bid_pricenumberBid price for auction-based pricing.
price_breakdownprice-breakdownBreakdown of the effective price for this package.
impressionsnumberImpression goal for this package
catalogscatalog[]Catalogs this package promotes.
format_idsformat-id[]Legacy named-format IDs supplied for this package on create_media_buy.
format_option_refsformat-option-ref[]Structured 3.1+ format option references supplied for this package on create_media_buy.
format_kindcanonical-format-kindDirect canonical selector supplied for this package on create_media_buy. One of: image, html5, display_tag, image_carousel, video_hosted, video_vast, audio_hosted, audio_daast, sponsored_placement, native_in_feed, responsive_creative, agent_placement, custom.
paramsobjectParameters for the direct canonical selector in `format_kind`, echoed from the create_media_buy request whenever the request included it.
targeting_overlaytargetingOptional restriction overlays for media buys.
measurement_termsmeasurement-termsAgreed billing measurement and makegood terms for this package.
performance_standardsperformance-standard[]Agreed performance standards for this package.
committed_metricscommitted-metric[]The binding reporting contract for this package — what the seller has agreed to populate in delivery reports.
creative_assignmentscreative-assignment[]Creative assets assigned to this package
format_ids_to_provideformat-id[]Format IDs that creative assets will be provided for this package
optimization_goalsoptimization-goal[]Optimization targets for this package.
start_timestringFlight start date/time for this package in ISO 8601 format.
end_timestringFlight end date/time for this package in ISO 8601 format.
pausedbooleanWhether this package is paused by the buyer.
canceledbooleanWhether this package has been canceled.
cancellationobjectCancellation metadata.
agency_estimate_numberstringAgency estimate or authorization number for this package.
creative_deadlinestringISO 8601 timestamp for creative upload or change deadline for this package.
contextcontextOpaque package-level correlation data echoed unchanged in responses, webhooks, and read surfaces.
extextExtension object for platform-specific, vendor-namespaced parameters.

creative-asset

Creative asset for upload to library — supports static assets, generative formats, and third-party snippets.

creative-asset fields — 14 fields, 3 required
FieldTypeRequiredDescription
creative_idstringrequiredUnique identifier for the creative.
namestringrequiredHuman-readable creative name
format_idformat-idLegacy named-format path.
format_kindcanonical-format-kind3.1+ canonical-format path. One of: image, html5, display_tag, image_carousel, video_hosted, video_vast, audio_hosted, audio_daast, sponsored_placement, native_in_feed, responsive_creative, agent_placement, custom.
format_option_refformat-option-ref3.1+ format-option path, optional.
assetsobjectrequiredAssets required by the format, keyed by asset_id or canonical asset_group_id.
inputsobject[]Preview contexts for generative formats - defines what scenarios to generate previews for
tagsstring[]User-defined tags for organization and searchability
statuscreative-statusFor generative creatives: set to 'approved' to finalize, 'rejected' to request regeneration with updated assets/message. One of: processing, pending_review, approved, suspended, rejected, archived.
weightnumberOptional delivery weight for creative rotation when uploading via create_media_buy or update_media_buy (0-100).
placement_refsplacement-ref[]Optional structured placement references where this uploaded creative should run when uploading via create_media_buy or update_media_buy.
placement_idsstring[]Legacy shorthand array of placement IDs where this creative should run when uploading via create_media_buy or update_media_buy.
industry_identifiersindustry-identifier[]Industry-standard or market-specific identifiers for this creative (e.g., Ad-ID, ISCI, Clearcast clock number, IDcrea).
provenanceprovenanceProvenance metadata for this creative.

targeting

Optional restriction overlays for media buys.

targeting fields — 28 fields, 0 required
FieldTypeRequiredDescription
geo_countriesstring[]Restrict delivery to specific countries.
geo_countries_excludestring[]Exclude specific countries from delivery.
geo_regionsstring[]Restrict delivery to specific regions/states.
geo_regions_excludestring[]Exclude specific regions/states from delivery.
geo_metrosobject[]Restrict delivery to specific metro areas.
geo_metros_excludeobject[]Exclude specific metro areas from delivery.
geo_postal_areaspostal-area[]Restrict delivery to specific postal areas.
geo_postal_areas_excludepostal-area[]Exclude specific postal areas from delivery.
daypart_targetsdaypart-target[]Restrict delivery to specific time windows.
axe_include_segmentstringDeprecated: Use TMP provider fields instead.
axe_exclude_segmentstringDeprecated: Use TMP provider fields instead.
audience_includestring[]Restrict delivery to members of these first-party CRM audiences.
audience_excludestring[]Suppress delivery to members of these first-party CRM audiences.
signal_targeting_groupspackage-signal-targeting-groupsBasic Boolean grouping for seller-offered signals.
signal_targetingsignal-targeting[]DEPRECATED.
frequency_capfrequency-capFrequency capping settings for package-level application.
property_listproperty-list-refReference to a property list for targeting specific properties within this product.
collection_listcollection-list-refReference to a collection list for including specific collections (programs, shows) within this product.
collection_list_excludecollection-list-refReference to a collection list for excluding specific collections (programs, shows) from this product.
age_restrictionobjectAge restriction for compliance.
device_platformdevice-platform[]Restrict to specific platforms.
device_typedevice-type[]Restrict to specific device form factors.
device_type_excludedevice-type[]Exclude specific device form factors from delivery (e.g., exclude CTV for app-install campaigns).
store_catchmentsobject[]Target users within store catchment areas from a synced store catalog.
geo_proximityobject[]Target users within travel time, distance, or a custom boundary around arbitrary geographic points.
languagestring[]Restrict to users with specific language preferences.
keyword_targetsobject[]Keyword targeting for search and retail media platforms.
negative_keywordsobject[]Keywords to exclude from delivery.

format

Represents a creative format with its requirements

format fields — 20 fields, 2 required
FieldTypeRequiredDescription
format_idformat-idrequiredThis format's own identifier — a structured object {agent_url, id}, not a string.
namestringrequiredHuman-readable format name
descriptionstringPlain text explanation of what this format does and what assets it requires
example_urlstringOptional URL to showcase page with examples and interactive demos of this format
accepts_parametersformat-id-parameter[]List of parameters this format accepts in format_id.
rendersobject[]Specification of rendered pieces for this format.
assetsany[]Array of all assets supported for this format.
deliveryobjectDelivery method specifications (e.g., hosted, VAST, third-party tags)
supported_macrosany[]List of universal macros supported by this format (e.g., MEDIA_BUY_ID, CACHEBUSTER, DEVICE_ID).
input_format_idsformat-id[]**DEPRECATED in 3.1.
output_format_idsformat-id[]**DEPRECATED in 3.1.
format_cardobjectOptional standard visual card (300x400px) for displaying this format in user interfaces.
accessibilityobjectAccessibility posture of this format.
supported_disclosure_positionsdisclosure-position[]Disclosure positions this format can render.
disclosure_capabilitiesobject[]Structured disclosure capabilities per position with persistence modes.
format_card_detailedobjectOptional detailed card with carousel and full specifications.
reported_metricsavailable-metric[]Metrics this format can produce in delivery reporting.
pricing_optionsvendor-pricing-option[]**DEPRECATED in 3.1.
canonicalcanonical-projection-refOptional v2 canonical-projection annotation.
canonical_parametersproduct-format-declaration**DEPRECATED in 3.1.

pricing-option

A pricing model option offered by a publisher for a product.

A oneOf across the pricing models, discriminated by pricing_model, so it has no flat field list. Merging the branches describes an object that cannot validate.

error

Standard error structure for task-specific errors and warnings

error fields — 10 fields, 2 required
FieldTypeRequiredDescription
codestringrequiredError code for programmatic handling.
messagestringrequiredHuman-readable error message
fieldstringField path associated with the error in JSONPath-lite format (e.g., 'packages[0].targeting').
suggestionstringSuggested fix for the error
retry_afternumberSeconds to wait before retrying the operation.
issuesobject[]Structured list of validation failures.
detailsobjectAdditional task-specific error details.
recoverystringAgent recovery classification. One of: transient, correctable, terminal.
sourcestringWho emitted this error entry. One of: producer, sdk.
sdk_idstringOptional identifier for the SDK that augmented this error entry.

brand-ref

Reference to a brand by domain and optional brand_id.

brand-ref fields — 5 fields, 1 required
FieldTypeRequiredDescription
domainstringrequiredDomain where /.well-known/brand.json is hosted, or the brand's operating domain
brand_idbrand-idBrand identifier within the house portfolio.
industriesstring[]Inline override for the brand's industries.
data_subject_contestationobjectInline override for the brand's contestation contact point.
brand_kit_overrideobjectInline override for brand-kit fields normally resolved from `/.well-known/brand.json` on `domain` (logo, colors, voice, tagline).

account-ref

Reference to an account by seller-assigned ID or natural key.

A oneOf across an account_id form and a brand plus operator natural key, so it has no flat field list. Merging the branches describes an object that cannot validate.

A client author's checklist

Frequently asked

Where are the AdCP schemas?
Under dist/schemas/<version>/ in the protocol repository. dist/schemas/latest.json is the pointer, and it carries five keys: latest, latest_stable, channel, path and index. Read whichever release it names. static/schemas/source/ is the build input and ships neither the bundled/ copies nor manifest.json.
How do AdCP schemas reference each other?
By absolute, version-pinned URL path, such as /schemas/<version>/media-buy/get-products-request.json. Every reference in a published release includes the version segment and every reference in the source tree omits it, so a resolver written against one tree fetches paths that do not exist in the other.
Should an AdCP client read index.json or manifest.json?
Both. index.json resolves the schemas and is the only file carrying both list_creative_formats variants. manifest.json is the only place the mutating flag, the specialism tags, the async response arms and error_code_policy exist. Each names operations the other omits, so the real operation list is the union of the two.
Does index.json list every AdCP schema in the release?
No. Some schemas have no index entry and no inbound $ref from anywhere in the release, including every file in error-details/ and every file in core/async-response-refs/. Others are absent from the index but still reachable, such as the canonical format schemas two hops down from core/product-format-declaration.json.

Related