spec(media-buy): billing authority + finality flags for 3.1 (#2391 part 1)#4735
Conversation
… 3.1; disputes deferred to #4734) Closes the prerequisite half of #2391 — a buyer reading 3.1 can answer "where do I look for the billing-grade number, and has it stopped moving?" without any new tasks. Existing `measurement_terms.billing_measurement` already names authority; new finality flags on both reporting surfaces mark when numbers are closed for invoicing. - `get-media-buy-delivery-response.json`: row-level `is_final` + `finalized_at` on `media_buy_deliveries[*]`; `finalized_at` on `by_package[*]` next to existing `is_final`. - `report-usage-request.json`: `final` (default true), `finalized_at`, `measurement_window` on each usage record. Symmetric with seller-side. Description acknowledges sales-agent receivers for buyer-attested / vendor-attested reconciliation. - `measurement-terms.json`: optional `finalization_deadline_hours` on `billing_measurement`. Miss → seller MAY fall back to seller-attested and handle under `makegood_policy`. - `get_media_buy_delivery.mdx`: replace "3.0 does not specify a dispute task" punt with normative "Final vs provisional" + "Who is authoritative for billing" sections. - `billing-authority.mdx`: new normative page with worked examples (seller-attested, buyer-3PAS, vendor-attested Nielsen). - `docs.json`: register the new page. Strictly additive — no field shape changes, no new required fields. Agents that don't emit the new flags remain spec-valid; absent semantics match the 3.0 baseline. The structured dispute task that builds on this foundation is tracked as #4734 for 3.2. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…line anchor, consistency MUST Three expert reviews (protocol, ad-tech product, docs) on the initial commit surfaced two blockers and several small fixes. Addressing them in one follow-up commit: Blockers fixed: - `report_usage.final`: changed from "default true on absence" to "absent means unknown." The original default would have silently promoted every daily pacing push into an invoice trigger the moment a seller wired up this logic. Now: receivers MUST NOT invoice on absent for buys where `billing_measurement` names the reporter as authoritative. Non-media-buy variants (signals/governance/creative/ brand) MAY treat absent as final, preserving 3.0 semantics. - `finalization_deadline_hours`: replaced the ambiguous "reporting_period.end OR window close" anchor with a single rule — when `measurement_window` is set, hours count from window close; otherwise from `reporting_period.end`. The OR was a multi-day divergence on windowed channels. Also documented symmetry — the deadline applies to whichever party is named in `vendor`, not just the buyer. Small fixes: - `is_final` row-level: added normative MUST that sellers MUST NOT emit `is_final: true` at the row level unless every package is final for the same window; package-level is authoritative on disagreement. Tightened description (row doesn't carry its own `measurement_window`). - `billing-authority.mdx`: BrandRef link to `/docs/brand-protocol/brand-json` instead of glossary; struck reference to phantom `delivery_reporting.finalization_window_hours` capability (only existed in 3.0 doc text, never shipped as a schema field); added reality callouts on holdco/operator pushers, two vendor-attested patterns (seller-pulled vs buyer-pushed), SSP RTB realistically staying seller-attested; added section distinguishing webhook `notification_type: "final"` from row `is_final`. - `get_media_buy_delivery.mdx`: vendor-attested bullet rewritten to reflect two operational patterns; symmetric deadline language. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Expert review + follow-upRan three expert reviewers (protocol, ad-tech product, docs) on the initial commit. Two findings were merge-blockers; the rest were small fixes. All addressed in Blockers fixed:
Small fixes:
Deferred:
🤖 Generated with Claude Code |
Summary
Closes the prerequisite half of #2391 — a buyer reading the 3.1 spec can answer "where do I look for the billing-grade number, and has it stopped moving?" without any new tasks:
measurement_terms.billing_measurement.vendor(BrandRef) already names authority — seller's ad server, buyer's 3PAS, or named third-party vendor.finalization_deadline_hoursgives sellers a graceful fallback to seller-attested when the authoritative party misses the deadline.The structured dispute task that builds on this foundation is tracked as #4734 for 3.2 — the data shape needed to dispute (final records with timestamps, attestation, measurement window, makegood menu) is already on the wire after this PR.
Changes
get-media-buy-delivery-response.json— row-levelis_final+finalized_atonmedia_buy_deliveries[*];finalized_atonby_package[*]next to existingis_final.report-usage-request.json—final(defaulttruewhen absent — preserves existing semantics),finalized_at,measurement_windowon each usage record. Symmetric with seller-side. Description acknowledges sales-agent receivers for buyer-attested / vendor-attested reconciliation.measurement-terms.json— optionalfinalization_deadline_hoursonbilling_measurement. Missed deadline → seller MAY fall back to seller-attested and handle undermakegood_policy.get_media_buy_delivery.mdx— replaced "AdCP 3.0 does not specify a structured dispute task" punt with normative "Final vs provisional" + "Who is authoritative for billing" sections; flags dispute task for 3.2.billing-authority.mdx— new normative advanced-topics page with worked examples (seller-attested default, buyer-3PAS, vendor-attested Nielsen).docs.json— register the new page under media-buy → Concepts.Backward compatibility
Strictly additive — no field shape changes, no new required fields. Agents that don't emit the new flags remain spec-valid; absent semantics match the 3.0 baseline.
Design conversation
The design walked through several alternatives that landed in their current shape:
measurement_terms.billing_measurement.submit_billing_measurementfor routine third-party reconciliation → noticedreport_usagealready covers this and just needed the same finality flag the delivery side gets.Test plan
billing-authority.mdxrenders + nav placement (docs/media-buy/advanced-topics/billing-authority)/docs/media-buy/advanced-topics/accountability,/docs/accounts/tasks/report_usage,/docs/media-buy/task-reference/get_media_buy_delivery,/docs/media-buy/media-buys/optimization-reporting)https://adcontextprotocol.org/schemas/v3/core/measurement-terms.jsonlink in the page footerget-media-buy-delivery-response.json,report-usage-request.json,measurement-terms.jsonis_final/finalcontinues to parse and behave as 3.0🤖 Generated with Claude Code