Skip to content

Normalize pricing_options[].modelpricing_model (creative vs product discriminator naming) #3085

Description

@bokelley

Issue: normalize pricing_options[].modelpricing_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.jsonproducts[].pricing_options[].pricing_model
  • creative/list-creatives-response.jsoncreatives[].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:

  1. 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).
  2. AJV/strict-validation environments reject the response with /creatives/0/pricing_options/0/model: must have required property 'model'.
  3. 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).

Metadata

Metadata

Assignees

No one assigned

    Labels

    claude-triagedIssue has been triaged by the Claude Code triage routine. Remove to re-triage.rfcProtocol change — auto-adds to roadmap board

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    Status
    Shipped

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions