DSA Platform

Work out which DSA layer you are (intermediary, hosting, platform, marketplace) and build the notice-and-action, statements of reasons and transparency duties that follow

DSA Platform

The Digital Services Act is layered, and the layer decides the duty list. The mistake that costs the most is a small team concluding "the DSA is for Big Tech" and missing that hosting duties have no size exemption. If one user can publish something another user sees, you are a hosting service and you owe notice-and-action and statements of reasons regardless of headcount.

What the micro and small exemption actually removes is the online platform duties in Section 3 — complaint handling, trusted flaggers, ads transparency, recommender disclosure. That is a real and significant relief. It is not an exemption from the DSA.

Not legal advice. Which layer applies, and whether content is illegal, are legal judgements. This skill produces the layer analysis, the duty list and the mechanisms.

  does anyone transmit / cache / store third-party info?
        │ no ──► not an intermediary. Record the exclusion + expires_if.
        ▼ yes
  hosting?  (you store info provided by a recipient)
        │ yes ──► Arts. 16-18  — NO size exemption
        ▼
  online platform?  (you also disseminate it to the public)
        │ yes ──► Section 3 — UNLESS micro/small
        ▼
  marketplace?  ──► trader traceability (Arts. 30-32)
        │
  45M+ monthly active EU recipients ──► VLOP, by Commission designation only

Use this when

  • Users can post anything another user can see: comments, reviews, profiles, uploads, shared documents, public snippets, a community forum.
  • You run a marketplace, an app store, or anything where third parties sell to consumers.
  • You rank or recommend user content, or run advertising against it.
  • Someone asks for your DSA point of contact or transparency report, which business customers now do routinely.

Do not use this when nothing a user submits is ever visible to another user. Record it: expires_if: any feature lets one user publish content another user can see. The comment feature, the shared-link feature and the public-profile feature are the three that flip it, and all three get shipped without anyone re-running the scoping.

Note that private messaging between users is still hosting if you store the messages — the public-dissemination test separates hosting from platform, not from the DSA.

Ask first

  1. "Can a user publish, upload or send something that another user sees? List every such surface." The layer question. Enumerate: comments, reviews, profile fields, avatars, file uploads, shared links, messages, forum posts.
  2. "Is any of it visible to the public, or only to a chosen recipient?" Public dissemination is what turns hosting into an online platform.
  3. "Do third parties sell goods or services to consumers through you?" Marketplace duties: trader traceability, and best-effort verification.
  4. "Headcount and turnover?" Decides Section 3 only.
  5. "Today, how does someone report illegal content, and what happens next?" If the answer is "they email support", that is the finding.
  6. "When you remove content or suspend an account, is the user told why, in a way they can challenge?" Art. 17 statements of reasons, and the internal complaint system.
  7. "Do you profile users for advertising or recommendations? Are any of them minors?" Arts. 26-28. Two hard prohibitions live here.
  8. "Are you established in the EU? If not, who is your legal representative?" Art. 13 requires a designated legal representative for non-EU providers.

What the law requires

Regulation (EU) 2022/2065. Fully applicable since 17 February 2024. Directly applicable — no transposition — though enforcement runs through national Digital Services Coordinators.

The layers and their duties

LayerWhoCore duties
All intermediariesMere conduit, caching, hostingSingle point of contact for authorities (Art. 11) and for recipients (Art. 12); legal representative if non-EU (Art. 13); terms and conditions including content-moderation information (Art. 14); transparency reports (Art. 15, not micro/small)
HostingYou store information provided by a recipientNotice and action (Art. 16); statement of reasons (Art. 17); report suspicions of criminal offences threatening life or safety (Art. 18)
Online platformsHosting plus dissemination to the publicEverything above, plus Section 3 — micro/small exempt
MarketplacesPlatforms allowing distance contracts with tradersTrader traceability (Art. 30), compliance by design (Art. 31), information on illegal products (Art. 32)
VLOP / VLOSE45M+ monthly active EU recipients, designated by the CommissionSystemic risk assessment, independent audit, data access, crisis response

Section 3, for online platforms above the size threshold

  • Art. 20 internal complaint-handling system, free, for at least six months after a decision.
  • Art. 21 out-of-court dispute settlement — users can go to a certified body and you must engage.
  • Art. 22 trusted flaggers — their notices get priority.
  • Art. 23 measures against misuse: suspend users who frequently post manifestly illegal content, and notifiers who frequently submit manifestly unfounded notices. Both directions, with prior warning.
  • Art. 25 no dark patterns: no interface that deceives, manipulates, or materially distorts a recipient's ability to make free decisions.
  • Art. 26 advertising transparency: clearly marked, who paid, why this user is seeing it. Art. 26(3): no ads targeted using special-category data.
  • Art. 27 recommender transparency: the main parameters, in plain language, in the T&Cs, plus a way to change them.
  • Art. 28 protection of minors: a high level of privacy, safety and security by design, and no advertising based on profiling where you are aware with reasonable certainty the recipient is a minor.

Arts. 26(3) and 28(2) are prohibitions, not disclosures. They are engineering constraints in the ad-serving path, not paragraphs in a policy.

Notice and action, specifically

Art. 16 requires a mechanism that is electronic, easy to access and user-friendly, and a notice must be able to carry: a substantiated explanation of why the content is illegal, the exact URL, the notifier's name and email (except for certain offences), and a good-faith statement. A notice with those elements gives you actual knowledge, which is what removes the hosting liability exemption under Art. 6 — so the timestamp on receipt matters legally.

You must act in a timely, diligent, non-arbitrary and objective manner, and confirm receipt.

What to produce

1. The layer analysis, with the reasoning:

dsa:
  layer: hosting                     # intermediary | hosting | platform | marketplace
  layer_reasoning: >
    Users upload documents and share them by link with named recipients. Stored
    on our infrastructure (hosting). Not disseminated to the public, so the
    online-platform duties in Section 3 are not engaged.
  public_dissemination: false
  size_exempt_section_3: true
  size_reasoning: "22 staff, EUR 3.1M turnover - micro/small"
  legal_representative: "not required; established in FI"
  duties: ["Art. 11", "Art. 12", "Art. 14", "Art. 16", "Art. 17", "Art. 18"]
  expires_if: "any surface makes user content visible to the public"

2. The notice-and-action endpoint, with the required fields and a timestamped receipt:

@dataclass
class Notice:
    url: str                       # exact location - required
    reason: str                    # substantiated explanation of illegality
    notifier_name: str | None      # may be omitted for certain offences
    notifier_email: str | None
    good_faith: bool
    received_at: datetime          # this timestamp is the actual-knowledge moment

    def complete(self) -> tuple[bool, list[str]]:
        missing = [f for f in ("url", "reason") if not getattr(self, f)]
        if not self.good_faith:
            missing.append("good_faith")
        return not missing, missing

Store every notice, including rejected ones, with the decision and its reasoning. That register is the evidence that you acted diligently and non-arbitrarily.

3. Statements of reasons. Every restriction — removal, demotion, demonetisation, suspension — produces one, to the affected user, containing: the decision and its scope, the facts relied on, whether automated means were used, the legal or T&Cs ground, and how to appeal. Online platforms must also submit them to the Commission's DSA Transparency Database.

4. Ad and recommender constraints, in code:

def can_target(user, segment) -> tuple[bool, str]:
    if segment.uses_special_category_data:
        return False, "Art. 26(3): ads may not be targeted using Art. 9 GDPR data"
    if user.is_minor_with_reasonable_certainty and segment.uses_profiling:
        return False, "Art. 28(2): no profiling-based ads to minors"
    return True, "ok"

A policy document does not implement Arts. 26(3) and 28(2). A function in the ad-serving path does.

5. T&Cs that say what the moderation actually is (Art. 14): the policies, procedures, tools and human review used, in clear and plain language. If minors are a target group, in terms they can understand.

6. A transparency report, unless micro/small: notices received and acted on, by category and source; own-initiative moderation; complaints and outcomes; automated means used and their error rates.

Every assessment carries a certainty. Each finding, each applicable or ruled-out regime, and the headline of the brief carry certainty (0–100) — the honest percent of the assessment that rests on verified sources and confirmed facts rather than inference, open unknowns and interpretation. Wherever you state an applicability, a classification, a citation-backed obligation or a finding, show the percentage and the single largest reason it is not higher: "ruled out NIS2 — certainty 66%: the national transposition was not read". references/certainty.md holds the anchors; the rules that matter here: an answer graded UNKNOWN caps anything resting on it at 70, an unread Directive transposition caps at 60, a classification pending counsel caps at 50, and a 100 requires every deciding fact SPECIFIC, every citation verified on EUR-Lex, every transposition read and every regime screened. Certainty is visibility, not a free pass — VAGUE stays rejected, an open blocker stays blocked.

