GET /legal/eu-act

Returns the consolidated version of a European Union act or article in force at a given date: text, status, validity dates and coverage metadata. The lookup is served from a local store built from EUR-Lex / Cellar data, so a covered reference resolves in milliseconds without an account or API key. The corpus currently covers a selected set of EU acts and is expanding; an uncovered reference returns 404, never a paid empty answer.

Use it when an agent needs grounded EU law text it should not infer from memory: the consolidated wording of a regulation, a directive article at a date, or the validity window of a served consolidation. See the live /catalog for the authoritative endpoint listing and price.

x402 golden rule: the agent pays for the answer to its question. A known act or article with a consolidation covering the requested date is a successful answer -> 200, even when the stored etat says the version is no longer the current legal state - in_force_at_date says so explicitly. Requests the service cannot answer - missing identifiers, invalid dates, unknown acts, unknown articles, or a date no consolidation covers and no repeal explains - leave the 200 range.

Parameters

ParameterTypeRequiredDescription
celexstringone identifierCELEX identifier, for example 32016R0679; case-insensitive
elistringone identifierELI identifier; used when celex is absent
articlestringnoArticle number within the act, for example 17; omit to resolve the whole act
datestringnoUTC date to resolve, strict format YYYY-MM-DD; defaults to today’s date

Provide at least one of celex or eli. If both are present, CELEX is used as the lookup identifier and both supplied identifiers are echoed in data. The celex is case-insensitive: 32016r0679 and 32016R0679 resolve to the same act, and the response echoes the canonical uppercase form.

GET /legal/eu-act?celex=32016R0679&article=17&date=2026-01-01

Resolve the whole act by omitting article:

GET /legal/eu-act?celex=32016R0679

Use ELI when the caller does not have a CELEX identifier:

GET /legal/eu-act?eli=eli/reg/2016/679/oj&article=17

200 response - UnifiedResponse

{
  "data": { ... },
  "provenance": {
    "source": "eur-lex-cellar",
    "fetched_at": "2026-06-20T12:00:00Z",
    "freshness": { "kind": "snapshot", "as_of": "2026-06-01T00:00:00Z" }
  }
}
  • provenance.source: source identifier from the served EUR-Lex store, commonly eur-lex-cellar.
  • freshness.kind: snapshot; as_of is the EUR-Lex dump date that backed the answer. Freshness is dated per dataset, so an EU answer reflects the EUR-Lex snapshot date, independent of the French corpus.
  • EU law data is derived from EUR-Lex / Cellar data and must be reused with attribution to the European Union / Publications Office.

Fields of data

FieldTypeDescription
celexstringEchoed when the request supplied celex
elistringEchoed when the request supplied eli
articlestringEchoed when the request supplied an article number
datestringEffective resolution date in YYYY-MM-DD form
labelstringHuman label for the resolved act or article
etatstringStatus carried as stored, never reinterpreted by the service
in_force_at_dateboolWhether the served text is the applicable law on date
applicable_fromstring | nullDate the act, or that specific article, becomes applicable - not the same as being in force
applicable_at_datebool | nullWhether it was applicable on date; null when applicable_from is null
applicability_scopestring | null"act" when the date is the act’s own application date, "article" when a derogation names that article
applicability_sourcestring | nullCitation of the provision carrying the date, so the verdict is checkable
textstringConsolidated text of the selected version; article level only (when article is supplied)
articlesstring arrayArticle numbers available at the date; act level only (when article is omitted)
versionobjectValidity period and source version identifier
coverage_windowobjectPeriod over which this act is actually queryable: from (inclusive), to (exclusive, null when open)
coverageobjectCompleteness marker for the served consolidation

data has two shapes. With an article, the response carries text (the consolidated article text). Without an article, it resolves the act and carries articles — the list of article numbers available at that date — with the act’s status and validity dates, but no text: the act never concatenates article texts, and each article’s text stays on ?article=.

celex, eli and article are omitted when they were not supplied. The first public version serves English text from the local store; if a source-store limitation or anomaly affects the served content, coverage.reason explains it without inventing missing law.

In force is not the same as applicable

An EU regulation enters into force shortly after publication, but it often applies later - and, increasingly, in stages, article by article. The GDPR entered into force on 2016-05-24 and applied from 2018-05-25. The AI Act has been in force in its entirety since 2024-08-01, yet its Article 5 applies from 2025-02-02 and its Article 50 only from 2026-08-02.

etat and in_force_at_date answer is this text in force. The four applicab* fields answer the question a compliance agent actually asks: does this apply to me on that date - so a 200 with etat: "vigueur" is never read as an unqualified “yes”.

These dates are not in the EUR-Lex metadata: no EU dataset publishes an application date per article. They are curated from each act’s own final provisions (“Entry into force and application”) and every answer carries the citation it came from in applicability_source.

