Overview
For a media buy to invoice deterministically, two questions must have machine-readable answers:- Whose number is authoritative? Different deals name different parties — the seller’s ad server, a buyer’s third-party ad server, or a named measurement vendor like Nielsen or IAS.
- Has that number stopped moving? Telemetry settles over hours, days, or weeks (broadcast C3 → C7 DVR accumulation, digital post-IVT scrubbing, podcast 30-day downloads, conversion dedup). Final numbers are billable; provisional numbers are not.
measurement_terms.billing_measurement (negotiated at create_media_buy) names authority; is_final / final flags with finalized_at timestamps (on get_media_buy_delivery and report_usage) mark closure.
This page ties those pieces together.
Billing authority and Reliable Reporting are separate contracts today.
Reliable Reporting
(experimental in 3.2) answers a different question: did the report I was
promised arrive, intact, on time? It gives the seller-produced feed
obligations, immutable revisions, a binding digest, health states, and — when
the seller opts in — a buyer-to-seller
sync_reporting_status
loop. None of that decides whose count governs the invoice, which is what
this page’s billing_measurement does.So both surfaces can read green while an invoice is still disputed: a buyer’s
consumer status can be received and the seller’s health complete on a feed
whose numbers sit outside max_variance_percent of the authoritative party’s.
reporting-delivery-config.json reserves an authoritative_party field
(seller | consumer, default seller) so the two models can be unified
additively. In 3.2 the only accepted value is seller; sellers MUST reject
consumer with UNSUPPORTED_FEATURE because no released minor defines the
buyer-deposited revision task. Tracked in
#7440.Naming authority
measurement_terms.billing_measurement carries:
Absence is informative: when
billing_measurement is absent the default is seller-attested, with no contractual finalization deadline.
Marking numbers as final
Final means settled for the named measurement window — not “final forever.” A broadcast row markedis_final: true for measurement_window: "c3" is final for C3; a later c7 row supersedes it with its own provisional → final lifecycle. A future structured dispute would join on (media_buy_id, reporting_period, measurement_window); 3.2 does not define one.
On get_media_buy_delivery
Each row in media_buy_deliveries[] carries:
is_final: boolean— row-level finality, equivalent to all packages in the row being final for the same window.finalized_at: string (date-time)— present iffis_final: true. Anchors any deadline declared inbilling_measurement.finalization_deadline_hours.- Per-package:
by_package[*].is_final,by_package[*].finalized_at,by_package[*].measurement_window,by_package[*].supersedes_window.
On report_usage
Predecessor path. For media-buy billing,
report_usage is the
pre-Reliable-Reporting channel for buyer- and vendor-attested numbers. It has no
obligations, no immutable revisions, no RFC 8785/JCS binding digest, no
supersession chain, and no status surface, so a missing or restated settlement
file is not detectable on the wire the way a missing reporting obligation is.
It remains the supported path for the buyer-attested and vendor-attested flows
below until a buyer-deposited revision task exists
(#7440). Non-media-buy
report_usage variants (signals, governance, creative, brand) are unaffected
and are not superseded by Reliable Reporting.final: boolean— absent means unknown. Settrueonly when the reporter has actually settled the numbers (e.g., post-SIVT month-end close). Setfalsefor preliminary records (daily pacing pushes, intra-period progress). Whenmeasurement_terms.billing_measurementnames this reporter as authoritative, the receiver MUST NOT invoice onfinal: falseor absent — request a final record first. For 3.0-style usage with nobilling_measurementand for non-media-buy variants (signals, governance, creative, brand — domains with no provisional state concept), receivers MAY treat absent as final, preserving existing behavior.finalized_at: string (date-time)— present ifffinal: true.measurement_window: string— SHOULD be set when the buy’sbilling_measurement.measurement_windowis set, so the receiver reconciles against the correct stage.
(account, media_buy_id, reporting_period) is later reported with final: true, that record supersedes any prior records for the period.
Distinguishing webhook finality from row finality
get_media_buy_delivery webhooks carry a top-level notification_type enum that includes "final" — this signals “this is the last scheduled notification for the campaign,” not that contained rows are final for invoicing. The two axes are independent: a webhook with notification_type: "final" may still contain rows where is_final: false (e.g., a campaign-end notification before C7 settles). Always check the per-row is_final for billing decisions.
How a seller produces an invoice
Seller-attested (default)
get_media_buy_delivery rows where is_final: true for the contracted measurement_window. No report_usage from the buyer is required.
Buyer-attested (3PAS)
- Buyer’s CM360 settles post-SIVT for the period.
- The buyer’s operator — in practice a holdco platform (e.g., Choreograph, Annalect, Acxiom) or an in-house agency engineering team that wraps the CM360 export — calls
report_usagewith the media-buy record:media_buy_id,impressions,vendor_cost,currency,final: true,finalized_at,measurement_window: "post_sivt". Daily pacing pushes (if used) setfinal: false; only the settled file setsfinal: true. - Seller compares against its own post-SIVT row from
get_media_buy_delivery(is_final: true, samemeasurement_window). If|seller - buyer| / max ≤ max_variance_percent, the seller invoices on the buyer’s numbers. - If variance exceeds threshold, the seller proposes a remedy from
makegood_policy.available_remedies. - If the buyer doesn’t publish a final record within
finalization_deadline_hours, the seller MAY invoice off its own seller-attested numbers and treat the late finalization as a breach undermakegood_policy.
Today’s reality: monthly 3PAS reconciliation is mostly handled out-of-band via CSV/PDF emailed to the seller’s AR team. This flow is the wire-format upgrade — the first adopters are likely holdco operators with the engineering to wrap CM360 / Flashtalking / Innovid exports in report_usage, working with sympathetic direct publishers rather than RTB SSPs.
Vendor-attested (named third party)
- Seller holds the vendor relationship (the common CTV pattern). The seller pulls C7 numbers from Nielsen (NPower, etc.) on its own schedule and publishes them on
get_media_buy_deliveryas a row withmeasurement_window: "c7",is_final: true, andfinalized_atset when the C7 window closes plus its internal processing. Noreport_usagepush from the buyer is needed; reconciliation happens against the seller’s row. - Buyer holds the vendor relationship. The buyer (or its operator) fetches the vendor’s authoritative numbers — e.g., an agency’s iSpot subscription, an in-house IAS dashboard export — and pushes them via
report_usageagainst the buy’s account withfinal: true,finalized_at, andmeasurement_window: "c7". The vendor itself does not call AdCP.
vendor.domain BrandRef identifies who the contract names, not who calls the API. The vendor’s own integration (NPower feed, IAS API, DV pinnacle) is out of AdCP scope.
Today’s reality: SSPs running RTB will keep being seller-attested for the foreseeable future — their billing systems were never designed for buyer-attested invoice basis andmax_variance_percentplusmakegood_policyis not enough commercial cover for them to retrofit it. The first real adopters here are CTV direct sellers (e.g., Disney, NBCU, Paramount) whose Nielsen-backed guarantees already invoice on a measurement vendor’s count — for them this PR just describes existing practice in structured terms.
Resolving disagreements today
When numbers disagree beyondmax_variance_percent, AdCP 3.0–3.1 expects out-of-band resolution between counterparties, backed by:
- The buy’s
makegood_policy.available_remedies— the menu of remedies (additional delivery, credit, invoice adjustment) the seller has pre-committed to. - Final records on both sides with
finalized_attimestamps — a full audit trail of who said what was final, when. - The original
committed_metricsandmeasurement_termscaptured atcreate_media_buy— what the parties signed up for.
under_review / seller_proposed_adjustment / buyer_accepted / unresolved_arbitration, and recording resolution in the audit log — does not exist in 3.2 and is not scheduled for it. The data shape needed to dispute (final records, attestation, measurement window, makegood menu) is already on the wire in 3.1, and Reliable Reporting has since added the first piece of the eventual lifecycle: reporting-status-issue.json carries issue_state (open / acknowledged / resolved / waived), opened_at, and an inert external_ref for correlation with each side’s own ticketing. A shared dispute lifecycle built on those fields is tracked in #7440.
A variance beyond max_variance_percent is not a
sync_reporting_status content_mismatch. That consumer status is reserved
for contract facts the accepted reporting configuration generation already
fixed — a frozen media buy missing from the denominator, a promised metric
absent, the wrong currency. A disagreement about how many impressions occurred
is a measurement dispute and stays here, under makegood_policy.
Worked example: buyer-attested 3PAS reconciliation
create_media_buy excerpt — measurement terms
get_media_buy_delivery — seller's final post-SIVT row
report_usage — buyer's final 3PAS push
|5120000 - 5040000| / 5120000 = 1.56% — well under the 10% threshold. Seller invoices on the buyer’s 5.04M impressions × the agreed rate. Both sides retain audit-traceable final records.
Related
measurement-terms— schemaget_media_buy_delivery— seller-side finality flagsreport_usage— buyer-side / third-party finality flags- Accountability — performance standards, makegood remedies, cancellation
- Reporting capabilities and measurement windows
- Reliable Reporting: implementing
reporting.core— the operational delivery contract for the seller-produced feed sync_reporting_status— buyer-to-seller consumption status, and why it is not a dispute channel