2026-04-14·13 min read·sota.io team

EU AI Act Art.50 Marking CoP 2nd Draft: Two-Layer AI Content Transparency System (2026)

The EU AI Office published the 2nd Draft of the Art.50 Marking Code of Practice in March 2026. The 2nd Draft supersedes the January 2026 1st Draft and introduces a structured Two-Layer marking architecture that will be the operational standard for AI-generated content transparency when the final CoP is adopted in June 2026 and enforcement begins August 2, 2026.

This post is a technical follow-up to our EU AI Act Art.50 transparency obligations guide. That post covered what Art.50 requires at the statutory level — chatbot disclosure, deepfake labeling, machine-readable marking. This post covers how to implement the marking obligation specifically: the Two-Layer architecture, the C2PA 2.0 technical requirements, content-type-specific rules, robustness thresholds, and what the 2nd Draft changes relative to the 1st.

If you build an image generator, video synthesis tool, text-to-speech system, or text generation API for EU users, the Marking CoP 2nd Draft defines the exact marking obligations you must meet before August 2, 2026.

Why a Separate Marking CoP Exists

Art.50(3) of the EU AI Act establishes the core marking obligation: providers of AI systems that generate synthetic audio, image, video, or text content shall ensure the outputs are marked in a machine-readable format, and deployers of those systems shall ensure visible disclosure to users.

The statutory text is intentionally technology-neutral. "Machine-readable format" and "visible disclosure" do not specify which standards, what robustness level, or how to handle format conversion scenarios where metadata is stripped. The Marking CoP fills this gap — it specifies which technical standards satisfy the Art.50(3) machine-readable marking requirement, defines minimum robustness thresholds, and structures the Two-Layer architecture that no individual technical standard covers end-to-end.

The CoP is developed by the AI Office under Art.56(1)(b) authority. Adherence creates a presumption of conformity with Art.50(3) obligations, shifting the enforcement burden to the AI Office to prove a violation rather than requiring providers to prove compliance. The Marking CoP is separate from the GPAI Code of Practice (which covers Art.52–55 obligations for GPAI model providers) — providers may be subject to both.

The Two-Layer Architecture

The 2nd Draft Marking CoP mandates that every AI-generated content output carries both layers simultaneously. Neither layer alone satisfies the CoP. The layers serve distinct functions that are not substitutable:

Layer 1: Machine-Readable Metadata Embedding

Layer 1 is the structured technical signal that automated systems — content platforms, browsers, fact-checking tools, regulatory inspection systems — can read without human involvement.

Primary standard: C2PA 2.0 (Coalition for Content Provenance and Authenticity)

The 2nd Draft designates C2PA 2.0 as the primary mechanism for Layer 1. A C2PA manifest is a cryptographically signed JSON-LD structure embedded in or associated with the content file, containing:

For GPAI model providers, the 2nd Draft requires that the C2PA manifest include the model card URI from the provider's Art.52(1)(b) technical documentation — linking the content signal back to the provider's compliance record. This is new in the 2nd Draft and was not in the 1st.

CAWG Extension: Creator Assertions Working Group

The 2nd Draft references the CAWG metadata assertion extension, which standardises how model identity is expressed within C2PA manifests. CAWG assertions are required when the generating model is a GPAI model subject to Art.52 obligations. The CAWG structure maps to the AI Office's GPAI model registry entries.

Fallback standards (when C2PA embedding is technically infeasible):

The 2nd Draft establishes a preference hierarchy: C2PA 2.0 > IPTC > XMP > ID3. Providers must use the highest-preference mechanism supported by the content format. Choosing a lower-preference standard when C2PA is technically feasible does not satisfy the CoP.

Layer 2: Human-Visible Indicator

Layer 2 is the signal perceptible to the human viewing or listening to the content, without requiring any technical tool to detect.

The 2nd Draft specifies three acceptable forms of Layer 2 marking, with different applicability depending on content type:

Form A — Persistent Visual Label (images, video frames):
A permanent UI element attached to or embedded in the rendered content. Must be legible at normal viewing distance, not obscured by UI chrome, and persist across format conversion if the converted format supports overlay. The 2nd Draft does not mandate specific label text but requires that it "unambiguously indicates AI generation or substantial AI modification" — acceptable formulations include "AI-generated", "Created with AI", "AI-synthesised content". Symbols without accompanying text are not sufficient alone.

