For developers · API + SDKs + MCP

Build on the AI-regulation dataset.

One audited JSON API — plus an MCP connector for your assistant. Every record source-linked, every endpoint versioned. Free self-serve key, no card.

$ pip install ai-law-trackerPYTHON
$ npm i @ailawtracker/ai-law-trackerJS / TS
BASE URLhttps://ai-law-tracker.com/api/v1
Quickstart

First call in under a minute

curl200 OK
$ curl "https://ai-law-tracker.com/api/v1/laws
        ?scope=state&jurisdiction=california" \
  -H "X-API-Key: alt_free_k3y"

{ "api_version": "v1",
  "data": [  ] }
quickstart.pyPYTHON
from ai_law_tracker import Client

alt = Client(api_key="alt_free_k3y")
laws = alt.laws.list(
    scope="state",
    jurisdiction="california")
quickstart.tsJS / TS
import { Client }
  from "@ailawtracker/ai-law-tracker";

const alt =
  new Client({ apiKey: "alt_free_k3y" });
const laws = await alt.laws.list({
  scope: "state",
  jurisdiction: "california" });
The surface

32 versioned endpoints, 4 scopes

Full API reference →
Laws & search8 ENDPOINTS
GET /v1/lawsGET /v1/laws/{id}GET /v1/search+ 5 more
Statutes, rules and enforcement actions with full citation trails.
Obligations & risk7 ENDPOINTS
GET /v1/obligationsGET /v1/penaltiesGET /v1/deadlines+ 4 more
Who must do what, by when — plus penalties and a reproducible risk score.
Changes & webhooks7 ENDPOINTS
GET /v1/changesPOST /v1/webhooksGET /v1/feed+ 4 more
A diff feed of the law — poll it, or subscribe to signed webhooks on change.
Meta & account10 ENDPOINTS
GET /v1/jurisdictionsGET /v1/healthGET /v1/me+ 7 more
Jurisdiction lists, theme taxonomy, dataset freshness, keys and usage.
MCP connector

33 tools in Claude & ChatGPT

Query the dataset straight from your assistant — search laws, pull deadlines, compare jurisdictions and cite primary sources without leaving the conversation.

Connect the MCP server
search_ai_lawsget_ai_lawlist_recent_changesget_ai_obligationsget_ai_penaltiesget_ai_deadlineslist_jurisdictionsget_law_sources+ 25 more
Pricing

Start free. Scale when you do.

Full pricing →
Starter
$49/mo
150 req/min · 5,000/day
Production headroom: higher limits, deep pagination, the change feed and record history.
Choose Starter
Pro
$99/mo
300 req/min · 10,000/day
Full change-feed history, the interpreted obligations layer, webhooks and priority support.
Choose Pro
Business
$299/mo
1,000 req/min · 15,000/day
Multiple keys, higher quotas and an SLA for teams that ship on the data.
Choose Business
Full API reference

Everything, in detail

Read-only, versioned access to every AI law and bill we track — US state & federal, the EU, and globally — with a changelog you can poll and HMAC-signed webhooks for changes. Get a free key in seconds.

Get a free keyWhat paid unlocksUse in Claude / ChatGPTInteractive referenceDashboardOpenAPI 3.1 specPostman collectionPricing
Base URL https://ai-law-tracker.com/api/v1
Ground truth for AI regulation: cited, deterministic, machine-readable.

Ask a general-purpose chatbot which AI laws apply to you and it will produce a fluent, confident, unciteable answer — and sometimes a statute that does not exist. This API answers the same question from a curated corpus of primary sources, with no language model anywhere in the path. Every obligation, deadline and penalty we return is retrieved verbatim from a real record and carries the government URL it came from. Same input, same output, every time.

Why teams pay — what paid unlocks

The free tier is not a crippled dataset — it is the full record quality at low volume. What you buy is the interpreted layer above the raw law, the change stream beneath it, and the headroom to run both in production.

The moat
The interpreted obligation layer

Turns "here is the statute" into "here is what you must do, by when, or you owe what."

Raw law records tell you a bill exists. /v1/obligations, /v1/assess and /v1/penalties answer the question a compliance team actually has: given this jurisdiction, sector and AI use, which duties attach, what is the deadline, who enforces it, and what is the penalty. The derivation runs through the same deterministic engine as our paid compliance report — no LLM in the path — so it cannot invent a statute, a deadline or a fine. Each item ships with its citation, the enforcing body, a primary-source URL and a source_tier you can audit.

GET /v1/obligationsPOST /v1/assessGET /v1/penaltiesGET /v1/sectors
Penalties open at Starter; obligations and assessments at Pro. Lower tiers get a 1-item preview, never a blank wall.
The reason to stay
Know the moment a law moves

A signed webhook the moment a record changes — instead of re-crawling the dataset on a timer.

Every observed insert and update lands in an append-only history, exposed as /v1/changes and the human-scannable /v1/feed with field-level diffs (status: "In committee" → "Passed House"). Poll it with a cursor, or stop polling entirely: subscribe a webhook and each change is delivered as an HMAC-SHA256-signed POST, retried with backoff and dead-lettered if your endpoint stays down. This is what a static PDF tracker structurally cannot give you.

GET /v1/changesGET /v1/feedGET /v1/laws/{id}/historyPOST /v1/webhooks
The change feed and per-record history open at Developer, and the window widens with tier. Webhooks open at Pro.
The scale
Built to run in production

See the full data quality for free. Pay when you put it in front of your users.

A free key returns the complete record — full fields, full filters — so you can evaluate the data properly before spending anything. What paid tiers add is production capacity: higher rate limits and durable daily quotas, deep pagination, bulk export at Business, and commercial use without the attribution backlink the free tier requires.

GET /v1/meGET /v1/lawsGET /v1/search
Volume, pagination depth and bulk export climb with each tier.
What the interpreted layer actually returns

A live record from the deterministic engine — not a mock-up. This page renders it by calling the same code /v1/obligations runs, so it always matches what the endpoint would answer today.

GET /v1/obligations?jurisdiction=colorado&sector=hr-recruiting&use=hiring
{
  "law": "NYC Local Law 144 (Automated Employment Decision Tools)",
  "jurisdiction": "New York",
  "layer": "landscape",
  "lifecycle": "in_force",
  "in_force": true,
  "not_yet_effective": false,
  "effective_date": "2023-07-05",
  "applies_because": "Notable New York AI law, included for the national landscape. It binds businesses in New York — it may not apply to you unless you operate there.",
  "obligation": "Employers using automated employment decision tools to screen candidates or employees for NYC positions must conduct an annual independent bias audit, publish a summary on the employer website, notify candidates at least 10 business days in advance, and offer an alternative selection process on request.",
  "deadline": null,
  "penalty": "$500 for first violation; $500 to $1,500 for each subsequent violation, per day per candidate; DCWP enforcement",
  "status": null,
  "citation": "NYC Admin. Code Section 20-870 et seq.; 6 RCNY Sections 5-300 to 5-304 (effective July 5, 2023)",
  "government_body": "NYC Department of Consumer and Worker Protection",
  "may_not_apply": true,
  "source_url": "https://www.nyc.gov/site/dca/about/automated-employment-decision-tools.page",
  "source_tier": "primary"
}

Note source_url and source_tier: every obligation is traceable to the government page it came from, and you can tell a primary source from a secondary one. Informational only — not legal advice.

What each tier unlocks

Every cell below is read straight from the capability matrix the API enforces at request time — this table cannot promise something the gate would refuse. Prices and billing live on the pricing page.

CapabilityFreeStarterProBusiness
Interpreted obligation layer
Obligations — GET /v1/obligations
Opens at Pro
Preview (1 item)Preview (1 item)FullFull
Risk assessment — POST /v1/assess
Opens at Pro
Preview (1 item)Preview (1 item)FullFull
Penalties & enforcement — GET /v1/penalties
Opens at Starter
Preview (1 item)FullFullFull
Change intelligence
Change feed — /v1/changes, /v1/feed
Developer+
30-day window90-day windowFull history
Per-record history — /v1/laws/{id}/history
Developer+
30-day window365-day windowFull history
HMAC-signed change webhooks
Pro+
3 endpoints25 endpoints
Volume & access
Records per request25100100100
Pagination depth (max offset)200100,000500,0005,000,000
Rate limit60/min · 300/day150/min · 5,000/day300/min · 10,000/day1,000/min · 15,000/day
Bulk exportIncluded

Enterprise is quoted per contract: unlimited API requests (no monthly quota, no overage) with 2,000 req/min guaranteed, full history, unlimited webhooks, bulk export, and OEM/resale terms — subject to Fair Use (we reach out before we throttle; bulk redistribution needs a licence). See /terms#fair-use.

See pricing & subscribeStart free

Quick start

Every endpoint works anonymously at a low rate. Add your key to raise the limit and identify your app.

cURL
# List the 5 most recently updated records
curl "https://ai-law-tracker.com/api/v1/laws?limit=5&sort=updated_at&order=desc" \
  -H "X-API-Key: alt_free_9f3c…"
JavaScript (fetch)
const res = await fetch(
  "https://ai-law-tracker.com/api/v1/laws?scope=state&jurisdiction=colorado",
  { headers: { "X-API-Key": process.env.ALT_API_KEY } }
);
const { data, meta } = await res.json();

