A warning is an immediate receipt. It MUST NOT become the only home for a continuing condition: a persistent forecast, pacing, creative, or budget conclusion also appears as current resource state. An indicator is not a separate resource—there is no indicator ID, history API, sub-version, or
get_indicators task.
An indicator says that the buyer should evaluate and probably address a condition. It does not claim that one universal remedy exists, authorize a mutation, or make seller-supplied text executable. Buyer products may translate an indicator into one or more recommendations, but any resulting change still uses its normal AdCP task, authorization, and governance path.
Where indicators live
get_media_buys carries three levels of current indicator state:
media_buy.relationship_notifications.projection_tasks includes list_creatives, the two assignment projections MUST agree on media_buy_id, package_id, creative_id, approval state, rejection reason, and scoped approval outcomes. Indicator state SHOULD converge, but separate reads can legitimately straddle a reevaluation; buyers reconcile toward the snapshot with the strictly newer indicators_as_of. The seller includes media_buy_id and approval_status on every creative assignment row, even when indicators are unknown. Inline-only sellers use get_media_buys without implementing this reverse projection.
Do not put assignment-specific fatigue or approval on the creative root. One creative can be fatigued or rejected on one publisher while remaining effective and approved elsewhere. When a multi-publisher assignment has mixed eligibility, the scalar is partially_approved and complete approval_scopes[] carries a disjoint partition: one row per normalized scope, using either publisher-wide or placement-specific rows for a publisher, never both. Uniform assignments omit the array.
Standard 3.2 catalog
The negotiated AdCP release defines these broad meanings, not a universal algorithm. Provider scores, thresholds, evaluation windows, native labels, suggested actions, deep links, and upstream attribution remain in namespaced
ext. A generic action dispatcher is intentionally absent; applying a recommendation still uses normal AdCP authorization, governance, idempotency, and readback.
Evaluated snapshot shape
indicator_types_evaluated is required with indicators. It prevents an empty fatigue result from being misread as an evaluation of pacing, budget, or another type. Every returned indicator.type MUST appear in this list; omitted types remain unknown.
indicators_as_of records when this evaluation completed. indicators_evaluated_scope optionally limits publisher or placement coverage. Omit scope coverage only when the named types were evaluated across the whole enclosing buy, package, or assignment. With partial coverage, every indicator includes a contained scope; unlisted scopes remain unknown.
Only type is required inside each indicator. detected_at, when known, remains stable throughout one uninterrupted occurrence. A relationship contains at most one item per (type, normalized scope set).
Unknown, clear, and monotonic state
- Omitted
indicatorsmeans unknown or not evaluated. indicators: []means evaluated-clear only forindicator_types_evaluatedand the declared coverage.- A non-empty array is the current assertion set for those types and coverage.
- A prior key clears only when absent from a successful direct snapshot with coverage containing the key and a strictly newer
indicators_as_of. - Equal-timestamp conflicting snapshots are invalid; buyers retain stored state.
- Filtered disappearance, incomplete pagination, a failed read, or uncovered scope never clears state.
- A successful direct unfiltered read showing that an assignment was deleted retires all keys for that relationship.
get_creative_delivery.
Querying
Uselist_creatives for portfolio-wide assignment indicator discovery:
assignment_projection: "matching" and assignment_limit; each result reports returned_assignment_count and assignments_truncated. A truncated reverse projection is discovery-only—repair complete state through get_media_buys. Reread known relationships without indicator_types when reconciling clearing.
get_media_buys.indicator_types matches an indicator at any of the three levels and returns the selected full buy. Use it for buy/package conclusions such as budget, inventory, audience, diversity, or pacing. Buyers MUST NOT send the filter unless every requested type appears in supported_indicator_types; a seller MAY reject a violation with UNSUPPORTED_FEATURE. This avoids an undetectable unfiltered superset on a response that has no filters_applied receipt.
Webhooks
supported_indicator_types declares polling readback independently of webhook support. A seller may expose indicators through get_media_buys and omit relationship_notifications entirely. Sellers that support push additionally declare media_buy.relationship_notifications; indicators.changed requires an indicator catalog, while creative.assignment_changed may be declared alone when the seller can detect assignment or approval changes. A creative-library seller may advertise the bounded list_creatives reverse projection inside that block. The capability also declares whether activity logs are available:
indicators.changed fires after the seller observes a semantic assertion-set or evaluation-coverage change. It does not fire because only indicators_as_of advanced. creative.assignment_changed fires when an assignment is added, removed, or its assignment-specific approval state/reason changes. Removing an assignment with stored indicators also fires indicators.changed with change_kind: "assignment_removed"; the two fires have no ordering guarantee.
Subscriptions are prospective and do not replay already-current indicators. After activation or reactivation, establish a complete baseline through get_media_buys: either enumerate known media_buy_ids, or request all seven status_filter values and follow pagination to exhaustion. Do not use indicator_types for this baseline. A material in-place creative-content update retires the prior assignment evaluation: the seller fires indicators.changed with change_kind: "invalidated" and omits the stale snapshot as unknown until reevaluated, or atomically publishes a strictly newer evaluation and fires updated.
Both payloads are small signed invalidations containing account, media-buy, package, and—when applicable—creative identity. Buyers:
- verify the registered webhook signature;
- dedupe by
idempotency_key; - reread
get_media_buyswithout an indicator filter (the boundedlist_creativesprojection may assist discovery but cannot prove complete state); and - reconcile from the snapshot, never from the webhook payload.
idempotency_key. Poll-based upstream integrations fire when they detect a change; capability support does not promise native-platform detection latency. Relevant delivery attempts appear on the declared repair reads when supports_webhook_activity is true and activity was requested.
Success warnings
Completedbuy_products and accept_proposal commitments and completed control_media_buy controls may return structured warnings[]. The 3.x create_media_buy and update_media_buy compatibility facades mirror the warning returned by the canonical operation they map to. Proposal planning (request_proposals and refine_proposals) carries forecasts in proposal state rather than using commitment warnings. Initial codes are:
Canonical commitments use the first two codes: direct or newly accepted purchases may report
inventory_shortfall_forecast, and an accepted flight amendment may report flight_change_creates_pacing_risk. control_media_buy does not change flight dates and therefore only uses inventory_shortfall_forecast from this initial catalog. fields_ignored_due_to_precedence remains a compatibility-facade receipt; canonical inputs reject conflicting intent instead of silently applying legacy precedence.
Every warning includes typed affected_resource identity so buyers can join it to durable state in multi-package and multi-creative responses. On compact commitment responses, package IDs come from purchase_bindings[]. Warnings never change success, never appear on terminal or submitted arms, and never grant action authority. Codes are the closed vocabulary of the negotiated AdCP release. details is seller-specific in 3.2; portable handling relies only on code and affected_resource. Whether inventory_shortfall_forecast surfaces as a warning on a completed commitment or instead blocks via input-required is seller discretion; a buyer unconditionally carries delivery risk on a MediaBuy committed with that warning.
A seller MUST NOT emit inventory_shortfall_forecast unless it advertises that indicator type, or flight_change_creates_pacing_risk unless it advertises pacing_risk. This keeps the promised durable readback available; fields_ignored_due_to_precedence is operation-relative and needs no indicator capability.