Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .github/workflows/validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,14 @@ jobs:
python-version: "3.12"
- name: Check every field in the body appears in Appendix A
run: python3 scripts/check_appendix.py

examples-match-spec:
name: Examples match the tables
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- run: pip install pyyaml
- run: python3 scripts/check_examples.py
22 changes: 11 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ server.
| :--- | :--- |
| **Current draft** | [`spec/openproposal-3.0.md`](spec/openproposal-3.0.md) |
| **Comment period opens** | 2026-09-22 |
| **Comment period closes** | 2026-10-22 |
| **Comment period closes** | 2026-11-10 |
| **Announcement** | [IAB Tech Lab introduces AAMP 3.0 with OpenProposal](https://iabtechlab.com/press-releases/iab-tech-lab-introduces-aamp-3-0-with-openproposal/) |
| **Short link** | [iabtechlab.com/AAMPv3](https://iabtechlab.com/AAMPv3) (points to this repository) |
| **How to comment** | [CONTRIBUTING.md](CONTRIBUTING.md) |
Expand Down Expand Up @@ -56,7 +56,7 @@ Pick the route that matches what you have to say:
| :--- | :--- |
| Flag something unclear, wrong, or missing | [Open a **Comment**](https://github.com/IABTechLab/OpenProposal/issues/new?template=comment.yml) |
| Propose specific normative wording | [Open a **Change request**](https://github.com/IABTechLab/OpenProposal/issues/new?template=change-request.yml), or send a pull request against `spec/openproposal-3.0.md` |
| Answer one of the 7 open questions | Comment on that question's [tracking issue](docs/open-questions.md) |
| Answer one of the open questions | Comment on that question's [tracking issue](docs/open-questions.md) |
| Report what happened when you tried to implement it | [Open **Implementation feedback**](https://github.com/IABTechLab/OpenProposal/issues/new?template=implementation-feedback.yml) |
| Ask a question rather than raise an issue | Use [Discussions](https://github.com/IABTechLab/OpenProposal/discussions) |

Expand All @@ -69,15 +69,15 @@ in [docs/disposition-log.md](docs/disposition-log.md). See

Three things to understand before the field tables make sense:

1. **No inheritance.** Every line item is fully self-contained. A field never
1. **No inheritance.** Every term of a line item is on the line item. A field never
takes its value from the parent proposal or a sibling line item.
2. **Every field carries exactly one mutability marker** (§ 3) — `immutable`,
`seller-set`, `selectable`, `settable`, `supplied`, `requestable` or
`derived`. The marker is what tells a buying agent whether it can act
unilaterally.
3. **Composition is constraint satisfaction, not negotiation.** Of 71 fields,
only 3 require a round trip with the counterparty. That ratio is the design
claim the draft is asking you to test.
`seller-set`, `selectable`, `settable`, `supplied`, `requestable`, `derived`,
`lifecycle`, `recorded`, `asserted` or `mixed`. The marker is what tells a
buying agent whether it can act unilaterally.
3. **Composition is constraint satisfaction, not negotiation.** Only `requestable`
fields require a round trip with the counterparty to resolve. Appendix B has the
count. That ratio is the design claim the draft is asking you to test.

## Downstream standards

Expand All @@ -89,8 +89,8 @@ OpenRTB 2.6). See § 1.1.

Machine-readable schemas are coming. They are not published with this first
draft, because the comment period is still deciding questions that shape
them. They will follow the first revision, after the comment period closes on
2026-10-22. Until then, [`examples/`](examples/) is the best reference for
them. They will follow the first revision, after the comment period closes.
Until then, [`examples/`](examples/) is the best reference for
shape. See [schema/README.md](schema/README.md).

## Contributors and governance
Expand Down
8 changes: 4 additions & 4 deletions docs/comment-process.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ or a documented decision not to change it.
| Phase | Dates | What happens |
| :--- | :--- | :--- |
| **1. Comment period opens** | 2026-09-22 | Draft frozen at a tagged version. Announcement published. Issues open. |
| **2. Comment period** | 2026-09-22 → 2026-10-22 (30 days) | Anyone may file. Maintainers triage and label within 5 business days of filing, but do not resolve. |
| **3. Comment period closes** | 2026-10-22 | No new comments enter the formal record. Later issues are labelled `post-comment` and considered for the following draft. |
| **2. Comment period** | 2026-09-22 → 2026-11-10 | Anyone may file. Maintainers triage and label within 5 business days of filing, but do not resolve. |
| **3. Comment period closes** | 2026-11-10 | No new comments enter the formal record. Later issues are labelled `post-comment` and considered for the following draft. |
| **4. Adjudication** | `TBD` → `TBD` | Working group works the queue. Every open comment gets a disposition. |
| **5. Disposition published** | `TBD` | [disposition-log.md](disposition-log.md) published in full. Commenters notified on their issue. |
| **6. Revised draft** | `TBD` | New draft tagged. Either ratification or a second comment period, depending on how much moved. |

> **Maintainers: phases 4–6 are still `TBD`.** Fill them before the comment
> period closes on 2026-10-22.
> period closes.

## Dispositions

Expand Down Expand Up @@ -59,7 +59,7 @@ Triage labels, applied on filing:
| :--- | :--- |
| `comment` | General comment on the draft |
| `change-request` | Proposes specific normative wording |
| `open-question` | Relates to one of the 7 questions in § 8 |
| `open-question` | Relates to one of the questions in § 8 |
| `implementation-feedback` | From someone who built against the draft |
| `editorial` | Typo, formatting, broken link — no normative effect |
| `normative` | Changes what the spec requires |
Expand Down
2 changes: 1 addition & 1 deletion docs/disposition-log.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
The formal record of every comment filed during the OpenProposal 3.0 public
comment period, and what was decided.

**Status: comment period open (2026-09-22 → 2026-10-22). No dispositions yet.**
**Status: comment period open (2026-09-22 → 2026-11-10). No dispositions yet.**

This file is updated as comments are adjudicated and published in full at the
end of the period. See [comment-process.md](comment-process.md) for what each
Expand Down
35 changes: 17 additions & 18 deletions docs/open-questions.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,14 @@ whether resolving inside one is worth the modelling cost.

---

### OQ-2 — Do seller catalogs (`catalog_ref`) belong in 3.0?
### OQ-2 — Is a fetchable reference to a seller catalog needed?

**Issue:** [#3](https://github.com/IABTechLab/OpenProposal/issues/3) · **Spec:** § 2.2
**Issue:** [#3](https://github.com/IABTechLab/OpenProposal/issues/3) · **Spec:** § 2.1

Or should the object stay fully inline until a later version? `catalog_ref`
buys compactness across a large shelf at the cost of a resolution step during
discovery and a versioning regime sellers must operate.
The object is fully inline. A seller reuses catalog entries in its own systems, and
a summary lists what § 2.1 names. A reference a buyer could fetch would buy
compactness across a large shelf at the cost of a fetch rule, a resolution step
during discovery, and a versioning regime sellers must operate.

**What would settle it:** how large a real shelf gets, and whether sellers
already maintain versioned, immutable catalog entries or would have to build
Expand Down Expand Up @@ -65,39 +66,37 @@ proposed fallback behaviour.

---

### OQ-5 — Is a `min_line_items` field needed?
### OQ-5 — Do `linked_execution` and `requires` cover bundle purchases?

**Issue:** [#6](https://github.com/IABTechLab/OpenProposal/issues/6) · **Spec:** § 2, § 4

The draft makes proposals subsettable unless binding terms mandate linked
execution. Does the proposal need an explicit `min_line_items` to require a
bundle purchase, or is that left to buyer discretion and the binding terms?
The draft makes proposals subsettable unless `linked_execution` is `all`, and a line
item can state `requires`. Does the proposal also need a `min_line_items` field?

**What would settle it:** whether sellers actually merchandise bundles that must
be bought whole, and whether "binding terms" is a precise enough hook.
**What would settle it:** whether sellers merchandise a bundle these two fields
can't express.

---

### OQ-6 — Should `payment_terms` and `invoicing_party` be catalog references?
### OQ-6 — Should `payment_terms` and `invoicing_party` repeat on every line item?

**Issue:** [#7](https://github.com/IABTechLab/OpenProposal/issues/7) · **Spec:** § 5.10

Rather than repeated on every line item, given they are usually identical across
a seller's shelf. Note this is in tension with the no-inheritance rule (§ 2) —
a `catalog_ref` is explicitly not inheritance, but the ergonomics are similar.
They are usually identical across a seller's shelf. Note this is in tension with the
no-inheritance rule (§ 2): sharing them would need another mechanism.

**What would settle it:** whether `billing` genuinely varies per line item in
practice (different supplier of record, different invoicing entity per
property).

---

### OQ-7 — `environments[]` needs validation against real inventory
### OQ-7 — `environments.available[]` needs validation against real inventory

**Issue:** [#8](https://github.com/IABTechLab/OpenProposal/issues/8) · **Spec:** § 5.2

The enum — `web_desktop`, `web_mobile`, `app_mobile`, `ctv`, `dooh`,
`audio_streaming` — is proposed, not derived from implementation experience.
The enum — `web_desktop`, `web_mobile`, `app_mobile`, `ctv`, `dooh`, each
defined in § 5.2.1 — is proposed, not derived from implementation experience.

**What would settle it:** sellers mapping their real inventory onto the enum and
reporting what does not fit.
Expand Down
19 changes: 10 additions & 9 deletions examples/line-item-audio.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,19 @@
line_item_id: "streaming-audio"
status: published
channel: audio
environments: { available: ["audio_streaming"], included: ["audio_streaming"] }
environments: { available: ["web_mobile", "app_mobile"],
included: ["web_mobile", "app_mobile"] }
formats: { available: ["audio/host-read-30s", "audio/produced-30s"],
included: ["audio/produced-30s"],
pricing: { "audio/host-read-30s": { delta_cpm: 9.00 } } }
deltas: { "audio/host-read-30s": { delta_cpm: 9.00 } } }

production:
available: [{ id: "seller_built", build_owner: seller, lead_time: "10 business days" },
{ id: "buyer_supplied", build_owner: buyer, lead_time: "0" }]
available: [{ id: "seller_built", build_owner: seller, lead_time: "P14D" },
{ id: "buyer_supplied", build_owner: buyer, lead_time: "P0D" }]
included: ["buyer_supplied"]
pricing: { seller_built: { delta_flat: 12000.00 } }
deltas: { seller_built: { delta_flat: 12000.00 } }

frequency_cap: { max: { min: 1, max: 6 }, period: "day", basis: listener }
frequency_cap: { count: { min: 1, max: 6 }, period: day, per: listener }

pricing:
- { cost_method: CPM, gross_rate: 18.00, floor: 15.84,
Expand All @@ -24,12 +25,12 @@ commitment:
basis: spend
amount: 60000.00
currency: USD
flight_start: "2026-10-06"
flight_end: "2026-12-21"
flight: { start: "2026-10-06T00:00:00Z", end: "2026-12-21T23:59:59Z" }
idempotency_key: "agency-a-camp1-streaming-audio-a7c33e10"

committed_metrics: [{ metric: completion_rate, value: 0.92, basis: seller_reported }]
visibility: public
buying_route: SSP_PLATFORM
transaction_mechanism: { available: ["PREFERRED_DEAL"], included: ["PREFERRED_DEAL"] }
transaction_mechanism: { available: ["preferred_deal"], included: ["preferred_deal"] }
serving_mode: dai
correlation_id: "ep-q4-2026-commitment/streaming-audio"
29 changes: 29 additions & 0 deletions examples/line-item-ctv-bonus.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# OpenProposal 3.0 — Example: Bonus line item (spec § 6.5)
# Illustrative only. A CTV bonus unlocked when the buyer commits to the display
# and CTV line items together, with at least 50,000 USD on display. Its price is
# its own: nothing is inherited from the line items it requires.
line_item_id: "weather-app-ctv-bonus"
status: published
channel: ctv
properties: { available: [{ id: "weather-app" }], included: ["weather-app"] }
environments: { available: ["ctv"], included: ["ctv"] }
formats: { available: ["ctv/instream-15s"], included: ["ctv/instream-15s"] }
creative_delivery: { method: seller_hosted, protocol: vast_4_2, secure_required: true }

frequency_cap: { count: { min: 1, max: 2 }, period: day, per: household }

requires:
all_of: ["business-daily-display", "weather-app-ctv"]
min_commitments:
- { line_item_id: "business-daily-display", basis: spend, amount: 50000.00, currency: USD }

pricing:
- { cost_method: FLAT, gross_rate: 0.00,
price_valid_until: "2026-12-01T23:59:59Z", currency: USD }

commitment_bounds: { max_impressions: 500000 }

visibility: registry_gated # its requires names the gated display line item
buying_route: SSP_PLATFORM
transaction_mechanism: { available: ["private_auction"], included: ["private_auction"] }
serving_mode: ssai
12 changes: 7 additions & 5 deletions examples/line-item-ctv.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ properties: { available: [{ id: "weather-app" }], included: ["weather-app"]
environments: { available: ["ctv"], included: ["ctv"] }
formats: { available: ["ctv/instream-15s", "ctv/instream-30s"],
included: ["ctv/instream-15s"],
pricing: { "ctv/instream-30s": { delta_cpm: 8.00 } } }
deltas: { "ctv/instream-30s": { delta_cpm: 8.00 } } }
creative_delivery: { method: seller_hosted, protocol: vast_4_2, secure_required: true }

frequency_cap: { max: { min: 1, max: 4 }, period: "day", basis: household }
frequency_cap: { count: { min: 1, max: 4 }, period: day, per: household }

pricing:
- { cost_method: CPM, gross_rate: 45.00, floor: 39.60,
Expand All @@ -20,16 +20,18 @@ commitment:
basis: spend
amount: 160000.00
currency: USD
flight_start: "2026-10-06"
flight_end: "2026-12-21"
flight: { start: "2026-10-06T00:00:00Z", end: "2026-12-21T23:59:59Z" }
idempotency_key: "agency-a-camp1-weather-app-ctv-3b7e0d52"

hold_status: { hold_available: true, hold_duration: "P14D",
hold_scope: line_item, state: held,
hold_expires_at: "2026-10-01T00:00:00Z" }

committed_metrics: [{ metric: completion_rate, value: 0.95, basis: seller_reported }]
visibility: public
buying_route: SSP_PLATFORM
transaction_mechanism: { available: ["PRIVATE_AUCTION"], included: ["PRIVATE_AUCTION"] }
transaction_mechanism: { available: ["private_auction"], included: ["private_auction"] }
serving_mode: ssai
correlation_id: "ep-q4-2026-commitment/weather-app-ctv"

# Inspecting this line item's VAST creative is subject to § 5.4.1.
37 changes: 18 additions & 19 deletions examples/line-item-display.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# OpenProposal 3.0 — Example: Display line item, fully worked (spec § 6.2)
# Shows selectable audiences with per-option pricing, a catalog reference,
# a buyer commitment, and settable bounds.
# Shows selectable audiences with per-option pricing, a buyer commitment, and
# settable bounds.
line_item_id: "business-daily-display"
status: published
channel: display
Expand All @@ -9,7 +9,7 @@ properties:
available: [{ id: "business-daily", domains: ["business-daily.example"] },
{ id: "markets-weekly", domains: ["markets-weekly.example"] }]
included: ["business-daily"]
pricing: { markets-weekly: { delta_cpm: 2.00 } }
deltas: { markets-weekly: { delta_cpm: 2.00 } }
max_select: 2

environments:
Expand All @@ -18,20 +18,20 @@ environments:

audiences:
available:
- catalog_ref: "examplepub/audiences/smb-decision-makers@3"
- { id: "ep:smb-decision-makers", provenance: first_party, addressable_scale: 2600000 }
- { id: "ep:hnw-investors", provenance: modeled, addressable_scale: 1100000 }
- { id: "ep:cfo-finance-leaders", provenance: first_party, addressable_scale: 480000 }
included: ["ep:smb-decision-makers"]
pricing: { "ep:hnw-investors": { delta_cpm: 4.00 },
deltas: { "ep:hnw-investors": { delta_cpm: 4.00 },
"ep:cfo-finance-leaders": { delta_cpm: 6.50 } }
max_select: 2

addressable_scale: 3200000 # derived; recomputed on selection
addressable_scale: 3200000 # asserted; recomputed on selection

activation_route:
available: ["publisher_side", "clean_room"]
included: ["publisher_side"]
pricing: { clean_room: { delta_cpm: 1.50 } }
deltas: { clean_room: { delta_cpm: 1.50 } }

buyer_supplied:
segments_allowed: true
Expand All @@ -42,13 +42,13 @@ buyer_supplied:
formats:
available: ["display/300x250", "display/728x90", "display/970x250"]
included: ["display/300x250"]
pricing: { "display/970x250": { delta_cpm: 3.00 } }
deltas: { "display/970x250": { delta_cpm: 3.00 } }

creative_delivery: { method: buyer_hosted, protocol: javascript_tag, secure_required: true }
materials_due: "2026-09-24"
materials_due: { at: "2026-09-24T23:59:59Z" }

geo: { allowed: ["US-NY", "US-CA", "US-IL", "US-TX"] }
frequency_cap: { max: { min: 1, max: 5 }, period: "day", basis: device }
frequency_cap: { count: { min: 1, max: 5 }, period: day, per: device }

pricing:
- cost_method: CPM
Expand All @@ -65,8 +65,7 @@ commitment:
basis: spend
amount: 80000.00
currency: USD
flight_start: "2026-10-06"
flight_end: "2026-12-21"
flight: { start: "2026-10-06T00:00:00Z", end: "2026-12-21T23:59:59Z" }
derived_units: 3333333 # derived: 80000.00 / 24.00 × 1000
idempotency_key: "agency-a-camp1-business-daily-display-8f42c1a9"

Expand All @@ -76,23 +75,23 @@ hold_status: { hold_available: true, hold_duration: "P7D",
committed_metrics:
- { metric: viewable_rate, value: 0.70, basis: mrc }
measurement_source:
available: [{ vendor: "IAS", attribution_window: "30d" },
{ vendor: "DoubleVerify", attribution_window: "30d" }]
available: [{ vendor: "IAS", attribution_window: "P30D" },
{ vendor: "DoubleVerify", attribution_window: "P30D" }]
included: ["IAS"]
shortfall_remedy: { available: ["makegood", "credit"], included: ["makegood"] }
reporting:
available: [{ feed_type: aggregate, cadence: daily, delivery_mechanism: api },
{ feed_type: log_level, cadence: daily, delivery_mechanism: s3 }]
available: [{ feed_type: aggregate, cadence: day, delivery_mechanism: api },
{ feed_type: log_level, cadence: day, delivery_mechanism: s3 }]
included: ["aggregate"]
pricing: { log_level: { delta_flat: 2500.00 } }
deltas: { log_level: { delta_flat: 2500.00 } }

visibility: registry_gated
required_credentials: [{ type: dsp_seat, scheme: jwt_keypair,
issuer: "dsp-a", id_required: true }]

buying_route: PUBLISHER_AD_SERVER
transaction_mechanism: { available: ["PROGRAMMATIC_GUARANTEED", "PREFERRED_DEAL"],
included: ["PROGRAMMATIC_GUARANTEED"] }
transaction_mechanism: { available: ["programmatic_guaranteed", "preferred_deal"],
included: ["programmatic_guaranteed"] }
serving_mode: client_side
buyer_requirements: { seat_required: true, dsp_allowed: ["dsp-a", "dsp-b"],
dsp_seat_id: "seat-99812", dsp_id: "dsp-a-prod",
Expand Down
Loading