Issue: normalize pricing_options[].model → pricing_options[].pricing_model
Repo: adcontextprotocol/adcp
Type: schema / breaking-track-additive
Severity: medium (causes recurring drift in implementations)
Target: 3.x minor (additive) → 4.0 major (rename-only)
Problem
The same compound noun pricing_options[] carries two different discriminator field names depending on whose subtree it appears in:
media-buy/get-products-response.json → products[].pricing_options[].pricing_model
creative/list-creatives-response.json → creatives[].pricing_options[].model
Both are oneOf discriminators with overlapping enum values (cpm, flat_fee, percent_of_media, per_unit, custom). The two schemas were authored independently; the asymmetry survives because nobody re-reads adjacent schemas side-by-side.
This is a recurring source of implementation drift. We've observed:
- SDK-built agents and human-written adapters omit
model on creative pricing options because they pattern-match from the products surface (where the field is pricing_model).
- AJV/strict-validation environments reject the response with
/creatives/0/pricing_options/0/model: must have required property 'model'.
- LLM-driven implementations (which read the spec once into context) routinely conflate the two — Claude-built agents in our
@adcp/client skill matrix get this wrong on a majority of creative_ad_server storyboard runs.
OpenRTB has been chastised for the same pattern (bidfloor vs floor historically). It's worth fixing while AdCP is still inside the early-3.x window.
Proposal
Rename creative/list-creatives-response.json:creatives[].pricing_options[].model to pricing_model. Match the products surface.
Backwards compatibility:
- 3.x minor cycle: accept both field names. Schema becomes
oneOf over model (deprecated, still valid) and pricing_model (preferred). Validators treat pricing_model as canonical when both are present.
- 4.0: remove
model.
Authoring rationale for picking pricing_model (not model):
- More discoverable in IDE autocomplete (longer, less ambiguous).
- Already the established name in the products surface, which buyers see first in most flows.
model is too generic — could conflict with future fields (model name, AI model id, etc.).
Files affected
schemas/v3/creative/list-creatives-response.json (lines defining pricing_options[].model)
- Any
bundled/ outputs derived from it
- Doc references in
docs/v3/creative/list_creatives.md and any examples
- llms.txt entries for
list_creatives
Validation
After the change, the cross-schema audit should pass: grep -r '"model"' schemas/v3/**/pricing_options* | grep -v pricing_model should return nothing.
Source
Surfaced during AdCP @adcp/client skill-matrix conformance runs (see adcontextprotocol/adcp-client issue #785) where this drift class accounts for ~25% of creative_ad_server storyboard failures. Independently confirmed by ad-tech protocol expert review.
Schema clarity grade for AdCP 3.0 discriminator consistency: B- (five of six discriminators consistent across domains; this is the one breaking the pattern).
Issue: normalize
pricing_options[].model→pricing_options[].pricing_modelRepo:
adcontextprotocol/adcpType: schema / breaking-track-additive
Severity: medium (causes recurring drift in implementations)
Target: 3.x minor (additive) → 4.0 major (rename-only)
Problem
The same compound noun
pricing_options[]carries two different discriminator field names depending on whose subtree it appears in:media-buy/get-products-response.json→products[].pricing_options[].pricing_modelcreative/list-creatives-response.json→creatives[].pricing_options[].modelBoth are
oneOfdiscriminators with overlapping enum values (cpm,flat_fee,percent_of_media,per_unit,custom). The two schemas were authored independently; the asymmetry survives because nobody re-reads adjacent schemas side-by-side.This is a recurring source of implementation drift. We've observed:
modelon creative pricing options because they pattern-match from the products surface (where the field ispricing_model)./creatives/0/pricing_options/0/model: must have required property 'model'.@adcp/clientskill matrix get this wrong on a majority ofcreative_ad_serverstoryboard runs.OpenRTB has been chastised for the same pattern (
bidfloorvsfloorhistorically). It's worth fixing while AdCP is still inside the early-3.x window.Proposal
Rename
creative/list-creatives-response.json:creatives[].pricing_options[].modeltopricing_model. Match the products surface.Backwards compatibility:
oneOfovermodel(deprecated, still valid) andpricing_model(preferred). Validators treatpricing_modelas canonical when both are present.model.Authoring rationale for picking
pricing_model(notmodel):modelis too generic — could conflict with future fields (model name, AI model id, etc.).Files affected
schemas/v3/creative/list-creatives-response.json(lines definingpricing_options[].model)bundled/outputs derived from itdocs/v3/creative/list_creatives.mdand any exampleslist_creativesValidation
After the change, the cross-schema audit should pass:
grep -r '"model"' schemas/v3/**/pricing_options* | grep -v pricing_modelshould return nothing.Source
Surfaced during AdCP
@adcp/clientskill-matrix conformance runs (seeadcontextprotocol/adcp-clientissue #785) where this drift class accounts for ~25% ofcreative_ad_serverstoryboard failures. Independently confirmed by ad-tech protocol expert review.Schema clarity grade for AdCP 3.0 discriminator consistency: B- (five of six discriminators consistent across domains; this is the one breaking the pattern).