Skip to main content
This page is the canonical sequence reference for media buy lifecycle. For conceptual background on the full lifecycle — campaign structure, package model, property targeting, and async operations — see Media Buy Lifecycle.

AdCP 3.2 flow

Capability discovery determines how the commercial commitment is formed. The two compact paths converge on the same MediaBuy lifecycle:
  1. Discover capabilities — read media_buy.lifecycle_tools and related creative capabilities.
  2. Form the commercial commitment — purchase a versioned published offer with buy_products, or accept a committed immutable proposal with accept_proposal.
  3. Supply creatives — use sync_creatives and explicit assignment operations. Compact purchase calls never carry creative bodies.
  4. Operate and reconcile — read get_media_buys, apply in-envelope changes with control_media_buy, and use get_media_buy_delivery for reporting.
Commercial changes outside the accepted envelope return REQUOTE_REQUIRED. Begin an amendment from the snapshot’s accepted_proposal_id, then revise, finalize, and accept the successor proposal.

State machine

Media buy states

submitted, working, and input-required are task-level statuses. They describe an operation such as buy_products or accept_proposal, not the MediaBuy itself. The completion artifact creates or updates the MediaBuy, whose state is then read through get_media_buys. See task status and MediaBuy state.

Transitions

Discovering valid actions at runtime

Rather than hardcoding the state machine, read valid_actions from get_media_buys. The seller returns exactly what the buyer can do in the current state:
control_media_buy requires the latest revision. The seller rejects a stale revision with CONFLICT, so concurrent controls cannot silently overwrite one another. available_actions tells compact clients whether the next change routes to control_media_buy, proposal refinement, creative assignment, or another task. Prefer it over inferring routing from the state enum. Use sync_creatives.assignment_operations for creative changes. Creative assignment is independent from commercial control and does not increment the MediaBuy revision merely because an assignment changed.

Guaranteed / PG deal variation

Guaranteed products require contractual commitment before delivery begins. In the compact lifecycle, sellers normally express negotiated guaranteed terms as a committed proposal:

What makes a guaranteed buy different

Accountability terms are part of the accepted commercial snapshot. A guaranteed proposal can carry:
  • performance_standards — viewability, IVT, completion rate, and other thresholds with measurement vendor
  • measurement_terms — who counts the billing metric, acceptable variance, and makegood remedies
  • cancellation_policy — notice period and cancellation fee for early termination
Omitting any of these on a guaranteed package causes the seller to return TERMS_REJECTED. IO acceptanceaccept_proposal can include structured io_acceptance when the committed terms require it. The operation may still return submitted or input-required while the seller completes human or counterparty review. Poll with get_task_status or use the configured task webhook. The completion artifact carries the media_buy_id. Makegoods — if the seller under-delivers against agreed performance_standards, they propose a remedy from the makegood_policy: additional_delivery, credit, or invoice_adjustment. The buyer accepts or disputes.
A seller who accepts without under-delivering earns a favorable accountability signal. See Accountability for performance standards, measurement terms, and makegood resolution.

Creative sync timing

When creatives are required

buy_products and accept_proposal do not accept creative bodies. After commitment, supply or update library creatives with sync_creatives, then use explicit assignment_operations to assign them to packages. A compact seller advertises the creative workflow it supports; callers should not infer an inline-creative path from older tool availability. When required formats lack creative coverage, the buy enters pending_creatives. After assignments cover the package’s effective format_options[], it moves to pending_start when the flight is in the future or active when delivery can begin. A direct buy_products call may set paused: true; resume it later with control_media_buy and the latest revision.

The creative_deadline

The MediaBuy snapshot can carry a creative_deadline; individual packages may carry their own. Package-level deadlines take precedence over the MediaBuy deadline. This matters for mixed-channel orders—a print package may have a material deadline days before digital packages in the same buy. After the deadline, new or replacement assignments for that package return CREATIVE_REJECTED. Delivery continues with the currently assigned creatives, or the package remains pending_creatives if none were accepted.

Effect on creatives when a buy ends

