What changed in this law between two dates?

For due diligence and regulatory watch an agent needs the text delta of a statute between two dates, not two full texts to diff itself. One call returns the structured segments and a unified patch.

An agent doing due diligence or regulatory watch eventually asks the sharpest question about a statute: what does it say now that it did not say before? The naive answer — fetch the full text at date A, fetch it at date B, diff the two — is exactly the part an agent cannot do reliably at scale or across corpus updates. One paid call — GET /legal/diff — resolves the version in force at each date and returns the text delta: a structured segment list and a git-style unified patch, for French and EU law alike.

Diffing two legal texts yourself looks easy and is not. You first have to resolve the correct version in force at each date — not just any text the model remembers — then tokenize and align them in a way that survives whitespace, punctuation and consolidation quirks, and do it consistently as the underlying corpus is refreshed. Two independent /legal/article calls glued together with a local diff drift apart the moment dates land on version boundaries.

GET /legal/diff does the resolution and the alignment in one place, so the delta is computed on the consolidated text as stored — the same way every time.

The call: the delta between date A and date B

Supply a French identity (code + article) or an EU identity (celex or eli, optional article), a required from (date A, the older snapshot), and an optional to (date B, defaults to today):

GET /legal/diff?code=code-civil&article=1240&from=2000-01-01&to=2026-01-01
GET /legal/diff?celex=32016R0679&article=17&from=2018-01-01

It returns the two resolved versions and the diff between them:

FieldWhat the agent learns
changedtrue when the two resolved texts differ
from_versionThe version in force at from (id, etat, dates); null if uncovered
to_versionThe version in force at to; null if uncovered
diffThe delta payload (see below); zeroed when changed: false

The diff block is designed for both a reasoning agent and a human reviewer:

FieldWhat it carries
segmentsWord-level structured diff: [ { op, text } ], opequal/insert/delete
unifiedGit-style unified patch (line-granularity)
addedTotal characters added
removedTotal characters removed

An agent walks segments to reason about what changed; a reviewer reads unified like any code review. added/removed give a cheap magnitude signal for triage.

”Nothing changed” is a successful answer

The honesty point: when from and to resolve to the same version, or the texts are identical, the response is a 200 with changed: false and an empty, zeroed diff. An unchanged article is an answer to the question, not an error — which matters for a watch loop that wants to confirm stability as much as detect change.

Per the x402 golden rule, the agent pays for the answer to its question. The 4xx range is reserved for what the service genuinely cannot process: INVALID_REF (no usable identity), MISSING_PARAM (no from), INVALID_DATE, UNKNOWN_ARTICLE, UNKNOWN_ACT.

Boundary semantics: a date outside all versions is empty text

A subtle, deliberate behaviour: if a date falls outside every known version — before the article’s first version, or after it was fully repealed — the service treats that side as empty text rather than erroring. The diff then reads as an insertion from nothing (“added since”) or a deletion to nothing (“removed since”), and the empty side is signalled by from_version: null or to_version: null.

{ "from_version": null,
  "to_version": { "version_id": "v-courant", "etat": "vigueur", "date_debut": "2016-10-01" },
  "changed": true,
  "diff": { "added": 123, "removed": 0, "segments": [ { "op": "insert", "text": "…" } ], "unified": "@@ -0,0 +1 @@\n+…" } }

This keeps the golden rule intact: a known article with a valid reference is always a 200, even when one date is uncovered. Read from_version/to_version for null before interpreting a large one-sided delta as a real amendment.

Coverage honesty

The diff is computed purely on the consolidated text as stored in a local snapshot. The service does not fetch sources at request time, search by keyword, infer missing versions, or interpret the legal significance of a change — it tells you the text moved, not what the move means. etat is carried verbatim, and provenance.freshness.as_of tells you which dump backed both resolutions; an amendment newer than the snapshot will not appear until the store is refreshed.

Where it sits in the x402 loop

Diff is the escalation step a monitor reaches for once it knows something changed:

  1. Discover the endpoint and call it; receive the 402.
  2. Pay — sign the chosen rail and replay the request.
  3. Diff — read changed, then segments / unified and the magnitudes.
  4. Branchchanged: false → confirm stability and move on; changed: true → surface the delta for review, or feed segments into downstream reasoning.

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.

The cheap-watch, expensive-diff pattern

diff is the costly, detailed end of a three-endpoint family — pair it with the cheap timeline poll so you only compute deltas when there is one to compute:

For a portfolio of provisions, POST /legal/diff/batch computes many deltas under one x402 settlement instead of one per article.

Used for what it is — a reliable, reproducible text delta between two dates — GET /legal/diff gives an agent the amendment itself, not two blobs to reconcile. For the full field reference, boundary semantics and error codes, see the GET /legal/diff 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.