Repository navigation
Description
What kind of change?
Change a field's type or shape
Which section?
5.6 — Commercial terms
Current text
| `cancellation_policy` | Object | selectable | `available[]` of cancellation rights with `pricing` per option |
| `exclusivity` | Object | selectable | `available[]` of exclusivity terms with `pricing` |Proposed text
§ 5.6, replace the two rows, and add § 5.6.6 and § 5.6.7:
| `cancellation_policy` | Selectable[CancellationOption] | OPTIONAL | selectable | See § 5.6.6. Absent: this field states no right to cancel, and `terms_refs[]` (§ 5.8) may state one |
| `exclusivity` | Selectable[ExclusivityOption] | OPTIONAL | selectable | See § 5.6.7. Nothing in effect: no exclusivity |
#### 5.6.6 Cancellation option
**`CancellationOption`** keys:
| Key | Type | Required | Meaning |
| :--- | :--- | :--- | :--- |
| `id` | String | REQUIRED | Option id (§ 3.1) |
| `notice_duration` | Duration | REQUIRED | Time from notice received to the earliest effective date: `P14D` is 14 days, `P0D` immediate |
| `max_share` | Fraction | REQUIRED | Cancellable share of the remaining commitment. `0`: non-cancellable |
| `fees[]` | Array[Fee] | REQUIRED | The fee, by how long before the reference date notice arrives. MUST be non-empty |
| `notice_reference` | VocabularyTerm | OPTIONAL | The date `before_reference` counts to. Core terms: `flight` (default) \| `install_date`. `flight`: `commitment.flight.start`. `install_date`: the posting or install date. No key in the record holds that date, so a fee that counts to it can't be computed from the record |
| `dated_shares[]` | Array[DatedShare] | OPTIONAL | Dates with their own `max_share`. Outside every entry's `window`, the top-level `max_share` applies |
**`Fee`** keys:
| Key | Type | Required | Meaning |
| :--- | :--- | :--- | :--- |
| `before_reference` | Duration | OPTIONAL | Default `P0D`. Measured from notice received to the `notice_reference` date, or to the `window.start` of the `dated_shares[]` entry that applies. The entry with the longest `before_reference` the notice meets applies; notice that meets none takes the shortest |
| `calculation` | Enum | REQUIRED | `none` \| `cancelled` \| `commitment` \| `fixed`. `none`: no fee. `cancelled`: `share` of the cancelled amount. `commitment`: `share` of `commitment.amount` without `delta_flat` charges, whatever has been delivered. `fixed`: `amount` |
| `share` | Fraction | REQUIRED when `calculation` is `cancelled` or `commitment` | The fee as a share |
| `amount` | Amount | REQUIRED when `calculation` is `fixed` | The fee as money |
**`DatedShare`** keys. An entry applies when the effective date falls in its `window`.
Notice then counts to `window.start`.
| Key | Type | Required | Meaning |
| :--- | :--- | :--- | :--- |
| `window` | Interval | REQUIRED | The dates it covers. An option's windows don't overlap |
| `max_share` | Fraction | REQUIRED | Cancellable share of the remaining commitment when this entry applies |
The effective date is the later of the date the buyer asks for and notice received
plus `notice_duration`. The remaining commitment is `commitment.amount`, without
`delta_flat` charges, less delivery (§ 5.6.5) through the effective date; the
cancelled amount is the part of it the buyer cancels, up to the `max_share` that
applies. These, and the base of a `commitment` fee, are money (§ 5.6): units and days
are valued as § 5.6.5 values delivery. The buyer owes that delivery, `production`
(§ 5.4) work completed by then, and the fee.
Exercise happens downstream (§ 1.1), against the option in effect. An entry's
`cancellation` (§ 4.4) records the notice. It changes no term, and the line item's
`status` stays `agreed`.
**`CancellationNotice`** keys:
| Key | Type | Required | Meaning |
| :--- | :--- | :--- | :--- |
| `option_id` | String | REQUIRED | The `id` of the option in effect that the notice exercises |
| `notice_received_at` | Instant | REQUIRED | When the seller received notice |
| `requested_effective_at` | Instant | REQUIRED | The effective date the buyer asks for |
| `cancelled_share` | Fraction | REQUIRED | The share of the remaining commitment cancelled, up to the `max_share` that applies |
#### 5.6.7 Exclusivity option
**`ExclusivityOption`** keys:
| Key | Type | Required | Meaning |
| :--- | :--- | :--- | :--- |
| `id` | String | REQUIRED | Option id (§ 3.1) |
| `scope` | Enum | REQUIRED | `category` \| `sole`. `category`: no other advertiser in `categories`. `sole`: no other advertiser |
| `categories` | TaxonomyCodes | REQUIRED when `scope` is `category` | `taxonomy` per AdCOM 1.0 List: Category Taxonomies. An id covers its descendants |
| `competitors[]` | Array[RegistrableDomain] | OPTIONAL | Advertiser domains also excluded |
| `separation` | VocabularyTerm | REQUIRED | Where the term holds. Core terms: `inventory` (all of this line item) \| `page` (each page) \| `pod` (each ad pod) \| `stream` (each content stream an ad server fills) \| `episode` (each podcast episode) \| `loop` (each DOOH screen's loop) |
| `window` | Interval | OPTIONAL | The dates the term holds, only where they fall inside `commitment.flight`. Default: the whole flight. With no overlap, the term holds on no date and the option's deltas still count (§ 5.6) |
A seller MUST decline a `commitment` whose term in effect conflicts with an
accepted term on the same inventory and dates.Why
§ 5.6 prices cancellation and exclusivity options but never defines an option. A buyer agent pays a delta for an id it can't evaluate. We keep the priced tiers and give each option a type.
The cancellation keys follow practice. The IAB/4A's Standard Terms and Conditions 3.0, § V(a), sets notice by line type: 14 days guaranteed, 7 non-guaranteed, 30 flat-fee or fixed placement. § V(a)(iv) keeps custom material owed. TV upfront options cancel a share per quarter, which dated_shares[] carries.
@clerongi, a seller, asks in #85, time-based cancellation penalties for OOH and DOOH fees that step at 60, 30, or 7 days before the start. fees[] takes that schedule. In OOH, notice often counts to the posting or install date, "because printed material and labor are already committed", so notice_reference follows @premesh's comment. Static OOH (#125) asks for the keys that would carry that date.
For exclusivity, Google Ad Manager competitive exclusion separates by page, pod, or stream. OpenRTB 2.6 cattax names the taxonomy, a value from AdCOM 1.0 List: Category Taxonomies. Separation units differ by channel, so separation is a VocabularyTerm, as cost_method is in our cost-method change request (#94).
For dominations, @premesh (OUTFRONT Media) asks on #93 for loop and location. loop is a core term, read against the screen loop in our DOOH properties change request (#96). location covers units outside the line item, and #96 gives a property a venue type, not a venue. So location waits on open question 6.
A cancellation applies downstream, as our agreed-baseline comment (#68) asks. Our pricing PR carries this text.
As drafted (§ 5.6):
sequenceDiagram
participant B as Buyer agent
participant S as Seller
participant D as Downstream system
B->>S: cancel under option "notice-14d", effective 2026-12-07
S->>S: read agreed record: an id and a price delta
Note over S: effective date, share, fee: no defined keys
Note over S,D: nothing defined to apply downstream
Proposed:
sequenceDiagram
participant B as Buyer agent
participant S as Seller
participant D as Downstream system
B->>S: change request: cancellation under "notice-14d", effective 2026-12-07
S->>S: effective date = later of requested date and notice + P14D
S->>S: max_share and the fees[] entry read from the option
S->>D: apply: flight end, fee
Note over B,S: change_requests[] records the notice; agreed terms stay frozen
Details and examples: Cancellation and exclusivity terms: full rationale and examples
Knock-on effects
- Breaking: an option with ad-hoc keys, or without the REQUIRED keys, no longer conforms.
- § 6: the CTV line item offers three
notice_durationvalues. The audio line item has a stepped fee and priced exclusivity, and the issued proposal records a notice. - § 4.4, which our post-agreement PR adds: each
change_requests[]entry can carrycancellation, aCancellationNotice. § 5.6.5 Cost methods comes with our pricing PR. - The conflict rule uses the seller decline in our lifecycle PR, which lists an exclusivity conflict among the allowed grounds. Separating competitors who bought without a term stays with the ad server.
Open questions for the working group
- Should the summary representation in § 2.1 Summary and full representations show whether a line item is cancellable? It could show the included option's
notice_duration, or both fields could stay out of the summary. - When notice arrives too late for the requested date, should the effective date move? IAB/4A's Standard Terms and Conditions 3.0, § V(a) moves it, and so does this change. Or should a seller be able to charge a short-notice fee instead?
- Should the cancellation option carry a
short_ratekey for the short rates in IAB/4A's Standard Terms and Conditions 3.0, § V(c), and a force majeure flag? Or should both stay in the legal terms thatterms_refs[]points to, per relationship and contract references (#27)? - Answered in our shared types PR. Should these category ids and the prefixed strings in buyer-supplied block lists (#25), such as
"IAB-CT3.0:<id>", share one form with audience taxonomy ids? Our change request on audience disclosure (#97) asks for that. Category ids here and in block lists shareTaxonomyCodes { taxonomy, ids[] }. In our audience PR, an audience option also names its taxonomy with an integer, from the OpenRTB segment taxonomies list. Itsdata_labelcarries the ids. - Answered in part in our parties PR: To separate competitors who bought without a term at serve time, should the buyer declare its advertiser domain and category? These are
adomainandcatin OpenRTB 2.6 Object: Bid. They could go inassets[]under § 5.4 Creative requirements, or stay with the creative downstream. @EvgenyAndroid's advertiser identity feedback (#126) noted that no field named the advertiser a commitment is for.commitment.advertisers[]names it by domain, which compares withcompetitors[]. Still open: the advertiser's category, and whether the seller reads either at serve time. - Answered in part by @premesh on this change request: Should one exclusivity term, scoped by location, live at the proposal or package level? Line items would reference it, as @premesh suggests on #93. A domination sold as several line items would then share one term, so their terms can't drift apart in negotiation. That term would name the venue that
locationseparation needs. Open question 3 on static OOH (#125) asks how static and digital line items reference each other. It has to fit the no-inheritance rule (§ 2), the proposal's binding terms (OQ-5 — Is amin_line_itemsfield needed? (#6)), and line-item dependencies (#23). From the seller side, yes.location"needs a scope that can sit across line items", so "the term lives at proposal or package level, with line items referencing itsid". Their comment on #6 adds that station dominations are bundles bought whole, and backs [Change] § 2, § 4.1, § 5.6 — Line-item dependencies and bonus lines (linked_execution, requires) #23'slinked_execution: allfor them. Still open: how the term fits the no-inheritance rule, and how it names a venue. - Should the text state the cancellation and exclusivity rules we left out? The rules issue lists them.
Would this break an implementation already built to this draft?
Yes — breaking
Alternatives you considered and rejected
A fixed exclusivity attribute loses the tiers. A terms_refs[] document (#27) isn't machine-evaluable.
You are commenting as
Other — IAB Tech Lab member (Postindustria).
Before you submit
- I have read CONTRIBUTING.md and agree my contribution may be published under this repository's licence.
- This contains no confidential or commercially sensitive information.
Revised 2026-11-03: Rewritten to the names and types in our pricing PR, with the notice recorded in change_requests[]. Question 4 is answered and question 5 in part; question 7 is new.
Analyzed and generated with the help of Claude, fully reviewed by me.
Activity
premesh commentedon Oct 27, 2026
The separation values are all web, CTV and audio constructs. For OOH, an exclusivity term needs two more:
loop: no competitor in the same digital loop on the covered screens. This is what a DOOH category exclusive usually means.location: no competitor on any face at the venue or site, static or digital. This is what a station or venue domination sells.locationneeds a scope that can sit across line items, since a domination is usually an ooh and a dooh line item together (see my reply on #93 OQ7). That suggests the term lives at proposal or package level, with line items referencing itsid.On notice: OOH cancellation is commonly measured against the posting or install date, not just the flight start, because printed material and labor are already committed. A
notice_reference: flight_start | install_datekey would cover it.