When no application date is on record for an act - or when the act sets no determined date, as with a directive that takes effect through national transposition measures - the four fields are null and coverage.reason says why. A date is never guessed. Staggered dates that apply to a single paragraph (AI Act Article 6(1), DSA Article 24(2)) are not modelled: such an article carries its act’s date, which is the date it applies in full - never an earlier one than reality.

version

FieldTypeDescription
version_idstringStable identifier of the selected source version
date_debutstringStart date of this version, inclusive, in YYYY-MM-DD
date_finstring | nullEnd date of this version, exclusive; omitted when current

coverage

FieldTypeDescription
completebooltrue when the store served an unambiguous consolidation
reasonstringPresent when complete: false, naming the source dump anomaly

Example - article in force

{
  "data": {
    "celex": "32016R0679",
    "article": "17",
    "date": "2026-01-01",
    "label": "Regulation (EU) 2016/679 (GDPR), Article 17",
    "etat": "vigueur",
    "in_force_at_date": true,
    "applicable_from": "2018-05-25",
    "applicable_at_date": true,
    "applicability_scope": "act",
    "applicability_source": "Regulation (EU) 2016/679, Article 99(2): \"It shall apply from 25 May 2018.\"",
    "text": "right to erasure",
    "version": {
      "version_id": "32016R0679-art-17-v1",
      "date_debut": "2018-05-25"
    },
    "coverage": { "complete": true }
  },
  "provenance": {
    "source": "eur-lex-cellar",
    "fetched_at": "2026-06-20T12:00:00Z",
    "freshness": { "kind": "snapshot", "as_of": "2026-06-01T00:00:00Z" }
  }
}

Example - whole act

When article is omitted, the service resolves the act and returns its status, validity dates and the list of article numbers available at that date. There is no text field at act level; fetch any article’s text by adding ?article=.

{
  "data": {
    "celex": "32016R0679",
    "date": "2026-01-01",
    "label": "32016R0679",
    "etat": "vigueur",
    "in_force_at_date": true,
    "articles": ["1", "2", "3", "17"],
    "version": {
      "version_id": "32016R0679-20180525",
      "date_debut": "2018-05-25"
    },
    "coverage": { "complete": true }
  },
  "provenance": {
    "source": "eur-lex-cellar",
    "fetched_at": "2026-06-20T12:00:00Z",
    "freshness": { "kind": "snapshot", "as_of": "2026-06-01T00:00:00Z" }
  }
}

Example - in force, not yet applicable

The AI Act is in force in its entirety, so its Article 50 resolves to a 200 with etat: "vigueur". Read on its own, that answer would be misleading: the article does not apply until 2026-08-02.

{
  "data": {
    "celex": "32024R1689",
    "article": "50",
    "date": "2026-01-01",
    "label": "Regulation (EU) 2024/1689 (AI Act), Article 50",
    "etat": "vigueur",
    "in_force_at_date": true,
    "applicable_from": "2026-08-02",
    "applicable_at_date": false,
    "applicability_scope": "act",
    "applicability_source": "Regulation (EU) 2024/1689, Article 113: \"It shall apply from 2 August 2026.\"",
    "text": "transparency obligations for providers and deployers of certain AI systems ...",
    "version": {
      "version_id": "32024R1689-art-50-v1",
      "date_debut": "2024-08-01"
    },
    "coverage": { "complete": true }
  },
  "provenance": {
    "source": "eur-lex-cellar",
    "fetched_at": "2026-06-20T12:00:00Z",
    "freshness": { "kind": "snapshot", "as_of": "2026-06-01T00:00:00Z" }
  }
}

Asking for Article 5 instead returns applicable_from: "2025-02-02" with applicability_scope: "article": Chapters I and II of the AI Act are covered by a derogation that names them, and the response cites it.

Example - expired consolidation within its validity window

If the requested date is covered by a historical consolidation, the answer is a 200. The service exposes the stored status and validity dates; it does not convert a non-current status into an HTTP error.

{
  "data": {
    "celex": "31999L0093",
    "article": "1",
    "date": "2005-01-01",
    "label": "Directive 1999/93/EC, Article 1 (repealed)",
    "etat": "vigueur",
    "in_force_at_date": true,
    "text": "e-signatures (expired)",
    "version": {
      "version_id": "31999L0093-art-1-v1",
      "date_debut": "2000-01-19",
      "date_fin": "2016-07-01"
    },
    "coverage": { "complete": true }
  },
  "provenance": {
    "source": "eur-lex-cellar",
    "fetched_at": "2026-06-20T12:00:00Z",
    "freshness": { "kind": "snapshot", "as_of": "2026-06-01T00:00:00Z" }
  }
}

Example - article deleted by an amending act

