You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The creative protocol has no revision model. Four gaps compound into one operational wall:
No versioning.sync_creatives upserts overwrite in place. No revision identifiers, no history, no rollback — only created_date/updated_date. "What changed between the last two versions of this creative" is unanswerable at the protocol level.
Update-vs-live-delivery is a wall, not a workflow. Creatives assigned to active, non-paused packages cannot be updated (INVALID_STATE); documented guidance is "pause the package first, or create a new creative version" with a different creative_id (sync_creatives best practices Welcome to adcp Discussions! #1/Rename Audience Activation Protocol to Signals Activation Protocol #6). Real ops need a hot-swap path — e.g. legal demands a disclaimer change on a live campaign — where the update goes through review while the current version keeps serving. Minting a new creative_id also severs the delivery-reporting join.
Re-approval after edit is unspecified. The status lifecycle covers rejected → processing on resubmit, but says nothing about an approved creative that is updated. Every seller will do something different, and some will keep serving materially changed content without re-review.
No cross-seller revision correlation. After trafficking to three sellers, an update is three independent syncs with three independent re-reviews and no shared identifier to answer "revision X is live on A, pending on B."
Proposed direction
Follow the native-localization precedent: capability-gated, sync_creatives-only mutation contract with strict readback, list_creatives authoritative.
Principles
A revision is a new state of a creative, not a new creative.creative_id stays the join key for delivery, billing, assignments; revision_id identifies the content state.
Revision identity is buyer-assigned (like creative_id, locale_variant_id). Syncing the same revision_id to N sellers gives cross-seller correlation for free — reconciliation is per-seller list_creatives reads, no central object.
Approval attaches to content, not the creative ID. Material change (assets, localization, format identity) invalidates prior review; non-material change (name, tags) never does.
Live creatives update through staging, never in place. With creative.supports_staged_updates, a material update to an actively delivering creative is accepted as a staged revision with its own review status; the approved revision keeps serving until the staged one is approved, then the seller promotes it atomically.
Surface sketch
Capabilities: creative.supports_revisions, creative.supports_staged_updates (implies the former). Non-supporting sellers behave exactly as today.
sync_creatives: optional creatives[].revision { revision_id, notes }; revisions immutable once accepted (REVISION_CONTENT_MISMATCH on reuse with different content; identical content is idempotent). Staged acceptance surfaces as action: "staged".
Readback: current_revision_id, staged_revision { revision_id, status, synced_at }, and list_creativesinclude_revisions → revisions[] { revision_id, synced_at, action, status, notes }. History is metadata; per-revision asset retention is seller-optional; diffing is buyer-side.
Normative re-review rule independent of the new capabilities: a material update to an approved creative MUST NOT be servable before re-review (new lifecycle edge approved → processing/pending_review); sellers MAY fast-path content identical to a previously approved revision — which is also the rollback path (re-sync prior content under a new revision_id).
creative.status_changed webhook gains optional revision_id + staged so pushes identify which revision transitioned.
Compatibility: all new fields optional; seller mints revision IDs when older buyers omit them; the action enum gaining "staged" is the only change pinned consumers must opt into; older sellers keep today's pause-or-remint workflow, detectable via capabilities.
Problem
The creative protocol has no revision model. Four gaps compound into one operational wall:
sync_creativesupserts overwrite in place. No revision identifiers, no history, no rollback — onlycreated_date/updated_date. "What changed between the last two versions of this creative" is unanswerable at the protocol level.INVALID_STATE); documented guidance is "pause the package first, or create a new creative version" with a differentcreative_id(sync_creatives best practices Welcome to adcp Discussions! #1/Rename Audience Activation Protocol to Signals Activation Protocol #6). Real ops need a hot-swap path — e.g. legal demands a disclaimer change on a live campaign — where the update goes through review while the current version keeps serving. Minting a newcreative_idalso severs the delivery-reporting join.rejected → processingon resubmit, but says nothing about anapprovedcreative that is updated. Every seller will do something different, and some will keep serving materially changed content without re-review.Proposed direction
Follow the native-localization precedent: capability-gated,
sync_creatives-only mutation contract with strict readback,list_creativesauthoritative.Principles
creative_idstays the join key for delivery, billing, assignments;revision_ididentifies the content state.creative_id,locale_variant_id). Syncing the samerevision_idto N sellers gives cross-seller correlation for free — reconciliation is per-sellerlist_creativesreads, no central object.creative.supports_staged_updates, a material update to an actively delivering creative is accepted as a staged revision with its own review status; the approved revision keeps serving until the staged one is approved, then the seller promotes it atomically.Surface sketch
creative.supports_revisions,creative.supports_staged_updates(implies the former). Non-supporting sellers behave exactly as today.sync_creatives: optionalcreatives[].revision { revision_id, notes }; revisions immutable once accepted (REVISION_CONTENT_MISMATCHon reuse with different content; identical content is idempotent). Staged acceptance surfaces asaction: "staged".current_revision_id,staged_revision { revision_id, status, synced_at }, andlist_creativesinclude_revisions→revisions[] { revision_id, synced_at, action, status, notes }. History is metadata; per-revision asset retention is seller-optional; diffing is buyer-side.approvedcreative MUST NOT be servable before re-review (new lifecycle edgeapproved → processing/pending_review); sellers MAY fast-path content identical to a previously approved revision — which is also the rollback path (re-sync prior content under a newrevision_id).creative.status_changedwebhook gains optionalrevision_id+stagedso pushes identify which revision transitioned.Compatibility: all new fields optional; seller mints revision IDs when older buyers omit them; the
actionenum gaining"staged"is the only change pinned consumers must opt into; older sellers keep today's pause-or-remint workflow, detectable via capabilities.Out of scope
get_creative_delivery(revision boundaries recoverable from promotion timestamps).