Form B — Invisible Watermark (audio, video):
A perceptually imperceptible but machine-detectable signal embedded in the signal content itself (not the container metadata). The 2nd Draft requires robustness to the specific distortions in each content type (see Robustness Requirements below). Invisible watermarking satisfies Layer 2 for audio and video where visual labels are contextually inappropriate (e.g., voice audio where no visual channel exists). For video, an invisible watermark may supplement or replace a persistent visual label if the provider can demonstrate equivalent detectability.

Form C — Interface-Level Disclosure (text):
For AI-generated text, the 2nd Draft acknowledges that watermarking mechanisms for text have not yet reached production-grade robustness across all text lengths and languages. Layer 2 for text is therefore an interface-level disclosure: a persistent notice in the UI that AI-generated text is present, displayed at the point of consumption, not merely in terms-of-service documentation. The 2nd Draft states this is an interim arrangement pending a separate Text Watermarking Technical Standard expected by Q4 2026.

Content-Type Implementation Requirements

The Two-Layer architecture applies differently depending on content type. The 2nd Draft provides type-specific implementation tables:

Images

Requirement2nd Draft Specification
Layer 1 standardC2PA 2.0 manifest (preferred), IPTC fallback
Layer 1 mandatory fieldsc2pa.ai-generative-training, model card URI (GPAI providers), actions record
Layer 2 formForm A (persistent visual label)
Label positionNot obscured; size ≥ 24px at 1x display
RobustnessMust survive JPEG re-compression at Q≥75, PNG lossless round-trip, 50% resize
Format conversionC2PA manifest must be preserved on PNG→JPEG, JPEG→WebP
ExemptionArt.50(6) exemption for obviously AI content applies; must be documented

Video

Requirement2nd Draft Specification
Layer 1 standardC2PA 2.0 with video-specific assertions
Layer 2 formForm A (first-frame overlay or persistent UI element) OR Form B (invisible watermark)
Frame-levelC2PA assertion applies to full video file; per-frame marking not required unless frames are distributed independently
Deepfake provisionIf video contains a deepfake (Art.50(4)), Form A is mandatory in addition to Layer 1; invisible watermark alone insufficient
RobustnessMust survive H.264/H.265 transcoding at standard bitrates, MP4 container rewrap

Audio

Requirement2nd Draft Specification
Layer 1 standardC2PA 2.0 (RIFF container), ID3 v2.4 (MP3 fallback)
Layer 2 formForm B (invisible audio watermark)
Watermarking methodAny perceptual audio watermarking scheme meeting robustness thresholds; provider must document method in technical record
TTS obligationText-to-speech providers are within scope of Art.50(3); synthetic voice must be marked even when voice clone consent was obtained
RobustnessMust survive MP3 re-encoding at ≥128kbps, sample rate conversion 44.1kHz↔48kHz

Text

Requirement2nd Draft Specification
Layer 1 standardNo technical standard finalised; metadata field in API response recommended
Layer 2 formForm C (interface-level disclosure) — interim arrangement
API requirementAPI responses generating AI text must include HTTP header or response field indicating AI generation
Text watermarkingOptional (state of art not yet CoP-ready); encouraged by 2nd Draft
ScopeApplies to text generation APIs, LLM SaaS products, AI writing assistants
ExemptionArt.50(5) editorial control exemption for assisted human writing applies

Robustness Requirements

The 2nd Draft introduces minimum robustness thresholds — a major addition over the 1st Draft which left robustness undefined. Robustness requirements apply to Layer 1 metadata and Layer 2 watermarks independently.

Layer 1 robustness:
C2PA manifests must not be silently stripped by the provider's own pipeline. The 2nd Draft requires that providers implement manifest validation at the content delivery step — if a manifest is missing from an output that should carry one, the output must not be served until the manifest is attached. This creates an internal gate requirement, not just a best-effort embedding.

For third-party content platforms receiving AI-generated content via API, the provider obligation extends to "reasonable technical measures to encourage manifest preservation" — specifically, the provider must document in their API developer documentation that manifest stripping violates Art.50(3).

