When did this law last change? Watch for regulatory drift

An agent monitoring a statute does not need to re-read the full text each time — it needs the version timeline. One compact call returns every version of a French or EU article with its dates and status.

An agent watching a statute for change has a cheaper question than “what does it say now?” — it is “has it changed since I last looked?” Re-reading the full consolidated text on every poll is wasteful and hard to diff. What it actually needs is the version timeline: every version an article has had, each with its validity dates and status. One compact paid call — GET /legal/history — returns exactly that, for French and EU law, and is the primitive a compliance monitor polls on.

The problem: monitoring is a timeline question, not a text question

Compliance monitoring, amendment tracking, regulatory-drift detection — they all reduce to noticing that a new version appeared. If an agent fetches full article text every time, it pays for a large payload and then has to detect change itself. The signal it really wants is small: a list of versions with start dates. A new entry, or a new open-ended current version, is the alert.

GET /legal/history is deliberately scoped to that. The payload answers when an article changed and which versions exist — not what the text says, and not what changed between two versions. Keeping it compact is what makes it cheap to poll on a schedule.

The call: the full version timeline, one identity

A single endpoint covers both corpora. Supply a French identity (code + article) or an EU identity (celex or eli, optionally article). There is no date parameter — history always returns the whole timeline:

GET /legal/history?code=code-civil&article=1240
GET /legal/history?celex=32016R0679&article=17

It returns:

FieldWhat the agent learns
versionsEvery known version, sorted by date_debut ascending
countNumber of versions (equals versions.length)
labelHuman label for the article

Each entry in versions[] is minimal and dated:

{
  "version_id": "v-courant",
  "etat": "vigueur",
  "date_debut": "2016-10-01"
}

date_debut is inclusive; date_fin is exclusive and omitted for the current version — so the entry with no date_fin is the one in force now. “When did it last change?” is the date_debut of that last entry. There is no text and no diff in the payload, by design.

How an agent monitors with it

The timeline turns drift detection into a tiny stored-state comparison:

  1. On first run, call /legal/history and store count (or the last version_id / date_debut).
  2. On each poll, call again and compare. A higher count, a new trailing version_id, or a freshly closed date_fin on what used to be the current version means the article changed.
  3. On a detected change, escalate: fetch the new text with GET /legal/article (or GET /legal/eu-act), or compute GET /legal/diff between the old and new dates.

The cheap, frequent poll is history; the expensive text/diff calls run only when the timeline says something moved.

Repealed is part of the timeline, not an error

If the most recent version is abroge, the article still returns its timeline — the repeal is data the agent is buying, with its own date_debut. Per the x402 golden rule, the agent pays for the answer to its question; a known article’s timeline is a successful answer → 200, even when it ends in a repeal. The 4xx range is reserved for what the service cannot answer: INVALID_REF (no usable identity), UNKNOWN_ARTICLE, UNKNOWN_ACT.

Coverage honesty: the snapshot bounds what you can see

The timeline reflects exactly what the served store dump contains. The service does not fetch Legifrance or EUR-Lex at request time, search by keyword, or infer missing versions. An amendment that postdates the snapshot appears only after the store is refreshed — and provenance.freshness.as_of tells you which dump backed the answer. For a monitor that matters: you are detecting drift as of the latest snapshot, so read as_of to know how current your view is. etat is carried verbatim as legal metadata.

Where it sits in the x402 loop

History is the recurring lightweight probe in a monitoring loop:

  1. Discover the endpoint and call it; receive the 402.
  2. Pay — sign the chosen rail and replay the request.
  3. Compare — read count and the trailing version against stored state.
  4. Branch — no change → done for this poll; change detected → escalate to text or diff.

Each paid call follows the same x402 pattern as every Invoket endpoint. The Quickstart walks the whole discover → 402 → pay → replay cycle with runnable snippets. Price and accepted rails are not pinned in this article — they are served live by the catalog; see the endpoint reference for the current figure.

Monitoring many articles at once

A real compliance watch covers a portfolio of provisions, not one article. POST /legal/history/batch returns the timelines for many references under one x402 settlement instead of one per article — which is what makes a scheduled sweep over a whole regulatory surface affordable.

GET /legal/history is the timeline primitive in a family of three: history (when did it change?), article / eu-act (what does a version say?), and diff (what changed?). Used for what it is — a compact, pollable change signal — it lets an agent watch the law cheaply and only pay for full text when something actually moved. For the full field reference and error codes, see the GET /legal/history documentation; for how agents discover and call Invoket endpoints, see For agents.

French law data is derived from the LEGI dataset published by DILA under the Licence Ouverte / Etalab open licence; EU law data is derived from EUR-Lex / Cellar made available by the Publications Office of the European Union.