When a media buy reaches rejected, canceled, or completed, creative assignments are released. For library-backed sellers, the creatives themselves are not deleted — they remain in the library with their existing review status and are available for assignment to other media buys. Inline-only sellers may retain package-scoped creative records for audit and reporting without exposing reusable library entries.

Health and dependency impairment

status describes operational state — is the buy serving, paused, or terminal? health is a separate orthogonal field describing whether upstream dependencies are intact: The two are orthogonal. A buy can be paused-and-impaired, pending_creatives-and-impaired, or active-and-impaired. Health does not change status; valid_actions is unaffected.

When health is impaired

health transitions to impaired when an upstream dependency referenced by the buy enters an offline state that affects delivery for at least one package:
  • An audience the buy targets transitions to suspended (consent expiry, TTL, policy enforcement).
  • A creative the buy uses transitions from approved to suspended (recoverable dependency/authorization loss), from suspended to rejected (terminal dependency/authorization loss), or from approved to rejected (post-approval revocation).
  • A catalog item the buy targets transitions to withdrawn (seller-initiated removal).
  • An event source the buy depends on enters insufficient (zero events received).
  • A property the buy targets is depublished via brand.json / adagents.json.
The buy’s impairments[] array carries one entry per affected dependency:

Materiality

Each entry in impairments[] MUST list at least one package whose ability to serve is degraded. Cosmetic effects (one rejected creative in a package that still has serviceable peers) MUST NOT be reported as impairments — they’re surfaced via the resource’s own status, not the buy’s.

Reverse direction

When the underlying resource returns to a serviceable state (audience re-syncs, creative re-approved), the seller MUST remove the corresponding entry from impairments[] and flip health to ok if no other impairments remain. The buyer sees the recovered state on the next snapshot read or via the next impairment push (which carries the closure).

Pushed via impairment webhook

When a buy’s health transitions or an impairment is added/removed, the seller fires an impairment notification against the buy’s push_notification_config. The payload reuses the impairment object shape plus the buy’s updated health. See the persistent webhook contract for delivery semantics (at-least-once, no-ordering, coalescence, replay via snapshot). Impairment webhooks identify affected packages with package_ids[] by design. Buyers that need package-level correlation context, such as context.buyer_ref, should call get_media_buys after receiving an impairment fire and read the package snapshot.

Materiality coverage

The MUST-strength materiality rule applies to resource types where the resource → buy join is cheap and 1:N — audience, event_source, property. For creative and catalog_item, materiality is SHOULD-strength: a creative in a large pool may not degrade serving when removed, and the join is more expensive for sellers to compute. Implementers SHOULD report conservatively when uncertain and MUST NOT report when serving is provably unaffected.

Remediation by reason_code

Each reason_code has a typical buyer remediation path. Sellers don’t fill this in per-impairment — buyer agents key remediation off reason_code directly. The table below is the protocol-level guidance; the per-impairment free-text remediation field carries seller-specific context that doesn’t fit the typical path (e.g., “we restored this audience yesterday; sync now to pick up the refresh”).

Triage ordering

Buyer agents triaging a non-empty impairments[] SHOULD sort entries by observed_at ascending — the oldest open impairment is the most likely to have already eaten into delivery. Webhook arrival time is not a reliable proxy: under the coalescence rule (see webhooks § Coalescence) the seller MAY batch multiple state changes into one fire, and re-emission under a fresh idempotency_key resets the transport timestamp without changing observed_at.

Impairments are operational signals, not commercial events

An impairment reports degraded delivery from upstream dependency change. It is not a billing event, makegood trigger, or credit dispute. Commercial remedies for under-delivery are governed by accountability_terms on guaranteed buys and remain out of scope for this surface. Integrators building dispute pipelines should drive them from delivery reports and accountability terms, not from impairments[].

Compliance