Failure modes

  • "The DSA is for Big Tech." Hosting duties have no size exemption. The comment feature put you in scope.

  • Treating the micro/small exemption as total. It removes Section 3 only. Arts. 11-18 remain.

  • A notice mechanism behind a support email. Art. 16 requires an electronic, easy-to-access, user-friendly mechanism that can carry the specified elements. A generic inbox is neither, and it also makes your actual-knowledge timestamp unprovable.

  • No statement of reasons. Content removed, user told nothing, no appeal route. Art. 17 breach on every removal, at scale.

  • Arts. 26(3) and 28(2) written as policy. They are prohibitions in the serving path. If the code can target a minor by profile, the policy is not a control.

  • Over-removal to be safe. The DSA also protects recipients: arbitrary removal, no reasons, no appeal is itself the breach. Diligent and non-arbitrary cuts both ways.

  • Forgetting the legal representative. A non-EU provider without a designated Art. 13 representative has an immediate, easily-checked gap.

  • Assuming VLOP duties apply because you are large. VLOP status follows a Commission designation. Absent one, you are not a VLOP.

Verify

Follow references/verification.md. For this skill specifically:

  1. Tier 0 — install, --help, classify a fixture service and emit duties.

  2. Tier 1 — pytest -q, offline:

def test_hosting_duties_have_no_size_exemption(brief_small_host):
    duties = classify(brief_small_host).duties
    assert "Art. 16" in duties and "Art. 17" in duties
    assert "Art. 20" not in duties          # Section 3 correctly exempt


def test_private_sharing_is_hosting_not_platform(brief_private_sharing):
    result = classify(brief_private_sharing)
    assert result.layer == "hosting"
    assert result.public_dissemination is False


def test_public_dissemination_makes_it_a_platform(brief_public_feed):
    assert classify(brief_public_feed).layer == "platform"


def test_no_user_content_is_ruled_out_with_an_expiry(brief_no_ugc):
    exclusion = classify(brief_no_ugc).exclusion
    assert "visible to the public" in exclusion["expires_if"] or \
           "another user can see" in exclusion["expires_if"]


def test_notice_requires_url_and_substantiated_reason():
    ok, missing = Notice(url="", reason="bad", good_faith=True,
                         notifier_name=None, notifier_email=None,
                         received_at=now()).complete()
    assert not ok and "url" in missing


def test_receipt_timestamp_is_recorded(notice_endpoint):
    response = notice_endpoint.submit(valid_notice())
    assert response.received_at is not None
    assert notice_endpoint.register[-1].received_at == response.received_at


def test_rejected_notices_are_kept_with_reasoning(notice_endpoint):
    notice_endpoint.reject(valid_notice(), reason="content is not illegal in FI")
    assert notice_endpoint.register[-1].decision_reasoning


def test_every_restriction_emits_a_statement_of_reasons(moderation):
    moderation.remove(content_id="c1", ground="T&Cs 4.2", automated=True)
    sor = moderation.statements[-1]
    for field in ("decision", "facts", "automated_means", "ground", "appeal_route"):
        assert getattr(sor, field) is not None


def test_special_category_targeting_is_refused():
    ok, reason = can_target(adult_user(), segment(uses_special_category_data=True))
    assert not ok and "Art. 26(3)" in reason


def test_profiling_ads_to_minors_are_refused():
    ok, reason = can_target(minor_user(), segment(uses_profiling=True))
    assert not ok and "Art. 28(2)" in reason


def test_non_eu_provider_needs_a_legal_representative(brief_us_host):
    finding = classify(brief_us_host).finding_for("Art. 13")
    assert finding.severity == "condition"


def test_vlop_duties_require_designation(brief_large_platform):
    duties = classify(brief_large_platform).duties
    assert not any("Art. 34" in d for d in duties)      # no designation, no VLOP duties
  1. Tier 2 — report: the layer and its reasoning, the duty list, whether the notice mechanism accepts every required element, and the median time from notice receipt to decision. That median is the number a Digital Services Coordinator will ask about.

  2. Tier 3 — submit a notice yourself, from outside, through the published mechanism. Time how long it takes to reach a human who can act, and check that a statement of reasons actually reaches the affected user. Both usually surprise people.

Then tell the user which layer you concluded and why, and that the layer analysis and any illegality assessment need confirming — you produced the mechanism, not the judgement.

Last updated: October 13, 2026

Files (2)

Jurisdiction
🇪🇺 European Union
Practice area
Tmt
License
MIT
Author
ArttuAn
Source
eu/tmt/skills/dsa-platform-arttuan

Test DSA Platform

Ask a legal question — get an answer generated live from this skill’s instructions.

Sign in to test this skill.