Use it in Claude & ChatGPT

The same data is exposed as an MCP (Model Context Protocol) server, so you can ask Claude or ChatGPT about AI regulation and it will query this dataset live — laws, jurisdictions, news, the change feed, and the interpreted obligations / penalties / risk layer. No key works at the anonymous tier; paste your key to unlock full tiers.

MCP endpoint https://ai-law-tracker.com/api/mcp (Streamable HTTP)
Claude — custom connector
  1. Claude.ai → Settings → Connectors → Add custom connector.
  2. URL: https://ai-law-tracker.com/api/mcp
  3. Under Request headers, add x-api-key = your AI Law Tracker key (optional — skip it to try the anonymous tier).
  4. Save, then ask e.g. “What AI hiring laws apply in California?”
ChatGPT — Custom GPT Action
  1. Create a GPT → Configure → Actions → Import from URL.
  2. Schema URL: https://ai-law-tracker.com/api/v1/openapi.json
  3. Authentication → API Key, custom header name X-API-Key, paste your key.
  4. In ChatGPT developer mode you can instead add the MCP endpoint above as an app.

Full setup notes (including the Connectors Directory / GPT Store path) live in docs/MCP-CONNECTOR.md. The connector is read-only and returns informational data — not legal advice.

Authentication

Pass your key on every request in either header:

X-API-Key: alt_free_9f3c…
# or
Authorization: Bearer alt_free_9f3c…

A missing key is fine — you're served as anonymous at the per-IP cap. An invalid or revoked key returns 401/403. Keep keys server-side.

Get a free key

Pick a product, enter your email — we'll mint a free-tier key and send it over. No card, no wait.

One active key per email, per product — an AI Law Tracker key does not use up your US Law Platform one. By requesting a key you agree to the Terms. Data is CC BY 4.0 — attribution required on the free tier.

Rate limits

Every response carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset. Over the limit returns 429 with Retry-After.

TierPer minutePer day
Anonymous (no key)20100
Free60300
Starter1505,000
Pro30010,000
Business1,00015,000
OEM / White-label1,50020,000
Enterprise2,0002,000,000

Need more? See paid tiers →

US Law Platform — /v1/us-law

A separate product from the AI-law endpoints above: the general US-law corpus (~31,800 records across 52 jurisdictions), classified into 33 branches and 227 subcategories. A key is licensed for one product line or both — check yours with GET /v1/me, which reports product, your record allowance and your export entitlement. On a surface outside your licence you are served at the public (keyless) level, and the X-ALT-Product-Scope response header says so.

Metered on records served, not just requests. A request cap stops a fast client; a record cap stops a patient one. Every response carries meta.record_budget with what is left in the day and 30-day windows.

EndpointWhat it doesAccess
GET /v1/us-lawList + filter the corpus (jurisdiction, instrument_type, branch, domain, in_force)Everyone, metered
GET /v1/us-law/searchFull-text + citation + EO-number searchEveryone, metered
GET /v1/us-law/records/{uid}One record in fullEveryone, metered
GET /v1/us-law/jurisdictionsPer-jurisdiction coverage rollupOpen — no key, not metered
GET /v1/us-law/taxonomyThe classification tree + corpus healthOpen — no key, not metered
GET /v1/us-law/exportBulk export manifest — signed part linksUS Law Business+ (licence)
GET /v1/us-law/export/downloadStream one part (NDJSON | CSV | JSON)Signed token only
GET /v1/us-law/opinionsUS case law — 988,554 published opinions (2015+): court, date range, case name, citationEveryone, metered
GET /v1/us-law/opinions/{cluster_id}One opinion record in fullEveryone, metered
GET /v1/us-law/courtsPer-court opinion coverage + the court lookupOpen — no key, not metered

US case law

988,554 published opinions filed 2015 onward, from federal appellate courts and state supreme/appellate courts. Each record identifies a decision — case name, court, filing date, docket number, reporter citation, and how many later opinions cite it — and links to the decision itself. There is no opinion text and no holding in this corpus. It is metered on the same record budget as /v1/us-law, not a second one, so nothing about your existing allowance changes.

# every opinion a court filed in a date window, newest first
curl "https://ai-law-tracker.com/api/v1/us-law/opinions?court=scotus&filed_from=2024-01-01&limit=25"   -H "X-API-Key: $ALT_KEY"

# by reporter citation (exact, case-sensitive) — or widen with citation_prefix
curl "https://ai-law-tracker.com/api/v1/us-law/opinions?citation=2022%20OK%2038" -H "X-API-Key: $ALT_KEY"

# by case name: websearch syntax, quoted phrases and -exclusion
curl "https://ai-law-tracker.com/api/v1/us-law/opinions?q=%22Trump%20v.%20Cook%22" -H "X-API-Key: $ALT_KEY"

# which courts we cover, and how deeply — no key needed
curl "https://ai-law-tracker.com/api/v1/us-law/courts?jurisdiction_level=federal"

Two things behave differently here because the table is a million rows, and they apply at every tier including Enterprise. meta.total is the query planner's estimate above 1,000 rows — always read meta.total_is_estimate, and pass count=exact (needs any key, takes seconds) when you need the real number. And sort=citation_count / cited_min have no index behind them, so they are refused with a 400 unless your query already carries a narrowing filter. Coverage is uneven and /v1/us-law/courts publishes it: 147 of the 293 registered courts hold zero opinions, and a zero there is a gap in our coverage, not a fact about the court.

Bulk export in two calls

Ask for any slice the list endpoint can filter. You get back the exact row count, what it will cost against your record allowance, and one signed, 15-minute link per 10,000-row part. The links carry no API key, so you can hand one to a loader without handing over your credential — and every download is still metered against the key that created it.

# 1. plan it — nothing is charged here
curl "https://ai-law-tracker.com/api/v1/us-law/export?format=csv&instrument_type=executive_order" \
  -H "X-API-Key: $ALT_KEY"
# -> { "export": { "records": 277, "parts": 1, "record_cost": 277, ... },
#      "parts": [ { "part": 1, "records": 277, "url": "...?token=...", "expires_at": "..." } ] }

# 2. pull each part (order matters; for CSV keep only the first header row)
curl -L -o part01.csv "<parts[0].url>"

Bulk export is not sold self-serve: taking the whole corpus as a file is arranged with us under licence, from the US Law — Business tier up. Exported records are metered against your allowance exactly as paged ones are. Every self-serve plan keeps full API access to the same data. See the ladder →

Enforcement layer — /v1/enforcement

AI enforcement actions and litigation at matter level — one row per dispute, not per press release. An agency action with a complaint, a settlement and a final order is three rows on /v1/enforcement (the news feed) and one matter here, with a timeline, parties, the relief imposed and the statutes invoked attached.

EndpointWhat it doesAccess
GET /v1/enforcement/mattersList, filter and search matters (agency, jurisdiction, type, status, AI role, dates, q)Everyone
GET /v1/enforcement/matters/{uid}One matter + its chain: events, parties, relief, statutes, source docsEveryone; chain sampled below Pro
GET /v1/enforcement/sourcesThe 254 monitored sources, with freshness and fault stateOpen — no key, not metered
GET /v1/enforcement/categoriesThe 13 controlled vocabularies every filter acceptsOpen — no key, not metered
GET /v1/enforcement/coverageHow many matters are held, publishable and withheldOpen — no key, not metered
GET /v1/enforcementThe enforcement + litigation NEWS feed (a separate dataset)Enterprise

What the tier meters is depth, not count. The registry is a few dozen matters, so a record budget would limit nothing. Listing and searching are open at every tier; the assembled dossier — parties, relief amounts, the event timeline, the cited statutes — is a 2-row sample below Pro, and chain_totals always reports the real size of every chain so you can see what a sample is a sample of.

# every FTC matter we hold
curl "https://ai-law-tracker.com/api/v1/enforcement/matters?agency=FTC&limit=25" \
  -H "X-API-Key: $ALT_KEY"

# one matter with its chain
curl "https://ai-law-tracker.com/api/v1/enforcement/matters/us-ftc-2026-cleo-ai-inc" -H "X-API-Key: $ALT_KEY"

# what we watch, and how much of it is answering right now — no key needed
curl "https://ai-law-tracker.com/api/v1/enforcement/sources?is_stale=true"

# how big the registry really is, including what is withheld — no key needed
curl "https://ai-law-tracker.com/api/v1/enforcement/coverage"

Two things to read before you quote a number from this dataset

1. Every matter is single_source. Each one is recorded from one official source and published with the URL it came from. verification is never withheld at any tier — read it, and follow source_url, before relying on any claim.

2. An empty result is a statement about us, not about the agency. Roughly half of the 254 registered sources are currently stale or disabled, and part of the registry is withheld pending review. /v1/enforcement/sources and /v1/enforcement/coverage both publish those numbers — including the withheld count — so coverage can be checked rather than assumed.

Endpoints

GET/v1/health
Liveness + backend status
Example request
curl "https://ai-law-tracker.com/api/v1/health" \
  -H "X-API-Key: alt_free_9f3c…"
Example response
{
  "api_version": "v1",
  "status": "ok",
  "backend": "supabase",
  "records": 697
}
GET/v1/laws
List legal records (filter, sort, paginate)

TIER-GATING: filters and sorting (scope, jurisdiction, status, in_force, updated_since, sort, order) are honoured at EVERY tier including anonymous — they are documented query semantics, so they are never silently dropped. What Free/anonymous callers get instead is low volume and shallow pagination: anon 5 rows per page with a trimmed field envelope, free-key 25 rows with the full field set. Developer+ raises the page size and unlocks deep pagination, the change feed and per-record history. When a request is capped, the response echoes meta.gated + an upgrade hint (it is never a hard error).

ParamInTypeDescription
scopequerystate | federal | eu | globalFilter by scope.
jurisdictionquerystringExact jurisdiction slug (e.g. colorado, eu, us-federal, canada).
statusquerystringCase-insensitive substring match on status.
in_forcequerybooleanFilter by the in_force flag.
updated_sincequerystringOnly records updated at/after this ISO timestamp.
qquerystringSubstring search over title + summary.
sortqueryupdated_at | record_date | title
orderqueryasc | desc
limitqueryinteger
offsetqueryinteger
Example request
curl "https://ai-law-tracker.com/api/v1/laws?scope=state&jurisdiction=value" \
  -H "X-API-Key: alt_free_9f3c…"
Example response
{
  "api_version": "v1",
  "data": [
    {
      "id": "5f9c2b0a-1e34-4d21-9a77-0c1b2d3e4f56",
      "scope": "state",
      "jurisdiction": { "slug": "colorado", "name": "Colorado", "abbr": "CO" },
      "identifier": "SB 24-205",
      "title": "Consumer Protections for Artificial Intelligence",
      "record_type": "bill",
      "status": "Signed — effective 2026-02-01",
      "in_force": null,
      "record_date": "2024-05-17T00:00:00Z",
      "summary": "Requires developers and deployers of high-risk AI systems to use reasonable care to avoid algorithmic discrimination…",
      "source": "leg.colorado.gov",
      "official_url": "https://leg.colorado.gov/bills/sb24-205",
      "updated_at": "2026-07-05T14:02:11Z",
      "attribution": "Data by AI Law Tracker (CC BY 4.0) — https://ai-law-tracker.com"
    }
  ],
  "meta": { "total": 564, "count": 1, "limit": 20, "offset": 0 }
}
GET/v1/laws/{id}
Get one record by uuid
ParamInTypeDescription
id *pathstring
Example request
curl "https://ai-law-tracker.com/api/v1/laws/5f9c2b0a-…" \
  -H "X-API-Key: alt_free_9f3c…"
Example response
{
  "api_version": "v1",
  "data": {
    "id": "5f9c2b0a-1e34-4d21-9a77-0c1b2d3e4f56",
    "scope": "state",
    "jurisdiction": { "slug": "colorado", "name": "Colorado", "abbr": "CO" },
    "identifier": "SB 24-205",
    "title": "Consumer Protections for Artificial Intelligence",
    "status": "Signed — effective 2026-02-01",
    "official_url": "https://leg.colorado.gov/bills/sb24-205",
    "updated_at": "2026-07-05T14:02:11Z",
    "attribution": "Data by AI Law Tracker (CC BY 4.0) — https://ai-law-tracker.com"
  }
}
GET/v1/laws/{id}/history
Full change timeline for one record

Every snapshot of the record (ascending observed_at), each with change_kind, changed_fields and the record values as of that snapshot. TIER-GATING: Developer+ only — anonymous/Free callers get 403 tier_upgrade_required. Lookback window climbs by tier: Developer 30 days, Pro 365 days, Business/Enterprise full history.

ParamInTypeDescription
id *pathstring
Example request
curl "https://ai-law-tracker.com/api/v1/laws/5f9c2b0a-…/history" \
  -H "X-API-Key: alt_free_9f3c…"
GET/v1/changes
Unified changelog (poll for what changed since X)

Time-ordered feed of every observed insert/update across the dataset, unioned from the append-only history of legal records and jurisdiction summaries. Poll with ?since=<meta.cursor>. TIER-GATING: Developer+ only — anonymous/Free callers get 403 tier_upgrade_required (the change feed is the paid differentiator). The lookback window is clamped per tier (Developer 30-day, Pro 90-day, Business/Enterprise full) — see meta.window.

ParamInTypeDescription
sincequerystringOnly changes observed after this ISO timestamp (pass the previous response meta.cursor to poll).
scopequerystate | federal | eu | globalFilter by scope.
jurisdictionquerystringExact jurisdiction slug.
entityquerylaw_record | jurisdictionRestrict to one dataset (default: both).
significantquerybooleanDrop internal metadata-only updates (keeps inserts + real field changes).
orderqueryasc | descOrder by observed_at.
limitqueryinteger
offsetqueryinteger
Example request
curl "https://ai-law-tracker.com/api/v1/changes?since=value&scope=state" \
  -H "X-API-Key: alt_free_9f3c…"
Example response
{
  "api_version": "v1",
  "data": [
    {
      "event_id": "a1b2c3d4-0000-4444-8888-abcdef012345",
      "entity": "law_record",
      "record_id": "5f9c2b0a-1e34-4d21-9a77-0c1b2d3e4f56",
      "scope": "state",
      "jurisdiction": { "slug": "washington", "name": "Washington", "abbr": "WA" },
      "identifier": "HB 1170",
      "change_kind": "update",
      "changed_fields": ["status"],
      "field_changes": [{ "field": "status", "from": "In committee", "to": "Passed House" }],
      "observed_at": "2026-07-07T09:15:44.512Z",
      "attribution": "Data by AI Law Tracker (CC BY 4.0) — https://ai-law-tracker.com"
    }
  ],
  "meta": {
    "count": 1, "limit": 50, "offset": 0, "order": "desc",
    "cursor": "2026-07-07T09:15:44.512Z",
    "window": { "tier": "free", "lookback_days": 90, "clamped": false }
  }
}
GET/v1/feed
Lean stream of recent significant changes

Convenience view over /changes with significant=true and no value diffs — the newest meaningful changes, human-scannable. TIER-GATING: same as /changes — Developer+ only (403 tier_upgrade_required for anonymous/Free).

ParamInTypeDescription
sincequerystringOnly changes observed after this ISO timestamp (pass the previous response meta.cursor to poll).
scopequerystate | federal | eu | globalFilter by scope.
jurisdictionquerystringExact jurisdiction slug.
entityquerylaw_record | jurisdictionRestrict to one dataset (default: both).
limitqueryinteger
Example request
curl "https://ai-law-tracker.com/api/v1/feed?since=value&scope=state" \
  -H "X-API-Key: alt_free_9f3c…"
GET/v1/jurisdictions
List covered jurisdictions with record counts
ParamInTypeDescription
scopequerystate | federal | eu | global
Example request
curl "https://ai-law-tracker.com/api/v1/jurisdictions?scope=state" \
  -H "X-API-Key: alt_free_9f3c…"
Example response
{
  "api_version": "v1",
  "data": [
    { "slug": "california", "name": "California", "abbr": "CA", "scope": "state", "count": 55 },
    { "slug": "eu", "name": "European Union", "abbr": "EU", "scope": "eu", "count": 12 }
  ],
  "meta": { "count": 74 }
}
GET/v1/countries
National (global-scope) jurisdictions with record counts
Example request
curl "https://ai-law-tracker.com/api/v1/countries" \
  -H "X-API-Key: alt_free_9f3c…"
GET/v1/states
US state jurisdictions with record counts
Example request
curl "https://ai-law-tracker.com/api/v1/states" \
  -H "X-API-Key: alt_free_9f3c…"
GET/v1/categories
Dataset facets: record_type + scope distributions
Example request
curl "https://ai-law-tracker.com/api/v1/categories" \
  -H "X-API-Key: alt_free_9f3c…"
GET/v1/news
AI-law news headlines (filter, keyword, date range; newest-first)

The audited AI-regulation news feed (headline + short excerpt + publisher + source URL — never full article text). Free/anon get a TASTE: fewer results, shallow pagination, only the newest headlines (a recency window) and the excerpt withheld. Developer+ gets the full archive, high volume and the excerpt. meta.window shows the tier recency floor; meta.gated + meta.upgrade show what was limited.

ParamInTypeDescription
scopequerystate | federal | eu | globalFilter by scope.
jurisdictionquerystringExact jurisdiction slug (e.g. california, federal, eu, global).
qquerystringKeyword substring search over the headline + excerpt.
fromquerystringOnly headlines published on/after this date (YYYY-MM-DD). Free/anon are clamped to their recency window (see meta.window).
sincequerystringAlias for `from` — poll for headlines since a date.
toquerystringOnly headlines published on/before this date (YYYY-MM-DD).
limitqueryintegerFree/anon are capped lower (a taste).
offsetqueryinteger
Example request
curl "https://ai-law-tracker.com/api/v1/news?scope=state&jurisdiction=value" \
  -H "X-API-Key: alt_free_9f3c…"
GET/v1/sectors
Sector index (valid slugs for /obligations, /penalties, /assess)
Example request
curl "https://ai-law-tracker.com/api/v1/sectors" \
  -H "X-API-Key: alt_free_9f3c…"
GET/v1/obligations
Derived AI-law obligations for a jurisdiction / sector / use

The interpreted "what must I do" layer — who must do what, by when, or owe what penalty — for the given context. Every obligation is grounded in a real law record + its primary source (no LLM). Provide at least a jurisdiction or a sector. NOT legal advice. Paid feature (Pro+); lower tiers receive a one-item preview (meta.preview=true) with an upgrade hint.

ParamInTypeDescription
jurisdictionquerystringA US state slug (e.g. california) OR a covered country slug (e.g. canada, eu-germany). See /jurisdictions.
sectorquerystringA sector slug (see /sectors), e.g. healthcare, finance, hr-recruiting.
usequerystringComma-separated AI uses: hiring, customer, content, analytics, product, other.
decision_impactqueryhiring_firing | credit_insurance | healthcare | housing | internal_only | not_sureWhat the AI decides about people (escalates applicability).
Example request
curl "https://ai-law-tracker.com/api/v1/obligations?jurisdiction=value&sector=value" \
  -H "X-API-Key: alt_free_9f3c…"
GET/v1/penalties
Penalty & enforcement dataset for the applicable laws

Per applicable law: the monetary/other penalty, enforcing body, citation, and primary source, plus a sector-level penalty-structure summary (full result only). Provide at least a jurisdiction or a sector. Paid feature (Developer+); lower tiers receive a one-item preview.

ParamInTypeDescription
jurisdictionquerystringA US state slug (e.g. california) OR a covered country slug (e.g. canada, eu-germany). See /jurisdictions.
sectorquerystringA sector slug (see /sectors), e.g. healthcare, finance, hr-recruiting.
Example request
curl "https://ai-law-tracker.com/api/v1/penalties?jurisdiction=value&sector=value" \
  -H "X-API-Key: alt_free_9f3c…"
POST/v1/assess
Company profile → applicable obligations + 1–10 risk score

The compliance-report engine (deterministic, no LLM — cannot hallucinate) as an API. POST a business profile; get the applicable AI-law obligations plus a reproducible 1–10 risk score with a named factor breakdown. state + sector are required. Paid feature (Pro+); lower tiers receive a preview (risk band + counts + one sample obligation; factor breakdown withheld).

Example request
curl "https://ai-law-tracker.com/api/v1/assess" \
  -X POST \
  -H "X-API-Key: alt_free_9f3c…"
POST/v1/keys
Self-serve: issue a FREE API key by email

Submit an email to mint a free-tier key. The plaintext key is emailed to that address (your durable copy — find it again there anytime) AND returned once in this response. We never store the plaintext server-side. One active free key per email; abusive request rates are throttled per IP.

Example request
curl "https://ai-law-tracker.com/api/v1/keys" \
  -X POST -H "Content-Type: application/json" \
  -d '{"email":"you@company.com"}'
Example response
{
  "api_version": "v1",
  "key": "alt_free_9f3c…  (shown once on screen; also emailed to you)",
  "key_prefix": "alt_free_9f3c",
  "id": "7c0d…",
  "tier": "free",
  "email": "you@company.com",
  "email_delivery": { "delivered": true },
  "note": "Copy your key now — shown once on this screen. We also emailed it to you, so you can always find it again in that email."
}
GET/v1/me
Your account: tier, limits & live usage (requires an API key)

Returns the presenting key's own account — tier, effective rate/quota limits, live durable usage (requests used today + this month, from the api_usage counter), remaining, reset times, and the capabilities the tier unlocks. The key IS the credential; no separate login. Powers the self-serve dashboard at /developers/dashboard. This call itself counts as one request.

🔑 Requires an API key
Example request
curl "https://ai-law-tracker.com/api/v1/me" \
  -H "X-API-Key: alt_free_9f3c…"
Example response
{
  "api_version": "v1",
  "data": {
    "key_prefix": "alt_free_9f3c",
    "tier": "free",
    "owner": "y••••@company.com",
    "revoked": false,
    "created_at": "2026-07-08T12:00:00Z",
    "last_used_at": "2026-07-09T14:22:07Z",
    "limits": { "per_min": 60, "per_day": 2000, "per_month": 60000 },
    "usage": {
      "tracking": true,
      "day":   { "used": 137, "limit": 2000,  "remaining": 1863,  "resets_in_seconds": 35080 },
      "month": { "used": 4210, "limit": 60000, "remaining": 55790, "resets_in_seconds": 2110480 }
    },
    "capabilities": {
      "list_max": 25, "full_fields": true, "advanced_filters": true,
      "changes_window_days": null, "history_window_days": null,
      "webhooks": 0, "bulk_export": false
    }
  }
}
DELETE/v1/me
Revoke your own key (requires an API key)

Self-service revoke of the presenting key. Irreversible — the key can no longer authenticate afterwards. Create a new key to keep using the API.

🔑 Requires an API key
Example request
curl "https://ai-law-tracker.com/api/v1/me" \
  -X DELETE \
  -H "X-API-Key: alt_free_9f3c…"
Example response
{
  "api_version": "v1",
  "data": {
    "key_prefix": "alt_free_9f3c",
    "tier": "free",
    "owner": "y••••@company.com",
    "revoked": false,
    "created_at": "2026-07-08T12:00:00Z",
    "last_used_at": "2026-07-09T14:22:07Z",
    "limits": { "per_min": 60, "per_day": 2000, "per_month": 60000 },
    "usage": {
      "tracking": true,
      "day":   { "used": 137, "limit": 2000,  "remaining": 1863,  "resets_in_seconds": 35080 },
      "month": { "used": 4210, "limit": 60000, "remaining": 55790, "resets_in_seconds": 2110480 }
    },
    "capabilities": {
      "list_max": 25, "full_fields": true, "advanced_filters": true,
      "changes_window_days": null, "history_window_days": null,
      "webhooks": 0, "bulk_export": false
    }
  }
}
POST/v1/webhooks
Subscribe to change events (Pro+ · requires an API key)

Create a webhook. When a matching legal record change is observed, an HMAC-SHA256-signed POST is delivered to target_url. The signing_secret is returned ONCE in this response. Verify each delivery (see x-webhooks). TIER-GATING: Pro+ only (Free/Developer allowance = 0 → 403 tier_upgrade_required). Per-key subscription cap: Pro 3, Business 25, Enterprise unlimited.

🔑 Requires an API key
Example request
curl "https://ai-law-tracker.com/api/v1/webhooks" \
  -X POST \
  -H "X-API-Key: alt_pro_…" \
  -H "Content-Type: application/json" \
  -d '{"target_url":"https://your-app.com/hooks/alt"}'
Example response
{
  "api_version": "v1",
  "data": {
    "id": "b3c4…",
    "target_url": "https://your-app.com/hooks/alt",
    "events": ["law.created", "law.updated"],
    "active": true,
    "signing_secret": "whsec_… (shown once)",
    "created_at": "2026-07-08T12:00:00Z"
  }
}
GET/v1/webhooks
List this key's webhooks
🔑 Requires an API key
Example request
curl "https://ai-law-tracker.com/api/v1/webhooks" \
  -H "X-API-Key: alt_free_9f3c…"
Example response
{
  "api_version": "v1",
  "data": {
    "id": "b3c4…",
    "target_url": "https://your-app.com/hooks/alt",
    "events": ["law.created", "law.updated"],
    "active": true,
    "signing_secret": "whsec_… (shown once)",
    "created_at": "2026-07-08T12:00:00Z"
  }
}
GET/v1/webhooks/{id}
Get one subscription
🔑 Requires an API key
ParamInTypeDescription
id *pathstring
Example request
curl "https://ai-law-tracker.com/api/v1/webhooks/5f9c2b0a-…" \
  -H "X-API-Key: alt_free_9f3c…"
DELETE/v1/webhooks/{id}
Unsubscribe
🔑 Requires an API key
ParamInTypeDescription
id *pathstring
Example request
curl "https://ai-law-tracker.com/api/v1/webhooks/5f9c2b0a-…" \
  -X DELETE \
  -H "X-API-Key: alt_free_9f3c…"
GET/v1/accuracy
Public accuracy ledger — source-health summary + change-observation stats

The machine-readable form of the public /accuracy page. Returns the latest source-liveness sweep summary (how many cited sources were checked, verified live, confirmed broken, or unverified), the count of confirmed-broken sources in the review queue, and the total append-only change-observations on record. Free/public: no tier gate, rate-limited like any endpoint. Every figure is a live count over real rows.

Example request
curl "https://ai-law-tracker.com/api/v1/accuracy" \
  -H "X-API-Key: alt_free_9f3c…"
GET/v1/enforcement
AI enforcement actions + litigation (agency actions and civil dockets; newest-first) — Enterprise only

AI-related regulatory enforcement (FTC/DOJ/SEC/state AG actions, etc.) and civil litigation (federal court dockets), over the same six AET fields — agency, respondent, allegation, outcome, penalty, statutory basis — plus forum for litigation rows. `change_type` tells the two lanes apart. ONLY status approved/published rows are ever returned: every draft the automated watch crons write starts pending and is invisible here until reviewed, so an empty data[] with meta.total: 0 is the expected response while a batch awaits approval — not an error. TIER-GATING: Enterprise-only. Anonymous, Free, and every self-serve paid tier (Developer $29 / Pro $99 / Business $299) get a hard 403 tier_upgrade_required — there is no teaser and no partial access below Enterprise. Same hard-gate pattern as /v1/changes, /v1/feed, and /v1/webhooks.

ParamInTypeDescription
scopequerystate | federal | eu | globalFilter by scope.
jurisdictionquerystringExact jurisdiction slug.
qquerystringKeyword substring search over title + summary.
agencyquerystringSubstring match on the acting agency/regulator (e.g. FTC, DOJ, California Attorney General).
change_typequeryenforcement | litigationRestrict to one lane: enforcement (agency actions) or litigation (civil dockets). Default: both.
date_fromquerystringOnly items recorded on/after this date (YYYY-MM-DD).
date_toquerystringOnly items recorded on/before this date (YYYY-MM-DD).
limitqueryinteger
offsetqueryinteger
Example request
curl "https://ai-law-tracker.com/api/v1/enforcement?scope=state&jurisdiction=value" \
  -H "X-API-Key: alt_free_9f3c…"
GET/v1/sectors/{sector}
One sector: overview + derived obligations & penalties

The free awareness OVERVIEW of a sector (name, risk, enforcement bodies, federal penalty structure) plus the DERIVED per-law obligations & penalties. The overview is open to every tier; the derived obligations/penalties are the interpreted layer — full for Pro+, a one-item preview (meta.preview=true) + upsell below. NOT legal advice.

ParamInTypeDescription
sector *pathstringA sector slug (see /sectors).
Example request
curl "https://ai-law-tracker.com/api/v1/sectors/{sector}" \
  -H "X-API-Key: alt_free_9f3c…"
GET/v1/deadlines
Upcoming AI-law effective / compliance dates (JSON or iCal)

A forward-looking compliance calendar derived deterministically from the curated corpus — each entry carries the VERBATIM source deadline text + primary-source URL (no fabricated dates; a jurisdiction whose deadline text has no explicit date is only counted in meta.undated). Free for every tier. Pass ?format=ical (alias ics) for an RFC 5545 .ics you can subscribe to (webcal). The interpreted "what must I do about each deadline" layer is on /obligations + /assess.

ParamInTypeDescription
scopequerystate | federal | eu | globalFilter by scope.
jurisdictionquerystringExact jurisdiction slug (e.g. california, eu-germany).
upcomingquerybooleanOnly future dates (default). Set false (or all=true) to include past effective dates.
formatqueryjson | ical | icsical/ics returns a text/calendar .ics feed.
Example request
curl "https://ai-law-tracker.com/api/v1/deadlines?scope=state&jurisdiction=value" \
  -H "X-API-Key: alt_free_9f3c…"
GET/v1/bills
Curated landmark-bill index

The named, name-searchable AI laws (valid slugs for /bills/{slug}), from the primary-sourced landmark registry. Free.

Example request
curl "https://ai-law-tracker.com/api/v1/bills" \
  -H "X-API-Key: alt_free_9f3c…"
GET/v1/bills/{slug}
One landmark bill: sources, citations, cross-links

One curated bill — core fields, tiered source URLs, citations (identifier + audited alternate names), and cross-links. Where a matching legal_records row exists, the response binds the live change timeline (links.history → /laws/{id}/history). Primary-sourced; the DB binding is best-effort (a miss omits the link, never fabricates it).

ParamInTypeDescription
slug *pathstringA bill slug (see /bills).
Example request
curl "https://ai-law-tracker.com/api/v1/bills/{slug}" \
  -H "X-API-Key: alt_free_9f3c…"
GET/v1/laws/{id}/sources
Source URLs backing one record (tiered primary/secondary)

A record's own official/.gov link plus the curated jurisdiction sources, each tiered primary/secondary. Basic tiers (anon/Free) get primary sources only; Developer+ get the full set incl. secondary/analysis links. Only real held URLs — never fabricated.

ParamInTypeDescription
id *pathstring
Example request
curl "https://ai-law-tracker.com/api/v1/laws/5f9c2b0a-…/sources" \
  -H "X-API-Key: alt_free_9f3c…"
GET/v1/laws/{id}/citations
Citation projection for one record

A record's identifier, title, audited alternate names, and a formatting-convenience suggested citation over public metadata (labelled — never an official cite). Free at every tier.

ParamInTypeDescription
id *pathstring
Example request
curl "https://ai-law-tracker.com/api/v1/laws/5f9c2b0a-…/citations" \
  -H "X-API-Key: alt_free_9f3c…"
POST/v1/auth/token
Self-serve: issue a FREE API token by email

A conventional token endpoint over the same key store as POST /keys. Submit an email; get a free-tier token, emailed once (durable copy) and returned once here. Only ever mints a FREE token (no privilege escalation); the owner/HMAC secret is never exposed. Paid tiers are granted via Polar checkout (POST /checkout). Throttled per IP; one active token per email.

Example request
curl "https://ai-law-tracker.com/api/v1/auth/token" \
  -X POST \
  -H "X-API-Key: alt_free_9f3c…"
POST/v1/report
On-demand AI compliance report (PDF or signed link) — the $79 report engine as an API

Generate the personalized, source-grounded AI-law compliance report for a business profile — the SAME deterministic engine behind the $79 /compliance-report product (no LLM in the grounded path — it cannot invent a statute, deadline, or penalty). POST state + sector (+ optional AI-use profile). Default response is JSON: the risk assessment (1–10 score + obligations) plus a signed `report.download_url` for the rendered PDF. Pass `format:"pdf"` (or send `Accept: application/pdf`) to stream the PDF binary inline instead. Paid feature (Pro+) with a monthly report quota per tier (Pro 5/mo, Business 25/mo); when the quota is exhausted the endpoint returns 402 with an upgrade / single-report hint. Lower tiers receive a preview (risk band + counts + one sample obligation) with the PDF/download withheld behind an upgrade hint. Informational only — NOT legal advice.

🔑 Requires an API key
Example request
curl "https://ai-law-tracker.com/api/v1/report" \
  -X POST \
  -H "X-API-Key: alt_free_9f3c…"
GET/v1/us-law
List + filter the general US law corpus

Statutes, regulations and federal executive instruments at title/chapter/part level, each with its official citation, status, effective date, the official government source URL, and a many-to-many classification into 33 branches and 227 subcategories. Records LINK to the official text; they do not reproduce it. METERED ON RECORDS SERVED, not just on requests. A request cap stops a fast client; a record cap stops a patient one, and only the second is priced against the size of the corpus. Every response carries `meta.record_budget` with what is left in the day and 30-day windows; exhausting it returns 429 `record_budget_exceeded` (distinct from 429 `rate_limited`). PRODUCT SCOPE: this endpoint belongs to the US Law Platform. A key licensed only for AI Law Tracker (`product: ai_law`) is NOT refused here — it is served at the PUBLIC (keyless) capability level, the same few records any anonymous caller gets. The response headers say so explicitly: `X-ALT-Product` (what your key holds), `X-ALT-Product-Surface` (`us_law`) and `X-ALT-Product-Scope` (`in_product` | `out_of_product`). Your request rate and daily/monthly quota are NEVER degraded — those are metered per key wherever you call. What degrades is capability: page size, pagination depth, field envelope and the record budget.

ParamInTypeDescription
branchquerystringPRIMARY branch id from /us-law/taxonomy. Matches only records whose primary classification is this branch - narrower than branch_any, and usually not what you want for a coverage question.
branch_anyquerystringBranch id matched against ANY assignment, primary or secondary. Records are genuinely multi-branch (HIPAA is health law AND privacy law), so this is the complete answer: branch=health_law matches 1,942 records, branch_any=health_law matches 2,852.
domainquerystringSubcategory id matched against ANY assignment, primary or secondary.
domain_primaryquerystringSubcategory id, primary classification only.
jurisdictionquerystringJurisdiction slug, e.g. california. Comma-separated for several: california,new-york.
jurisdiction_levelquerystringfederal and/or state, comma-separated.
instrument_typequerystringDocument KIND: statute, regulation, executive_order, proclamation, agency_guidance, constitution, presidential_memorandum... Comma-separated for several. SCARCE types (executive orders, proclamations, agency guidance and other presidential instruments - about 3% of the corpus) are content-gated below the top tiers: the response is a small real SAMPLE, reported as meta.sampled with meta.sampled_reason "scarce_instrument_type", never a silent truncation. Listing a scarce type alongside a common one still arms that gate.
statusquerystringin_force, superseded, repealed, enacted, unknown. Comma-separated for several.
in_forcequerybooleanOperative law only (or only non-operative).
is_bindingquerybooleanWhether the instrument carries the force of law. false selects the guidance-type corpus.
effective_fromquerystringEffective on or after this date (YYYY-MM-DD).
effective_toquerystring
enacted_fromquerystring
enacted_toquerystring
repealed_fromquerystring
repealed_toquerystring
retrieved_sincequerystringRecords WE re-fetched on or after this time. This is our freshness stamp, NOT a claim that the law changed then - for that see /us-law/records/{record_uid}/history.
verified_sincequerystringRecords WE re-verified on or after this time. Same caveat as retrieved_since.
citationquerystringExact citation match, case-insensitive - e.g. 45 CFR Part 164. Use citation_prefix to widen.
citation_prefixquerystringCitation starts-with, e.g. 45 CFR for everything under that part.
identifierquerystringExact identifier match, e.g. Pub. L. 117-58.
record_uidquerystringFetch specific records by uid; comma-separated, up to 100. The batch form of /us-law/records/{record_uid}.
qquerystringSubstring match on title / short title / citation. For ranked full text over the summary as well, use /us-law/search.
sortqueryeffective_date | enacted_date | repealed_date | retrieved_at | last_verified_at | title | citation
orderqueryasc | desc
limitqueryintegerClamped to your tier cap; the clamp is reported in `meta.gated`.
offsetqueryintegerClamped to your tier pagination depth.
Example request
curl "https://ai-law-tracker.com/api/v1/us-law?branch=value&branch_any=value" \
  -H "X-API-Key: alt_free_9f3c…"
