Skip to main content
What this gets you: an early-warning system for your own product - know when the law you depend on moved, and when a state or agency you depend on gains coverage, instead of finding out by accident. Two different questions live on this page, and they need two different tools.

The sync filter: changedSince

changedSince takes a YYYY-MM-DD date and restricts a search to sections we have OBSERVED change on since then. It is the purpose-built answer to “what moved since my last run”, and it needs no snapshot files and no diffing of your own.
Then read each hit’s history with GET /us/statutes/section/{actId}/changes (1 credit) when you need to know what actually moved. changedSince and that endpoint are the same event stream, so a hit here always has a history there.

Four things that decide whether your job is correct

  • These are observed changes, not effective dates. A refresh compared the publisher against the copy we held and found it different. The date is when we SAW it, which is an upper bound on when it took effect.
  • Coverage is bounded by capture, not by the age of the law. Change capture began long after the corpus did, it is per-source, and events are swept at 24 months. An empty result means no captured change in the window, never that nothing was amended.
  • A window that is too broad is refused, not truncated. Match too many sections and the call returns 422 telling you to use a later date or a state filter. That is deliberate: a partial change set would look complete to a sync job, which would then mark itself current having never seen the sections that were cut. Narrow with corpusType and state.
  • A search still needs a query. changedSince narrows a search, it is not a firehose of everything that moved. Run it once per topic you actually track, which is what makes the result small enough to act on.
Paging is bounded: limit caps at 50 and offset at 70, so the deepest reachable result is 120. If a window is returning full pages, tighten it with a later date, a state list, or a narrower corpusType rather than trying to page through it.
An empty window is a real answer and is charged the ordinary 4-credit search price. “Nothing moved since Tuesday” is what lets a nightly job do nothing with confidence. Read creditsConsumed rather than assuming.

A nightly job

Python

The other question: a jurisdiction gaining a new corpus

changedSince tells you a section moved. It cannot tell you that a state you do not yet query has just gained regulations, because there was nothing there to change. For that, snapshot GET /us/statutes/coverage on a schedule and diff the snapshots. Coverage is free and rate limited, so daily or weekly is plenty.
1

Fetch and flatten the coverage matrix

The response is wrapped as { "data": {...}, "meta": {...} }. Inside data you get a corpusTypes legend and a jurisdictions array, where each jurisdiction carries a corpora object mapping a corpusType token to its ingested section count (the same distinct-section count Coverage shows, not the larger passage count used internally for retrieval).
Python
A trimmed data payload:
2

Persist and diff

Save each snapshot as JSON so the next run has a baseline, then compare the two maps for a new jurisdiction, a new corpus within a known jurisdiction, or an existing corpus whose count grew.
Python
Example output on a run where a state gained regulations:
A growing count is a coarse signal. It says the corpus got bigger, not which sections moved, and a re-ingest that replaces sections one for one leaves the count flat. Use the diff to decide that something happened, then use changedSince to find out what.

Law Change Alerts

Section-level change notifications with a webhook or email, no polling.

Compare a rule across states

Get the comparable provision in other states in one call.

Enrich a citation database

Attach canonical citations, excerpts, and source links to a batch of rows.

Coverage matrix

The human-readable jurisdiction and corpus matrix.
Last modified on September 6, 2026