Layer 2 robustness (invisible watermarks):
The 2nd Draft specifies three robustness tiers:

The 2nd Draft does not mandate a specific watermarking algorithm but requires providers to document their chosen method, robustness test results against the tier thresholds, and update procedures if the method is found to be defeated.

GPAI Model Provider Obligations

GPAI model providers under Art.50(3) carry the Art.50 marking obligation at the model/API level, not just at the downstream application level. The 2nd Draft specifies additional requirements for GPAI providers:

Technical documentation obligation (Art.52 + Marking CoP):
GPAI providers must include marking implementation documentation in their Art.52 technical documentation: which marking methods are used, what robustness tier is achieved, and how downstream providers access or invoke the marking functionality.

Downstream provider enablement:
GPAI providers must make marking functionality available to downstream providers in a "technically accessible and economically reasonable" form. If a GPAI API generates images, the API must expose C2PA manifest attachment — downstream providers cannot implement C2PA marking for outputs they did not generate. The 2nd Draft clarifies that downstream providers are not liable for a GPAI provider's failure to expose marking functionality, provided the downstream provider has contractually required marking compliance.

Model card URI in C2PA manifest:
As noted above, GPAI providers must include the model card URI (from Art.52(1)(b) documentation) in every C2PA manifest they generate. The URI must resolve to a machine-readable model card — a JSON-LD document following the CAWG schema, accessible at the declared URI.

What Changed from the 1st Draft

The 2nd Draft made five substantive changes from the January 2026 1st Draft:

  1. Model card URI requirement added — 1st Draft did not require GPAI providers to include model card URIs in C2PA manifests. Added to enable AI Office to trace specific model versions from content signals.

  2. Robustness tiers formalised — 1st Draft used qualitative language ("reasonable robustness"). 2nd Draft introduces three tiers with specific test criteria.

  3. Text marking interim status clarified — 1st Draft was ambiguous about text obligations. 2nd Draft explicitly designates Form C as an interim arrangement and commits to a Text Watermarking Technical Standard by Q4 2026.

  4. Layer 2 hierarchy for video — 1st Draft allowed invisible watermark alone for video. 2nd Draft requires Form A (visible) for video containing deepfakes under Art.50(4).

  5. Downstream provider liability clarification — 1st Draft was silent on downstream liability for GPAI providers' marking failures. 2nd Draft clarifies the allocation.

Timeline

DateEvent
January 2026Art.50 Marking CoP 1st Draft published
March 2026Art.50 Marking CoP 2nd Draft (current)
April–May 2026Stakeholder consultation period
June 2026Final Marking CoP adoption
August 2, 2026Art.50(3) enforcement begins; Marking CoP presumption of conformity applies

The three-month gap between final CoP adoption (June) and enforcement (August) is the implementation window. Providers who are CoP-compliant by August 2 benefit from the presumption of conformity; providers who are not will be assessed directly against the Art.50(3) statutory standard by national market surveillance authorities.

Python Tooling: MarkingCoP Compliance Tracker

from dataclasses import dataclass, field
from enum import Enum
from datetime import date
from typing import Optional

class ContentType(Enum):
    IMAGE = "image"
    VIDEO = "video"
    AUDIO = "audio"
    TEXT = "text"

class Layer1Standard(Enum):
    C2PA_2 = "c2pa_2.0"
    IPTC = "iptc_photo_metadata"
    XMP = "xmp"
    ID3 = "id3_v2.4"
    API_HEADER = "api_response_header"
    NOT_IMPLEMENTED = "not_implemented"

class Layer2Form(Enum):
    FORM_A_VISUAL_LABEL = "form_a_persistent_visual"
    FORM_B_INVISIBLE_WATERMARK = "form_b_invisible_watermark"
    FORM_C_INTERFACE_DISCLOSURE = "form_c_interface_disclosure"
    NOT_IMPLEMENTED = "not_implemented"

class RobustnessTier(Enum):
    TIER_1_MINIMUM = 1
    TIER_2_STANDARD = 2
    TIER_3_HIGH = 3

@dataclass
class ContentTypeMarkingStatus:
    content_type: ContentType
    layer1_standard: Layer1Standard
    layer1_model_card_uri: Optional[str]  # required for GPAI providers
    layer2_form: Layer2Form
    robustness_tier_achieved: Optional[RobustnessTier]
    robustness_test_date: Optional[date]
    downstream_marking_exposed: bool  # for GPAI APIs
    notes: str = ""

    def cop_compliant(self, is_gpai_provider: bool = False, eu_users: int = 0) -> bool:
        """Check 2nd Draft CoP compliance for this content type."""
        if self.layer1_standard == Layer1Standard.NOT_IMPLEMENTED:
            return False
        if self.layer2_form == Layer2Form.NOT_IMPLEMENTED:
            return False
        if is_gpai_provider and not self.layer1_model_card_uri:
            return False  # model card URI required for GPAI
        if is_gpai_provider and not self.downstream_marking_exposed:
            return False
        required_tier = self._required_tier(is_gpai_provider, eu_users)
        if self.robustness_tier_achieved is None:
            return False
        if self.robustness_tier_achieved.value < required_tier.value:
            return False
        return True

    def _required_tier(self, is_gpai_provider: bool, eu_users: int) -> RobustnessTier:
        if is_gpai_provider:
            return RobustnessTier.TIER_3_HIGH
        if eu_users > 10_000:
            return RobustnessTier.TIER_2_STANDARD
        return RobustnessTier.TIER_1_MINIMUM

    def gap_report(self, is_gpai_provider: bool = False, eu_users: int = 0) -> list[str]:
        gaps = []
        if self.layer1_standard == Layer1Standard.NOT_IMPLEMENTED:
            gaps.append(f"[{self.content_type.value}] Layer 1: No machine-readable marking implemented")
        elif is_gpai_provider and not self.layer1_model_card_uri:
            gaps.append(f"[{self.content_type.value}] Layer 1: Model card URI missing from C2PA manifest (GPAI requirement)")
        if self.layer2_form == Layer2Form.NOT_IMPLEMENTED:
            gaps.append(f"[{self.content_type.value}] Layer 2: No human-visible/detectable indicator implemented")
        if is_gpai_provider and not self.downstream_marking_exposed:
            gaps.append(f"[{self.content_type.value}] GPAI: Downstream providers cannot invoke marking via API")
        required_tier = self._required_tier(is_gpai_provider, eu_users)
        if self.robustness_tier_achieved is None or self.robustness_tier_achieved.value < required_tier.value:
            gaps.append(
                f"[{self.content_type.value}] Robustness: Tier {required_tier.value} required, "
                f"{'none achieved' if not self.robustness_tier_achieved else f'Tier {self.robustness_tier_achieved.value} achieved'}"
            )
        return gaps

@dataclass
class MarkingCoPTracker:
    provider_name: str
    is_gpai_provider: bool
    eu_active_users: int
    content_types: list[ContentTypeMarkingStatus] = field(default_factory=list)
    final_cop_date: date = date(2026, 6, 30)
    enforcement_date: date = date(2026, 8, 2)

    def days_to_enforcement(self) -> int:
        return (self.enforcement_date - date.today()).days

    def overall_compliance(self) -> dict:
        results = {}
        for ct_status in self.content_types:
            results[ct_status.content_type.value] = ct_status.cop_compliant(
                self.is_gpai_provider, self.eu_active_users
            )
        return results

    def all_gaps(self) -> list[str]:
        gaps = []
        for ct_status in self.content_types:
            gaps.extend(ct_status.gap_report(self.is_gpai_provider, self.eu_active_users))
        return gaps

    def summary(self) -> str:
        compliance = self.overall_compliance()
        compliant_count = sum(1 for v in compliance.values() if v)
        total = len(compliance)
        gaps = self.all_gaps()
        days = self.days_to_enforcement()
        lines = [
            f"=== Art.50 Marking CoP — {self.provider_name} ===",
            f"Content types compliant: {compliant_count}/{total}",
            f"Days to enforcement: {days}",
            f"GPAI provider: {self.is_gpai_provider}",
            f"EU active users: {self.eu_active_users:,}",
        ]
        if gaps:
            lines.append(f"\nGaps ({len(gaps)}):")
            for gap in gaps:
                lines.append(f"  - {gap}")
        else:
            lines.append("\nAll implemented content types meet CoP requirements.")
        return "\n".join(lines)

# Example: Image generation SaaS, GPAI API provider, 50k EU users
tracker = MarkingCoPTracker(
    provider_name="MyAI Image Generator",
    is_gpai_provider=True,
    eu_active_users=50_000,
    content_types=[
        ContentTypeMarkingStatus(
            content_type=ContentType.IMAGE,
            layer1_standard=Layer1Standard.C2PA_2,
            layer1_model_card_uri="https://myai.example.com/model-card.json",
            layer2_form=Layer2Form.FORM_A_VISUAL_LABEL,
            robustness_tier_achieved=RobustnessTier.TIER_2_STANDARD,  # not yet Tier 3
            robustness_test_date=date(2026, 3, 15),
            downstream_marking_exposed=True,
        ),
        ContentTypeMarkingStatus(
            content_type=ContentType.TEXT,
            layer1_standard=Layer1Standard.API_HEADER,
            layer1_model_card_uri="https://myai.example.com/model-card.json",
            layer2_form=Layer2Form.FORM_C_INTERFACE_DISCLOSURE,
            robustness_tier_achieved=RobustnessTier.TIER_1_MINIMUM,
            robustness_test_date=date(2026, 4, 1),
            downstream_marking_exposed=True,
        ),
    ],
)
print(tracker.summary())

Running the example will surface the gap: image robustness is Tier 2 but Tier 3 is required for GPAI providers.

Art.50 Marking CoP 2nd Draft: 35-Item Implementation Checklist

Layer 1 — Machine-Readable Marking (10 items)

Layer 2 — Human-Visible/Detectable Indicators (10 items)

Robustness Requirements (7 items)

GPAI-Specific Requirements (5 items)

Governance & Readiness (3 items)

Connection to Other EU AI Act Obligations

The Marking CoP does not operate in isolation:

Art.50(4) deepfake provision: The CoP's Layer 2 Form A requirement for videos containing deepfakes is the CoP operationalisation of Art.50(4)'s deployer obligation to disclose artificial representations of real persons. Form C (interface-level notice) does not satisfy Art.50(4) for deepfakes — persistent visible marking on the content itself is required.

Art.52–55 GPAI obligations: The GPAI CoP (Final, July 2025) includes the Art.52(1)(b) machine-readable model card. The Marking CoP's GPAI requirements (model card URI in C2PA manifest) create a direct technical link between the GPAI CoP and the Marking CoP. GPAI providers must satisfy both.

GDPR Art.25 Privacy by Design: AI content marking records (who generated what, when, with which model) constitute personal data where the content depicts real persons. Marking infrastructure must incorporate data minimisation — C2PA manifests should not embed more personally identifiable information than required for the marking function.

AI Liability Directive (ALD): C2PA manifests and watermark records will constitute technical evidence in ALD-governed liability disputes. AI-generated content that caused harm and can be traced back to a provider via a C2PA manifest facilitates fault attribution under the ALD's Art.4 disclosure regime. Robust marking is both a compliance obligation and a liability record.

What to Do Before August 2026

The practical sequence for providers:

April–May 2026 (stakeholder consultation open): Implement Layer 1 C2PA marking for image outputs. This is the highest-priority item: C2PA 2.0 has mature library support (Python c2pa-python, JavaScript c2pa-js, Rust c2pa), and the 2nd Draft's C2PA requirements are stable enough to build against.

May 2026: Complete robustness testing against the tier applicable to your user scale. Document results. Assign internal owner.

June 2026 (final CoP adoption): Review final CoP for any changes from 2nd Draft. Update implementation if required. Initiate CoP signatory registration with AI Office if pursuing the presumption-of-conformity pathway.

August 2, 2026 (enforcement begins): All content types must be marked. Documentation must be inspection-ready. Downstream API documentation must state marking obligations.

The Marking CoP 2nd Draft is specific enough to build against now. Waiting for the final June 2026 text carries implementation risk: a 60-day window from final CoP to enforcement is tight for integrating C2PA manifest generation, robustness testing, and deploying visible marking UI components across all production surfaces.

See Also