GET/v1/us-law/search
Full-text, citation and presidential-number search over the US law corpus

Websearch-syntax full text ("quoted phrases", -exclusion) with a citation-substring fallback; the strategy that answered is reported in `meta.strategy`. A query that is a presidential document number ("EO 14110", "Proclamation 10925") is resolved against the INDEXED number column only — a miss returns nothing with an explanatory `meta.notice`, never a guessed match, because misidentifying a presidential document is worse than returning nothing. METERED ON RECORDS SERVED, not just on requests. A request cap stops a fast client; a record cap stops a patient one, and only the second is priced against the size of the corpus. Every response carries `meta.record_budget` with what is left in the day and 30-day windows; exhausting it returns 429 `record_budget_exceeded` (distinct from 429 `rate_limited`). PRODUCT SCOPE: this endpoint belongs to the US Law Platform. A key licensed only for AI Law Tracker (`product: ai_law`) is NOT refused here — it is served at the PUBLIC (keyless) capability level, the same few records any anonymous caller gets. The response headers say so explicitly: `X-ALT-Product` (what your key holds), `X-ALT-Product-Surface` (`us_law`) and `X-ALT-Product-Scope` (`in_product` | `out_of_product`). Your request rate and daily/monthly quota are NEVER degraded — those are metered per key wherever you call. What degrades is capability: page size, pagination depth, field envelope and the record budget.

ParamInTypeDescription
q *querystring
branchquerystringPRIMARY branch id from /us-law/taxonomy. Matches only records whose primary classification is this branch - narrower than branch_any, and usually not what you want for a coverage question.
branch_anyquerystringBranch id matched against ANY assignment, primary or secondary. Records are genuinely multi-branch (HIPAA is health law AND privacy law), so this is the complete answer: branch=health_law matches 1,942 records, branch_any=health_law matches 2,852.
domainquerystringSubcategory id matched against ANY assignment, primary or secondary.
domain_primaryquerystringSubcategory id, primary classification only.
jurisdictionquerystringJurisdiction slug, e.g. california. Comma-separated for several: california,new-york.
jurisdiction_levelquerystringfederal and/or state, comma-separated.
instrument_typequerystringDocument KIND: statute, regulation, executive_order, proclamation, agency_guidance, constitution, presidential_memorandum... Comma-separated for several. SCARCE types (executive orders, proclamations, agency guidance and other presidential instruments - about 3% of the corpus) are content-gated below the top tiers: the response is a small real SAMPLE, reported as meta.sampled with meta.sampled_reason "scarce_instrument_type", never a silent truncation. Listing a scarce type alongside a common one still arms that gate.
statusquerystringin_force, superseded, repealed, enacted, unknown. Comma-separated for several.
in_forcequerybooleanOperative law only (or only non-operative).
is_bindingquerybooleanWhether the instrument carries the force of law. false selects the guidance-type corpus.
effective_fromquerystringEffective on or after this date (YYYY-MM-DD).
effective_toquerystring
enacted_fromquerystring
enacted_toquerystring
repealed_fromquerystring
repealed_toquerystring
retrieved_sincequerystringRecords WE re-fetched on or after this time. This is our freshness stamp, NOT a claim that the law changed then - for that see /us-law/records/{record_uid}/history.
verified_sincequerystringRecords WE re-verified on or after this time. Same caveat as retrieved_since.
citationquerystringExact citation match, case-insensitive - e.g. 45 CFR Part 164. Use citation_prefix to widen.
citation_prefixquerystringCitation starts-with, e.g. 45 CFR for everything under that part.
identifierquerystringExact identifier match, e.g. Pub. L. 117-58.
record_uidquerystringFetch specific records by uid; comma-separated, up to 100. The batch form of /us-law/records/{record_uid}.
sortqueryrelevance | effective_date | enacted_date | title
orderqueryasc | descIgnored when sort=relevance.
limitqueryinteger
offsetqueryinteger
Example request
curl "https://ai-law-tracker.com/api/v1/us-law/search?q=value&branch=value" \
  -H "X-API-Key: alt_free_9f3c…"
GET/v1/us-law/taxonomy
The classification tree + corpus health (OPEN — no key, not metered)

The 33 branches and 227 subcategories the corpus is classified into, with descriptions, so a consumer can build ?branch= / ?domain= filters without guessing. Deliberately OPEN to everyone and NOT metered: it DESCRIBES the corpus, it is not the corpus, and a classification a customer cannot inspect is a black box. Also returns `meta.health` — `records_total`, `records_placeholder` (records still in the `other_unclassified` bucket) and `avg_domains_per_record`. That placeholder count is published rather than hidden: it is the honest measure of how far the classification actually reaches, and it is the number every public coverage claim on the site is checked against.

Example request
curl "https://ai-law-tracker.com/api/v1/us-law/taxonomy" \
  -H "X-API-Key: alt_free_9f3c…"
GET/v1/us-law/jurisdictions
Per-jurisdiction coverage rollup (OPEN — no key, not metered)

One row per jurisdiction: record counts by instrument type, the code edition held, and the verification stamps. Aggregated in the database — this endpoint must never be answered by paging the corpus, since inviting a caller to walk 31,800 records just to count them is exactly the bulk copy the record budget exists to prevent. Open for the same reason as /us-law/taxonomy: coverage is how you evaluate the dataset before paying for it.

ParamInTypeDescription
jurisdiction_levelqueryfederal | state
Example request
curl "https://ai-law-tracker.com/api/v1/us-law/jurisdictions?jurisdiction_level=federal" \
  -H "X-API-Key: alt_free_9f3c…"
GET/v1/us-law/opinions
List, filter and search 988,554 US court opinions

Published opinions filed 2015-01-01 onward from federal appellate courts and state supreme/appellate courts. Each record IDENTIFIES a decision — case name, court, filing date, docket number, reporter citation, and how many later opinions cite it — and links to the full decision at `absolute_url`. THERE IS NO OPINION TEXT AND NO HOLDING IN THIS CORPUS. `q` is a websearch full-text match over the CASE NAME only (quoted phrases and -exclusion work: `"Trump v. Cook"`, `monsanto -durnell`), and every response that ran one says so in `meta.search_field`. Do not describe this endpoint as searching the text of decisions. METERED ON RECORDS SERVED, on the SAME budget as /v1/us-law rather than a second one. That is deliberate: a separate allowance would have widened every existing key the day this dataset shipped. Every response carries `meta.record_budget`; exhausting it returns 429 `record_budget_exceeded`. TWO LIMITS COME FROM THE SIZE OF THE TABLE, NOT FROM YOUR TIER, and they apply identically at every tier including Enterprise. (1) `meta.total` is the PLANNER’S ESTIMATE above 1,000 rows — it measured 53% low on one full-text query — so it is always accompanied by `meta.total_is_estimate`; pass `count=exact` for the true number, at up to ~3.3 s. (2) `sort=citation_count` and `cited_min` have no index behind them and are refused with 400 unless the query already carries a narrowing filter; unfiltered, they are cancelled by the database statement timeout. PRODUCT SCOPE: this endpoint belongs to the US Law Platform. A key licensed only for AI Law Tracker is served here at the public (keyless) level, reported in `X-ALT-Product-Scope` — not refused.

ParamInTypeDescription
courtquerystringCourt slug, comma-separated for several (max 25), e.g. scotus,ca9. The valid values are published by /us-law/courts, which needs no key.
court_levelquerystringfederal_appellate, state_supreme and/or state_appellate, comma-separated.
jurisdiction_levelquerystringfederal and/or state, comma-separated. `state` covers both state_supreme and state_appellate. Combined with court_level it means the INTERSECTION; a contradictory pair returns an empty page rather than a silently dropped filter.
cluster_idquerystringFetch specific opinions by cluster id; comma-separated, up to 100. The batch form of /us-law/opinions/{cluster_id}.
filed_fromquerystringFiled on or after this date (YYYY-MM-DD).
filed_toquerystringFiled on or before this date (YYYY-MM-DD).
qquerystringWebsearch full-text over the CASE NAME. Quoted phrases and -exclusion supported. It does NOT search opinion text — this corpus holds none.
citationquerystringExact reporter citation, e.g. 2022 OK 38. CASE-SENSITIVE against the canonical citation: the index that makes this a 212 ms lookup instead of a 6.3 s scan cannot answer a case-insensitive match.
citation_prefixquerystringCitation starts-with, e.g. "2022 OK" for that year and reporter. The deliberate widening of `citation`, asked for by name so you know which you got.
cited_minqueryintegerOnly opinions cited by at least this many later opinions. Requires at least one narrowing filter (see the endpoint description).
sortquerydate_filed | citation_countcitation_count requires at least one narrowing filter. case_name sorting is not offered — no index, and nobody pages a million captions alphabetically.
orderqueryasc | desc
countqueryestimated | exactexact costs up to ~3.3 s and needs a key (any key, including a free one) — an unauthenticated request that can pin a database core for 3 s is a self-inflicted denial-of-service. A keyless caller silently gets `estimated` and sees `count` in meta.gated.
limitqueryintegerClamped to your tier cap; the clamp is reported in meta.gated.
offsetqueryintegerClamped to your tier pagination depth.
Example request
curl "https://ai-law-tracker.com/api/v1/us-law/opinions?court=value&court_level=value" \
  -H "X-API-Key: alt_free_9f3c…"
