Skip to content

feat: add price_breakdown schema for pricing transparency#1594

Merged
bokelley merged 6 commits into
mainfrom
bokelley/price-breakdown-schema
Mar 25, 2026
Merged

feat: add price_breakdown schema for pricing transparency#1594
bokelley merged 6 commits into
mainfrom
bokelley/price-breakdown-schema

Conversation

@bokelley

@bokelley bokelley commented Mar 20, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds an optional price_breakdown object to all pricing options and packages, enabling sellers to disclose how fixed_price was derived from the rate card (list_price) through adjustments.

Motivation

Driven by DBCFM (German standard) mapping gaps and Swiss market requests. Sellers who need to express multi-step price calculations (rate card → fees → discounts → commissions → settlement terms) currently must use ext objects, making them unreadable by other AdCP-compliant systems.

Design

Four adjustment kinds based on their economic effect:

Kind Effect on buyer price Effect on publisher revenue
fee Increases it Increases it
discount Reduces it Reduces it
commission None — budget includes it Reduces it (revenue split)
settlement None — post-invoice Reduces actual payment

Key invariant: list_price with all fee and discount adjustments applied sequentially = fixed_price. Fees increase the running price; discounts reduce it. All monetary values rounded to currency precision at each step.

Budgets are always denominated at the fixed_price level, inclusive of commissions. A buyer agent comparing rates across sellers uses fixed_price directly.

Optional beneficiary field on adjustments identifies who receives the value (sellers.json domain, AdCP account ID, or party name) for multi-intermediary transparency.

Changes

New schemas:

  • enums/adjustment-kind.json — four-value enum: fee, discount, commission, settlement
  • pricing-options/price-breakdown.json — breakdown object with list_price, ordered adjustments array, and optional beneficiary per adjustment

Modified schemas (added optional price_breakdown and eligible_adjustments):

  • All 9 pricing option schemas (CPM, vCPM, CPC, CPCV, CPV, CPP, CPA, flat-rate, time)
  • core/package.json (confirmed line item)

Documentation:

  • New "Price Breakdown", "Beneficiary", and "Eligible Adjustments" sections in pricing-models.mdx

Backward Compatibility

Fully backward-compatible. All new fields are optional. Sellers who don't need breakdowns omit price_breakdown entirely — zero overhead to existing implementations.

Test plan

  • Schema validation passes (415 schemas)
  • All 501 tests pass
  • TypeScript typecheck passes
  • Mintlify link check and accessibility scan pass
  • Ad tech protocol expert review — no OpenRTB conflicts, clean IAB alignment
  • Documentation expert review — invariant, examples, and formulas verified
  • Code review — schema correctness, draft-07 compliance confirmed
  • Security review — no vulnerabilities, defensive constraints added (maxItems, maxLength, exclusiveMinimum)

🤖 Generated with Claude Code

bokelley and others added 6 commits March 25, 2026 19:43
Adds an optional price_breakdown object to all pricing options and
packages, enabling sellers to disclose how fixed_price was derived
from the rate card (list_price) through adjustments.

Three adjustment kinds: discount (changes buyer price), commission
(revenue split only), and settlement (post-invoice terms like cash
discounts). Motivated by DBCFM mapping gaps and Swiss market
requests, but designed to be market-neutral.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Lets buyer agents discover which adjustment kinds (discount, commission,
settlement) apply to a pricing option before negotiation.

Driven by DBCFM gap analysis — DBCFM marks each rate with
discountable/commissionable/cash_discountable flags.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Schema: change rate maximum to exclusiveMaximum (100% discount is
nonsensical). Docs: clarify planning-layer scope (no OpenRTB
propagation), list_price is fully-loaded gross, mixed rate/amount
invariant example, separate fixed-price vs auction package examples,
commission compounding for multi-intermediary, rate/amount constraints,
forward compatibility note.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Docs: add explicit formulas for rate/amount application, currency-
precision rounding rule, zero-discount edge case (fixed_price must
equal list_price), auction list_price convention, rate range notation
(0 < rate < 1), seller-populated read-only note on packages, separate
eligible_adjustments example ID.

Schema: clarify invariant applies only when fixed_price is present,
add rounding rule to description.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds a fourth adjustment kind (fee) for additive costs like ad serving
fees, data/targeting surcharges, and brand safety verification. Without
this, these costs are opaque within list_price. The invariant is now:
list_price with fee and discount adjustments applied = fixed_price.

Adds optional beneficiary field on adjustments to identify who receives
the value (sellers.json domain, AdCP account ID, or party name).
Enables multi-intermediary transparency for commission reconciliation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@bokelley bokelley force-pushed the bokelley/price-breakdown-schema branch from 85a67e9 to 4f30010 Compare March 25, 2026 10:43
@github-actions

Copy link
Copy Markdown
Contributor

Schema Link Check Results

Commit: 4f30010 - feat: add fee kind and beneficiary field to price_breakdown

⚠️ Warnings (schema not yet released)

These schemas exist in source but haven't been released yet. The links will be broken until the next version is published:

  • https://adcontextprotocol.org/schemas/v3/enums/si-session-status.json
    • Schema exists in latest (source) but not yet released in v3
    • Action: This link will work after next 3.x release is published

To fix: Either:

  1. Wait for the next release and merge this PR after the release is published
  2. Use latest instead of a version alias if you need the link to work immediately (note: latest is the development version and may change)
  3. Coordinate with maintainers to cut a new release before merging

@bokelley bokelley enabled auto-merge (squash) March 25, 2026 11:03
@bokelley bokelley disabled auto-merge March 25, 2026 11:32
@bokelley bokelley merged commit 3f140cc into main Mar 25, 2026
15 checks passed
@bokelley bokelley deleted the bokelley/price-breakdown-schema branch March 25, 2026 11:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant