A law change alerts API watches a specific government source, re-reads it on a schedule, and tells you which individual sections changed since the last read. You get a webhook when a section moves, plus a diff of the old and new text. That is different from a legal news feed, and it is also different from an official announcement that a law takes effect on a date. It is a change in the published text, detected by machine, delivered to your system so a human or an agent can go look.
If your product carries a customer obligation that points at a statute or a rule, this is the piece you can't build cheaply yourself. Re-reading millions of sections on a cadence is the whole job.
Reviewed and corrected on 12 October 2026. This is general information, not legal advice.
TL;DR
- A board is one tracked corpus source. It is identified by a corpus type plus a jurisdiction, and jurisdiction is null for federal boards. Each board carries its own refresh cadence.
- Discovery is free.
GET /boardslists every watchable source, each row carrying the interval it runs on and when we last pulled the source from its publisher, so you can build your subscription UI before you spend a credit. - A change event is a detected difference between two retrievals of the same section. It is a signal to look, not a legal conclusion, and not an effective-date announcement.
- Webhooks fail. Design for it. Push is the latency channel. The changes endpoint is the source of truth. The deliveries endpoint is how you reconcile the two.
- Check a board's last retrieval before you trust its silence.
lastRetrievedAtandcadenceonGET /boardslet you compare when we last pulled a source with how often it is declared to refresh, before you wire an alert to it. - This is per-section change detection, and
asOfbuilds on it. The corpus holds the current text of each citation. An earlier text is rebuilt from the changes we recorded, which is whatasOf=YYYY-MM-DDon the section body endpoint does.

Your compliance product receives an alert that a section of a regulation changed overnight, and one customer's obligation points at it. What should happen before anyone is told the law changed?
Filed under our legal data infrastructure series.
Everything upstream of the webhook is How We Know a Law Changed. The limit no alert feed gets past is Amendment History and Point-in-Time Law.
A short history: the paper version of a change alert
Lawyers had this problem long before webhooks. A statute book was printed once and the law kept moving afterwards. The fix was the supplement. A University of South Carolina law library research guide describes the setup that still exists for the official U.S. Code: a fresh edition every six years and "five annual hardbound cumulative supplements" in between. Annotated codes do it with "a cumulative pocketpart inserted in the back of that volume or a separate cumulative softbound supplement."
A Hacker News commenter described what that looked like around 1960: "There are frequent supplements to the books (each book had a slip in the cover to insert a supplement), and cumulative indexes every so often" (tzs, Hacker News, October 2014). Years later the same commenter summed up the whole apparatus of indexes, summaries and citation books as "essentially a database system, implemented entirely in books" (tzs, Hacker News, July 2022).
The "is this still good law" half of the job got its own product early. In 1873, Frank Shepard, a salesman for a Chicago legal publisher, designed and published his first citation book, Illinois Citations, according to the History of Information timeline. It listed which later authorities cited an earlier one, and "Shepardizing" is still what lawyers call that check.
Look at what those systems have in common with a webhook. Somebody else does the watching and hands you a small update, and you still have to read it. Nobody Shepardized a case and then stopped reading cases. The alert tells you where to look.
The model in one paragraph
A board is one tracked corpus source. A watch is your subscription to a board. A change event is one section on that board whose text differed between two retrievals. A delivery is one attempt to push one change event to your endpoint.
Four nouns. Everything else in this post is what happens between them.
What a board actually is
A board isn't a keyword. It is a source we already re-read on a schedule for the corpus itself, exposed as something you can subscribe to. The cadence is the interval the board is declared on. It is a staleness window, not a promise to you and not a ceiling on how often the source is re-pulled.
Boards are keyed on corpus type plus jurisdiction. cfr has no jurisdiction, because the Code of Federal Regulations is federal. state plus tx is the Texas statutory code. state_regulation plus ny is the New York administrative code. A federal board's jurisdiction field is null, and that is the discriminator your code should switch on. The uppercase names the search endpoints use (CFR, USC) are matched case-insensitively, but a state board's corpusType is its own name, so copy it from GET /boards.
Here are the boards with no state, as GET /boards?state=federal listed them on 12 October 2026 (14 boards). The corpusType on a board is lowercase and does not always match the name you search with: the Sentencing Guidelines and the US tax treaties share one board, and the agency manuals have a board of their own. Read each board's own cadence from GET /boards.
| Board as listed | corpusType on the board | Declared cadence |
|---|---|---|
| eCFR | cfr | daily |
| Federal Register | federal_register | daily |
| Federal Register notices (curated: withdrawals, comment periods, guidance) | federal_register_notice | monthly |
| USC | usc | weekly |
| US Statutes at Large (session laws) | session_law | monthly |
| Federal agency guidance | agency_guidance | monthly |
| Agency manuals (DOJ JM, USCIS PM, ...) | agency_manuals | monthly |
| Federal administrative adjudications | agency_adjudication | monthly |
| Federal Rules of Procedure | federal_rules | monthly |
| Federal local court rules | federal_local_rules | weekly |
| US Sentencing Guidelines + US tax treaties | federal_primary_law | monthly |
| Statute compilations (acts as amended) | statute_compilation | monthly |
| State constitutions (all states, single monthly pass) | state_constitution | monthly |
| State Dept. of Insurance bulletins | state_insurance_bulletins | monthly |
State boards follow the same shape, one board per jurisdiction, each with a two-letter state: state for statutory codes, state_regulation for administrative codes, state_rules for court rules, plus per-state boards such as state_constitution, state_insurance_bulletins and state_ag_opinion where they exist (on 12 October 2026 Texas and New York each had six boards). GET /boards?corpusType=state lists the statute boards. A jurisdiction can be covered without being watchable, so a missing board is not a missing corpus.
Step 1: list the boards, for free
GET /boards costs nothing. Call it first and cache it, because it is also where you read each source's cadence and last retrieval.
curl -s https://api.vaquill.ai/api/v1/boards \
-H "Authorization: Bearer vq_key_..."
Each board comes back with two fields your integration should care about:
cadencetells you how often that board refreshes, which bounds how quickly a change on it can reach you. Set your customer-facing expectations from this field, and make no promise of fresher data than it supports.lastRetrievedAttells you when we last pulled that source from its publisher. If this is old relative tocadence, do not read silence as nothing changed.
Check total and hasMore. The registry grows as corpora are added, so a client that assumes one page holds every board will eventually render a partial list as "every source we track" and quietly hide corpora from your users.
Step 2: create a watch
A watch binds a board to a delivery target. In the simplest form that is a corpusType, a state (omit it, or pass federal, for a federal board), a channel (webhook, email or both) and, for webhooks, a webhookUrl on your side. Add a webhookSecret and every delivery carries an X-Vaquill-Signature: sha256=<hex> header, an HMAC-SHA256 of the raw request body, so your handler can check the message is intact. The law change alerts reference lists every field a watch accepts, along with the plan limits on webhook delivery and on how many watches an account can hold.
curl -X POST https://api.vaquill.ai/api/v1/watches \
-H "Authorization: Bearer vq_key_..." \
-H "Content-Type: application/json" \
-d '{
"corpusType": "cfr",
"channel": "webhook",
"webhookUrl": "https://example.com/hooks/vaquill",
"webhookSecret": "a-secret-only-you-know",
"scope": {"title": "29", "part": "1910"}
}'
Not run in our October 2026 review: creating a watch changes an account, so this request follows the OpenAPI document and the alerts guide rather than a live call.
Scope narrowly. A watch on cfr with no scope is a watch on more than 222,000 sections of a board declared daily. That is reasonable for a regulatory monitoring product and a bad default if you are watching the four rules one customer's obligation depends on. A scope narrows a watch in one of four mutually exclusive ways: a hierarchy prefix (title, chapter, part, section), one exact section by its actId, a named source on the boards that fold several bodies of law together, or a publishing agency. A scoped watch stays silent when nothing inside its scope changed, so your alert volume becomes reviewable by a human.
Do not make the webhook your only path. Decide this now, because retrofitting reconciliation onto a push-only integration is a rewrite.
Step 3: test it before you trust it
There is a test operation on a watch for one reason: your endpoint will be wrong the first time. Wrong path, wrong auth header, a body parser that rejects the content type, a load balancer that returns 200 before your handler runs.
Fire the test, confirm your handler wrote a row, then go live. The test is sent with an X-Vaquill-Event: board.test header so your handler can tell it from a real board.updated event, it is not stored in delivery history, and a watch accepts one test every 30 seconds.
Step 4: read the changes
GET /watches/{watchId}/changes (MCP tool list_watch_changes) gives you the change events on a watch. This is the endpoint you poll, and where your reconciliation loop lives. Keep the meta.cursor from each page and pass it back as sinceId to get only what is new, with order=asc while catching up. It covers the source's whole captured history, not only the period since you subscribed, and its events are swept after five years.
Poll it on a schedule that matches the board cadence plus a safety margin. For a daily board, every few hours is plenty. For a weekly board, daily is plenty. The point of the poll is completeness, not latency. A webhook body names at most 10 changed sections and reports the rest in changesOverflowCount, and the id on each item is directly usable as the sinceId that pages the remainder.
Step 5: get the diff
GET /watches/{watchId}/changes/{changeId}/diff (MCP tool get_watch_change_diff) returns the text of one changed section before and after. That is what makes this useful rather than noisy. It is the one metered route in the alerts family, at 4 credits, and it is refunded when it cannot resolve the text. An amended section returns both sides, an added section only the new text, and a removed section only the last text we held.
A section-level diff tells you whether the change was a substantive amendment to an exposure limit or an editorial fix to a cross-reference. Without it you are forwarding "something changed in 29 C.F.R. 1910" to a compliance analyst, which teaches them to ignore you.
For any section, watched or not, there is also a section-level change history (GET /us/statutes/section/{actId}/changes, 1 credit). If you already know the actId, you can read its change record directly without holding a watch.
Step 6: reconcile with deliveries
GET /watches/{watchId}/deliveries (MCP tool list_watch_deliveries) is the audit trail of push attempts, newest first, and it only has history for watches on the webhook or both channel. Delivery history is kept for 90 days. It is the endpoint most integrations skip and then wish they had.
Here is the concrete failure it solves. Your webhook handler sits behind a deploy. For 40 minutes it returns 502. A daily board fires during that window. Your system has no row for that change, no error, and no signal that anything is missing, because a webhook that never arrived leaves no evidence on your side.
The fix is a reconciliation job, not better uptime:
- Every hour, list changes on each watch since your last stored cursor.
- For anything you haven't already processed, process it.
- When a customer asks "why did I not get alerted about X," list deliveries for that watch and answer with an actual attempt record instead of a shrug.
Read deliveryHealth on that route on a schedule of your own. It turns to failing after three consecutive failed attempts, and nothing else notifies you: no email, no callback, and the watch stays active while every delivery fails. Deliveries do not follow redirects, so a 3xx counts as a failed delivery and the endpoint you register should be its final URL.
What developers say about webhooks
The "push for speed, pull for completeness" design is old. In a 2013 Hacker News thread about webhooks, a commenter wrote: "Write a polling (or hanging-get) system, but use webhooks as an unreliable but lower-latency push mechanism. In this setup, webhooks give you low-latency updates (when they work), and polling ensures completeness." (philsnow, Hacker News, September 2013).
More than a decade later the advice hasn't moved. In an Ask HN thread on how people monitor and retry failed webhooks in production, one reply lists rules that "have saved us", starting with "Persist before responding. Never process inline. Write payload to DB, return 200 fast." It ends with a line worth taping to a monitor: "Relying on provider retries alone has bitten us more than once." (blundergoat, Hacker News, February 2026).
Stripe's webhook documentation says the same thing about duplicates: "Webhook endpoints might occasionally receive the same event more than once," and suggests logging the event IDs you've processed so you can skip repeats. That is the upsert-on-event-id advice from the tip above, written by a payments company that has to get this right.
Legal alerts add one twist to the generic advice. A missed payment event costs money, and a missed rule change can cost a customer a compliance deadline, so the reconciliation poll is cheap insurance that you'll want in place before the first real alert.
What a change event is, and what it is not
This is the part that decides whether your product is trusted or embarrassing.
A change event is: the text of one section, retrieved from the government publisher, differing from the text of that same section retrieved on the previous cycle.
A change event is not:
- An official announcement that a law takes effect on a date. Publishers post amendments on their own schedule, sometimes before the effective date, sometimes after.
- A statement that the change is substantive. A typo fix, a renumbered cross-reference, and a re-flowed table all produce a real textual difference.
- A legal conclusion. Nothing in a diff tells you whether your customer's obligation moved.
The right consumer behavior is: a change event is a signal to look. Route it to a diff, apply your own materiality filter, and only then page a human. The four false positive families that make that filter necessary are catalogued in how we know a law changed.
Design notes worth reading before you wire it up
Check the last retrieval before you wire an alert
A cadence is a schedule, and a schedule does not promise the last run worked. A watch on a board nobody is re-reading will never fire, which is why you compare lastRetrievedAt with cadence before you wire an alert.
Some jurisdictions are covered but not watchable at all, so GET /boards is the list of what can be watched and never the list of what is covered.
Point-in-time text is a reconstruction
The corpus behind a board holds one current text per citation, and asOf=YYYY-MM-DD on the section body endpoint rebuilds an earlier text from the before-side of the first change we observed after your date. Where we hold a publisher's own printed editions (the CFR annual editions, for one) it returns the edition that governs your date instead. Elsewhere it is a reconstruction. The asOf block reports isBounded when the answer rests on when change capture began, and a section we know changed but cannot rebuild comes back unavailable. That is worth knowing before integration rather than during it. Legal Data Provenance describes how the sourcing works.
Also available: amendment history and a lastAmendedYear on each section, a yearFrom/yearTo currency filter that reads the last amendment year the publisher credits, and the changes endpoint, which replays the captured history of a source. If your use case is "show me the verified text as it stood in 2019," check the asOf block on every answer, and Amendment History and Point-in-Time Law sets out the snapshot-and-watch pattern that adds your own record.
Sourcing, because it changes what an alert means
Boards read the government publisher's own copy wherever one is published. Where a state points to a commercial publisher for its current consolidated text (Vermont's court rules, for one) or only offers an unofficial free copy (Massachusetts regulations, for one), the coverage guide says so.
A secondary compiler can add its own editorial latency and its own error surface between the legislature and you. If your alert says a rule moved, you want the provenance chain to be one hop, and every result carries the publisher's own source URL where the publisher provides one, so a lawyer can click through and confirm.
The same surface over MCP
Every operation here is also published as an MCP server at mcp.vaquill.ai, using the same vq_key_ credential, and set up in the Vaquill AI MCP integration guide. The tool names map one to one:
| Operation | MCP tool |
|---|---|
| Discover watchable sources | list_boards |
| Create a subscription | create_watch |
| Change a subscription | update_watch |
| Remove a subscription | delete_watch |
| Fire a test delivery | test_watch |
| Read change events | list_watch_changes |
| Read one per-section diff | get_watch_change_diff |
| Audit push attempts | list_watch_deliveries |
| Read a section's change history | get_section_changes |
That means an agent can hold a watch and reason about its own diffs without you writing an HTTP client. For how that fits a broader agent setup, see our guide on adding legal research to an AI agent over MCP.
A worked integration, end to end
A compliance platform tracks one customer obligation: hazard communication labeling under 29 C.F.R. 1910.1200.
- Call
GET /boards, find theCFRboard, readcadenceas daily. That is the expectation you set internally. - Create a watch scoped to the CFR part the obligation depends on (
{"title": "29", "part": "1910"}), withwebhookUrlpointing at your ingest handler. - Fire the test. Confirm a row lands. Ship.
- On each webhook, fetch the diff and run your materiality rule. Cross-reference renumbering goes to a log. A changed substantive requirement goes to the analyst queue.
- Hourly, poll changes since your stored cursor and process anything the push missed.
- Weekly, compare each board's
lastRetrievedAtagainst itscadence. A board that has gone quiet is your upstream alarm, and it can fire before a customer notices. That comparison is written out in the coverage monitoring recipe.
Step 6 is the one teams skip. A silent source and a source with no changes look identical from inside your database. Comparing lastRetrievedAt with cadence tells them apart.
Who this is wrong for
- Teams who need verified historical text. Earlier text is a reconstruction from recorded changes, bounded by when capture began, with published editions only for some corpora, so a "what did this say in 2019" product needs its own checks.
- Teams who want editorial analysis. A diff is raw. A lawyer's summary of what a change means is a different product.
- Teams tracking case law. These boards cover statutes, regulations, court rules, constitutions, session laws, and agency guidance. Primary law, not opinions.
- Teams watching a board that is not being polled. A watch can't conjure a retrieval that isn't happening, so compare
lastRetrievedAtwithcadencebefore you rely on one.
You can browse the watchable sources and the alert model on the Law Change Alerts page, and check per-jurisdiction currency at the API coverage docs.
FAQ
What is a law change alerts API?
It is an API that re-reads government legal publishers on a schedule and tells you which individual sections changed since the last read. You subscribe to a source, receive a webhook when a section moves, and fetch a per-section diff of the old and new text. It is change detection over primary law, not a news feed.
How is a change event different from an effective date?
A change event means the published text differed between two retrievals. An effective date is a legal fact the publisher or the legislature states separately. A section can change in the published text before, on, or after its effective date, so treat a change event as a prompt to check the effective date, not as the answer.
What happens if my webhook endpoint is down?
You lose the push notification for that event, which is why the changes endpoint exists. Poll it on a cadence that matches the board, process anything you haven't seen, and use the deliveries endpoint to see the record of push attempts. An integration built only on webhooks has no way to detect what it missed.
How often do boards refresh?
It depends on the board, because cadence follows the publisher. On 12 October 2026 the eCFR and Federal Register boards declared daily, the USC and federal local court rules boards weekly, and most others monthly, including state regulations, court rules and constitutions. Read cadence from GET /boards rather than hardcoding it, and read lastRetrievedAt alongside it.
Can I get the text of a section as it stood on a past date?
Yes, by adding asOf=YYYY-MM-DD to a section body request. The CFR annual editions, and the few other corpora where we hold published editions, answer from a printed edition we hold. Everything else answers from the change events this post is about: the text is rebuilt from the first recorded change after your date, which is why watching and asOf share one record. isBounded shows when the answer rests on when capture began rather than on the law, and a section we know changed but cannot rebuild returns unavailable. You also get amendment history per section, a lastAmendedYear, a yearFrom/yearTo currency filter, and a changes endpoint that replays the captured history of a source.
Does listing boards cost credits?
No. GET /boards is free, along with GET /us/statutes/coverage. Discovery being free is deliberate, because you should be able to build your subscription UI and your monitoring before you commit to spending.
How do I avoid alerting my customers on typo fixes?
Fetch the diff for every change event and apply your own materiality rule before escalating. Editorial fixes, renumbered cross-references, and template re-renders all produce real textual differences. The diff is what separates a substantive amendment from formatting noise.
Which jurisdictions are not covered?
Statutes and regulations cover 50 states, DC, Puerto Rico, Guam, the Northern Mariana Islands, the US Virgin Islands and American Samoa. Coverage varies by corpus, and GET /us/statutes/coverage is the authoritative list. Each board reports its own cadence and lastRetrievedAt, and GET /boards lists what can be watched, which is narrower than what is covered: the alerts guide names seven state statute jurisdictions that are covered but not watchable.
Is this available over MCP?
Yes. The full board and watch surface is published as an MCP server at mcp.vaquill.ai with the same vq_key_ credential, so an agent can list boards, create watches, and read diffs as tools.
New legal AI guides, weekly.
Further Reading
Evaluating a Legal Data Vendor: The Security and Deployment Questions to Ask
Read postAmendment History and Point-in-Time Law: What a Legal API Can and Cannot Tell You
Read postWhy Legal Data Cannot Refresh Faster Than Its Publisher
Read postHow We Know a Law Changed: Boards, Diffs, and the False Positives Nobody Talks About
Read postLegal Data Provenance: How to Tell Where a Statute Actually Came From
Read postHybrid Search Over 20 Million Legal Passages: Why Semantic Alone Fails on Law
Read post
Co-Founder & CTO
Priyansh leads engineering and AI at Vaquill AI: the pipelines that pull statutes, regulations and court rules from every US jurisdiction's official publisher, and the REST API, MCP server and open dataset that serve them.