GET/v1/us-law/opinions/{cluster_id}
One court opinion, in full

The complete record for one CourtListener cluster id — the `cluster_id` field of any list result. Provenance (absolute_url, source_authority, bulk_edition, retrieved_at) is never withheld at any tier: the link to the decision is how you check our work, and withholding it to build an upsell would mean selling an unverifiable claim. The record identifies the decision; it does not contain it. `meta.corpus.full_text_at` points at the opinion itself. To fetch many at once use /us-law/opinions?cluster_id=1,2,3 (up to 100).

ParamInTypeDescription
cluster_id *pathintegerCourtListener cluster id.
Example request
curl "https://ai-law-tracker.com/api/v1/us-law/opinions/{cluster_id}" \
  -H "X-API-Key: alt_free_9f3c…"
GET/v1/us-law/courts
Court-opinion coverage, per court (OPEN — no key, not metered)

One row per REGISTERED court: how many opinions we hold, how many carry a reporter citation, and the earliest and latest filing dates. It is both the coverage table and the lookup the `court=` filter needs — a filter whose valid values are undiscoverable is not a filter, which is why this is open. 293 courts are registered and 146 hold opinions, so 147 rows come back with `opinions: 0`. They are not hidden: omitting them would overstate coverage. Read the date spans too — scotus shows 37,792 rows because CourtListener publishes orders and summary dispositions as clusters, and those thin out sharply after 2020. THE COUNTS ARE MATERIALISED AND THE RESPONSE SAYS WHEN. Computed live the aggregate takes 2.8 s against 988,554 rows, which on a keyless endpoint would be a self-inflicted denial-of-service. So every response carries `meta.counts_refreshed_at`, and `meta.counts_stale` goes true once the rollup is more than 48 hours old (the refresh runs daily). The numbers are never presented as current — they are presented with the timestamp that says how current they are.

ParamInTypeDescription
court_levelqueryfederal_appellate | state_supreme | state_appellate
jurisdiction_levelqueryfederal | state
with_opinionsquerybooleantrue = only courts we hold opinions for; false = only the registered courts we hold nothing for.
Example request
curl "https://ai-law-tracker.com/api/v1/us-law/courts?court_level=federal_appellate&jurisdiction_level=federal" \
  -H "X-API-Key: alt_free_9f3c…"
GET/v1/us-law/export
Bulk export manifest — NOT self-serve, licensed tiers only

Plans a bulk export of any slice /us-law can filter and returns a MANIFEST: the exact row count, what it will cost against your record allowance, and one SIGNED, short-lived download URL per part (NDJSON | CSV | JSON). The bytes come from the signed part URLs; this call serves no records and charges nothing. NOT SOLD SELF-SERVE AT ANY PRICE. Taking the whole corpus as a file is a licensing conversation, not a checkout — every self-serve plan keeps full API access to the same data and pages it instead. A below-tier caller gets 403 `tier_upgrade_required` naming the tier it opens at. Part URLs carry a signed token rather than your API key, so a link can be handed to a loader without handing over your credential; every download is still metered against the key that created it. PRODUCT SCOPE: this endpoint belongs to the US Law Platform. A key licensed only for AI Law Tracker (`product: ai_law`) is NOT refused here — it is served at the PUBLIC (keyless) capability level, the same few records any anonymous caller gets. The response headers say so explicitly: `X-ALT-Product` (what your key holds), `X-ALT-Product-Surface` (`us_law`) and `X-ALT-Product-Scope` (`in_product` | `out_of_product`). Your request rate and daily/monthly quota are NEVER degraded — those are metered per key wherever you call. What degrades is capability: page size, pagination depth, field envelope and the record budget.

ParamInTypeDescription
formatqueryndjson | csv | json
fieldsqueryfull | basicA tier restricted to the trimmed envelope cannot obtain the full one by asking; `basic` can only be chosen downward.
jurisdictionquerystring
instrument_typequerystring
branchquerystring
domainquerystring
in_forcequeryboolean
Example request
curl "https://ai-law-tracker.com/api/v1/us-law/export?format=ndjson&fields=full" \
  -H "X-API-Key: alt_free_9f3c…"
GET/v1/us-law/records/{record_uid}
One US-law record, in full

The complete record for one record_uid, including provenance (official_url, source_authority, full_text_url, full_text_sha256, retrieved_at, last_verified_at). Provenance is never withheld at any tier: on a legal surface the citation and the link to the government source are how you check our work, and withholding them to create an upsell would mean selling an unverifiable claim. To fetch many at once use /us-law?record_uid=uid1,uid2 (up to 100).

ParamInTypeDescription
record_uid *pathstring
Example request
curl "https://ai-law-tracker.com/api/v1/us-law/records/{record_uid}" \
  -H "X-API-Key: alt_free_9f3c…"
GET/v1/us-law/records/{record_uid}/history
What changed on this record (capture began 2026-08-20)

The recorded change log for one record: one entry per changed FIELD, newest first, across status, dates, citation, identifier, title, instrument type, classification, source URLs and summary. READ meta.capture_started_at BEFORE READING data. Nothing recorded a record-level diff on this corpus before 2026-08-20, and there is deliberately NO BACKFILL, because a backfill would have to invent what the record used to say. An empty result therefore means "we did not observe a change since capture began" and says so in meta.notice — it is NEVER a claim that the law has not changed. TIER: sampled below Pro (the most recent few entries, with the true total stated), full at Pro and above on either product ladder.

ParamInTypeDescription
record_uid *pathstring
Example request
curl "https://ai-law-tracker.com/api/v1/us-law/records/{record_uid}/history" \
  -H "X-API-Key: alt_free_9f3c…"
GET/v1/us-law/compare
Cross-jurisdiction comparison — what does every state say about X?

One row per jurisdiction holding law in a branch or subcategory, with record counts, how many are in force, the split by instrument type, the latest effective date and when we last verified it. This is the answer you would otherwise have to page the entire 31,867-record corpus to assemble. COUNTING. `records` counts EVERY domain assignment, primary or secondary; `records_primary` counts only records whose PRIMARY classification is this branch. Both are reported because they differ a lot (health_law: 2,852 vs 1,942) and a comparison built on primary assignments alone would report that a state has no privacy law when its privacy statutes happen to be filed under consumer protection first. TIER. Ordinary single-field filtering on /us-law is open at every tier including keyless — discovery is never the thing that is metered. This is the assembled answer, so below Pro it returns a real 5-jurisdiction SAMPLE with the true totals stated in meta, and the full table at Pro and above on either product ladder.

ParamInTypeDescription
branchquerystringBranch id from /us-law/taxonomy. Either branch or domain is required.
domainquerystringSubcategory id, for a narrower comparison. Mutually exclusive with branch.
jurisdiction_levelqueryfederal | state
in_force_onlyquerybooleanOnly jurisdictions holding at least one operative record.
Example request
curl "https://ai-law-tracker.com/api/v1/us-law/compare?branch=value&domain=value" \
  -H "X-API-Key: alt_free_9f3c…"
GET/v1/us-law/export/download
Download one part of a bulk export

Streams a single part of an export planned by GET /us-law/export. Authenticated by the SIGNED TOKEN in the manifest, not by an API key — so a part URL can be handed to a loader without handing over your credential. Tokens are short-lived and each download is still metered against the key that created the manifest. Any API key sent alongside is ignored: authority here comes from the token.

ParamInTypeDescription
token *querystringThe signed token from a manifest part URL.
Example request
curl "https://ai-law-tracker.com/api/v1/us-law/export/download?token=value" \
  -H "X-API-Key: alt_free_9f3c…"
GET/v1/disclosures
SEC EDGAR AI risk disclosures (ENTERPRISE ONLY)

AI-related risk-factor disclosures extracted from SEC EDGAR filings. ENTERPRISE-ONLY: there is no teaser and no partial access on any self-serve tier — a below-tier caller gets 403 tier_upgrade_required, never a trimmed response. Documented here so the capability is discoverable; the gate is in the route, not in this spec.

🔑 Requires an API key
ParamInTypeDescription
qquerystring
companyquerystring
cikquerystringNumeric CIK.
formquerystringFiling form type, e.g. 10-K.
date_fromquerystring
date_toquerystring
limitqueryinteger
offsetqueryinteger
Example request
curl "https://ai-law-tracker.com/api/v1/disclosures?q=value&company=value" \
  -H "X-API-Key: alt_free_9f3c…"
GET/v1/enforcement/matters
Enforcement + litigation matters — list, filter and search

Regulatory enforcement actions and private litigation involving AI, at MATTER level: forum, agency, parties, status, relief and the statutes invoked. One row per dispute, not per press release — an agency action with a complaint, a settlement and a final order is three rows on /v1/enforcement and ONE matter here. OPEN AT EVERY TIER since 2026-08-22. It used to answer a hard 403 below Enterprise, which made the dataset invisible and therefore unsellable. What is metered instead is DEPTH: the assembled chain on /enforcement/matters/{matter_uid} — parties, relief amounts, the event timeline and the cited statutes — is sampled below the paid step. A record budget would have been theatre on a 91-row registry. A SECOND GATE THAT IS NOT ABOUT MONEY: 30 of 91 matters are duplicates of another row or still carry an untranslated CAPTION, and are withheld from every caller not licensed for the raw registry — `meta.registry.withheld_not_publish_ready` reports how many THIS query hid. A further 6 ARE published with one descriptive field nulled and named in `unavailable_fields`; withholding a $1.4bn settlement because its forum_name has an untranslated clause would have been a worse answer. See /enforcement/coverage for the full breakdown. READ `verification` BEFORE QUOTING ANYTHING. Every matter currently held is `single_source`. An empty data[] means no matter matched — never that an agency has taken no action. /enforcement/sources says which of the 254 monitored sources are actually answering.

🔑 Requires an API key
ParamInTypeDescription
jurisdictionquerystringJurisdiction slug, comma-separated for several.
jurisdiction_levelquerystringfederal, state and/or multistate, comma-separated.
forum_typequerystringComma-separated. Values from /enforcement/categories.
matter_typequerystringenforcement_action, civil_litigation, guidance_document, investigation, inquiry_6b. Comma-separated.
matter_statusquerystringComma-separated. Values from /enforcement/categories.
agencyquerystringAgency code, e.g. FTC, DOJ, SEC, Texas AG. Comma-separated for several; a single value may contain spaces, parentheses and accents. NOTE: an agency_code that itself contains a COMMA cannot be matched here, because the comma is the multi-value delimiter — three live values are in that state. Use q= for those; it searches agency_code as a substring.
ai_rolequerystringComma-separated. Several roles mean the matter carries ALL of them.
domainquerystringPrimary subject domain id, comma-separated.
verificationquerystringCorroboration level. Currently every held matter is single_source.
date_fromquerystringBounds filed_date, which is null on 71 of 91 matters — a date filter therefore EXCLUDES the undated majority.
date_toquerystring
qquerystringSubstring over caption, summary and agency.
sortqueryfiled_date | first_seen_at | last_verified_at | closed_date
orderqueryasc | desc
limitqueryintegerClamped to your tier cap; the clamp is reported in meta.gated.
offsetqueryinteger
Example request
curl "https://ai-law-tracker.com/api/v1/enforcement/matters?jurisdiction=value&jurisdiction_level=value" \
  -H "X-API-Key: alt_free_9f3c…"
GET/v1/enforcement/matters/{matter_uid}
One enforcement matter, with its chain

The matter plus its EVENTS (timeline), PARTIES, RELIEF, statutory CITATIONS and the SOURCE DOCUMENTS each claim traces to. This is the dossier the product is sold on. THE CHAIN IS WHAT IS METERED. Below the paid step each chain is a 2-row sample and `data.chain_totals` reports the true size of every one of them — never an empty wall, and never a sample you cannot tell is a sample. Listing and searching matters stays fully open. FIELDS THAT LOOK LIKE HEDGES AND ARE THE PRODUCT: `events[].is_date_estimated` (the source gave a year, not a day), `verification`, `laws[].link_status` (`unlinked` = we hold the citation verbatim but have not resolved it — a confidently wrong citation is worse), and `duplicate_of`. PARTIES ARE REDACTED BY POLICY, in the database, not here: 97 of 235 party rows publish and the rest are withheld — named private individuals and minors by default. See the pii_class and redaction_policy vocabularies on /enforcement/categories. A 404 is returned both for a matter that does not exist AND for one withheld pending review, on purpose: distinguishable codes would turn the readiness gate into an enumeration oracle.

🔑 Requires an API key
ParamInTypeDescription
matter_uid *pathstringAn opaque stable key, not a description — read caption for the matter name.
Example request
curl "https://ai-law-tracker.com/api/v1/enforcement/matters/{matter_uid}" \
  -H "X-API-Key: alt_free_9f3c…"
GET/v1/enforcement/sources
What we monitor, and whether it is answering (OPEN — no key, not metered)

The 254 official sources behind the enforcement layer — agency newsrooms, AG press feeds, court dockets — with the last successful read, the fault state and whether each is stale against its own silence budget. IT PUBLISHES THE BAD NEWS. 132 of 254 are enabled and 123 are stale (measured 2026-08-22). Those go out as they are, on the same argument /v1/us-law/jurisdictions publishes its OLDEST verification stamp: an enforcement product whose coverage table only showed the healthy sources would be advertising, not data. FAULTS ARE CLASSIFIED, NOT QUOTED. `last_fault_reason_code` is a closed vocabulary (blocked, unauthorized, not_found, timeout, adapter_missing, egress_unavailable, other) with a one-line label; the raw internal fault text never leaves the server. Read this before concluding anything from an empty /enforcement/matters result: a stale source is a gap in OUR monitoring, never a statement that an authority has taken no action.

ParamInTypeDescription
jurisdiction_levelqueryfederal | state | multistate | territory | local | international
is_enabledqueryboolean
is_stalequerybooleantrue = sources not read inside their own max_silence_hours.
Example request
curl "https://ai-law-tracker.com/api/v1/enforcement/sources?jurisdiction_level=federal&is_enabled=value" \
  -H "X-API-Key: alt_free_9f3c…"
GET/v1/enforcement/categories
The enforcement controlled vocabularies (OPEN — no key, not metered)

Thirteen closed vocabularies, 104 terms: matter_type, matter_status, forum_type, party_role, party_kind, relief_type, event_type, ai_role, law_relation, verification, jurisdiction_level, pii_class and redaction_policy. `code` is the API value; `label` and `description` are for display. These are the exact values the /enforcement/matters filters accept, which is why the endpoint is open: a documented filter whose valid values are undiscoverable is not a filter. TWO OF THEM DESCRIBE WHAT WE DO NOT PUBLISH. pii_class and redaction_policy are the terms behind the party gate that withholds 138 of 235 party rows. Publishing the vocabulary is how that policy becomes checkable rather than merely asserted.

ParamInTypeDescription
kindquerystringReturn just one vocabulary.
Example request
curl "https://ai-law-tracker.com/api/v1/enforcement/categories?kind=value" \
  -H "X-API-Key: alt_free_9f3c…"
GET/v1/enforcement/coverage
How big the enforcement registry actually is (OPEN — no key, not metered)

Counts the registry rather than serving it: matters held, matters publishable, and how many are withheld as duplicates or for untranslated internal language — plus breakdowns by matter type, jurisdiction level and agency, and the de-duplicated monetary relief total. THE WITHHELD COUNTS ARE THE POINT. A caller who sees `total: 61` on /enforcement/matters would reasonably conclude the registry IS 61 matters. It is 91: 11 duplicates and 21 untranslated captions (overlapping) leave 30 withheld, and 6 of the published ones carry a nulled field. This is the same commitment /v1/us-law/taxonomy makes by publishing `records_placeholder`. The relief total is computed over PUBLISHABLE, de-duplicated matters only and says so in `relief.basis`. Summed naively across all 91 rows it is wrong by at least the $3.2M DOJ/OpenAI settlement, which is present twice under two matter_uids.

Example request
curl "https://ai-law-tracker.com/api/v1/enforcement/coverage" \
  -H "X-API-Key: alt_free_9f3c…"

Webhooks & signature verification

Subscribe with POST /v1/webhooks. Each change is delivered as an HMAC-SHA256-signed POST to your target_url. The signing_secret is returned once when you create the webhook.

HeaderMeaning
X-ALT-Signaturesha256=<hex HMAC-SHA256 of `${timestamp}.${rawBody}` under your signing_secret>
X-ALT-TimestampUnix seconds; folded into the signed content (reject if skew is large).
X-ALT-Eventlaw.created | law.updated
X-ALT-DeliveryDelivery uuid — use as an idempotency key.
X-ALT-Webhook-IdThe subscription uuid.

Verify each delivery before trusting it — recompute the signature over `${timestamp}.${rawBody}`:

Node.js — verify a delivery
const crypto = require('crypto');
function verify(req, secret) {
  const ts = req.headers['x-alt-timestamp'];
  const sig = (req.headers['x-alt-signature'] || '').replace(/^sha256=/, '');
  const expected = crypto.createHmac('sha256', secret).update(`${ts}.${req.rawBody}`).digest('hex');
  const a = Buffer.from(sig), b = Buffer.from(expected);
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}

Errors

Every error uses one uniform shape:

{
  "api_version": "v1",
  "error": {
    "code": "rate_limited",
    "message": "Rate limit exceeded for the minute window. Retry in 42s.",
    "docs": "https://ai-law-tracker.com/developers",
    "retry_after": 42
  }
}

Common codes: invalid_key (401), revoked_key (403), not_found (404), rate_limited (429), backend_unavailable (503).

License & attribution

Data is licensed CC BY 4.0 — free to use commercially with attribution. Attribution is mandatory on the free tier (a dofollow link to ai-law-tracker.com) and optional on paid tiers. Informational only — not legal advice. Verify against each record's official_url before relying on it.