An article removed from an act by a later act (for example Articles 12-15 of the e-Commerce Directive, replaced by the Digital Services Act on 2024-02-17) still answers 200: the last known wording is served, and in_force_at_date: false states that it is no longer the applicable law. That flag is the one to branch on. Deducing it from etat and the validity dates is genuinely error-prone, because the two corpora encode a repeal in opposite ways: EU law opens a repeal version that starts at the repeal, French law closes the last version’s interval instead. /legal/article and /legal/eu-act answer the same question the same way, at the same price.

{
  "data": {
    "celex": "32000L0031",
    "article": "14",
    "date": "2026-07-25",
    "label": "Directive 2000/31/EC, Article 14",
    "etat": "abroge",
    "in_force_at_date": false,
    "text": "...last known wording before deletion...",
    "version": {
      "version_id": "32000L0031-art-14-abroge",
      "date_debut": "2024-02-17"
    },
    "coverage": { "complete": true }
  },
  "provenance": {
    "source": "eur-lex-cellar",
    "fetched_at": "2026-07-25T12:00:00Z",
    "freshness": { "kind": "snapshot", "as_of": "2026-07-20T00:00:00Z" }
  }
}

Coverage honesty

The service answers from a local snapshot of EUR-Lex / Cellar data. It does not fetch EUR-Lex at request time, search by keyword, interpret case law, translate missing language versions or infer absent articles. etat is carried from the source store as legal metadata; callers should treat it as the authoritative status for the selected consolidation.

coverage.complete: false is reserved for source-store anomalies, such as overlapping versions where the service selected the most recent start date. Unknown acts, unknown articles and dates not covered by any known consolidation are not partial paid answers: they return 4xx errors.

The service distinguishes an act that is out of scope from an article number that does not exist inside a covered act. When the act itself is not in the store, the error is UNKNOWN_ACT — even if an article was supplied, since it is the act that is missing, not the article. When the act is covered but the article number is unknown, it is UNKNOWN_ARTICLE. The covered set of EU acts is listed in the live /catalog entry.

Historical depth varies per act

Consolidated EU law is published act by act, and the Publications Office does not publish every past state of every act. coverage_window reports, on every answer, the period this act can actually be read over: from inclusive, to exclusive (null when the window is still open).

The e-Commerce Directive is the sharpest case: in force since 2000, it is only queryable from 2024-02-17, because neither the base act nor the 2000 consolidation is published in any manifestation we can retrieve. Asking for an earlier date returns OUT_OF_COVERAGE_WINDOW — a limit on our coverage, not a statement that the law did not exist:

{
  "error": "act `32000L0031` is covered from 2024-02-17 onwards; the store has no data for 2020-01-01. Historical depth varies per act: this is a coverage limit, not a statement about the law",
  "code": "OUT_OF_COVERAGE_WINDOW"
}

Inside the window, a date that no consolidation covers stays NO_VERSION_AT_DATE: the act is covered, that article simply had no version then. Both are 4xx and neither is billed. Windows are derived from the versions actually served, so they never promise more than the store holds — and /legal/history returns the same window with the timeline, so a monitoring agent knows how far back to go before spending a call.

Errors

Only requests the service cannot answer leave the 200 range.

StatuscodeCase
400INVALID_REFBoth celex and eli are missing or empty
400INVALID_DATEdate is present but not strictly formatted as YYYY-MM-DD (zero-padded: 2026-07-05, not 2026-7-5)
404UNKNOWN_ACTThe act identifier is well formed but no matching act exists, even when an article is supplied
404UNKNOWN_ARTICLEThe act is covered, but the requested article is not present in it
404OUT_OF_COVERAGE_WINDOWThe date falls outside the act’s coverage_window — that period is not covered for this act
404NO_VERSION_AT_DATEWithin the window, the act or article exists but no consolidation covers the date and no repeal explains the gap
500INTERNALInternal error (detail logged, not exposed)
{ "error": "query parameter `celex` (e.g. `32016R0679`) or `eli` is required", "code": "INVALID_REF" }
{ "error": "invalid `date` `2018`; expected ISO calendar format YYYY-MM-DD", "code": "INVALID_DATE" }
{ "error": "no act `39999R9999` found in the store", "code": "UNKNOWN_ACT" }

An unknown act with an article still reports the missing act, not a missing article:

{ "error": "no act `32099R9999` found in the store", "code": "UNKNOWN_ACT" }
{ "error": "no article `999` found in act `32016R0679`", "code": "UNKNOWN_ARTICLE" }
{ "error": "Directive 1999/93/EC, Article 1 (repealed) has no consolidated version in force on 2020-01-01", "code": "NO_VERSION_AT_DATE" }

Attribution

EU law data is derived from EUR-Lex / Cellar data made available by the Publications Office of the European Union. Reuse must preserve attribution to the European Union and EUR-Lex.

See also

  • GET /legal/article - French law article text in force at a date from the LEGI dataset.
  • For agents - discovery surfaces, the live /catalog and how settlement works.