The impairment.coherence assertion verifies that the buy’s impairments[] surface stays in sync with the underlying resources it references. It is a cross-resource invariant — it observes both the resource transition and the buy snapshot in the same compliance run. Forward rule. Every entry in a buy’s impairments[] MUST reference a resource whose current status is an offline state — audience: suspended (on audience-status), creative: suspended or creative: rejected (on creative-status), catalog_item: withdrawn (on catalog-item-status), event_source: insufficient (the assessment-status value surfaced through event-source-health.status), or a property depublished via brand.json / adagents.json. A buy reporting an impairment whose referenced resource is no longer offline fails the check — the seller has stale state on the buy. Inverse rule. Any resource in an offline state that is referenced by a non-terminal buy MUST appear in that buy’s impairments[]. A seller that transitions a resource without propagating to the affected buys fails the check — the seller has stale state on the resource. Health-iff rule. A non-terminal buy’s health MUST be impaired whenever impairments[] is non-empty, and MUST be ok whenever impairments[] is empty. This is a strict iff — stale health: "impaired" with an empty impairments[] (or health: "ok" with a non-empty impairments[]) violates the rule even when the forward and inverse rules are individually satisfied. Out of scope. All three rules relax on buys in terminal status (completed, canceled, rejected). Sellers MAY leave impairments[] and health in whatever state they held at the terminal transition — they are not required to clean up. Buyers MUST NOT treat post-terminal drift as a coherence violation; the buy is no longer serving and synchronisation is wasted effort. Materiality (the requirement that package_ids be non-empty) is enforced at the schema layer by package_ids: minItems: 1 on impairment.jsonimpairment.coherence does not re-check it. Snapshot is one of several propagation surfaces. Sellers declare which surfaces they use via capabilities.media_buy.propagation_surfaces on get_adcp_capabilities — a non-exclusive array, so a seller mirroring impairments on both the buy snapshot AND firing webhooks declares ["snapshot", "webhook"] (the common case for premium guaranteed sellers). The three surface values:
  • snapshot — seller populates health + impairments[] on get_media_buys reads. The contract above governs this surface; impairment.coherence storyboards grade it when declared, not_applicable otherwise.
  • webhook — seller fires notification-type: impairment webhooks via push_notification_config. Subject to the persistent-channel webhook contract.
  • out_of_band — seller propagates via channels outside the AdCP protocol surface (email, dashboard, partner-specific feeds). Long-tail and enterprise-bundled platforms commonly use this when impairment workflows are managed in human channels. Sellers declaring only ["out_of_band"] are not graded by snapshot or webhook compliance — their bar is the offline agreement.
Default when absent is ["snapshot"]. Each surface is independent of the others; declare the actual mix of surfaces buyers will observe on the agent. A seller with impairment data in their API under a non-AdCP field name (a mapping gap) SHOULD document the mapping rather than declare out_of_band — the spec’s gap is what out_of_band legitimately covers. Relationship to other invariants. impairment.coherence complements status.monotonic, which observes single-resource transitions only. The two run together on every specialism whose storyboard exercises both a resource-state transition and a media-buy snapshot read — audience-sync, creative-ad-server, creative-template, creative-generative, sales-catalog-driven. The cross-resource exercise that drives non-NA grading is the dependency-impairment storyboard (media_buy_seller/dependency_impairment, creative-track), which forces a creative on an active buy into an offline state (approved → suspended for recoverable dependency loss or approved/suspended → rejected for terminal revocation), verifies the buy reflects health: impaired with a matching impairments[] entry, recovers or replaces the creative, and verifies the buy returns to health: ok with impairments[] cleared. Audience-track and catalog-track variants are follow-ups, pending force_audience_status / force_catalog_item_status support in the compliance test controller. See the Snapshot and log contract for the read-side rules that tie impairments[] (snapshot) to the impairment push (log).
For library-backed sellers, creative library state and creative assignment state are tracked independently. A creative that was assigned to a canceled buy still has whatever review status it earned and can be immediately assigned to a new buy. Inline-only sellers expose package-scoped creative status on get_media_buys but do not advertise reusable library creatives. See creative state and assignment state.

See also

  • Media Buy Lifecycle — full lifecycle reference: campaign structure, package model, async operations
  • buy_products — purchase versioned published offers directly
  • accept_proposal — accept committed new-buy, amendment, or cancellation terms
  • control_media_buy — apply revision-checked operational controls
  • sync_creatives — upload and update library creatives when the seller advertises creative.has_creative_library: true
  • Accountability — performance standards, measurement terms, makegood resolution
  • Optimization & Reporting — delivery monitoring, dimensional reporting, campaign updates